proxy_ssl_certificate 本身不能单独实现双向 tls,必须与 proxy_ssl_certificate_key、proxy_ssl_verify、proxy_ssl_trusted_certificate 四指令协同配置,并配合 proxy_ssl_name、proxy_ssl_server_name 等补充指令及后端证书校验才能完成 mtls。

配置 proxy_ssl_certificate 本身不能单独实现双向 TLS(mTLS),它只是 Nginx 向后端出示客户端证书的必要环节。真正完成双向认证,必须让它和另外三个关键指令协同工作,并确保后端服务也启用客户端证书校验。
必须同时配置的四个核心指令
这四条需写在同一个 location 或 upstream 块中,缺一不可:
-
proxy_ssl_certificate /path/to/nginx-client.crt:Nginx 向后端出示的证书,必须由后端信任的 CA 签发(不能是自签名终端证书) -
proxy_ssl_certificate_key /path/to/nginx-client.key:对应私钥,权限必须设为600(如chmod 600 nginx-client.key) -
proxy_ssl_verify on:开启对后端服务器证书的校验(默认是off,不启用等于没验证) -
proxy_ssl_trusted_certificate /path/to/upstream-ca-bundle.pem:后端服务器证书链所依赖的根/中间 CA 证书(PEM 格式,仅含 CA 证书,不含私钥或终端证书)
补充关键指令(避免常见失败)
以下配置不是可选,而是生产环境中极易出错的边界情况应对项:
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
-
proxy_ssl_name "api.internal.example.com":显式指定期望的后端域名,用于匹配后端证书中的 SAN 字段;若proxy_pass使用 IP 或变量(如https://$host),此项必须设置,否则校验直接失败 -
proxy_ssl_server_name on:启用 SNI,确保 TLS 握手时发送正确 server name,对接泛域名、云服务或 mTLS 后端时必需 -
proxy_ssl_verify_depth 2:若后端证书由中间 CA 签发(例如:根 CA → 中间 CA → 后端证书),此处需设为对应层级,否则证书链校验失败 -
proxy_ssl_protocols TLSv1.2 TLSv1.3:明确协议范围,禁用不安全旧版本,防止协议降级干扰校验
后端服务必须同步启用客户端证书校验
Nginx 出示证书只是单方面动作。若后端不强制要求并验证该证书,整个链路就退化为单向 TLS:
- 若后端是 Nginx:需配置
ssl_client_certificate和ssl_verify_client on - 若后端是 Envoy:需在
tls_context中启用require_client_certificate: true并加载对应 CA - 若后端是 Spring Boot + Tomcat:需配置
server.ssl.trust-store及client-auth: need
证书文件规范与验证方法
确保文件内容合规,否则校验静默失败:
-
proxy_ssl_certificate和proxy_ssl_trusted_certificate文件都必须是 PEM 格式,每张证书以-----BEGIN CERTIFICATE-----开头、-----END CERTIFICATE-----结尾 -
proxy_ssl_trusted_certificate文件中只允许包含根 CA 和中间 CA 证书,按“根→中间”顺序拼接,中间无空行;不能含私钥、不能含 Nginx 自己的证书、也不能含后端终端证书 - 验证 CA 文件有效性:
openssl pkcs7 -print_certs -in /path/to/ca-bundle.pem -noout能正常输出即为合法










