在重装客户端之前,先记下三件事:隧道维持了多久、断开时客户端说了什么、这期间机器是否休眠或切换过网络。这份记录是你之后唯一能拿出的证据,而重装通常会把它抹掉。以可重复的间隔断开,说明是定时器或状态过期;在随机时刻断开,说明是路径问题。下面的顺序能避免你同时改动三处、最后什么也没学到。

第一步:记录间隔和错误原文

先看客户端自己的日志,而不是服务商的控制台。在 Linux 客户端上,服务日志加上隧道的实时状态就能覆盖大部分内容:

journalctl -u openvpn-client@client --since '3 hours ago' | tail -60
journalctl -u wg-quick@wg0 --since '3 hours ago' | tail -40
wg show
ip -s link show wg0

记录最后一次成功握手的时刻和流量停止的时刻,而不只是图标变色的那一刻。事后才提示断开的图形客户端,报告的可能是内核几秒前就已到达的状态。

保留错误的原文。超时、认证被拒、适配器或驱动报错指向三个不同的层次,而这个问题上大部分白费的功夫,都来自把它们当成同一类。把那一行原样抄进记录。

第二步:只改一个变量,不要改配置文件

保持设备和配置不变,把机器换到另一个接入网络,例如手机热点。这是把客户端和路径分开的最便宜的一次测试。要跑够时间,覆盖原来的故障间隔;两分钟稳定并不能说明三十分钟时的那次断开。

带网口的笔记本提供了第二种对比,可以彻底把 Wi-Fi 排除在外。如果两种接入下隧道都稳定,那么原来的接入网络就值得关注:接入点之间的漫游、翻译表过期的家用路由器,或者重置长连接的上游链路。

写下你改的是哪一个变量。只有其他一切保持不变,比较才成立,这包括服务器端点和一天中的时段。

第三步:把间隔对应到某一层

一次良好会话的时长,是你手上信息量最大的单个数字。在动定时器之前,先对照这份清单:

  • 休眠或恢复后断开: 隧道状态熬过了挂起,网络接口却没有。检查客户端在恢复时的重连行为,以及服务是重启隧道还是等待流量。
  • 只在空闲时断开: 中间有环节让流过期了。keepalive 正是为这种情况存在的。
  • 在固定的会话时长断开: 是重新认证或密钥轮换事件,而不是路径故障。日志在恰好那个间隔上出现明确的拒绝,就是线索。
  • 在大流量传输或大页面时断开: 应该怀疑 MTU 和分片,而不是空闲定时器。

空闲这一种情况,设置与协议相关,两端都要看。服务器端 OpenVPN 的 keepalive 10 60 每 10 秒发一次 ping,60 秒没有 ping 就重连;NAT 后面的 WireGuard 客户端在 peer 配置块里用 PersistentKeepalive = 25。OpenVPN 还会按定时器重新协商数据通道,即 reneg-sec,在 2.x 中默认是 3600 秒。

不要照抄其他服务商指南里的激进数值。在有丢包的移动链路上设很短的超时,恰恰会造成它本该避免的断开;而服务器下发的值会覆盖你在客户端配置里设的值。

第四步:只比较一个受支持的替代方案

如果服务商同时提供 UDP 和 TCP 配置,就用同一台设备、同一个网络去跑另一种。要用真正对应的文件,而不是在复制出来的配置里改传输方式。UDP 会被重置的路径上,TCP 配置稳定,只能把问题缩小到那条路径,并不能证明 TCP 在所有地方都更好。

同样的逻辑也适用于服务器端点。换一台服务器试,把原来的结果放在旁边。如果只有一个出口会重置会话,那是关于那个端点的证据,而不是把笔记本上每个适配器都重建一遍的理由。

任何切换之后,都要重复原来的触发条件,并确认流量实际去了哪里。恢复了上网,并不等于流量走在隧道里;而一个悄悄回落到直连路径的客户端,从浏览器看是正常的。

验证修复,并保留回退余地

修复要靠复现原来的触发条件来验证,而不是靠一次连接成功。让隧道空闲超过原来的故障间隔,挂起再恢复一次,然后检查握手的时长和出口地址:

wg show wg0 latest-handshakes
curl -m 5 -sS https://ifconfig.me
cp client.ovpn client.ovpn.bak   # before editing timers

在行为撑过一整个工作日之前,保留旧配置和旧的定时器取值。如果断开又回来了,先恢复备份,然后一次只改一处重新应用,让第二次尝试从已知状态出发。

如果日志一直干净,隧道仍以可重复的间隔断开,下一步就是那一会话的服务器侧。带上客户端的会话标识和确切的断开时间,因为正是这一对信息让服务器日志可被检索。协议的 link 选项记录在 OpenVPN 2.6 手册 里,需要某个取值的确切语义时可以查。

相关文章