公元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" 对失效边界的主动管理

工程关注点通常包括:

  • 谁先崩溃;
  • 在哪里崩溃;
  • 崩溃后是否还能继续前进。

罗马军团最终失败,并非因为士兵不够优秀。 问题出在:它将“开阔地上的正确”,直接延伸到了森林。

今天很多系统部署的问题,也往往出现在环境已经进入森林,配置却仍停留在大道。

而真正有效的行动,通常来自:

  • 重新划定能力边界;
  • 主动压缩不确定性;
  • 在结构延续之前,先验证结构如何失效。