WSS握手中止主因是TLS阶段失败,需排查Nginx代理配置(proxy_ssl_verify、proxy_ssl_name、proxy_ssl_server_name)、后端证书有效性(域名匹配、链完整)及SSL/TLS协议兼容性(ssl_protocols、ssl_ciphers)。

WSS(WebSocket Secure)代理在 Nginx 中出现握手中止,常见原因是证书链不完整、域名不匹配或 TLS 配置不当,导致浏览器或客户端在 TLS 握手阶段拒绝连接。排查需从 Nginx 配置、证书有效性、SSL/TLS 协议协商三个层面入手。
检查 Nginx 的 WSS 代理配置是否启用 HTTPS 上游
Nginx 本身不“终止”WSS,而是将 WebSocket Upgrade 请求透传给后端 HTTPS 服务(如 wss://backend:443)。若后端是自签名证书或域名与证书不一致,Nginx 默认会校验并中止连接。
- 确认
proxy_pass指向的是https://地址(不是http://),且后端实际监听 HTTPS - 添加
proxy_ssl_verify off;(仅用于测试)临时绕过证书校验,验证是否为证书问题 - 若必须校验,需同步配置
proxy_ssl_trusted_certificate指向可信 CA 证书文件(如后端用私有 CA 签发) - 确保
proxy_ssl_name与后端证书的 CN 或 SAN 完全一致(例如proxy_ssl_name "api.example.com";)
验证后端服务证书是否匹配请求域名
WSS 客户端(如浏览器)发起连接时,URL 中的域名(如 wss://api.example.com/ws)必须被后端证书的 Subject Alternative Name(SAN)覆盖。
- 用 OpenSSL 直连后端,查看证书详情:
openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts - 检查输出中
X509v3 Subject Alternative Name是否包含请求域名;若显示verify error:num=20:unable to get local issuer certificate,说明证书链缺失 - 若后端是 Node.js/Python 等自建服务,确认启动时加载的证书 PEM 文件包含完整链(域名证书 + 中间 CA 证书,顺序不能颠倒)
抓包确认握手在哪一阶段失败
单纯看 Nginx error log 可能只显示 upstream SSL certificate verify failed,但无法区分是证书不匹配、过期还是协议不兼容。
- 在 Nginx 机器上用
tcpdump抓取到后端的流量:tcpdump -i any -w wss.pcap host backend_ip and port 443 - 用 Wireshark 打开,过滤
ssl.handshake,观察 Client Hello 后是否有 Server Hello → Certificate → Server Hello Done 流程 - 若 Client Hello 后直接收到 TCP RST 或无响应,大概率是后端 TLS 层拒绝(证书不匹配或协议版本不支持);若收到 Certificate 但后续断开,可能是证书链不全或 SNI 不匹配
补充:Nginx 自身 SSL 配置对 WSS 的影响
虽然 WSS 握手主要发生在后端,但 Nginx 作为反向代理,其 ssl_* 指令会影响与客户端的 TLS 连接,间接干扰 WSS 升级。
- 确保
ssl_protocols TLSv1.2 TLSv1.3;(禁用 TLSv1.0/1.1,避免协商失败) - 检查
ssl_ciphers是否包含客户端支持的套件(如 Chrome 当前默认要求 ECDHE) - 务必设置
proxy_set_header Host $host;和proxy_set_header X-Forwarded-Proto $scheme;,否则后端可能因 Host 头不匹配拒绝 Upgrade - 确认
proxy_http_version 1.1;和proxy_set_header Upgrade $http_upgrade;已正确配置,否则无法完成 WebSocket 升级











