开启 proxy_ssl_verify 后直接 502 是因验证闭环缺失:必须同时配置 proxy_ssl_verify on、proxy_ssl_trusted_certificate、proxy_ssl_name 和 proxy_ssl_server_name,且 proxy_ssl_verify_depth 需匹配证书链长度(通常设为 2 或 3),否则 tls 握手在 ssl_do_handshake() 阶段中断。

proxy_ssl_verify 开启后为什么直接 502?
单独写 proxy_ssl_verify on; 必然失败,Nginx 会拒绝建立连接并返回 502。它不是开关式配置,而是一套验证闭环:缺任一环节,TLS 握手就在 SSL_do_handshake() 阶段中断。
必须同时存在以下四项,且全部位于同一作用域(如 location 或 upstream 块内):
-
proxy_ssl_verify on;—— 启用校验动作本身 -
proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;—— 指向含根证书 + 中间 CA 的 PEM 文件;不能只放后端证书,也不能依赖系统默认路径而忽略 Nginx 进程读取权限 -
proxy_ssl_name "api.internal.example.com";—— 显式声明期望的 SAN 域名;若proxy_pass写的是 IP(如https://10.0.1.5)或变量(如https://$host),此项不设则校验直接跳过域名匹配,但多数后端证书不含 IP SAN,结果仍是失败 -
proxy_ssl_server_name on;—— 启用 TLS SNI;否则后端可能返回默认证书(比如自签名或泛域名证书),与proxy_ssl_name不符
proxy_ssl_verify_depth 设多少才不踩坑?
默认值 1 只认“终端证书 → 根 CA”直连链,但生产环境几乎全是三级结构:终端证书 → 中间 CA(如 Let’s Encrypt R3)→ 根 CA(如 ISRG Root X1)。设成 1 就等于拒掉所有合规商用证书。
推荐按实际链长设为 2 或 3:
- 两级链(终端 + 一个中间 CA)→
proxy_ssl_verify_depth 2; - 三级链(终端 + 中间 CA + 根 CA)→
proxy_ssl_verify_depth 3; - 自签名证书 → 仍需设为
1,但前提是proxy_ssl_trusted_certificate文件里已包含该自签根证书
设太高(如 5)不会报错,但会放宽对不可信中间签发者的限制,削弱验证意义。
后端证书链不全导致 verify failed 怎么查?
错误日志出现 certificate verify failed,90% 是后端没返回完整证书链。Nginx 不会自动补全,它只验证你给它的那一截。
安全更新和维护 CLI Proxy API(CPA)部署与配置。用于 CPA 镜像升级、配置变更、认证目录兼容修复、上线验证与回滚。适用于用户提到“CPA 更新/升级/配置改了/容器重建/回滚”等场景。
用这条命令手动确认后端实际返回了什么:
openssl s_client -connect api.internal.example.com:443 -servername api.internal.example.com -showcerts
重点看两处:
- 输出中
-----BEGIN CERTIFICATE-----出现几次?只有 1 次说明只返回了终端证书 - 最后一行
Verify return code:是不是0?非零值(如21)代表链断裂
修复方式二选一:
- 让后端服务(如 Nginx、Apache、Spring Boot)配置时把中间 CA 追加进证书文件,形成完整链
- 在 Nginx 的
proxy_ssl_trusted_certificate文件里,把缺失的中间 CA 内容追加进去(PEM 格式,多个证书可拼接)
proxy_ssl_name 匹配失败的隐蔽陷阱
proxy_ssl_name 不是 Host 头,也不是 URL 路径,它只用来比对后端证书里的 Subject Alternative Name(SAN)字段。大小写敏感、通配符规则严格:
-
proxy_ssl_name "*.example.com";不匹配api.example.com(标准 RFC 要求通配符只覆盖一级子域) -
proxy_ssl_name "API.EXAMPLE.COM";不匹配 SAN 为api.example.com的证书(DNS 名称比对区分大小写) -
proxy_ssl_name "example.com";不匹配 SAN 为www.example.com的证书,除非证书里明确写了example.com
最稳妥的做法:用 openssl x509 -in cert.pem -text -noout 查看后端证书实际 SAN 列表,然后一字不差地抄进 proxy_ssl_name。
真正容易被忽略的是 SNI 和 proxy_ssl_name 的协同逻辑——proxy_ssl_server_name on 控制是否发送 SNI,而 proxy_ssl_name 控制校验时拿哪个字符串去比对;两者不一致,验证就失去意义。










