Nginx 代理传递给反向代理
Nginx proxy pass to reverse proxy
我对 nginx 还很陌生,一直使用当前配置。
我也检查了ssl - nginx does redirect, , nginx proxy_pass, nginx proxy rewrite and another post related to my question。
我还研究了其他一些 post,但目前对我没有帮助。我没有阅读所有围绕主题 nginx
和 proxy
.
的大约 21500 post
Google 也未能引导我找到解决方案。
当前设置是:
[CMS (Plone in LAN)]<--->[Reverse-Proxy (Apache / http://oldsite.foo)]
这是旧站点设置。基本上我们需要重新设计 CMS。但是它已经随着至少两个开发人员(他们从未见过面)的大量依赖和自写模块而发展。将其正确更换将是仅一年的任务。 Apache配置中也有一些奇怪的东西,所以我们现在不能避免使用Apache。
很遗憾,我们需要尽快进行光学重新设计。
所以我们想到了在 Nginx 中使用 Diazo/XSLT 来重新设计旧网站并向我们的评估员展示一些结果。
因此我尝试了以下设置:
[Plone]<--->[Apache]<--->[Proxy (XSLT in Nginx / https://newsite.foo)]
这是我的 xslt_for_oldsite
配置文件(Cache-Control 仅用于调试):
add_header Cache-Control no-cache;
server {
server_name newsite.foo;
server_tokens off;
listen b.b.b.b:80;
return 301 https://$server_name$request_uri;
access_log /var/log/nginx/newsite.port80.access.log;
error_log /var/log/nginx/newsite.port80.error.log;
}
server {
server_name newsite.foo;
server_tokens off;
listen b.b.b.b:443 ssl;
access_log /var/log/nginx/newsite.port443.access.log;
error_log /var/log/nginx/newsite.port443.error.log;
ssl_certificate /etc/ssl/certs/nginx.crt;
ssl_certificate_key /etc/ssl/private/nginx.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5:!ADH:!AECDH;
ssl_session_cache shared:SSL:5m;
proxy_http_version 1.1;
#proxy_set_header X-Forwarded-Host $host:$server_port;
#proxy_set_header X-Forwarded-Server $host;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header Connection "";
# proxy_ignore_headers Expires;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-forwarded-host $host;
sub_filter_types *;
sub_filter_once off;
sub_filter "http://oldsite.foo" "https://newsite.foo";
location / {
proxy_pass http://oldsite.foo/;
proxy_redirect off;
#proxy_redirect http://oldsite.foo/ https://newsite.foo/;
proxy_set_header Host $host;
}
}
如果我启动浏览器连接到 http://oldsite.foo 然后它加载:
- 1 HTML 来自旧站点的文档
- 3 CSS 个来自旧站点的文件
- 来自旧站点的 9 个 JS 文件
- 来自旧站点的 10 个图形文件
但是如果我使用我的浏览器获取 https://newsite.foo 然后它加载:
- 1 HTML 来自新闻站点的文档
- 只有 5 个图形文件来自 oldsite(我的浏览器直接请求)
- 其他都不见了
虽然通过 wget https://newsite.foo -o index.html
收到的 HTML 文档的所有链接都修改为 https://newsite.foo
(正确地将 http://oldsite.foo
替换为 https://newsite.foo
),但浏览器会显示所有链接未修改:http://oldsite.foo
而不是 https://newsite.foo
.
我得到以下服务器 header curl -I https://newsite.foo
:
HTTP/1.1 200 OK
Server: nginx
Date: Fri, 11 Sep 2020 10:28:15 GMT
Content-Type: text/html
Connection: keep-alive
Accept-Ranges: none
Accept-Ranges: bytes
X-Varnish: 1216306480
Age: 0
Via: 1.1 varnish
Set-Cookie: I18N_LANGUAGE="de"; Path=/
Via: 1.1 oldsite.foo
Vary: Accept-Encoding
Cache-Control: no-cache
我玩过 add_header
、proxy_set_header
和 proxy_redirect
。我也试过了
location ~* .* {
proxy_pass http://oldsite.foo$request_uri;
proxy_redirect off;
proxy_set_header Host $host;
}
但是 none 我的更改改变了 nginx 的行为,它将 GET 请求重定向到 http://oldsite.foo 并显示答案,就好像它们来自 https://newsite.foo 一样。
我无法回答这些问题:
- 为什么我的浏览器一直连接到 http://oldsite.foo?它应该连接到 https://newsite.foo .
- 为什么 HTML 中的链接在
wget
的版本和我的浏览器之间不同?
- 为什么超过一半的网站无法访问超过 https://newsite.foo 的浏览器?
- 我该如何解决这个问题?
有没有人可以为我指明正确的方向?
提前致谢。至少感谢你阅读我的 post.
此致。
同时我找到了解决方案。
Apache 发送了 gzipped 数据,sub_filter 无法处理它(参见 official documentation: sub_filter)。
事实上,我试图通过使用 proxy_set_header Accept-Encoding "";
来避免这种情况,但它没有用。
原因是这部分必须设置在location context.
因此,在撰写本文时 (2020-09-15),Ubuntu 20.04 LTS、Nginx 1.14.0 的正确配置是:
...
server {
server_name newsite.foo;
server_tokens off;
listen b.b.b.b:443 ssl;
access_log /var/log/nginx/newsite.port443.access.log;
error_log /var/log/nginx/newsite.port443.error.log;
ssl_certificate /etc/ssl/certs/nginx.crt;
ssl_certificate_key /etc/ssl/private/nginx.key;
# Double check and modify this part BEFORE using in production:
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5:!ADH:!AECDH;
ssl_session_cache shared:SSL:5m;
location / {
proxy_http_version 1.1;
proxy_set_header Accept-Encoding ""; # MUST be written HERE in this context!
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://oldsite.foo;
proxy_redirect off;
sub_filter_types text/html text/css text/javascript; # If unsure you may use '*'
sub_filter_once off;
sub_filter http://oldsite.foo https://newsite.foo;
}
...
感谢 adrianTNT who pointed out the crucial part for me (see ).
我对 nginx 还很陌生,一直使用当前配置。
我也检查了ssl - nginx does redirect,
我还研究了其他一些 post,但目前对我没有帮助。我没有阅读所有围绕主题 nginx
和 proxy
.
Google 也未能引导我找到解决方案。
当前设置是:
[CMS (Plone in LAN)]<--->[Reverse-Proxy (Apache / http://oldsite.foo)]
这是旧站点设置。基本上我们需要重新设计 CMS。但是它已经随着至少两个开发人员(他们从未见过面)的大量依赖和自写模块而发展。将其正确更换将是仅一年的任务。 Apache配置中也有一些奇怪的东西,所以我们现在不能避免使用Apache。
很遗憾,我们需要尽快进行光学重新设计。
所以我们想到了在 Nginx 中使用 Diazo/XSLT 来重新设计旧网站并向我们的评估员展示一些结果。
因此我尝试了以下设置:
[Plone]<--->[Apache]<--->[Proxy (XSLT in Nginx / https://newsite.foo)]
这是我的 xslt_for_oldsite
配置文件(Cache-Control 仅用于调试):
add_header Cache-Control no-cache;
server {
server_name newsite.foo;
server_tokens off;
listen b.b.b.b:80;
return 301 https://$server_name$request_uri;
access_log /var/log/nginx/newsite.port80.access.log;
error_log /var/log/nginx/newsite.port80.error.log;
}
server {
server_name newsite.foo;
server_tokens off;
listen b.b.b.b:443 ssl;
access_log /var/log/nginx/newsite.port443.access.log;
error_log /var/log/nginx/newsite.port443.error.log;
ssl_certificate /etc/ssl/certs/nginx.crt;
ssl_certificate_key /etc/ssl/private/nginx.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5:!ADH:!AECDH;
ssl_session_cache shared:SSL:5m;
proxy_http_version 1.1;
#proxy_set_header X-Forwarded-Host $host:$server_port;
#proxy_set_header X-Forwarded-Server $host;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header Connection "";
# proxy_ignore_headers Expires;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-forwarded-host $host;
sub_filter_types *;
sub_filter_once off;
sub_filter "http://oldsite.foo" "https://newsite.foo";
location / {
proxy_pass http://oldsite.foo/;
proxy_redirect off;
#proxy_redirect http://oldsite.foo/ https://newsite.foo/;
proxy_set_header Host $host;
}
}
如果我启动浏览器连接到 http://oldsite.foo 然后它加载:
- 1 HTML 来自旧站点的文档
- 3 CSS 个来自旧站点的文件
- 来自旧站点的 9 个 JS 文件
- 来自旧站点的 10 个图形文件
但是如果我使用我的浏览器获取 https://newsite.foo 然后它加载:
- 1 HTML 来自新闻站点的文档
- 只有 5 个图形文件来自 oldsite(我的浏览器直接请求)
- 其他都不见了
虽然通过 wget https://newsite.foo -o index.html
收到的 HTML 文档的所有链接都修改为 https://newsite.foo
(正确地将 http://oldsite.foo
替换为 https://newsite.foo
),但浏览器会显示所有链接未修改:http://oldsite.foo
而不是 https://newsite.foo
.
我得到以下服务器 header curl -I https://newsite.foo
:
HTTP/1.1 200 OK
Server: nginx
Date: Fri, 11 Sep 2020 10:28:15 GMT
Content-Type: text/html
Connection: keep-alive
Accept-Ranges: none
Accept-Ranges: bytes
X-Varnish: 1216306480
Age: 0
Via: 1.1 varnish
Set-Cookie: I18N_LANGUAGE="de"; Path=/
Via: 1.1 oldsite.foo
Vary: Accept-Encoding
Cache-Control: no-cache
我玩过 add_header
、proxy_set_header
和 proxy_redirect
。我也试过了
location ~* .* {
proxy_pass http://oldsite.foo$request_uri;
proxy_redirect off;
proxy_set_header Host $host;
}
但是 none 我的更改改变了 nginx 的行为,它将 GET 请求重定向到 http://oldsite.foo 并显示答案,就好像它们来自 https://newsite.foo 一样。
我无法回答这些问题:
- 为什么我的浏览器一直连接到 http://oldsite.foo?它应该连接到 https://newsite.foo .
- 为什么 HTML 中的链接在
wget
的版本和我的浏览器之间不同? - 为什么超过一半的网站无法访问超过 https://newsite.foo 的浏览器?
- 我该如何解决这个问题?
有没有人可以为我指明正确的方向?
提前致谢。至少感谢你阅读我的 post.
此致。
同时我找到了解决方案。
Apache 发送了 gzipped 数据,sub_filter 无法处理它(参见 official documentation: sub_filter)。
事实上,我试图通过使用 proxy_set_header Accept-Encoding "";
来避免这种情况,但它没有用。
原因是这部分必须设置在location context.
因此,在撰写本文时 (2020-09-15),Ubuntu 20.04 LTS、Nginx 1.14.0 的正确配置是:
...
server {
server_name newsite.foo;
server_tokens off;
listen b.b.b.b:443 ssl;
access_log /var/log/nginx/newsite.port443.access.log;
error_log /var/log/nginx/newsite.port443.error.log;
ssl_certificate /etc/ssl/certs/nginx.crt;
ssl_certificate_key /etc/ssl/private/nginx.key;
# Double check and modify this part BEFORE using in production:
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5:!ADH:!AECDH;
ssl_session_cache shared:SSL:5m;
location / {
proxy_http_version 1.1;
proxy_set_header Accept-Encoding ""; # MUST be written HERE in this context!
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://oldsite.foo;
proxy_redirect off;
sub_filter_types text/html text/css text/javascript; # If unsure you may use '*'
sub_filter_once off;
sub_filter http://oldsite.foo https://newsite.foo;
}
...
感谢 adrianTNT who pointed out the crucial part for me (see