Android IKEv2 信任错误:发送中间 CA,而不是根证书
手机拒绝网关,因为它收到的证书链过早结束。请判断:发送中间证书、修正身份,还是更换密钥类型。
手机拒绝连接并输出 No trusted RSA public key found for vpn.example.net,而同一张网关证书在同一网络的笔记本电脑上却工作正常。诱人的做法是重新签发证书。动手之前,先弄清你遇到的是三种故障中的哪一种,因为只有一种与证书内容有关。该消息涵盖证书链不完整、身份不匹配以及不支持的密钥或签名,每种都有不同的修复方式。
一条消息背后的三种故障
Android 会构建一条从网关证书到 VPN 配置文件中选定 CA 的证书链,然后对照配置文件检查服务器名称。通知报告的是结果,而不是阶段。信任故障意味着无法用交换中提供的证书完成证书链;身份故障意味着证书链已验证但名称不匹配;算法故障意味着设备或配置文件不接受该密钥类型或签名。
| What you see | What it points to | First move |
|---|---|---|
| Chain stops after the leaf in the daemon log | intermediate not loaded or not sent | load the intermediate as CA material |
| Chain validates, name differs from the profile | identity mismatch | fix the profile name or the certificate SAN |
| Chain validates, handshake still fails | key or signature not accepted | compare 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 版本接受的密钥类型和签名方案不同,而且配置文件类型本身就限制了选项。如果网关使用较旧或不常见的组合,在假定证书损坏之前,先将其与设备所支持的组合进行比较。守护进程日志会显示握手比信任故障时推进得更远,这就是证书链不再成为问题的信号。
不要把中间证书作为用户根证书安装到手机上
把缺失的中间证书作为用户证书安装到手机上,会让警告消失,并改变手机对所有接受用户安装根证书的应用的信任模型。它还会掩盖一个会波及下一个客户端的交付缺陷,并使网关继续向未来每一台设备发送不完整的证书链。持久的修复在服务器上,只需一次,就惠及所有客户端。
在变更记录中把三项决定分开:传输了哪些证书、比较了哪个身份、协商了哪种算法。一个总是发送完整证书链的网关、一个正确命名证书的配置文件,以及机群支持的密钥类型,是三个小事实,而它们就是这次故障的全部。