手机拒绝连接并输出 No trusted RSA public key found for vpn.example.net,而同一张网关证书在同一网络的笔记本电脑上却工作正常。诱人的做法是重新签发证书。动手之前,先弄清你遇到的是三种故障中的哪一种,因为只有一种与证书内容有关。该消息涵盖证书链不完整、身份不匹配以及不支持的密钥或签名,每种都有不同的修复方式。

一条消息背后的三种故障

Android 会构建一条从网关证书到 VPN 配置文件中选定 CA 的证书链,然后对照配置文件检查服务器名称。通知报告的是结果,而不是阶段。信任故障意味着无法用交换中提供的证书完成证书链;身份故障意味着证书链已验证但名称不匹配;算法故障意味着设备或配置文件不接受该密钥类型或签名。

What you seeWhat it points toFirst move
Chain stops after the leaf in the daemon logintermediate not loaded or not sentload the intermediate as CA material
Chain validates, name differs from the profileidentity mismatchfix the profile name or the certificate SAN
Chain validates, handshake still failskey or signature not acceptedcompare key type against the device

依靠证据判断,而不是依次尝试各种修复。对守护进程用日志级别 2 试一次,就能判断你处在哪一行,而且比重新签发一张从来没错过的证书成本更低。

先判断:整条证书链是否到达?

strongSwan 发送为该连接配置的证书,而中间证书是独立的凭据。必须先把它们作为 CA 证书加载,守护进程才能将其放入载荷,因此这样一种布局——服务器证书由中间证书签发、根证书是信任锚、中间证书只存在于 CA 的构建目录——恰好产生此故障:线上只有叶子证书,手机上证书链过早结束。

在 swanctl 部署中用 swanctl --list-certs,或在旧版 starter 中用 ipsec listcerts,检查守护进程持有什么。中间证书应作为 CA 证书出现,且其上还有根证书。如果缺失,任何客户端选项都无济于事;如果存在,就进入下一个问题。

接着检查它是否会被发送。swanctl.conf 参考记录了 send_cert,其默认值 ifasked 仅在对方请求时发送证书;always 则无论如何都发送。旧版对应项是 ipsec.conf 中的 leftsendcert=always。该设置控制的是发送,而不是可用性,因此无法弥补守护进程从未加载的中间证书。

如果证书链不完整,请在守护进程查找的位置加载中间证书

把中间证书放进 CA 目录,而不是放在叶子证书旁边:ipsec.conf 配置对应 /etc/ipsec.d/cacerts,swanctl 对应 /etc/swanctl/x509ca,或者你的软件包所替换的路径。重新加载配置并再次列出证书。某些版本也会发送在叶子文件中包含证书链的捆绑包,但 CA 目录是跨版本和软件包都通用的布置方式。

也要从客户端一侧验证。手机只能看到交换所携带的内容,因此日志级别 2 的守护进程日志应显示中间证书出现在传输的证书中。如果日志显示了它而手机仍然失败,说明你处在表格的另一行,继续调整 CA 文件不会改变结果。

如果证书链完整,请停止修改证书

身份故障是 VPN 配置文件中的名称与证书中的名称不匹配。Android 会将你配置的服务器身份与它验证过的证书进行比较,因此当证书写的是主机名、而配置文件指向地址,或者配置文件写的主机名不在证书覆盖范围内时,会在证书链验证成功后失败。修正错误的一侧,并在任一方变化时保持配置文件与证书一致。

算法故障出现在证书链有效且名称匹配时。不同 Android 版本接受的密钥类型和签名方案不同,而且配置文件类型本身就限制了选项。如果网关使用较旧或不常见的组合,在假定证书损坏之前,先将其与设备所支持的组合进行比较。守护进程日志会显示握手比信任故障时推进得更远,这就是证书链不再成为问题的信号。

不要把中间证书作为用户根证书安装到手机上

把缺失的中间证书作为用户证书安装到手机上,会让警告消失,并改变手机对所有接受用户安装根证书的应用的信任模型。它还会掩盖一个会波及下一个客户端的交付缺陷,并使网关继续向未来每一台设备发送不完整的证书链。持久的修复在服务器上,只需一次,就惠及所有客户端。

在变更记录中把三项决定分开:传输了哪些证书、比较了哪个身份、协商了哪种算法。一个总是发送完整证书链的网关、一个正确命名证书的配置文件,以及机群支持的密钥类型,是三个小事实,而它们就是这次故障的全部。

相关文章