Nginx双向SSL认证需配置服务端证书、CA证书及启用ssl_verify_client on;所有.key文件权限须设为600,校验失败返回495/496时建议统一拦截为403。

在 Nginx 中配置双向 SSL 认证(mTLS),核心是让服务器不仅出示自己的证书,还强制客户端提供并验证其证书。这需要三类文件协同工作:服务端证书与私钥、客户端信任的 CA 证书(用于验签)、以及明确启用校验的指令。配置本身不复杂,但路径、权限和证书链完整性极易出错。
准备三类必要证书文件
双向认证依赖三个关键文件,必须提前准备好并确认格式正确:
- 服务端证书(server.crt)和私钥(server.key):由可信 CA 签发,用于向客户端证明 Nginx 身份;PEM 格式,内容不能混入注释或多余空行
- CA 证书(ca.crt):必须是 PEM 格式,仅含公钥(不含私钥),且必须能完整验证客户端证书的签发链;若使用自建 CA,此即你的根证书或中间证书合并后的 bundle
- 客户端证书(client.crt)和私钥(client.key):由上述同一 CA 签发,供客户端在 TLS 握手时提交;Nginx 不需要 client.key,但生成和分发时需用到
注意:所有 .key 文件权限必须设为 600(如 chmod 600 /etc/nginx/ssl/*.key),否则 Nginx 启动会失败。
在 server 块中添加双向认证指令
在 Nginx 的 HTTPS server 配置块内,加入以下关键指令(顺序无关,但建议集中放置):
-
ssl_certificate /path/to/server.crt;和ssl_certificate_key /path/to/server.key;—— 这是单向 HTTPS 的基础,不可省略 -
ssl_client_certificate /path/to/ca.crt;—— 指定用于验证客户端证书签名的 CA 公钥文件 -
ssl_verify_client on;—— 强制要求客户端提供有效证书;调试阶段可用optional,但生产环境必须为on -
ssl_verify_depth 2;—— 设置证书链验证深度;一般填1(直签)或2(根 CA → 中间 CA → 客户端证书)即可
可选增强:添加 ssl_protocols TLSv1.2 TLSv1.3; 和 ssl_ciphers HIGH:!aNULL:!MD5; 关闭老旧协议与弱加密套件。
透传证书信息给后端服务
如果后端应用需要识别客户端身份(例如做权限控制或审计日志),可在 proxy_pass 前添加头信息:
-
proxy_set_header X-Client-Verify $ssl_client_verify;—— 值为SUCCESS或FAILED -
proxy_set_header X-Client-DN $ssl_client_s_dn;—— 包含客户端证书的可分辨名称(DN),如CN=api-client,OU=dev,O=company -
proxy_set_header X-SSL-Issuer $ssl_client_i_dn;—— 客户端证书签发者 DN
这些变量仅在 ssl_verify_client on 且校验成功时有值,后端可通过读取 HTTP 头获取可信身份信息。
处理校验失败的访问请求
客户端未提供证书、证书过期、签名无效或不被 CA 信任时,Nginx 默认返回 HTTP 495(SSL Certificate Error)或 496(SSL Certificate Required)。建议统一拦截并返回友好提示:
- 在 server 块中添加:
error_page 495 496 = @deny_access; - 再定义 location:
location @deny_access { return 403 "Client certificate is required and must be valid."; }
这样既避免暴露内部错误细节,又明确传达安全策略。


















