你把管理员消息里的预共享密钥粘贴到 NetworkManager 对话框里,勾上显示,密钥逐字符都对得上。连接仍然在隧道建立之前就以认证失败告终。第一次遇到时我以为是密钥错了;其实不是。真正决定守护进程读到什么的是另外两件事:插件为该连接写出的机密文件,以及这个值穿过对话框时有没有发生变化。

下面的排查路线让密钥从字段走到文件,正是这个顺序能告诉你它丢在了哪一步。请在失败的那台机器上做,而不是能用的那台,因为两台机器的差别通常是文件布局,而不是密钥。

从对话框开始,但不要相信字段

打开连接的 IPsec 选项卡,把密钥重新敲一遍而不是粘贴。从聊天消息、PDF 或密码管理器里复制的密钥,末尾可能带着字段不显示的换行,而屏幕上看到的字符依然正确。

点击显示密码的控件,看字符串的结尾而不是中间。如果光标在文本下方留出空行,把它删掉再重打最后一个字符。仅这一处修改就解决了这类报告里相当大的一部分,而且比读任何日志都省事。

如果密钥来自会折行的工单系统,请换一个不折行的渠道索取。不要用眼睛并排比对两串字符,而是和管理员核对长度;折行处丢掉的字符在比例字体里根本看不出来。

顺着密钥走进 /etc/ipsec.d

插件从不把 PSK 当作命令行参数交给 IPsec 守护进程。它会把值写进一个机密文件,并设法让守护进程把它包含进来;如果还没有 include 行,就在 /etc/ipsec.secrets 里补上一行。对话框里保存的只是生成该文件的输入,不是实际生效的值。

在改动任何东西之前,先列一下现有什么:

ipsec --version
sudo ls -l /etc/ipsec.d/*.secrets /etc/ipsec.d/ipsec.nm-l2tp.secrets 2>/dev/null
sudo grep -n "include" /etc/ipsec.secrets

更老的插件版本会为每个连接写一个文件,文件名取自连接的 UUID,例如 /etc/ipsec.d/nm-l2tp-ipsec-<uuid>.secrets。在面板里删除配置并不一定删掉那个文件。如果上一台服务器留下的旧文件还在磁盘上、还照样被包含,守护进程就可能选中一个你早已不用的配置里的机密,于是可见字段明明正确,连接却失败。

弄懂 1.2.12 的改动对升级做了什么

插件 1.2.12 把按连接分开的机密文件换成了一个共享文件 /etc/ipsec.d/ipsec.nm-l2tp.secrets。升级并不会清理更早的按 UUID 命名的文件,而已有的 include /etc/ipsec.d/*.secrets 行仍旧把它们包含进来。1.2.16 版本改动的是默认提议的处理方式,不是机密的布局。

这段历史解释了为什么两台看起来配置相同的机器表现不同。密钥是一样的,守护进程包含的文件集合却不一样。删除孤立文件时,先把它挪到一边而不是直接删掉,确认连接可用,记下可用状态之后再删除。改名保存的好处是:如果故障其实在别处,旧值还能找回来。

区分存储格式容纳不了的字符

strongSwan 关于共享机密字符串的文档指出,该值不能包含换行或双引号字符。从文档里粘贴来的密钥可能就带着其中之一,而在普通对话框里完全看不出差别。

自 1.2.12 起,保存的值已经不再等同于纯文本。插件会先把 PSK 做 base64 编码再写进文件,发行说明把这种编码列为双引号在密钥中变得可接受的原因。所以输入到字段里的引号是可以表示的;但并不是每个控制字符都如此。

长度是另一种约束。L2TP/IPsec 软件之间没有通行的最小长度:有的客户端接受短于二十个字符的密钥,有的网关则强制要求下限。如果短密钥被拒,那条规则属于服务器策略或该客户端的校验,在本地把什么调高都不会改变它。

判断是哪一层认证失败

先运行 ipsec --version,因为 strongSwan 与 Libreswan 使用的文件名和语法不同,针对其中一个的建议可能弄坏另一个。然后从客户端消息或守护进程日志里读出失败阶段:抱怨预共享密钥,和用户名密码被拒是两件不同的事。

PSK 认证的是隧道两端。L2TP 内部的身份则由用户名和密码认证,IPsec 关联建立之后交给 PPP 处理。PSK 正确但账号不对仍然会失败,而换账号也修不好一个守护进程从来没读对的密钥。

关闭工单时,把这四项都写下来:插件版本、正在使用的机密文件、密钥是重打还是粘贴的、以及报错里点名的那一层。这样以后有人重走这条路,就能直接跳到能用的机器和失败机器之间的差别上。

相关文章