前两天收到一个来自去不图床用户的反馈,说在香港区域访问图床时出现了 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}
SNI 有点像邮寄包裹到公寓楼而不是独栋的房子。将邮件邮寄到某人的独栋房子时,仅街道地址就足以将包裹送给收件人。但当包裹进入公寓楼时,除街道地址外,还需公寓号码。否则,包裹可能无法送达收件人或根本无法交付。
许多 Web 服务器更像是公寓大楼而不是独栋房子,因为它们承载多个域名,因此仅 IP 地址不足以指示用户尝试访问哪个域。这可能会导致服务器显示错误 SSL 证书,从而阻止或终止 HTTPS 连接。就像如果没有正确的收件人签名,包裹将无法送到指定的地址一样。
当多个网站托管在一台服务器上并共享一个 IP 地址,并且每个网站都有自己的 SSL 证书,在客户端设备尝试安全连接到其中一个网站时,服务器可能不知道验证哪一个 SSL 证书。
服务器名称指示旨在解决此问题。SNI 是 TLS 协议的扩展,该协议在 HTTPS 中使用。包含在握手流程中,以确保客户端设备能够尝试访问网站的正确 SSL 证书。该扩展使得可以在 TLS 握手期间指定网站的主机名或域名,而不是在握手之后打开 HTTP 连接时指定。
解决方法 {#解决方法}
将下面的代码加入到 Nginx 配置文件的 location
块中,注意将 7bu.top
改为要反代的域名:
|-------------|-----------------------------------------------------------|
| 1 2
| proxy_ssl_name 7bu.top; proxy_ssl_server_name on;
|
某塔发向代理配置文件完整示例如下:
|---------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| location ^~ / { proxy_pass https://c.dusays.com:443; proxy_set_header Host 7bu.top; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_http_version 1.1; proxy_ssl_name 7bu.top; proxy_ssl_server_name on; # proxy_hide_header Upgrade; add_header X-Cache $upstream_cache_status; #Set Nginx Cache if ( $uri ~* "\.(gif|png|jpg|css|js|woff|woff2)$" ) { expires 1m; } proxy_ignore_headers Set-Cookie Cache-Control expires; proxy_cache cache_one; proxy_cache_key $host$uri$is_args$args; proxy_cache_valid 200 304 301 302 2440m; }
|
CDN 设置项 {#CDN-设置项}
这种情况一般出现在 Nginx 反代,偶尔使用 CDN 时也会出现这个问题,大多都是配置 CDN 的时候没有设置 SNI 导致的问题。可以通过设置回源 HOST 来解决,下图以 99CDN 面板为例: