OpenConnect 可以完成隧道握手,却仍然让你没有通往私网的路线,因为客户端和修改本地网络状态的辅助脚本是两个不同的程序。认证只能证明网关接受了会话,并不能证明之后装上了哪个接口、哪些路由或哪些解析器设置。大多数令人困惑的报告都来自用一个旧答案里的副本替换辅助脚本,这会改变机器上每条连接的行为。在改动它的任何一部分之前,先定位正在运行的客户端真正调用的那个辅助脚本。

两个程序,两种职责

客户端负责传输、认证和隧道设备。单独的辅助脚本负责隧道建立之后本地系统上发生的事:接口上的地址配置、通往网关公布的子网的路由,以及解析器配置。OpenConnect 辅助脚本的文档介绍了这种分工以及辅助脚本获得的环境。这个区分在故障时很重要,因为被拒绝的密码和缺失的路由不是同一个事件,即使桌面只用一个对话框来显示两者。

记住这个分工也能解释为什么连接会报告成功,而私有名称依然解析不了。两种情况下隧道都处于工作状态,不同的只是本地集成这一步。

定位正在运行的客户端所用的辅助脚本

路径在打包构建时确定,并且可以在每次调用时覆盖,所以你在另一个发行版里记住的文件可能跟这条连接毫无关系。要问正在运行的进程,而不是随手打开的那份文档。

openconnect --version
ps -o args= -C openconnect
dpkg -L openconnect | grep -i script
ls -l /etc/vpnc/ 2>/dev/null

如果进程命令行带有 --script 参数,那么该文件优先于编译时的默认值。像 /etc/vpnc/vpnc-script 这样的旧路径可能存在却根本没被使用,这就是为什么删掉或修改它对较新的构建毫无影响。也要看修改日期,一个多年没人碰过的辅助脚本,强烈说明真正干活的是软件包里的默认值。

NetworkManager 集成是第三个所有者,有自己的辅助脚本和自己的配置文件设置。在这一层之上再叠一个路由或解析器脚本,会让路由重复,并留下一个被两个程序都声称在管理的解析器。每条连接只选一个所有者,测试前把另一个关掉。

读第一个失败的操作,而不是最后一条警告

接口配置、路由安装、解析器选择和过期状态清理是彼此独立的步骤,而最后打印出来的警告往往是清理阶段的抱怨,不是真正断开连接的那个故障。向上读到第一个具体失败的操作。一个指出文件名或地址的辅助脚本错误,比十行拆除噪音更有价值。

把预期的本地结果和观察到的结果作比较:隧道设备存在,通往某个已知私有地址的路由经过它,解析器能回答一个私有名称。前两项成功、第三项失败的辅助脚本指向的是解析器策略,而不是路由。完全不配置设备的辅助脚本很可能从未被执行,那是权限问题而不是网络问题。在重写任何逻辑之前,先确认可执行位和服务账户。

验证连接、重连和断开

配置只是契约的一半,因为同一个辅助脚本必须在隧道关闭时恢复或移除它持有的状态。只添加路由却从不移除的辅助脚本,会给机器留下一条比会话活得更久的陈旧路径。

ip -brief address show tun0
ip route get 10.24.8.15
resolvectl status tun0
journalctl -u NetworkManager -b --no-pager | grep -i -E 'vpnc|script'

在连接状态下运行前三行,断开连接,然后再运行一遍,确认路由和解析器条目都已消失。第四行显示辅助脚本到底有没有被调用,以及服务用的是哪个可执行路径。把这两组输出记进工单,因为正是前后对比让清理缺陷变得一目了然。

让辅助脚本保持由软件包提供,并对服务账户可执行,因为 在受限的服务策略下,即使在你的 shell 里能跑的脚本也可能被拒绝。当确实需要定制时,把它的目的和所有者记录下来,并在每次升级时与打包版本作比较。来路不明的辅助脚本分支,是少数能让一条本来正常的连接在一年后失败的东西之一。

相关文章