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,但目前对我没有帮助。我没有阅读所有围绕主题 nginxproxy.

的大约 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 然后它加载:

但是如果我使用我的浏览器获取 https://newsite.foo 然后它加载:

虽然通过 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_headerproxy_set_headerproxy_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 一样。

我无法回答这些问题:

有没有人可以为我指明正确的方向?

提前致谢。至少感谢你阅读我的 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 ).