nginx 与后端 mtls 冲突需确认双方角色对齐:nginx 作为 tls 客户端须提供 client.crt/.key、验证 upstream-ca.pem 并开启 proxy_ssl_verify on;后端须强制校验客户端证书且信任其 ca;还需启用 proxy_ssl_server_name on 和 proxy_ssl_name 确保 sni 与域名匹配。

排查 Nginx 反向代理与后端服务之间的 TLS 双向加密(mTLS)冲突,核心在于确认“谁在验证谁”以及“证书和协议是否真正对齐”。不是配置了 proxy_ssl_certificate 就自动完成双向认证,而是整个握手链路上每个环节都必须协同生效。
确认 Nginx 和后端各自的角色与能力
先明确责任边界:
- Nginx 是 TLS 客户端(连接上游时),必须能提供有效客户端证书 + 私钥,并能验证后端服务的证书
- 后端服务是 TLS 服务端,必须启用 client certificate required,且信任 Nginx 所用证书的签发 CA
- 双方支持的 TLS 版本、加密套件、签名算法需有交集;例如旧版 Java 后端不支持 TLSv1.2 或 AES-GCM 套件,就会握手失败
检查关键 proxy_ssl 指令是否成对启用
单独设置 proxy_ssl_certificate 不起作用。必须同时配置以下四项,缺一不可:
-
proxy_ssl_certificate /etc/nginx/ssl/client.crt—— PEM 格式证书(含链),不含私钥 -
proxy_ssl_certificate_key /etc/nginx/ssl/client.key—— 对应私钥,权限建议600 -
proxy_ssl_trusted_certificate /etc/nginx/ssl/upstream-ca.pem—— 用于验证后端证书的 CA 根证书 -
proxy_ssl_verify on—— 必须为on,否则跳过证书校验,失去身份确认意义
验证 SNI 和域名匹配是否被忽略
当后端使用多域名 HTTPS(如 SNI 部署),而 Nginx 未传递 Server Name,会导致证书验证失败或连接拒绝:
- 添加
proxy_ssl_server_name on,确保 Nginx 在 TLS 握手时发送 SNI 扩展 - 若 upstream 使用域名(如
backend.example.com:8443),还需显式设置proxy_ssl_name backend.example.com - 否则 Nginx 默认用 IP 地址做证书主机名比对,必然失败
用 openssl 手动模拟握手快速定位断点
绕过 Nginx,直接测试后端是否真正接受 mTLS:
- 测试后端是否要求客户端证书:
openssl s_client -connect backend:8443 -servername backend.example.com -cert client.crt -key client.key -CAfile upstream-ca.pem - 若返回
Verify return code: 0 (ok)且有完整证书链,说明后端配置正确 - 若提示
SSL alert number 42(bad_certificate)或tlsv1 alert unknown ca,说明 CA 不被信任或证书格式错误
不复杂但容易忽略











