前两天收到一个来自去不图床用户的反馈,说在香港区域访问图床时出现了 502 Bad Gateway 的错误,经过排查后发现是 Nginx 反代 SSL_do_handshake 出现问题,这里分享一下该问题的解决思路。
问题说明
是否遇到过使用 Nginx 反代网站时出现 502 Bad Gateway,明明正常访问都没问题 , 可是反代就 502 Bad Gateway , 查看错误日志显示:
1 | 2024/07/15 17:14:08 [error] 245105#0: *1324376 SSL_do_handshake() failed (SSL: error:1408F10B:SSL routines:ssl3_get_record:wrong version number) while SSL handshaking to upstream, client: 69.162.124.229, server: 7bu.top, request: "GET / HTTP/1.1", upstream: "https://211.101.237.240:443/", host: "7bu.top", referrer: "https://7bu.top" |
初步分析问题发现是由于网站启用 SNI,Nginx 反代时默认没有加入以下参数,故无法成功 handshake 上游的 SSL,则导致 502 Bad Gateway 错误:
1 | proxy_ssl_server_name on; |
什么是 SNI
SNI 有点像邮寄包裹到公寓楼而不是独栋的房子。将邮件邮寄到某人的独栋房子时,仅街道地址就足以将包裹送给收件人。但当包裹进入公寓楼时,除街道地址外,还需公寓号码。否则,包裹可能无法送达收件人或根本无法交付。
许多 Web 服务器更像是公寓大楼而不是独栋房子,因为它们承载多个域名,因此仅 IP 地址不足以指示用户尝试访问哪个域。这可能会导致服务器显示错误 SSL 证书,从而阻止或终止 HTTPS 连接。就像如果没有正确的收件人签名,包裹将无法送到指定的地址一样。
当多个网站托管在一台服务器上并共享一个 IP 地址,并且每个网站都有自己的 SSL 证书,在客户端设备尝试安全连接到其中一个网站时,服务器可能不知道验证哪一个 SSL 证书。
服务器名称指示旨在解决此问题。SNI 是 TLS 协议的扩展,该协议在 HTTPS 中使用。包含在握手流程中,以确保客户端设备能够尝试访问网站的正确 SSL 证书。该扩展使得可以在 TLS 握手期间指定网站的主机名或域名,而不是在握手之后打开 HTTP 连接时指定。
解决方法
将下面的代码加入到 Nginx 配置文件的 location
块中,注意将 7bu.top
改为要反代的域名:
1 | proxy_ssl_name 7bu.top; |
某塔发向代理配置文件完整示例如下:
1 | location ^~ / |
条评论