客户端证书证明的是设备,不只是口令
双向 TLS 在验证服务器身份的同时,也认证客户端是否能够使用证书对应的私钥。但它并不天然证明某台物理设备的身份。可复制的软件私钥可以被带到别处使用;硬件绑定和设备证明需要额外机制。因此,标题中的设备身份应理解为注册和签发策略所赋予的身份,而不是 TLS 自动确认的硬件事实。 完成认证仍然需要授权 TLS 1.3 的证书式客户端认证中,服务器请求证书,客户端通过 CertificateVerify 证明自己能够使用对应私钥。只发送一份公开证书文件并不够。双方都必须应用各自的信任规则,检查证书链和适当用途;客户端还要验证服务器名称,不能因为自己提交了凭据就放弃验证对端。 服务端信任哪些客户端 CA,与客户端信任哪些服务器 CA,是两个方向的决定。应只接受预期签发者,并明确使用哪个已验证证书字段表示工作负载身份。URI SAN 可以存放应用标识,但谁有资格拿到这个标识,取决于签发者的注册规则。证书里出现了名字,不代表它自动拥有所有 API 权限。 “要求必须提供证书”也不同于“请求对方有的话就提供”。Go 的 RequireAndVerifyClientCert 要求有效客户端证书,而可选模式可能允许没有证书的连接通过。认证之后仍需根据已验证身份执行授权,因此合法访客可以得到 HTTP 403,而获准读取的客户端得到 HTTP 200,这两个结果不矛盾。 坏掉的样子 没有证书、签发者不受信任、凭据过期或扩展用途不合适,都可能阻止客户端认证。把服务端改为任意证书都接受,或者关闭客户端对服务器的验证,只是隐藏边界,不是在修复凭据问题。应区分握手失败和应用层拒绝,让排查人员能定位到实际负责的那一层。 私钥需要受控存储、签发、轮换和事件响应。续签证书并不必然更换私钥;被盗且仍被接受的私钥可能用于冒充,不能把等待过期当作唯一处置方式。Go 的证书 Verify 不执行吊销检查,因此发布了一条吊销记录,也不等于每个调用方已经应用它,接受策略必须另行核实。 TLS 终止位置还决定了身份在哪里被建立。后端收到调用方自行填写的身份 Header,不代表后端就验证了调用方证书。受信任的身份传递需要自己的认证边界和防伪造规则;凭据或权限变化时,既有连接、恢复会话如何处理,也必须有明确的生命周期策略。 快速验证 保存为 mtls_probe.go,使用 Go 1.23 或更新版本运行 go run mtls_probe.go。程序在内存中生成客户端 CA 和凭据,把 notBefore 回拨一分钟,并把 notAfter 设为生成时刻之后一小时。回环服务端使用 httptest 自带的测试服务器证书,配套测试客户端信任这张证书。两侧信任库都不安装到系统全局,也不打印或写出私钥。 ...