Nginx反向代理HTTPS后端时需启用proxy_ssl_server_name on并配合proxy_ssl_name指定SNI域名,否则TLS握手因缺失server_name扩展而失败导致502。

当 Nginx 反向代理 HTTPS 后端微服务时,若后端使用 SNI(Server Name Indication)区分多域名证书,而 Nginx 默认不发送 SNI 信息,就会在 TLS 握手阶段失败,触发 502 Bad Gateway 错误。典型日志提示如:SSL_do_handshake() failed ... tlsv1 alert internal error 或 temporarily disabled while SSL handshaking to upstream。根本原因不是网络不通、服务宕机或超时,而是上游服务器收不到客户端意图访问的域名,无法选择对应证书完成握手。
确认是否为 SNI 导致的 502
排查需聚焦协议层,而非单纯检查服务连通性:
- 用
curl -v https://your-upstream-domain直连后端,确认能正常返回(证明服务本身可用) - 查看 Nginx 错误日志(
/var/log/nginx/error.log),定位到具体 upstream 连接失败行,重点识别含SSL、handshake、tlsv1 alert的报错 - 抓包验证(可选):在 Nginx 机器上执行
tcpdump -i any port 443 -w nginx-to-upstream.pcap,用 Wireshark 打开,检查 Client Hello 是否携带server_name扩展字段 —— 若缺失,即为 SNI 问题
启用 proxy_ssl_server_name 并正确配置 host 头
该指令控制 Nginx 在 TLS 握手时是否向后端发送 SNI 域名,默认为 off,必须显式开启。同时需确保 Host 请求头与 SNI 域名一致,否则部分严格校验的后端(如某些网关或 Istio sidecar)可能拒绝请求:
安装并运行 Aperture(Lightning Labs 的 L402 闪电反向代理),用于创建 L402 付费墙、配置付费 API 端点、为其他代理托管付费内容或测试 L402 认证流程。
- 在
location块中启用:proxy_ssl_server_name on; - 显式设置 Host 头:
proxy_set_header Host your-backend-domain.com;(不能用$host或$http_host,因可能被客户端篡改) - 确保
proxy_pass指向 HTTPS 地址,且域名与 SNI/Host 一致,例如:proxy_pass https://your-backend-domain.com/;
在 upstream 场景下仍需指定 proxy_ssl_name
若你使用 upstream 块做负载均衡(如对接多个微服务实例),仅设 proxy_ssl_server_name on 不够。Nginx 会解析 upstream 中的域名得到 IP,但 TLS 握手仍需明确告知服务器名称。此时必须配合 proxy_ssl_name:
- upstream 定义保持简洁,只写域名+端口:
upstream api_backend { server api.example.com:443; } - 在 location 中添加:
proxy_ssl_name "api.example.com";(值必须是字符串,加引号) - 同时保留:
proxy_ssl_server_name on;和proxy_set_header Host "api.example.com"; - 注意:
proxy_ssl_name的值应与证书中 Subject Alternative Name(SAN)匹配,否则可能触发证书校验失败
补充关键配置避免连锁问题
SNI 配置生效后,还需检查配套项,防止其他环节中断链路:
-
禁用证书校验(开发/测试环境):若后端用自签名或私有 CA 证书,需加
proxy_ssl_verify off;,否则握手也会失败 -
维持 HTTP/1.1 连接复用:添加
proxy_http_version 1.1;和proxy_set_header Connection "";,避免连接被过早关闭 -
调整超时以覆盖握手耗时:SNI + 双向认证等场景握手可能变长,建议设
proxy_connect_timeout 10s;(不低于 5 秒) -
验证配置语法:修改后务必运行
nginx -t,再nginx -s reload










