nginx代理wss后端时必须协同配置proxy_ssl_verify on、proxy_ssl_trusted_certificate、proxy_ssl_name和proxy_ssl_server_name on四项指令,并辅以proxy_ssl_session_reuse off等加固项,才能构建完整tls证书校验链路。

要让 Nginx 在代理 WebSocket(WSS)后端时真正校验证书,不能只开 proxy_ssl_verify on,必须构建一个完整、闭环的 TLS 验证链路。重点不是“能不能连上”,而是“连上的是否是预期的、可信的、未被篡改的服务”。尤其当后端是自签名证书、私有 CA 签发或使用内部域名时,漏配任一环节都会导致 502 或静默绕过校验。
必须协同配置的四个核心指令
这四项必须同时出现在 location 或 upstream 块中,缺一不可:
-
proxy_ssl_verify on;—— 启用校验开关(默认为off,不显式开启等于完全不校验) -
proxy_ssl_trusted_certificate /etc/nginx/ssl/internal-ca.pem;—— 指向可信根 CA 或中间 CA 的 PEM 文件(仅含证书,不含私钥或后端证书) -
proxy_ssl_name "ws.internal.company.com";—— 显式声明期望匹配的主机名,用于比对后端证书中的 SAN 字段;若proxy_pass写的是 IP 或变量(如https://$backend_host),此项必须设置 -
proxy_ssl_server_name on;—— 强制 TLS 握手发送 SNI,确保后端返回对应域名的正确证书(对接多证书网关、云负载均衡或泛域名 WSS 服务时尤为关键)
WebSocket 场景下的特殊加固项
普通 HTTP 反代的校验逻辑在 WebSocket 下更易被绕过,需额外限制:
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
-
proxy_ssl_session_reuse off;—— 关闭 TLS session 复用,防止异常证书状态被缓存复用(例如某次握手用了错误证书,后续复用会跳过校验) -
proxy_ssl_verify_depth 3;—— 默认只验 1 层(终端→根),但企业内网常见“终端→中间 CA→根 CA”三级链,设为 3 更稳妥 -
proxy_ssl_protocols TLSv1.2 TLSv1.3;—— 明确禁用 TLSv1.0/1.1,防止协议降级攻击干扰证书校验流程 -
确认后端监听地址为
0.0.0.0而非127.0.0.1—— 否则 Nginx 从本机发起连接时可能因绑定策略失败,表现为连接超时或 handshake failed
信任证书文件的准备与验证要点
proxy_ssl_trusted_certificate 所指文件是整个验证的信任锚点,必须严格合规:
- 格式为纯 PEM,每张证书以
-----BEGIN CERTIFICATE-----开头、-----END CERTIFICATE-----结尾 - 只允许拼接可信根 CA 和中间 CA 证书(可多个,顺序不限),禁止混入私钥、后端服务的
.crt、fullchain.pem或任何非证书内容 - 推荐路径:
/etc/nginx/ssl/upstream-ca.crt,权限设为644,确保 nginx worker 进程可读 - 验证方式:
openssl pkcs7 -print_certs -in /etc/nginx/ssl/upstream-ca.crt -noout应能正常输出证书信息
调试与确认校验是否真实生效
配置完成后,不能只看请求是否通,要确认校验逻辑真实触发:
- 临时启用 debug 日志:
error_log /var/log/nginx/error.log debug;(加在http或server块),重载后触发一次 WSS 连接,检查日志中是否有SSL_do_handshake() failed、certificate subject name does not match或unable to get local issuer certificate - 用
openssl s_client -connect ws.internal.company.com:443 -servername ws.internal.company.com直连后端,观察输出中证书块数量及Verify return code:非 0 表示链不全或不可信 - 若后端是自签名证书,
proxy_ssl_trusted_certificate必须显式指向该证书本身(cp backend.crt /etc/nginx/ssl/backend-ca.crt),不能留空或误用系统 ca-bundle










