IPsec 提案里到底有什么?IKE 与 ESP 字段
提案是一份完整的要约,而不是一堆算法的集合。看哪些字段属于 IKE、哪些属于 ESP,以及为什么一处不匹配就会否决整套。
IKE 已经启动,两端都声明支持 AES,隧道却仍然以 NO_PROPOSAL_CHOSEN 失败。日志给出了提案的名字,却没有指出哪个字段没有匹配上。提案是一份完整的要约,一个不兼容的字段就会让整个组合失效,而不只是那一行。把它当成一堆彼此独立的算法选择来读,正是这种不匹配长期隐形的原因。
两套各自独立提案列表的协商
IKEv2 会建立两个安全关联。第一个是 IKE SA,用来保护控制交换本身;第二个是 CHILD SA,用来通过 ESP 承载你的流量。两者各有自己的提案列表,对端可以接受其中一个而拒绝另一个。
这种分离解释了一个常见困惑:能正常工作的 IKE SA 只能证明控制通道的算法匹配。如果 CHILD 提案失败,即便第一阶段已经完成、日志顶部看起来健康,隧道也不会承载任何数据包。
每个列表内部的顺序同样重要。响应方从发起方按序排列的要约中挑选,因此把兼容面更宽的条目挪到较窄的条目之前,就会改变最终安装哪套算法,而任何一个算法名称都没有变。请在配置中固定这个顺序,不要依赖默认值。稳定的顺序也让不同站点之间的日志对比有意义。
哪些字段属于哪份提案
字段集合不大,但在两套协商中并不完全相同。要按行读表,因为一列中的字段可能在另一列里没有。语法因实现而异;strongSwan 的提案文档就是一个具体的参考。
| Field | IKE SA proposal | CHILD SA proposal |
|---|---|---|
| Encryption | Required | Required |
| Integrity | Required unless AEAD | Required unless AEAD |
| PRF | Required | Not present |
| DH group | Required | Only for PFS |
| ESN | Not present | Optional |
加密字段指出算法,在多数语法里还包括密钥长度。完整性字段指出用于校验密文的哈希,PRF 则指出为 IKE SA 派生密钥材料的函数。DH 组负责建立新的共享秘密材料,因此它出现在两侧,但目的并不相同。
扩展序列号只属于数据路径。它扩大了序列空间,并作为 CHILD 提案的一部分进行协商,所以这里出现不匹配只会拒绝 CHILD 要约,IKE SA 不受影响。
一份完整要约是如何被选中的
每份提案都是一个集合,响应方寻找的是一个所有必填字段都可接受的集合。两个列表都可能包含 AES 和 SHA-256,却仍然没有兼容条目,因为密钥长度、PRF 或 DH 组不同。比较是按提案进行的,不是按算法。
当没有任何匹配时,响应方会连同失败的 SA 类型一起发送 NO_PROPOSAL_CHOSEN。修改配置之前,先读清这条通知指的是哪份提案列表;IKE 提案被拒时去改 ESP 算法,只会浪费一轮排查。
调整配置档时,值得了解选择行为。有些实现偏好发起方的顺序,另一些会按本地策略重新排序,所以在两个厂商之间能跑通的算法套件可能消失,只要你把发起连接的一侧对调。
AEAD 是删掉一个字段,而不是增加一个
AES-GCM 与 ChaCha20-Poly1305 在一次运算中同时完成认证与加密。当其中任一被选用于 ESP 时,完整性算法不会单独协商,因为 AEAD 构造已经覆盖了它。因此把 AES-GCM 与 SHA-256 配在一起的提案,最好情况是冗余,最坏情况是被拒绝。
PRF 在 IKE 侧仍然是独立的,因为它为控制通道派生密钥,而不是保护载荷。正因如此,IKE 提案可以合法地把 AEAD 算法与 PRF 和 DH 组组合在一起,而对应的 ESP 提案只列出 AEAD 算法和可选的 PFS 组。
密钥长度是加密令牌的一部分,所以 AES-128-GCM 与 AES-256-GCM 是不同的要约。从假定使用 256-bit 密钥的教程里复制来的配置档,无法与配成 128-bit 的端点匹配,尽管两行都写着 AES-GCM。两端可以就算法族达成一致,却仍会因为连字符后面那个数字而互相拒绝。
要读已安装的 SA,而不是配置
配置好的提案列表是一份要约,已安装的 SA 才是结果。在 strongSwan 和 Linux 内核上,两种视图都可用:
sudo swanctl --list-sas
sudo ip xfrm state
sudo ip xfrm policyswanctl --list-sas会打印每个 SA 协商出的算法,包括 CHILD 是否使用 AEAD。 ip xfrm state 则显示内核实际安装了什么,而这里正是确认重协商没有退回与你记录不同的套件的地方。
修复之后,把这段输出保存在配置旁边。当客户端更新改变了默认值时,记录下来的套件就是对照的基线,而对比会直接指向变动的字段,不必从零开始调查。