Nginx启用mTLS需四要素闭环:统一CA签发的PEM格式证书、ssl_verify_client on强制校验、ssl_client_certificate指向纯净CA文件、proxy_set_header透传$ssl_client_verify与$ssl_client_s_dn至后端。

要实现企业级最高级别的访问安全,Nginx 必须启用 SSL 双向认证(mTLS),即服务端不仅提供证书供客户端验证,还强制校验客户端提交的数字证书。这不是简单加个证书就能生效,而是涉及证书体系、Nginx 配置、变量透传和运维细节的一整套闭环控制。
一、CA 与证书必须严格统一且格式纯净
服务端和客户端证书必须由同一个根 CA 签发,且 CA 证书文件(ssl_client_certificate 指向的文件)只能是 PEM 格式、不含私钥、无 BOM、无多余空格或换行。常见失败原因不是客户端没证书,而是 Nginx 加载的 CA 文件开头多了不可见字符,或混入了 server.crt 或私钥内容。
- 用 openssl x509 -in ca.crt -text -noout 能正常输出,说明格式可用;报 unable to load certificate,大概率是 DOS 换行(\r\n)或编码问题
- 不要拼接多个证书:除非明确需要中间 CA 链,否则 ssl_client_certificate 只应指向根 CA 的 .crt 文件(如 cacert.pem)
- 所有证书(CA、server、client)的 Organization Name(O) 和 Organizational Unit Name(OU) 字段建议保持一致,避免因字段不匹配导致验证静默失败
二、Nginx 必须启用强制校验模式
ssl_verify_client on 是唯一生产可用的取值。设为 optional 或 optional_no_ca 等同于关闭认证——Nginx 会接收证书但不做签名和有效期检查,$ssl_client_verify 永远返回 SUCCESS,完全失去双向认证意义。
- on:客户端必须提供证书;证书必须能被 ssl_client_certificate 中的 CA 验证通过;任一环节失败(签名错、过期、吊销、CN/O 不匹配),Nginx 直接返回 400 Bad Request
- 务必配合 ssl_client_certificate /etc/nginx/ssl/ca.crt 和 ssl_verify_depth 2(若含中间 CA,可适当调高)
- 禁用弱协议与旧 cipher:ssl_protocols TLSv1.2 TLSv1.3;推荐 cipher 如 ECDHE-ECDSA-AES128-GCM-SHA256
三、把可信身份信息可靠传递给后端服务
Nginx 默认只在校验层使用客户端证书,不会自动转发任何证书内容。后端(如 API 服务)若需识别用户或做细粒度鉴权,必须显式透传关键变量:
- proxy_set_header X-Client-Verify $ssl_client_verify:值为 SUCCESS / FAILED / NONE,用于快速判断校验结果
- proxy_set_header X-Client-DN $ssl_client_s_dn:提取完整 Subject,例如 CN=api-client-01,OU=backend,O=YourCorp
-
proxy_set_header X-Client-CN $ssl_client_s_dn 可配合 map 指令提取 CN 字段,例如:
map $ssl_client_s_dn $client_cn {
~CN=([^,]+) $1;
}
再用 proxy_set_header X-Client-CN $client_cn
四、配套加固与日常运维要点
双向认证不是配置完就一劳永逸。企业环境中还需关注证书生命周期、日志审计和异常响应:
- 启用 ssl_crl 或 OCSP Stapling(配合 ssl_stapling on)实时校验证书吊销状态
- 在 access_log 中记录 $ssl_client_verify 和 $ssl_client_s_dn,便于溯源分析
- curl 测试时用:curl --cert client.crt --key client.key --cacert ca.crt https://api.example.com;若报 unable to get local issuer certificate,优先排查 Nginx 端 ca.crt 路径与内容,而非客户端
- 定期轮换 CA 私钥和客户端证书,避免长期暴露风险;客户端证书建议设置较短有效期(如 90 天),配合自动化签发流程


















