双向认证怎么判读
mTLS 是双向认证:服务端在握手里发出 CertificateRequest(类型 13)索取客户端证书,客户端回一个 Certificate(类型 11)并用 CertificateVerify 证明自己持有对应私钥。抓包上最直观的判断就是「ServerHello 之后出现客户端方向发出的 Certificate」。客户端证书缺失或不受信时,服务端会以握手失败类告警收场,客户端侧报错往往比较含糊。
基本信息
| 关键字段 | tls.handshake.type == 13(请求)与 11(客户端证书) |
|---|---|
| 触发条件 | 服务端配置要求客户端证书,如网关、服务网格、专线对接 |
| 失败表现 | certificate_required(116)、bad_certificate(42)、unknown_ca(48) 或 handshake_failure(40) |
| 证书可见性 | 包内可展开看主题与有效期,但需能解密 |
典型使用场景
- 确认某个客户端是否真的完成了双向认证,而不是只做了服务端证书校验
- 排查「证书已安装仍被拒」:核对客户端证书链是否完整
- 网关或服务网格场景验证 mTLS 是否真的生效
- 审计:确认哪些服务端口开启并强制要求客户端证书
- 取证:服务端日志不全时用抓包还原握手过程
过滤与判读
过滤与判读
tshark -r t.pcap -Y "tls.handshake.type==13 || tls.handshake.type==11" -T fields -e frame.number -e ip.src -e tls.handshake.type
# 13 由服务端发出=要求客户端证书;11 由客户端发出=客户端证书,即 mTLS
tshark -r t.pcap -Y "tls.alert_message.desc==116" # certificate_required(TLS 1.3)
# 逐帧看:ClientHello → ServerHello → Certificate(S) → CertificateRequest → Certificate(C) → Finished握手消息对照
| 消息 | type | 方向 | 含义 |
|---|---|---|---|
| ClientHello | 1 | 客户端到服务端 | 声明能力与支持的参数 |
| ServerHello | 2 | 服务端到客户端 | 给出选中的参数 |
| Certificate | 11 | 双向都可能 | 服务端证书或客户端证书 |
| CertificateRequest | 13 | 服务端到客户端 | 要求提供客户端证书,是 mTLS 的信号 |
| CertificateVerify | 15 | 各自的发送方 | 用私钥签名,证明持有证书对应的私钥 |
| Finished | 20 | 双向 | 校验握手完整性,之后进入应用数据 |
客户端证书同样可以在抓包里看到主题、颁发者与有效期,排错不必只依赖服务端日志。但在 TLS 1.3 中这些消息已加密,需要导出会话密钥才能查看具体内容。
证书撤销检查失败在部分实现里也归入握手失败,告警描述码不一定直观。遇到「证书看着没问题却握手失败」时,要结合服务端日志确认是否卡在 OCSP 或 CRL 检查环节。
排查顺序
- 先确认服务端是否发了 CertificateRequest,没有就说明没启用双向认证
- 确认客户端是否回了 Certificate,回了但失败要看证书链是否完整
- 确认客户端证书是否过期、密钥用法是否包含客户端认证
- 确认服务端信任库是否包含签发该客户端证书的根或中间证书
- 核对失败发生在握手哪个阶段,用帧号顺序定位是证书还是 Finished 之后的应用层错误