Nginx 反向代理防止更改其他位置的主机
Nginx reverse proxy prevent changing host for other locations
我花了几天时间尝试完成这件事,但我做不到。我有两个 Web 应用程序,一个是生产应用程序,一个是测试应用程序,假设 https://production.app
和 https://testing.app
。我需要在 https://production.app/location
下创建一个指向 https://testing.app/location
的反向代理(目前我只需要产品中测试环境的一项功能)。我创建的配置确实代理了这个确切位置,但该功能还从 /static
目录加载资源,导致请求 https://production.app/static/xyz.js
而不是 https://testing.app/static/xyz.js
,并且 /static
不能代理。有没有办法仅在这个代理流量中更改 headers,使其成为 https://testing.app/static
(当然还有任何其他位置)?
以下是我当前的配置(仅关于代理的指令):
server {
listen 443 ssl;
server_name production.app;
root /var/www/production.app;
location /location/ {
proxy_pass https://testing.app/location/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
祝你有美好的一天:)
你的问题标题写得不好。它与“更改 headers” 无关,nginx 位置虽然本质上与请求处理相关,但也不是正确的术语。它应该类似于“如何以与其他方式不同的方式提供代理页面请求的资产”。
好的,我们开始吧。首先,你真的了解下面的配置到底是做什么的吗?
location /location/ {
proxy_pass https://testing.app/location/;
}
在 https://testing.app
上游名称之后指定的 URI 前缀 /location/
具有以下效果:
location
指令中指定的 /location/
前缀从已处理的 URI 中截断。
- 已处理的 UIR 在被传递到上游之前被添加了
proxy_pass
指令中指定的 /location/
前缀。
也就是说,如果这些前缀相等,则以下配置将执行相同的操作以消除这些步骤(因此处理请求的效率会稍微高一些):
location /location/ {
proxy_pass https://testing.app;
}
了解这是我们将要使用的技巧的关键概念。
因为从 /location/
页面发出的所有静态资产请求都将具有 HTTP Referer
header equal to http://production.app/location/
(well, unless you specify no-referer
as you page referrer policy,如果你是,除非你改变它,否则整个技巧将根本不起作用) ,我们可以重写一个符合某些条件的请求 URI(比如以 /static/
或 /img/
前缀开头),使用下面的 if
块(应该放在server
配置级别):
if ($http_referer = https://production.app/location/) {
rewrite ^/static/ /internal$uri;
rewrite ^/img/ /internal$uri;
...
}
我们可以使用任何前缀,这里使用的 /internal
仅作为示例,但是使用的前缀不应干扰您现有的路由。接下来,我们将使用 internal
关键字定义该特殊位置:
location /internal/ {
internal;
proxy_pass https://testing.app/;
}
此处 http://testing.app
上游名称后的尾部斜线是必不可少的部分。它将使代理的 URI 返回到其原始状态,删除之前 rewrite
指令添加的 /internal/
前缀,并将其替换为单个斜杠。
您可以将此技巧用于多个页面,使用正则表达式模式匹配 Referer
header 值,例如
if ($http_referer ~ ^https?://production\.app/(page1|page2|page3)/) {
...
}
除静态资产外,您不应该尝试此操作,否则它会破坏应用程序路由机制。这也只是一种仅应用于测试目的的解决方法,我不建议长期用于生产。
顺便说一句,你确定你真的需要那个吗
proxy_set_header Host $host;
在你所在的位置?你真的明白它的意思吗,或者你只是从其他配置中使用它 copy-pasting ?检查 this 答案,如果出现问题,请不要感到惊讶。
我花了几天时间尝试完成这件事,但我做不到。我有两个 Web 应用程序,一个是生产应用程序,一个是测试应用程序,假设 https://production.app
和 https://testing.app
。我需要在 https://production.app/location
下创建一个指向 https://testing.app/location
的反向代理(目前我只需要产品中测试环境的一项功能)。我创建的配置确实代理了这个确切位置,但该功能还从 /static
目录加载资源,导致请求 https://production.app/static/xyz.js
而不是 https://testing.app/static/xyz.js
,并且 /static
不能代理。有没有办法仅在这个代理流量中更改 headers,使其成为 https://testing.app/static
(当然还有任何其他位置)?
以下是我当前的配置(仅关于代理的指令):
server {
listen 443 ssl;
server_name production.app;
root /var/www/production.app;
location /location/ {
proxy_pass https://testing.app/location/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
祝你有美好的一天:)
你的问题标题写得不好。它与“更改 headers” 无关,nginx 位置虽然本质上与请求处理相关,但也不是正确的术语。它应该类似于“如何以与其他方式不同的方式提供代理页面请求的资产”。
好的,我们开始吧。首先,你真的了解下面的配置到底是做什么的吗?
location /location/ {
proxy_pass https://testing.app/location/;
}
在 https://testing.app
上游名称之后指定的 URI 前缀 /location/
具有以下效果:
location
指令中指定的/location/
前缀从已处理的 URI 中截断。- 已处理的 UIR 在被传递到上游之前被添加了
proxy_pass
指令中指定的/location/
前缀。
也就是说,如果这些前缀相等,则以下配置将执行相同的操作以消除这些步骤(因此处理请求的效率会稍微高一些):
location /location/ {
proxy_pass https://testing.app;
}
了解这是我们将要使用的技巧的关键概念。
因为从 /location/
页面发出的所有静态资产请求都将具有 HTTP Referer
header equal to http://production.app/location/
(well, unless you specify no-referer
as you page referrer policy,如果你是,除非你改变它,否则整个技巧将根本不起作用) ,我们可以重写一个符合某些条件的请求 URI(比如以 /static/
或 /img/
前缀开头),使用下面的 if
块(应该放在server
配置级别):
if ($http_referer = https://production.app/location/) {
rewrite ^/static/ /internal$uri;
rewrite ^/img/ /internal$uri;
...
}
我们可以使用任何前缀,这里使用的 /internal
仅作为示例,但是使用的前缀不应干扰您现有的路由。接下来,我们将使用 internal
关键字定义该特殊位置:
location /internal/ {
internal;
proxy_pass https://testing.app/;
}
此处 http://testing.app
上游名称后的尾部斜线是必不可少的部分。它将使代理的 URI 返回到其原始状态,删除之前 rewrite
指令添加的 /internal/
前缀,并将其替换为单个斜杠。
您可以将此技巧用于多个页面,使用正则表达式模式匹配 Referer
header 值,例如
if ($http_referer ~ ^https?://production\.app/(page1|page2|page3)/) {
...
}
除静态资产外,您不应该尝试此操作,否则它会破坏应用程序路由机制。这也只是一种仅应用于测试目的的解决方法,我不建议长期用于生产。
顺便说一句,你确定你真的需要那个吗
proxy_set_header Host $host;
在你所在的位置?你真的明白它的意思吗,或者你只是从其他配置中使用它 copy-pasting ?检查 this 答案,如果出现问题,请不要感到惊讶。