OpenVPN 客户端上个月还能用,现在启动就失败,报 ca md too weak,而磁盘上的配置文件与当初能用的那份逐字节相同。这条报文说的是证书颁发机构证书上的签名,与数据加密算法、auth 摘要或账户密码无关。三个条件决定修法是换新的身份材料、换一条证书链,还是有意识地调整策略。按顺序走完,就能避免那种常见结局:为了让隧道恢复,把主机上每一个 TLS 连接都削弱。

这条错误到底在说什么

OpenSSL 在构建证书链时抛出这一校验错误,原因是被当作 CA 的证书上带有一个签名摘要,而库的安全级别已不再接受它。MD5 在默认级别就被拒绝,SHA-1 则在级别提高后被拒绝。这里更关键的不是叶子证书的摘要,而是给它签名的签发方证书上的摘要。同一套策略也可能拒绝一张在签发当日完全普通的根证书。

这就是为什么改 auth 或 data-ciphers 对这个故障毫无作用。那些设置管的是握手之后数据包如何被保护,而被拒绝的对象是一份在隧道存在之前就要检查的身份文件。一张证书可以安稳地处在有效期内,却仍然带着库不会接受的签名。

把这几项检查在脑子里分开,错误就不再显得神秘。有效期、密钥用途和签名摘要彼此独立,而刚刚失败的恰好只有一项。

条件一:被拒绝的对象是根证书吗?

把配置文件里的每张证书打印出来,读 subject 和 issuer 字段。自签名的根证书两处取值相同,它的签名算法正是整条链所依赖的。弱摘要如果就在那里,它下面每一张叶子证书都会继承这个问题。把算法写在 subject 旁边,后面的比对才能靠对照而不是靠记忆。

打包的 CA 文件常常包含多个块,所以要确认真正被加载的是哪一块,而不是想当然地认为第一块有问题。命令 openssl x509 -in ca.pem -noout -subject -issuer -text 一次只描述一张证书,因此包里若有多张,得先拆开。把打印出的签名算法与根据根证书生成年代所预期的摘要做比较。

在弱根证书之下用 SHA-256 签发的叶子证书照样失败,因为链校验会一路向上走到顶。正是这个次序让下一个条件变得重要。

条件二:签发方在你手里吗?

如果根证书属于你所在的组织,长久之计是换一张使用现代摘要的新根证书,并重新签发叶子证书,作为一次配置更新下发。代价是一个维护窗口,以及为那些当天无法接受更新的设备做安排。

如果证书链由第三方签发,修法就是向那家运营方提出请求,本地唯一有用的动作是停止依赖旧材料。改 PEM 文本或重新保存文件,改变不了签名所覆盖的任何内容。

有一种中间情形值得点名:一张内部根证书早于当前默认值,却仍在为其他系统信任的材料签名。替换它意味着审计每一个使用方,包括用指纹钉住旧证书的专用设备。在排期之前先把这些使用方数清楚,因为漏掉一个的根证书替换,会把一个启动错误换成一次服务中断。

条件三:降低级别还会接受什么

降低安全级别,或者选择 OpenVPN 的旧版证书配置,会让客户端重新接受旧摘要。它同时也放松了同一个库里其他检查,而且是对该进程建立的每一个连接。

在实验室里,或者在准备替换材料期间作为短暂的过渡,只要把例外限定在单一配置并写明结束日期,这还可以辩护。作为共享主机上的永久设置,它会悄悄扩大这台机器上每个 TLS 客户端所信任的范围。

把例外连同负责人和移除步骤一起写下来。半年之后,一次没有记录的级别改动与一次失误无法区分,下一位工程师不会知道它曾经是一个决定。

把结论写成规则

当你控制签发方、又能把使用方一一列出时,就更换证书链;控制不了就升级给签发方。只有在替换已经排期时,才把降级当作有日期、有范围的例外。别的做法都只是把同一张证书留在原处,把风险挪到更不显眼的地方。

然后用一台干净的客户端重新测试配置,确认握手能够完成;如果仍然失败,就保留那段精确的拒绝原文。一条准确的错误信息,是你交给下一层负责人的最便宜的东西。

相关文章