确认问题源头是nginx连接后端https服务握手失败,关键看日志中“while ssl handshaking to upstream”:若存在,说明proxy_pass协议错配、sni未启用(需proxy_ssl_server_name on及proxy_ssl_name)或ssl会话复用异常。

直接看 Nginx 错误日志里有没有 “while SSL handshaking to upstream” 这行,就能确认是不是 Nginx 去连后端 HTTPS 服务时卡在握手阶段——这才是真正的问题源头,不是证书过期、TLS 版本低,而是代理配置本身出了偏差。
先锁定日志里的关键线索
Nginx 把握手失败记在 /var/log/nginx/error.log(路径以实际配置为准)。执行:
grep "SSL handshaking.*upstream" /var/log/nginx/error.log | tail -20
重点识别:
- 出现
while SSL handshaking to upstream→ 问题出在 Nginx 主动连接后端 HTTPS 时 - 若是
while SSL handshaking, client: xxx→ 问题在 Nginx 接收外部请求环节,和后端无关
绝大多数握手中断都属于前者,别一上来就调 ssl_handshake_timeout 或换证书。
检查 proxy_pass 协议是否真实匹配
最常见错误:Nginx 配了 https://backend:443,但后端根本没开 HTTPS。
比如 Spring Boot 默认监听 HTTP 的 8080 端口,Node.js 用 http.createServer(),这时 proxy_pass https://127.0.0.1:8080 就会强制发起 TLS 握手,而对方只认明文,直接断连,日志常报 wrong version number。
验证方法很简单:
- 在 Nginx 服务器上执行
curl -v http://127.0.0.1:8080/health - 再执行
curl -v https://127.0.0.1:8080/health
哪个能返回 200,就说明后端实际支持哪种协议,proxy_pass 必须严格对应。
确认 SNI 是否启用并指定目标主机名
当后端是多域名 HTTPS 服务(如 K8s Ingress、云厂商 API、Nginx 自身反代多个站点),必须让 Nginx 在 TLS 握手时带上正确的主机名,否则后端无法选择证书,直接拒绝。
在对应 location 或 upstream 的 proxy 配置块中加:
-
proxy_ssl_server_name on;(开启 SNI 扩展) -
proxy_ssl_name "api.example.com";(双引号包裹,大小写敏感;若 upstream 是 IP,必须显式指定) - 同时补上
proxy_set_header Host "api.example.com";(保持 Host 头一致)
不加proxy_ssl_server_name on,Nginx 默认不发 SNI,后端日志可能报sslv3 alert handshake failure。
临时关闭 SSL 会话复用排查状态错乱
默认开启的 proxy_ssl_session_reuse on 在后端重启、证书轮换或节点不一致时容易引发握手失败。
可临时改为:
proxy_ssl_session_reuse off;
观察是否恢复。若有效,说明是会话缓存状态不一致导致,后续再评估是否需保留复用并优化后端证书更新流程。











