nginx启用mtls必须四要素共存于同一server块:listen 443 ssl、ssl_certificate与key、ssl_client_certificate指向纯净ca pem文件、ssl_verify_client on;还需设ssl_verify_depth匹配证书链深度,并透传$ssl_client_verify和$ssl_client_s_dn至后端。

要在 nginx.conf 中真正启用基于客户端证书的双向认证(mTLS),不能只加一行 ssl_verify_client on,必须确保四个核心配置项共存于同一个 server 块内,并满足格式、路径和逻辑闭环要求。
四要素必须同在 server 块中
缺一不可,顺序无关,但必须全部出现在同一 server 定义里:
-
启用 HTTPS 监听:用
listen 443 ssl;—— 没有它,TLS 层不启动,验证无从谈起 -
服务端证书与私钥:用
ssl_certificate和ssl_certificate_key指向 Nginx 自身的有效证书(含匹配域名的 SAN) -
可信 CA 公钥文件:用
ssl_client_certificate /path/to/ca.crt指向签发客户端证书的根 CA 或中间 CA 的 PEM 文件(仅证书内容,不含私钥,开头为-----BEGIN CERTIFICATE-----) -
强制校验开关:用
ssl_verify_client on;—— 生产环境禁用optional,否则等于未启用认证
验证深度要匹配实际证书链
若客户端证书由“根 CA → 中间 CA → 客户端”三级签发,默认 ssl_verify_depth 1 只能验证到中间 CA,无法上溯至根,导致 $ssl_client_verify 显示 FAILED: unable to get issuer certificate。
- 先在本地用
openssl verify -CAfile ca.crt client.crt验证证书链是否完整 - 根据层级设
ssl_verify_depth 2(两级签发)或3(含多级中间) - 确保
ca.crt文件中 PEM 证书拼接顺序正确(中间 CA 在前、根 CA 在后)
把验证结果和身份信息透传给后端
Nginx 不会自动转发证书内容,后端需依赖这些变量做用户识别、权限控制或审计存档:
-
proxy_set_header X-Client-Verify $ssl_client_verify;—— 值为SUCCESS/FAILED/NONE -
proxy_set_header X-Client-DN $ssl_client_s_dn;—— 提取CN=xxx,OU=yyy,O=zzz等字段 -
proxy_set_header X-Client-Cert $ssl_client_cert;—— Base64 编码的完整客户端证书(仅在验证成功时有效)
关键细节与常见避坑点
这些细节常被忽略,却直接决定配置能否生效:
-
ssl_client_certificate文件必须是纯净 PEM 格式:无 BOM、无 DOS 换行(\r\n)、无多余空格或注释;可用openssl x509 -in ca.crt -text -noout测试是否可读 - 所有证书文件路径必须是绝对路径,且 Nginx worker 进程有读取权限:
ca.crt设为644,server.key必须为600 -
ssl_verify_client不能写在location块里 —— Nginx 不支持该语法;如需路径级控制,应全局开启 + 后端鉴权配合 - 禁用弱协议与旧 cipher:
ssl_protocols TLSv1.2 TLSv1.3;,推荐 cipher 如ECDHE-ECDSA-AES128-GCM-SHA256











