Nginx:DNS 转换期间将请求代理到外部服务器

Nginx:DNS 转换期间将请求代理到外部服务器

我正在将网站迁移到具有另一个 IP 地址的新位置。

为了让用户顺利过渡并尽可能避免停机,我计划更改 DNS,然后将代理请求从旧服务器更改为新服务器。

但是我在 nginx 中的代理测试不起作用,而且我无法弄清楚原因。我在浏览器中只看到一个完全空白的页面。nginx 错误日志中没有任何内容。在另一端,没有传入请求。下面的代理配置在我们当前的设置中运行良好,我们将 nginx 代理到 3 个 Web 服务器(负载平衡),从端口 443 到端口 80。

我想知道问题是否与 SSL->SSL 代理有关?我应该代理 443->443,还是 443->80,还是 80->443?

test-proxy.example.com -> test.example.com

server {
     listen 12.34.56.78:443;
     server_name test-proxy.example.com;

     ssl on; 
     ssl_certificate /etc/letsencrypt/live/test-proxy.example.com/fullchain.pem;
     ssl_certificate_key /etc/letsencrypt/live/test-proxy.example.com/privkey.pem;
     include /etc/letsencrypt/options-ssl-nginx.conf; 

     location / { 
        proxy_pass  https://test.example.com:443;
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
        proxy_redirect off;
        proxy_buffering off;
        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:  https;
        proxy_set_header        Connection          "";
        proxy_connect_timeout       600;
        proxy_send_timeout          600;
        proxy_read_timeout          600;
        send_timeout                600;
     }
}   

# test-proxy.example.com 80
server {
     listen 12.34.56.78:80;
     server_name  test-proxy.example.com;

     #Let's Encrypt: Let requests for acme challenge pass 
     include /etc/nginx/acme.conf;

     location / { 
          rewrite ^(.*) https://test-proxy.example.com$1 permanent;
     }
}

答案1

首先,Host当 Web 服务器为多个不同的域提供服务(考虑serverWeb 服务器配置文件中的多个块)并监听同一个 TCP 端口时,会使用 HTTP 标头。为了确定哪个块server应该处理请求,Web 服务器会根据Host标头值选择适当的块。也就是说,标头值错误的请求Host可能根本无法到达您的 Web 后端。即使它到达了您的后端,Web 应用程序本身也可能决定拒绝回答此类请求或做出错误行为(例如,它可以使用错误的Host值来生成一些无处可去的链接或请求无法交付的资产)。

如果没有这样的机制,整个共享托管概念将是不可能的(或者我们每个 IP 地址只能有一个 Web 服务器)。当 SSL 出现时,所有流量都加密了,服务器名称指示(SNI)机制的发明是为了允许 Web 服务器查看这些信息,并继续能够为 SSL 加密的 HTTP 流量选择正确的服务器块。一些非常旧客户端(例如 Android 2.3、W​​indows XP 上的 IE)不知道如何使用 SNI 扩展,因此无法访问使用共享托管服务提供商提供的 HTTPS 站点。

现在回到你的问题。显然,你的远程服务器希望Host将标头设置为test.example.com。这正是 nginx 默认发送的内容(使用proxy_pass指令中的服务器名称)。但是,你将其更改为$host变量值,即test-proxy.example.com,这是你的远程服务器完全意想不到的(可能它根本看不到代理请求)。

常用的配置如下

server {
    server_name example.com;
    location / {
        proxy_set_header Host $host;
        proxy_pass http://localhost:5000;
    }
}

以相反的方式工作 - 它允许后端 Web 应用程序查看真实域名,example.com而不是localhost:5000(否则将被发送)。 在你的情况下,它不会带来任何好处,只会带来坏处。

相关内容