续期之后,一半环境重新连接成功,三台设备却拒绝,各自给出关于网关身份的警告。续期本身是例行操作。这三台设备保留的是对旧对象的固定,而 证书固定并不等于 CA 列表、名称校验或信任存储条目。在触碰任何客户端之前,先比较这三种机制。

一次续期,两种表现

重新连接的客户端其信任判断仍然通过,而拒绝的客户端有一条新证书无法满足的要求。这个差异是信息,不是噪声。准确阅读失败客户端的提示。名称不匹配、签发者未知和指纹变化是三种不同的判断,只有最后一种指向固定。

还要检查失败客户端选择了哪个配置文件。存在于自身存储中的导入副本,不会因为管理员在别处修改原始文件而改变。

续期替换的是对象,而不只是日期

指纹标识证书编码后的内容。续期会生成新证书,因此即使主体名称和公钥保持不变,指纹也会改变。对信任 CA 并校验名称的客户端来说,这是预期之内且无害的。对配置为只接受一张证书的客户端来说这是致命的,对信任存储从未收到新签发者的客户端同样致命。

openssl x509 -in server.pem -noout -subject -issuer -dates -fingerprint -sha256
openssl x509 -in server.pem -noout -pubkey | openssl sha256

第二行回答的是另一个问题:密钥对是否幸存。复用密钥的续期会保留该值,只更换证书,而这正是管理员容易误以为什么都没变的情形。检查已部署的证书,而不是构建主机上的那一份。比较仓库里的文件只能证明生成了什么,不能证明监听方此刻在呈现什么。

弄清客户端固定的是什么

有些客户端在配置文件里保存指纹,并在每次连接时比较。另一些把它存进平台的信任存储,还有一些只依赖 CA。每种情况的修复方式都不同,所以要先识别机制。

grep -n 'peer-fingerprint' /etc/openvpn/client/*.conf
openssl s_client -connect gw.lab.example.net:443 -servername gw.lab.example.net < /dev/null 2>&1 | openssl x509 -noout -fingerprint -sha256

第一条命令显示常规配置里的固定;第二条显示端点此刻实际提供的指纹。两者不同时,你不靠猜测就定位了故障。不要把新值粘贴到每一个抱怨的客户端里。因签发者问题而拒绝的客户端会继续拒绝,而你只会让自己相信指纹才是问题,其实并不是。

比较各后端提供的证书

时好时坏的结果通常意味着不止一个端点,只对一台节点做的续期会让其余节点继续呈现旧对象。要按地址而不是共享名称来比较各后端。

for h in 10.30.0.11 10.30.0.12; do echo "$h"; openssl s_client -connect $h:443 -servername gw.lab.example.net < /dev/null 2>&1 | openssl x509 -noout -subject -dates -fingerprint -sha256; done

某个节点落后的池子,正好解释了客户端第二次尝试才连上、第一次却失败。它也解释了一项在用户投诉时仍然通过的监控检查。先把落后修好。在每个节点都提供新证书之前滚动信任配置,会出现什么都不工作的窗口;之后才滚动,则让客户端不可预测地失败。

通过受管路径更改信任

在往任何地方接受之前,先通过已经可信的管理通道确认替换。看似合理的到期日并不是所有权的证明。通过拥有该配置的流程更新受管配置,安排好可接受身份的重叠期,并保留部署所要求的名称校验。没有名称校验的固定,比它所取代的 CA 信任更弱。

然后逐个客户端验证:连接、确认它接受了哪个身份,并记录它现在信任的证书版本。被忽略过一次的警告,往往会在下一次续期时回来。

相关文章