Android IKEv2:用户证书与 CA 各司其职
一个字段证明手机是谁,另一个决定该信任哪个网关。Android 的 IKEv2 配置把两者分开,因为握手本身就分两个方向。
一个同时要求用户证书和 CA 证书的 Android IKEv2 界面,看起来像是把同一件事问了两遍。并非如此。IKEv2 在同一次交换中、沿两个方向认证双方,而手机在每个方向上扮演不同角色:它必须证明自己是谁,也必须决定信任哪个网关。用户证书回答第一个问题,受信任的 CA 回答第二个问题,两者谁也替代不了谁。
同一次交换中的两个认证方向
IKEv2 分两个阶段建立控制通道。第一次交换协商算法与密钥;第二次即 IKE_AUTH,携带双方各一个 AUTH 负载,以及各自的身份。该负载是对整次交换计算的签名或 MAC,并用接收方已经信任的东西来验证。
网关用自己的证书证明身份,手机则把该证书的链条验证到一个它愿意信任的根,然后检查证书中的身份是否与它打算连接的网关一致。手机用自己的凭据证明身份,网关用签发客户端证书的 CA 来验证它。
这就是两个字段背后的全部机制。用户证书是手机关于自身的一项声明;CA 字段则是关于它会相信谁的声明。只有其中一个而缺另一个的配置无法完成双向认证,重试多少次都改变不了这一点。两种失败看起来甚至不同:缺少用户密钥时手机根本无法生成签名,而缺少信任锚时它无法接受网关的证书。
| Material | Role | What it cannot do |
|---|---|---|
| User certificate plus its private key | Proves possession of the enrolled client identity | Establish that the gateway is the right one |
| Trusted CA certificate | Validates the gateway chain under the intended identity checks | Prove the client's identity to the gateway |
| Expected gateway identity | Pins which server the phone accepts | Grant that user access to every private resource |
Android 配置构建器要求什么
Google 的 IKEv2 配置构建器 把每种认证方法分别暴露出来,而不是合并成一个证书模式。数字签名方法需要用户证书、私钥和服务器根 CA。其他方法需要用户名和密码,或预共享密钥。
请仔细读这一签名,因为它编码了上面的机制。用户名和密码方法中没有用户私钥的字段,PSK 方法中也没有网关信任锚的字段,原因很简单:这些方法证明的是不同的事情。把密码粘贴到证书字段里把两者混在一起,得到的配置会在 IKE_AUTH 失败,而报错信息不会点名其中任何一个。
数字签名方法记录的私钥类型是 RSA。标有 IPsec 或证书的菜单并不意味着支持 ECDSA;基于它支持这一假设搭出来的配置,在网络还没参与之前就会在平台 API 上失败。
为什么只有公开的用户证书还不够
AUTH 负载是用客户端私钥对整次交换做出的签名。持有公开证书能让网关校验签名;对手机毫无帮助,因为它需要私钥才能生成签名。只导入 .crt 而 把私钥落下,是这类失败中最常见的一种。
Android 的密钥基础设施正反映了这一点。选择客户端身份要经过 KeyChain,它要求访问相应的私钥,而不只是一条证书条目。把两者一起安装的注册包或设备管理工作流,才是获得可用身份的常规方式;手工复制一个证书文件通常不是。
所以配置里的这两项并不是一个证书包和它的副本。一项是平台必须能用来签名的密钥对,另一项是平台用来比对的信任锚。把两者当作两个独立事实来检查:这个配置能签名吗?它知道该信任谁吗?
信任锚属于应用,而不属于手机
把根证书装进用户存储并不会让每个 Android 应用都信任它:从 Android 7 起,应用必须通过网络安全性配置主动选择加入,而在该版本之前,用户安装的 CA 被接受的范围要宽得多。应用的信任配置可能各不相同,管理自己信任材料的 VPN 客户端甚至可能根本不看用户存储。这就是同一个 CA 文件在一个客户端里可用、在另一个里却像被忽略的原因。
于是有两种归属模型。系统托管的 VPN 配置使用设备的证书安装或管理员注册流程,配置随后引用预期的 CA。应用托管的 VPN 保留自己的信任材料,使用自己文档化的导入流程,它可能与 Android 设置界面完全无关。修复断链的地方也在这里:系统托管的情形在 CA 存储和配置选择中,应用托管的情形在客户端自己的导入界面上。
在导入任何东西之前先确定自己处于哪种模型,然后确认当前配置的信任选择。如果运维方的说明与客户端菜单不一致,对那次安装而言以客户端文档化的行为为准,但 CA 仍必须通过你能验证的渠道来自运维方。文件名并不能证明是谁签发的。
先选模式,再选文件
证书模式需要客户端密钥对、网关侧的签发 CA、用于网关证书的信任锚,以及对这张证书必须携带哪个身份的预期。用户名和密码模式用凭据替代客户端密钥对,但保留对网关的信任要求。PSK 模式用共享密钥替代两者,它改变的是信任模型,而不是简化它。
无论选哪种,都保持常规校验开启。客户端若提供不校验选项,它取消的正是 CA 字段存在的意义;它并不能修复缺失的信任锚。仅仅因为连接在没有校验时也能工作就接受任何服务器证书,也是同样的问题。
然后在正确的地方验证:导入材料,连接一次,并在客户端的连接详情中确认网关身份正是你预期的那个,且配置报告的正是你打算使用的认证方法。用错方法却连接成功,是一个你还没弄懂的配置,等运维方下次收紧策略时它就会失败。