IKEv2的麻烦:为什么 Android 能连,而 iPhone 与 Windows 会沉默断开
公元9年,条顿堡森林。
罗马军团仍保持着帝国时代最先进的建制:重装步兵、工程体系、标准化后勤、统一指挥。它在开阔地几乎不可战胜。但进入森林与沼泽后,问题开始出现。道路消失,传令失效,长矛阵型无法展开。罗马人仍能局部推进,但体系默认成立的前提,已经在环境中逐渐失效。
IKEv2 的跨平台兼容问题,很像这场森林中的行军。
Android 能连接,并不意味着系统已经稳定。 它只说明:某一条路径,在某一种客户端实现下成立。
而 iOS 与 Windows 的沉默断开,往往会暴露另一件事:
你依赖的,并非统一的“协议标准”,而是“客户端实现对标准的解释”。
危险并不来自错误日志。 “没有错误”的沉默状态,往往更难定位。
在 OpenWrt 上使用 strongSwan 部署 IKEv2 时,很多人会天然形成一种判断:
```text id=”1” HTTPS 正常 证书可信 Android 能连接 = 系统已完成
但 Native IKEv2 与浏览器生态并不相同。
它更接近老帝国的军用道路系统:强调稳定、保守、有限变化、长期兼容。
因此它会天然排斥一些“现代但变化频繁”的默认配置。
例如:
* ECDSA 证书
* 不完整证书链
* CERTREQ 省略
* 过窄 proposal
* 非标准 NAT-T 行为
这些配置在 Android 上可能完全正常。
因为 Android strongSwan App 本身就更接近“现代军团”。
它会:
* 自动补链
* 自动容错
* 使用现代 TLS 栈
* 接受更多加密协商
但 Windows RasMan 与 iOS Native IKEv2 并不具备同样能力。
它们更像仍沿用旧制的边境驻军。
协议写在那里,实现却停留在另一个时代。
---
很多人会把问题归因于“免费证书”。
这个抽象层级过高。
问题通常出现在:
```text id="2"
Let's Encrypt 默认偏向 ECDSA
以及:
```text id=”3” IKEv2 原生客户端对 ECDSA 的兼容长期不稳定
这两者之间,存在明确的工程链路。
必须拆开分析。
---
先看条件。
IKEv2 的证书验证,与 HTTPS 不同。
浏览器生态默认具备:
* AIA 自动补链
* 在线 OCSP
* 中间证书缓存
* 激进兼容策略
但 Native IKEv2 通常没有。
因此:
```text id="4"
HTTPS 可访问
≠
IKEv2 可连接
条件已经发生变化。
如果服务端:
```hocon id=”5” send_cert = ifasked
而客户端没有主动 CERTREQ,那么 strongSwan 可能根本不会发送完整证书。
Android 会补。
Windows/iOS 可能直接沉默。
这里需要明确:
```text id="6"
谁负责补齐结构
这是责任边界问题。
再看能力。
ECDSA 并非“不安全”。 它在现代 TLS 中表现很好。
但能力成立需要环境。
IKEv2 Native Stack 的真实能力边界如下:
| 客户端 | HTTPS ECDSA | IKEv2 ECDSA |
|---|---|---|
| Android strongSwan | 强 | 强 |
| iOS Safari | 强 | 中等 |
| Windows Edge | 强 | 弱于 HTTPS |
| Windows Native VPN | 无关 | 长期存在兼容历史问题 |
这意味着:
同一个系统里的不同组件,并不共享同一种密码学能力。
很多人没有意识到这一点。
他们倾向于认为:
```text id=”7” 系统浏览器支持 = 系统 VPN 支持
事实并非如此。
---
工程问题随之出现:
当 Android 正常,而 Windows/iOS 失败时,你到底应该优化哪一层?
继续调 proposal?
继续改 NAT?
继续研究日志?
还是先回退到更保守、更稳定的结构?
这就是结构性反问。
---
成熟系统通常优先选择“边界清晰”的方案,而非持续追逐最新特性。
所以大量商业 VPN 厂商至今仍默认:
```text id="8"
RSA2048
原因在于:
RSA 的失效边界更加明确。
它在:
- Windows
- iOS
- 老运营商 NAT
- 企业网关
- 长期升级链
中的行为更加稳定。
这是一种工程上的“保守性胜利”。
于是行动路径就很明确。
第一步,不应继续扩大变量。
而应先收缩变量。
例如:
```hocon id=”9” send_cert = always send_certreq = yes
再例如:
```text id="10"
ECDSA
→
RSA2048
这里的行动目标是:
```text id=”11” 跨客户端最小不确定性
---
然后才进入第二阶段。
即 proposal 收敛。
很多人喜欢把 proposal 写得极窄:
```hocon id="12"
aes256-sha256-modp2048
理论上没有问题。
现实中却可能导致:
- Windows 某些版本无法协商
- iOS fallback 失败
- NAT-T 下行为异常
协议标准仍然成立。 客户端实现的“能力边界”已经发生偏移。
因此更稳定的结构通常会采用:
```text id=”13” 核心强约束 + 有限兼容冗余
而不是:
```text id="14"
绝对纯净的密码学洁癖
这里还有一个更深的问题。
为什么 Android strongSwan App 往往“什么都能连”?
因为它更接近:
```text id=”15” 应用层重新实现的一套现代 IPsec 栈
Windows/iOS Native VPN 同时承担着:
* 企业兼容
* 历史升级
* 老设备适配
* 长周期稳定性
它们更关注:
```text id="16"
十年后仍能连接
这决定了它们天然保守。
因此,IKEv2 的工程目标可以拆解为:
- 让协议能够工作;
- 让不同年代、不同实现、不同网络环境下的协议持续工作。
前者偏向实验室验证。 后者对应长期系统工程。
最终,很多 VPN 部署失败,来源于责任划分失效。
客户端以为服务端会补链。 服务端以为客户端会请求证书。 管理员以为 Android 能连就代表系统完成。
每一方都“部分正确”。
于是系统整体失效。
真正稳定的 IKEv2 架构,通常具备几个特征:
- RSA2048 作为基础兼容层
- fullchain 明确发送
- CERTREQ 不省略
- proposal 存在有限冗余
- MOBIKE 显式验证
- NAT-T 行为可观测
这些配置并不追求“先进技术”标签。
它们对应的是:
text id="17"
对失效边界的主动管理
工程关注点通常包括:
- 谁先崩溃;
- 在哪里崩溃;
- 崩溃后是否还能继续前进。
罗马军团最终失败,并非因为士兵不够优秀。 问题出在:它将“开阔地上的正确”,直接延伸到了森林。
今天很多系统部署的问题,也往往出现在环境已经进入森林,配置却仍停留在大道。
而真正有效的行动,通常来自:
- 重新划定能力边界;
- 主动压缩不确定性;
- 在结构延续之前,先验证结构如何失效。