nginx 实现 mtls 需同时配置服务端证书和强制客户端证书校验:准备 server.crt/.key、ca.crt、client.crt/.key 四类文件;在 server 块中设 ssl_certificate、ssl_client_certificate 和 ssl_verify_client on;透传 x-client-dn 或 x-client-verify 至后端,并可按 location 精细化启用。

要在 Nginx 中真正实现客户端证书双向认证(mTLS)来保护核心接口,关键不是“加个证书”,而是让 Nginx 同时完成两件事:向客户端证明自己(用服务端证书),并强制客户端出示可信身份(用 CA 校验证书)。单配 ssl_certificate 只是 HTTPS,不算 mTLS。
准备好四类必要证书文件
缺一不可,且不能混用:
-
服务端证书(
server.crt)和私钥(server.key):部署在 Nginx 上,用于建立 HTTPS 连接并证明自身身份; -
CA 根证书(
ca.crt):PEM 格式、仅含公钥、不含私钥;Nginx 用它验证客户端证书是否由你信任的 CA 签发,有效期、签名、吊销状态均在此校验; -
客户端证书+私钥(
client.crt+client.key):分发给合法调用方,用于发起带证书的 TLS 请求; - 注意:
ssl_client_certificate指令只接受 CA 证书,填 client.crt 或 server.crt 都会失败。
在 server 块中启用强制客户端校验
这是 mTLS 生效的核心开关,必须与服务端证书配置共存:
- 启用 HTTPS 监听:
listen 443 ssl http2; - 加载服务端身份:
ssl_certificate /etc/nginx/certs/server.crt;和ssl_certificate_key /etc/nginx/certs/server.key; - 指定可信 CA 并强制验证:
ssl_client_certificate /etc/nginx/certs/ca.crt;+ssl_verify_client on; - 设置合理校验深度:
ssl_verify_depth 2;(覆盖根 CA + 一级中间 CA); - 禁用弱协议:
ssl_protocols TLSv1.2 TLSv1.3;,推荐强加密套件。
把客户端证书信息安全透传给后端
Nginx 默认不转发证书内容,后端若需做 CN/OU 白名单、有效期检查或 SAN 匹配,必须显式透传:
- 传递校验结果:
proxy_set_header X-Client-Verify $ssl_client_verify;(值为 SUCCESS 或 FAILED); - 传递可读身份标识:
proxy_set_header X-Client-DN $ssl_client_s_dn;(如CN=payment-service,OU=backend,O=BankX); - 如需原始证书供后端二次解析,用 Base64 编码:
proxy_set_header X-Client-Cert $ssl_client_cert;; - 避免直接透传未编码二进制:
$ssl_client_raw_cert易引发 header 截断或解析错误。
按路径精细化启用,兼顾安全与兼容性
并非所有接口都需要 mTLS。将严格认证限定在敏感路径,既降低管理成本,又避免影响常规流量:
- 在特定 location 中设为可选:
location /api/v1/core/ { ssl_verify_client optional; } - 后端逻辑检查
X-Client-Verify是否等于SUCCESS,再结合X-Client-DN做白名单判断; - 配合自定义错误页拦截异常:
error_page 495 496 = @deny_access;,返回统一 403,不暴露握手细节。











