NO_PROPOSAL_CHOSEN 在任何 PPP 用户名被检查之前就会到达,这既是有用的事实,也是这条消息容易误导人的原因。它只报告某一方拒绝了提议,却不报告哪个参数不一致,也不说明拒绝发生在构建 IKE 关联时,还是发生在随后协商流量保护时。这两种可能性背后对应两种不同的修法,而人们最先去动的 PFS 复选框只与其中一种有关。

一条消息,两套提议

IKEv1 L2TP/IPsec 的安排包含两轮依次进行的协商。阶段 1 用加密算法、完整性算法和 Diffie-Hellman 组构建 IKE 安全关联。阶段 2 随后协商流量如何受到保护,而 PFS 要求属于第二轮对话。

PhaseWhat is agreedWhat a rejection here means
Phase 1Encryption, integrity, DH group for the IKE SANo management tunnel exists, so nothing later can run
Phase 2ESP transforms plus the PFS group policyThe IKE SA negotiates, then child negotiation fails

由于阶段是先后进行的,失败出现的位置就能告诉你该比对哪一份列表。这正是这条消息的全部诊断价值,值得在改动任何设置之前先提取出来。

为什么 PFS 复选框修不好阶段 1

关闭 PFS 改变的是阶段 2 的属性。如果双方从未在阶段 1 上达成一致,ESP 对话根本不会发生,因此该复选框对拒绝毫无影响,这也是为什么切换它只会得到同样的错误,只是时间戳不同。

反向的错误同样常见。IKE 关联成功并不能证明 ESP 提议可以接受,更不能证明阶段 2 的组是一致的。请把已建立的管理隧道只当作关于阶段 1 的证据。人们看到绿线便认为「隧道通了」,然后在一个小时里折腾错误的阶段,因为没有任何信息告诉他们第二轮协商根本没有开始。

先读日志,再选算法

从真正处理这条连接的后端上,收集紧挨着拒绝之前的那几行消息,并把它们与同一次尝试对应起来。少了这层对应,你读的是另一条连接的历史,并据此得出结论。

journalctl -b -u NetworkManager --since "10 min ago"
ipsec statusall          # strongSwan
ipsec whack --status     # Libreswan

从这些行里回答两个问题:阶段 1 的关联是否建立,以及哪一次交换失败了。这两个答案把排查范围缩小到一份属性列表。一条孤立的通知,周围没有任何上下文,做不到这一点,无论照搬论坛帖子里的提议多么诱人。从使用另一种后端的机器上复制一条可用字符串,通常只是把一个拒绝换成另一个稍晚出现的拒绝。

后端语法不通用

在比对任何内容之前,先记录 NetworkManager-l2tp 的版本和 IPsec 后端的版本。Libreswan 与 strongSwan 既不共用提议语法,也不共用完全相同的算法集合,因此在一边可用的字符串在另一边就是语法错误。已安装的后端还可能按策略拒绝 IKEv1,那样任何提议都不会被接受。

项目的 README 记录了这些后端差异,并把阶段 1 与阶段 2 的字段分开处理。请把它当作结构文档来读,而不是当作开启所有历史加密算法和一个弱组的邀请,因为只能靠这种方式才连得上的连接,并不是被要求搭建的那个连接。

先就套件达成一致,再逐段验证

向网关运维方确认哪些 IKE 与 ESP 套件受支持并获得批准,然后把这一答复与客户端实际发出的提议比对,而不是与它的配置文件比对。如果分歧具体出在阶段 2 的 PFS 上,就选定一个受支持的组,或明确批准的「不使用 PFS」策略。不要从错误名称去推断策略。

当唯一的交集需要组织已不再接受的密码学时,决定权在网关或协议迁移这一层。把客户端字符串一路放宽到能协商为止,等于在交付一个已知弱点的同时,还在旁边打上绿色对勾。

修正真正的差异之后,先确认 IPsec 建立,再排查 L2TP 与 PPP,并把之后出现的任何认证拒绝都归到下一阶段。然后在批准的测试流程中演练续期,因为第一次关联建立成功,说明不了它余下的寿命。

相关文章