上周还能用的 VPN 配置在 Ubuntu 发行版升级后失效,而日志几乎不提升级这件事。它点名的是失败的那一层:TLS 握手、为数据通道协商的加密算法、被安装的软件包,或程序启动时加载的 OpenSSL 副本。每一层都有自己的报错形态和修法,所以先分类、再改配置。在日志点名之前,不要假定配置有错。

哪一层失败:握手、加密算法、软件包还是库

先读客户端日志,再动配置。输出里最早出现的错误才是定位那一层的依据;后面打印的内容通常都是这次失败的连带结果。如果客户端根本起不来,该看的是 VPN 日志之外的另一个文件。

证书与签名方面的报错,或关于密钥长度的提示,来自控制通道以及管辖它的库策略。以 DEPRECATED OPTION 开头的警告,则属于数据通道的协商。

形如 Unrecognized option 的行属于第三类:新程序不再接受旧程序容忍过的指令,所以要重写配置,而不是放宽库策略。打包类失败又是另一副样子,因为它发生在任何隧道代码运行之前。缺程序、插件加载不了、仓库指向了错误的代号,都会造成这种形态。四种症状、四个排查位置,修法之间几乎没有重叠。

握手失败时,是 TLS 策略在拒绝证书

Ubuntu 22.04 把系统换到 OpenSSL 3,该分支的默认安全级别对证书签名和密钥长度比 20.04 更严格。用较旧摘要签发的 CA 证书,或低于当前阈值的密钥,现在会在握手阶段失败。由于还没通过任何认证,这个错误读起来像密码错误或服务器已死。

范围最小的修法是把加密串只挂到这一条连接上。在桌面编辑器里打开配置,进入高级设置,把 DEFAULT:@SECLEVEL=0 填进 TLS 加密字段。NetworkManager 的 keyfile 在 [vpn] 一节里取同样的值:

[vpn]
tls-cipher=DEFAULT:@SECLEVEL=0

重启 NetworkManager 再重连,因为守护进程会缓存解析过的配置,否则会继续用手里那份。保留之前先弄懂这一行:它是对若干证书与密钥参数的阈值,不是某个加密算法名,调低等于放宽单份配置的接受范围。记下是哪个服务器要求的,等运营方重发合规材料后再去掉。改 /etc/ssl/openssl.cnf 则会把这个阈值施加到所有读取该文件的程序上,远超 VPN 本身。

OpenVPN 2.6 要求把加密算法列入协商

Ubuntu 22.10 带来了 OpenVPN 2.6,在这个版本里 --cipher 不再单独决定数据通道的加密。它还必须出现在协商用的 data-ciphers 列表中,否则客户端会打印弃用警告,随后无法建起隧道。

同一时期的 NetworkManager 插件仍然只写旧指令。这个细节把诊断劈成两半:手工改好的配置能从 shell 连上,却仍可能从桌面小程序失败。把列表加到连接文件的 [vpn] 一节:

data-ciphers=AES-256-CBC

用服务器实际通告的值,而不是你记忆中的值;推送 AES-256-GCM 的服务器不会与只列 CBC 的客户端协商。重启管理器并重连,然后从 shell 复现一次,把加密算法同时显式用于协商与回退:

sudo openvpn --config client.ovpn --data-ciphers AES-256-CBC --data-ciphers-fallback AES-256-CBC

如果这条命令能建起隧道,说明服务器、证书与凭据都没问题,剩下的唯一故障就是管理器保存的那项设置。关于 keysize 指令的警告属于同一轮清理:注释掉它,并把原文件留在配置旁边。

软件包与插件故障看起来像 VPN 故障

升级后的失败并非都出在密码学上。在发行版不使用的代号下添加 OpenVPN 仓库,会得到永远装不上的包,所以拿 lsb_release -a 的报告去核对添加过的列表文件。缺少 universe 组件或安全源,会得到根本找不到的包。两种情况都不碰配置,隧道也无从谈起。

先读包管理器的报错,再看 VPN 日志。客户端根本没装上时,改多少配置都不会有握手。

两因素配置不再询问,是同一故事在插件上的版本。质询来自认证插件,升级把它丢掉或换掉后,配置完好,提示却消失了。重新安装受支持的插件,而不是为了连上就删掉第二因素。

厂商库可能藏在策略报错背后

有一种模式值得记住,因为它能击穿所有策略修法。硬件厂商的配置工具会安装自己的 OpenSSL 库,并在加载器搜索路径里把它们排在系统副本之前。于是客户端对着没人升级过的库启动,启动失败看起来和证书被拒一模一样。

重装 VPN 包不会改变先找到哪一个库,降低 TLS 级别也触不到并非来自系统的那份库。问加载器:程序真正解析的是哪些加密对象:

ldd /usr/sbin/openvpn | grep -i -E 'ssl|crypto'

删除或重指厂商副本,然后重跑同一项检查。回配置之前,必须让预期版本处于使用中。

钉住旧客户端只是买时间,不是解决

留住上一版客户端,只要保留期还在,隧道就能恢复。它同时冻结了该包的安全更新,并把同样的故障排到下次升级,所以这是一份带日期的绕行方案,而非解决方法。

若仍要钉住,就显式 hold 住该包,免得无人值守升级把钉住撤销;写下原因与复查日期,并为厂商下一次发布配置设提醒。真正值得盯的条件是:有服务器配置开始协商当前算法;一旦出现,钉住就没有任何理由了。反过来,没有记录的钉住会在半年后变成没人解释得清的故障,因为当时动手的人已经离开,文件里什么都没留下。

下次 VPN 又死在发行版升级后,按顺序问五个问题:哪一层先报错、TLS 策略是否拒绝证书、加密算法能否双向协商、包与插件是否真的装上、进程加载的是哪个库。五问全部干净,再谈降级。

相关文章