连接卡住,客户端退出,屏幕上最后一行是 death_handler: Fatal signal 15 received。这一行报告的是中断,而不是原因。在 IPsec 日志里,往上一行几乎总会有 NO_PROPOSAL_CHOSEN,这一对消息指向交换的第 2 阶段:双方在该阶段比较加密与哈希选项,一旦没有任何共同项就停下来。此时登录凭据还没有发送,所以重输密码不可能改变结果。

在 Linux 客户端上,通常是两件事掏空了这个交集。本地守护进程可能不再实现配置文件所要求的 Diffie-Hellman 组,或者配置文件把第 1 阶段的提案放进了第 2 阶段的字段。两者都会在日志里留下痕迹,而且都不是账号问题。

这两条消息究竟在说什么

IKE 分轮次协商。第 1 阶段建立受保护的通道并选定自己的算法;第 2 阶段即子 SA,用另一套参数承载流量。NO_PROPOSAL_CHOSEN 是响应方在所有被提议的组合都不可接受时返回的通知,它在 INFORMATIONAL 交换中以 [ HASH N(NO_PROP) ] 的形式出现。

信号 15 是另一回事:有东西让本地进程停止,处理程序把它记录了下来。两行同时出现时,顺序是因果的:先拒绝,后关停。

在动登录凭据之前先读协商过程

在守护进程写日志的位置提高日志级别,然后一边观察输出一边重连。在 NetworkManager 主机上,L2TP 插件会把该级别传给后端,消息按发行版落到 journal 或传统 syslog 文件里。下面任一命令都能显示这次交换:journalctl -f -u NetworkManager | grep -Ei 'pluto|charon|no_prop|proposal' 或 tail -f /var/log/syslog | grep -Ei 'pluto|charon|ike'。

提到 pluto 的行来自 libreswan,提到 charon 的来自 strongSwan,两者用不同措辞描述同一状态。值得找的是那种点名缺失组的写法,例如 algorithm 'modp1024' is not supported,因为它把含糊的失败变成了具体的失败。

modp1024 去了哪里

Diffie-Hellman 第 2 组弱到让若干发行版从 3.30 起不再把它编译进 libreswan。于是多年前写好的、或从只列 aes128-sha1-modp1024 的网关指南里抄来的配置文件,会向本地守护进程要求它根本做不到的事。较新的 NetworkManager-l2tp 构建让这种结局更可能发生:从 1.2.16 起,它们用 Windows 10 与 iOS 风格的提案替换整套参数,并在检测到 libreswan 后丢掉 modp1024。对端往往是无辜的,它仍然提供的正是你配置的那个组。

正是这种不对称让故障显得随机。旧客户端能连上,同一份配置在新笔记本上连不上,而服务端配置从未动过。造成破坏的是版本漂移。

两种影响范围不同的修复

便宜的修复是停止硬写算法。清空编辑器里的两个提案字段,让插件挑选对端能接受的组合;如果网关支持现代组,协商无需额外工作就能完成。

第二种修复通过安装 strongSwan 让旧网关继续可用,它的软件包在多数发行版里仍实现第 2 组。这是更换守护进程,所以有代价:删除前先确认主机上其他隧道是否依赖 libreswan 配置,并预料到 Fedora 上 NetworkManager 与 strongSwan 插件之间出现 SELinux 拒绝。那些拒绝出现在审计日志而不是 IKE 跟踪里,因此安装刚成功时隧道也可能看起来是坏的。有效的顺序是先装 dnf install strongswan,再卸 rpm -e libreswan。

能对上的提案字符串,以及它们周围的陷阱

当字段必须手工填写时,第 1 阶段和第 2 阶段取不同的值。一对已知对 Meraki 风格对端可用的组合,在第 1 阶段提供 aes128-sha1-modp1024,其后是 3des-sha1-modp1024,两者都用感叹号收尾以让集合严格,因此只会发送这些提案。

第 2 阶段随后收窄到 aes128-sha1 与 3des-sha1,同样带严格标记,且完全不加 Diffie-Hellman 后缀。第 2 阶段的行里带 -modp1024,就是第 1 阶段的值放错了字段,响应方每次重试都会拒绝它。把这一行复制到第二份配置里,第二份配置也会同样失败,一次手误就这样变成整批事故。

其他故障戴着同一个弹窗,却并不是提案不匹配。在 KDE 上,即使装好了插件,L2TP 类型仍可能被列出,但每个连接都会立刻断掉,因为连接编辑器和运行时辅助程序是分开打包的。无头主机可以复用可用桌面上的配置:从 /etc/NetworkManager/system-connections/ 复制,把权限设为 600,然后运行 nmcli con reload。用 nmcli con up id work-l2tp 把它拉起来,因为裸写需要 UUID,并删掉任何过时的 ifname 项,否则在其他一切都正确时管理器会回一句 Could not find source connection。

预共享密钥可以存成明文,也可以存成 0s 加 base64;两种形式都能用,但值必须与网关逐字节一致,包括你一起复制进来的行尾空白。

相关文章