我正在将网站迁移到具有另一个 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 服务器为多个不同的域提供服务(考虑server
Web 服务器配置文件中的多个块)并监听同一个 TCP 端口时,会使用 HTTP 标头。为了确定哪个块server
应该处理请求,Web 服务器会根据Host
标头值选择适当的块。也就是说,标头值错误的请求Host
可能根本无法到达您的 Web 后端。即使它到达了您的后端,Web 应用程序本身也可能决定拒绝回答此类请求或做出错误行为(例如,它可以使用错误的Host
值来生成一些无处可去的链接或请求无法交付的资产)。
如果没有这样的机制,整个共享托管概念将是不可能的(或者我们每个 IP 地址只能有一个 Web 服务器)。当 SSL 出现时,所有流量都加密了,服务器名称指示(SNI)机制的发明是为了允许 Web 服务器查看这些信息,并继续能够为 SSL 加密的 HTTP 流量选择正确的服务器块。一些非常旧客户端(例如 Android 2.3、Windows 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
(否则将被发送)。 在你的情况下,它不会带来任何好处,只会带来坏处。