第一秒就退出的 VPN,与连上之后才失败的 VPN 完全是两回事,而常见的错误就是把它们当成同一类。这里没有握手,没有证书交换,也没有可检查的路由。日志里的一行就能决定几种互不相关的修复中哪一种适用,跳过它就要花一下午去改一份从未被读取的配置。先读那一行。

三条只读命令就能带你到那里:先用 journalctl -u openvpn@server -b --no-pager,再用 systemctl status openvpn@server,以及查看 UDP 监听者及其属主的 ss -lunp。

第一行决定分支

端口冲突和二进制缺失都会在一秒内终止启动,留下的第一行却不同。地址已被占用的消息会点出端口;可执行文件缺失会点出已不存在的路径;条件失败或配置文件缺失则会点出文件。这三者指向不同的修复,而重装客户端对哪一个都没有帮助。在运行任何其他命令之前,先把第一条失败抄进笔记。

留意会掩盖原始行的重试循环。带有 重启策略 的单元可能把首次失败埋在一打相同的行下面,所以按单元过滤、从头读起的 journalctl -b 胜过看末尾。

还有谁占着 1194 端口

罪魁祸首通常不是有人刻意配置的第二台服务器。意料之中的是另一个终端里仍活着的、手动启动的客户端,或是碰巧选了同一端口的第二个配置档,又或是自带隧道占着 1194 的厂商套件。套接字属主会出现在 ss -lunp 里;把那个 PID 交给 systemctl status,就能知道是不是某个单元在负责。要通过它自己的控制路径把它停掉,而不是发信号。

向由单元管理的进程发送信号通常会触发重启,同样的失败片刻后又会出现,看起来像新问题。对单元用 systemctl stop,对厂商安装用套件自带的服务命令,只有对自己在那个 shell 里手动启动的东西才用信号。

清除之后残留的单元

清除会删除二进制文件;手工写下的单元文件,通常位于 /etc/systemd/system 之下,却能幸存。随后 Systemd 会重试一个指向已不存在路径的单元,而消息说的是那个缺失的文件,不是昨天的卸载。systemctl status 会在顶部附近显示单元的片段路径,所以删除任何东西之前先用 dpkg -S 核对。孤儿消失后,systemctl daemon-reload 和 systemctl reset-failed 会清掉状态;否则之后每次状态检查都会继承它。

当 which openvpn 给出的结果在 /usr/local 之下时,正在起作用的二进制来自厂商安装器,而不是 apt。这类安装器通常自带监听者、自带启动项和自带配置目录,所以删掉看得见的命令,套接字依旧被占着。

按厂商文档的方式卸载它,用 ss -lunp 确认端口已空闲,只有在需要时才装上发行版客户端。

重试之前先把状态理清

在下结论之前先清掉失败状态:systemctl reset-failed 会移除计数器,之后 systemctl status 报告的是单元当前的状态,而不是它的历史。启动一次,然后读那一次实例自己的日志,而不是整台机器的汇总状态。隧道什么都没传送、单元却报告活动,这是另一个问题,而且常见得多。两者在缺陷报告里常被混为一谈,因为最后都以用户说 VPN 不工作了收尾。

记下你走的是哪条分支:端口冲突、二进制缺失、配置缺失。下次再遇到会认得更快。

相关文章