Nginx HTTPS代理证书信任链错误源于其作为客户端校验后端证书失败,需检查三方面:一是后端是否返回完整证书链(域名证书+中间证书),可用openssl s_client验证;二是Nginx是否启用SNI并正确设置proxy_ssl_server_name和proxy_ssl_name;三是proxy_ssl_trusted_certificate指定的CA文件是否包含正确根/中间证书且格式合规。

排查 Nginx HTTPS 代理导致的证书信任链错误,关键在于明确 Nginx 此时是“客户端”角色——它要验证后端 HTTPS 服务的证书是否可信。错误通常不来自浏览器,而来自 Nginx 自身校验失败,日志里常见 certificate verify failed 或直接返回 502。重点查三件事:证书链是否完整送达、SNI 是否正确触发、信任根是否被识别。
检查后端是否返回了完整的证书链
安卓、curl、Nginx 等较严格的客户端要求服务器在 TLS 握手时一次性发送“域名证书 + 所有中间证书”,不能只发终端证书。Nginx 作为代理若收不到完整链,就无法向上游验证。
- 用命令模拟 Nginx 的视角:
openssl s_client -connect 后端IP:443 -servername backend.example.com -showcerts - 观察输出中
BEGIN CERTIFICATE块的数量和顺序:第一块必须是你域名的证书,第二块起应为中间证书(Issuer 和下一块 Subject 匹配),不能含根证书 - 如果只看到一块证书,说明后端配置遗漏了中间证书;需将其拼接到 fullchain.pem 并在后端服务中正确加载
确认 Nginx 是否启用了 SNI 并指定了目标域名
当 proxy_pass https://10.0.0.5 这类 IP 地址写法时,Nginx 默认不发送 SNI,后端可能返回默认证书(如通配符或错误域名),导致 SAN 不匹配。
- 必须在
location或upstream块内启用并指定:proxy_ssl_server_name on;proxy_ssl_name "backend.example.com"; - 确保
proxy_ssl_name的值与后端证书中的 SAN 完全一致(注意大小写、www.前缀、通配符格式) - 若
proxy_pass使用变量(如https://$backend_host),proxy_ssl_name更不可省略
验证 Nginx 本地信任库是否包含对应根/中间 CA
proxy_ssl_verify on 启用后,Nginx 会用 proxy_ssl_trusted_certificate 指定的文件做链式校验。这个文件不是给浏览器看的,而是给 Nginx 自己用的。
- 该文件必须是 PEM 格式,仅含可信 CA 证书(根证书 + 中间证书),不能含私钥、域名证书或 root CA 的重复项
- 推荐路径:
/etc/nginx/ssl/upstream-ca.crt(权限 644),内容可来自 Let’s Encrypt 的isrgrootx1.pem + lets-encrypt-r3.pem,或内网 CA 的根证书 - 检查命令:
openssl x509 -in /path/to/upstream-ca.crt -text -noout | grep "Subject:",确认列出的是你期望的 CA
快速定位是否为私钥与证书不匹配
虽不属“信任链”范畴,但报错常混在一起(如 X509_check_private_key:key values mismatch),尤其发生在手动更新证书后。
- 在后端服务器上执行比对(非 Nginx 机器):
openssl x509 -noout -modulus -in cert.pem | openssl md5openssl rsa -noout -modulus -in key.pem | openssl md5 - 两行输出必须完全一致;不一致说明私钥与证书不是一对,需重新生成或核对来源
- 注意:Nginx 本身不校验私钥,但后端服务若配错,会导致握手失败,间接表现为 Nginx 502











