Nginx实现严格mTLS需区分下游(客户端→Nginx)和上游(Nginx→后端)双向认证:下游原生支持,需ssl_verify_client on等四要素;上游开源版不真正支持,须用Nginx Plus、Envoy或降级方案。

要在 Nginx 反向代理中实现严格的 SSL 双向认证(mTLS),必须分清两个独立方向:前端客户端到 Nginx 的下游认证(Nginx 作为服务端),以及 Nginx 到后端服务的上游认证(Nginx 作为客户端)。开源 Nginx 原生只完整支持前者;后者需特别处理,否则所谓“双向”只是单向校验。
下游 mTLS:强制校验客户端证书
这是 Nginx 原生稳定支持的部分,关键在于四要素齐备且可信:
- 在 同一个 server 块 中启用 HTTPS:
listen 443 ssl; - 加载自身服务端身份:
ssl_certificate /path/to/server.crt;和ssl_certificate_key /path/to/server.key; - 指定用于验证客户端的根 CA 或中间 CA 证书:
ssl_client_certificate /etc/nginx/ssl/ca-bundle.pem;(PEM 格式,仅含公钥,不含私钥) - 开启强校验模式:
ssl_verify_client on;(optional不校验签名,生产环境禁用) - 根据证书链层级设深度:
ssl_verify_depth 2;(例如:根 CA → 中间 CA → 客户端证书) - 权限必须严格:
server.key文件权限为600,CA 文件建议644,Nginx 进程用户需有读取权限
上游 mTLS:Nginx 主动向后端出示客户端证书
标准开源 Nginx(截至 1.25)不支持真正意义上的上游 mTLS。虽有 proxy_ssl_certificate 等指令,但多数版本实际忽略客户端证书发送,导致后端收不到证书而拒绝连接。若必须实现,可选以下路径:
- 使用商业版 Nginx Plus:完整支持
proxy_ssl_certificate+proxy_ssl_certificate_key+proxy_ssl_trusted_certificate+proxy_ssl_verify on - 改用原生支持的替代组件:Envoy 或 HAProxy 承担上游 TLS 层,Nginx 仅做最外层 HTTPS 终止
- 降级内网通信方案:后端关闭 TLS,改用 HTTP 内网直连,通过
proxy_set_header X-Client-DN $ssl_client_s_dn;透传可信身份,并配合 IP 白名单或 JWT 校验
透传与错误处理:让后端可信复用校验结果
Nginx 不会自动转发客户端证书内容,需显式透传变量供后端决策:
-
proxy_set_header X-Client-Verify $ssl_client_verify;—— 值为SUCCESS或FAILED -
proxy_set_header X-Client-DN $ssl_client_s_dn;—— 提取 CN、OU、O 等字段,便于后端映射用户 -
proxy_set_header X-Client-Cert $ssl_client_cert;—— Base64 编码的完整证书(仅在ssl_verify_client on且校验成功时有效) - 自定义错误页拦截握手失败:
error_page 495 496 = @clientcertfail;,避免暴露默认 Nginx 提示
证书链与调试要点
常见失败多源于证书格式或信任链问题,建议逐项确认:
- 用
openssl verify -CAfile ca-bundle.pem client.crt本地验证客户端证书是否能被 CA 正确签发 - CA 文件不能含 BOM、DOS 换行符或空行;可用
file ca.crt和head -n1 ca.crt检查开头是否为-----BEGIN CERTIFICATE----- - 若后端使用私有 CA,其根证书必须加入
proxy_ssl_trusted_certificate所指文件,不能依赖系统默认证书包 - 启用 SNI 避免 SAN 匹配失败:
proxy_ssl_server_name on;+proxy_ssl_name "backend.example.com";


















