双向认证排错
双向认证(mTLS)要求服务端与客户端互为验证:服务端除出示自己的证书外,还会请求客户端证书并校验其链与用途。失败通常集中在三处:客户端证书缺失或已过期、服务端未信任其签发者、证书缺少 clientAuth 用途。用 s_client 携带客户端材料复现,可以把问题定位到服务端配置还是客户端材料。
基本信息
| 客户端复现 | s_client -cert 与 -key 携带客户端材料,观察 verify 输出 |
|---|---|
| 服务端配置 | ssl_client_certificate 指定信任的客户端 CA,ssl_verify_client 打开校验 |
| 用途约束 | 客户端证书需包含 clientAuth 扩展用途,或由 CA 策略覆盖 |
| 常见误判 | 服务端证书与会话问题都表现为握手失败,需要分别定位 |
| 排查顺序 | 先确认服务端是否请求了客户端证书,再查链与用途 |
典型使用场景
- 服务间调用启用双向认证后,部分调用方握手失败
- 排查「服务端证书正常、客户端证书被拒」的链不完整问题
- 评估签发模板:用服务器模板签发的客户端证书缺少 clientAuth
- 排查客户端证书过期:这类证书的有效期常被忽略
- 会话恢复干扰排查:复用连接会跳过证书请求,需先走完整握手
复现与验证
复现与验证
# 携带客户端材料复现,观察校验结果
openssl s_client -connect api.example.com:443 -servername api.example.com -cert client.pem -key client.key -CAfile ca.pem </dev/null 2>&1 | grep -iE 'verify|error|certificate'
# 检查客户端证书的用途扩展
openssl x509 -in client.pem -noout -text | grep -A1 'Extended Key Usage'
openssl x509 -in client.pem -noout -dates # 核对有效期nginx 服务端配置
nginx 服务端配置
ssl_client_certificate /etc/nginx/ssl/client-ca.pem; # 信任的客户端 CA
ssl_verify_client on; # 强制校验客户端证书
ssl_verify_depth 2; # 按实际层级设置
# 在日志格式中加入 $ssl_client_s_dn 便于记录访问主体常见失败点
| 失败点 | 症状 | 处理 |
|---|---|---|
| 缺少 clientAuth | 链正确但仍被拒 | 用客户端证书模板重新签发 |
| 客户端 CA 未受信 | 报 unknown ca | 把签发用 CA 加入服务端信任文件 |
| 客户端证书过期 | 握手失败,日志含 expired | 重新签发并同步分发 |
| 链不完整 | 服务端只看到叶证书 | 客户端提供完整链 |
会话恢复会跳过部分证书请求交互:用长连接或复用会话复现时可能看不到真实问题。排错阶段先确保走完整握手路径,再单独评估复用场景下的行为差异。