开放问答
mTLS 证书轮换窗口期新旧证书并存,如何量化验证旧连接不再依赖已吊销旧证?
该问题的正文、回答与评论。
提问者 温墨白-299 · 状态 open
mTLS证书轮换gRPC安全加固Go
【背景】 我在给一套内部服务做安全加固,目标是"证书 90 天强制轮换 + 轮换期间业务无感"。栈是 Go 1.22 + gRPC,跑在 3 节点自建 K8s 1.28,没有 Istio,mTLS 由应用层自己用 crypto/tls 的 Config.ClientAuth=RequireAndVerifyClientCert 做,CA 是自签的,每服务一对 ECDSA P-256 证书(CN=服务名)。
【现象 / 卡点】 轮换流程本身不复杂:新证书签发 → 滚动重启 → 旧证书吊销。真正的风险出在"窗口期":
- gRPC 是长连接,老连接上跑的还是旧证书,滚动重启只影响新连接;
- 客户端如果 keepalive 设得很长(我们现在是 1h),可能整个轮换窗口都没触发重连,仍在用旧证书通信——此时旧证书是否已被吊销?如果没吊,攻击者拿到旧私钥还能用多久?
- 我目前的"验证"只是看 SLO 没掉,但没有一个可复现的手段去回答:"此刻线上还有多少条连接在用旧证书?"
【已尝试的排查与结果】
- 在 server 侧用 tls.ConnectionState 暴露 peer 证书序列号:能拿到,但没有聚合视图,不知道哪些 Pod 上还有旧证书的活跃连接;
- 把 keepalive 从 1h 降到 5min:能加速换证,但这是"碰运气",不是"保证",而且对延迟敏感的服务不敢这么调;
- 用 CA 侧吊销旧证书(CRL):Go 的 crypto/tls 默认不查 CRL,这条路走不通,除非自己实现。
【期望得到的答案形态】 希望得到:
- 一个可落地的"轮换完成判定"——不是看 SLO,而是有明确的信号(比如全集群所有活跃连接都换成新证书序列号后才算完成);
- 一个可复现的验证命令/脚本(比如用 openssl s_client 或 grpcurl 主动探测 + 服务端指标聚合);
- 关于"CRL 是否必须上"的取舍建议:在自签 CA 场景下,不上 CRL 的最小风险敞口到底有多大,怎么在文档里写清楚。
谢谢。
评论
暂无评论。