proxy_ssl_verify_depth 应设为后端证书链实际层级数(如根→中间→服务证书则设为3),且必须配合 proxy_ssl_verify on、proxy_ssl_trusted_certificate、proxy_ssl_name 和 proxy_ssl_server_name 四项指令协同生效,否则静默降级。

要让 Nginx 在代理内网微服务时既不误拒合法证书,又不放行过深不可信链,proxy_ssl_verify_depth 的配置关键在于“匹配实际链长、不盲目放宽、且必须配套验证机制”。
先确认你后端证书的真实链层级
内网微服务常用私有 CA,链结构往往比公网更灵活。不能凭经验设为 2 或 3,得实测:
- 用
openssl s_client -connect backend-svc:443 -showcerts抓取完整证书链,数一数从终端证书开始,到你信任的根 CA,中间有多少级(含中间 CA) - 常见情况:自签根直接签发 → 链长为 1;私有 CA 分“根 CA → 中间 CA → 服务证书” → 链长为 3
- proxy_ssl_verify_depth 应设为该链长度值,不是“层数减 1”也不是“层数加 1”——它定义的是“最多允许几级签名关系”,即终端证书为第 1 级,其签发者为第 2 级,依此类推
必须同步启用并配齐四项基础指令
单独调这个参数毫无作用,Nginx 会静默降级为不校验:
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
-
proxy_ssl_verify on;—— 开启校验开关(默认是 off) -
proxy_ssl_trusted_certificate /etc/nginx/certs/internal-ca-bundle.pem;—— 文件里必须包含你信任的全部 CA 证书(根 + 所有中间),顺序无关,但缺一不可 -
proxy_ssl_name "backend-svc.internal";—— 明确指定期望的 SNI 域名,尤其当proxy_pass写的是 IP 或变量时,否则证书里的 SAN 匹配失败 -
proxy_ssl_server_name on;—— 让 Nginx 在 TLS 握手时发送 SNI,否则后端可能返回默认证书,导致 CN/SAN 不匹配
深度设置不宜过高,也别硬套“最小够用”教条
安全与可用需平衡,尤其在内网可控环境中:
- 设为 1:仅接受终端证书直连根 CA。适用于自签或极简 PKI,但多数企业级内部 CA 都不满足,容易触发 502
- 设为 2 或 3:覆盖绝大多数两级或三级链部署,推荐起点
- 设为 4 及以上:除非你明确使用了多层嵌套中间 CA(如分地域/分部门多级中间签发),否则没必要;链越长,潜在不可信中间环节越多,校验效力下降
- 注意:
proxy_ssl_verify_depth控制的是“签名路径最大跳数”,不是“证书文件里能放几个证书”——后者由trusted_certificate文件内容决定
验证是否真正生效的三个动作
改完别只 reload 就完事:
- 查 error.log:发起请求后,若看到
SSL_do_handshake() failed或certificate verify failed (XX: unable to get local issuer certificate),说明链不全或 depth 不够 - 手动模拟握手:
openssl s_client -connect backend-svc:443 -CAfile /etc/nginx/certs/internal-ca-bundle.pem,看是否显示Verify return code: 0 (ok) - 临时加日志:在 location 块中加
log_subrequest on;,配合$ssl_client_cert和$ssl_server_name变量,确认 Nginx 实际收到和使用的证书与 SNI 是否符合预期

















