睡眠后 VPN 失效:隧道掉了,还是应用过期了?
Wi-Fi 恢复不代表隧道恢复。唤醒后对比三种状态:接口、激活与应用的会话。
盖子打开,无线图标回来了,VPN 却仍显示已连接。第一个内网页面随即卡到超时,新开的标签页也一样。有三种不同的东西能造成这个现象,也需要三种不同的处理:隧道没熬过睡眠、没有任何机制要求重新激活配置,或者应用还攥着几小时前就已死掉的会话。把它们区分清楚,比重新安装任何东西都快。
唤醒后可能坏掉的是三样东西
第一个候选是隧道本身。接口可能还带着地址,而与对端的关联已经消失,所以指示灯并不能证明链路可用。比睡眠时间更早的握手就是线索,一条命令就能看到。
第二个是激活。很多客户端会自己重连;有些不会,而没有被要求恢复的配置就那样放着,看起来像是配好了。这种失败在设计上就是静默的,因为没有任何环节报错。
第三个是应用。浏览器标签、SSH 会话或数据库连接可以作为一个文件描述符熬过网络变化,而它下面的传输早已死去。于是一个新会话完全正常,这恰恰说明隧道一直都是好的。
改动任何设置之前先对比这三者,因为它们的修复方法并不重叠。重启一个从未被要求重启的客户端,只会浪费你需要的证据。在碰配置之前,先写下症状符合哪一个候选。这一句话通常就决定了剩下的排查方向。
第一:隧道回来了吗
看接口和对端状态,而不是客户端自己的状态文字。有地址却没有近期握手的接口,只是名义上存在的隧道。
ip -brief addr show wg show ip route show table all | head -20
如果接口完全不见,隧道没有存活,问题就变成本该由谁把它带回来。如果接口在但握手很旧,就需要重建与对端的关联,客户端可能在等流量来触发。
也要检查路由和 DNS 配置。隧道可以没有路由地回来,这会造成接口是通的、内部域名却仍由错误服务器解析的混乱状态。
第二:有东西要求它回来吗
比较的价值正在这里体现。NetworkManager 对 OpenVPN 插件配置和原生 WireGuard 连接的处理并不相同,而 连接设置参考 明确写出 connection.autoconnect 不会激活 VPN 配置;随连接一起拉起 VPN 的机制是 connection.secondaries。
nmcli connection show --active nmcli -f connection.autoconnect,connection.secondaries connection show "Work VPN" journalctl -u NetworkManager -b --no-pager | tail -40
如果每次手动重连都能修好,那就是缺少激活的签名,而不是隧道坏了。日志通常会显示接口掉下去,却没有任何东西把它带回来。
不要急着加睡眠钩子。在网络恢复之前就触发的钩子,会和它想帮忙的那个进程抢时间,把一个可复现的问题变成偶发问题。
第三:应用是不是握着旧状态
在碰 VPN 之前,先向同一目标开一个全新的会话。如果新会话能用而旧会话不能,隧道就是好的,是应用握着一条死连接。
这是三项检查里最便宜、也最常被跳过的一项,因为出问题的窗口就在屏幕上。关掉它,再打开,记下问题是否还在。如果新会话能用,就彻底停止对隧道的排查。如果新会话也失败,应用是症状而不是原因。
有些应用在超时后会自己恢复,所以症状可能看起来过了几分钟就自愈了。这种行为指向应用而不是隧道,值得单独记录。同事说它自己好了,描述的正是这种模式,而不是运气。
让对比可复现
把变量控制到最小:同一个接入网络、同一个睡眠时长、每次都是同一个首个请求。然后记录两个结果:手动重连能否修好,以及再睡一次是否会让故障重现。
最后这个观察最能可靠地区分三种候选。旧会话失败后新会话能用,就不是隧道问题,重装客户端也不会改变这一点。
WireGuard 的持久 keepalive 在这幅图里只应被当作 NAT 映射保活。它发送数据包以保持映射打开,并不能阻止机器入睡,也无法在进程被挂起时继续发送。
把发现写进工单:三者中哪一个坏了、是什么修好了它、你如何复现。下周一打开盖子的人会感谢你,答案也不必从零再发现一次。