本质是TLS握手阶段SNI未正确传递,导致后端因无法匹配证书而拒绝连接,Nginx收到SSL握手失败即返回502;需配置proxy_ssl_server_name on、proxy_ssl_name与Host头三者严格一致,并确保证书校验配套。

这个问题本质是 TLS 握手阶段 SNI(Server Name Indication)未正确传递,导致后端服务(如微服务网关、Istio sidecar、多域名共用 IP 的 HTTPS 服务)无法选择匹配的证书,直接拒绝连接,Nginx 收到握手失败就返回 502 —— 并非后端宕机,而是“还没开始通信就卡在握手了”。
确认是否为 SNI 导致的 502
别先改配置,先看日志:
- 打开 /var/log/nginx/error.log,搜索关键词:
SSL_do_handshake() failed、tlsv1 alert internal error、handshaking to upstream - 如果报错中含
alert number 80或certificate verify failed(但你没开proxy_ssl_verify),高度可疑 - 关键验证:用
curl -v https://your-backend-domain.com能通,但 Nginx 代理访问同域名却 502 → 说明问题出在 Nginx 发起连接时的行为,而非网络或后端本身
核心三要素必须严格一致
当 proxy_pass 直接写域名(如 https://api.example.com/)时,需同时满足:
-
proxy_ssl_server_name on;—— 启用 SNI 发送功能 -
proxy_set_header Host "api.example.com";—— 必须写死字符串,不能用$host或$http_host(易被客户端篡改) -
proxy_pass https://api.example.com/;—— 域名必须完整、大小写敏感,不能写成 IP 或省略https://
三者值必须完全相同,否则某些后端(如 Envoy、Istio)会因 Host 与 SNI 不一致而拒绝请求,返回 403/404 或直接断连。
用了 upstream?必须显式指定 proxy_ssl_name
upstream 块里只写 server api.example.com:443;,Nginx 解析后只剩 IP,SNI 信息丢失,proxy_ssl_server_name on 失效。此时必须补:
-
proxy_ssl_name "api.example.com";—— 值必须是双引号包裹的字面量,且与后端证书的 SAN(Subject Alternative Name)或 CN 完全一致 - 若后端用泛域名证书
*.internal.com,这里就得填svc.internal.com,不能填internal.com - 禁止写
proxy_ssl_name $host;—— SSL 握手发生在变量解析前,Nginx 启动时就会报错
证书链与验证要配套处理
如果启用了证书校验(proxy_ssl_verify on;),但没配可信 CA,也会触发 502,错误提示易与 SNI 混淆:
- 添加
proxy_ssl_trusted_certificate /etc/nginx/certs/ca-bundle.crt; - 该文件必须是 PEM 格式,包含完整的根证书 + 所有中间证书(顺序不限,但缺一不可)
- 若不验证证书,确保关闭:
proxy_ssl_verify off;(生产环境慎用)


















