租约续租与 VPN 故障在日志里一起出现得太频繁,以至于人们断定其中之一导致了另一个。时间上的重合是真的;因果关系通常不是。续租是发往发放租约的服务器的单播请求,请求继续使用同一绑定,服务器可以在客户端一个地址都不变的情况下延长它。围绕事件检查客户端自身的取值,就能把安静续租的租约和在运行中的隧道下方真正发生变化的网络区分开来。

从掉线的客户端开始

先打开客户端的连接日志,把掉线时间记录到秒。然后打开同一分钟的操作系统网络日志,按顺序读接口做了什么。这个顺序就是全部调查:断开之前的 DHCP 事件、DHCP 事件之前的断开,以及两者之间空无一事的两次事件,是三种不同的发现。在隧道已经在重连时只提到租约的那行日志是装饰,不是证据。

边排查边写下时间线,不要只记在脑子里。不同工具的时间戳很少完全对齐,而这种偏差有时本身就是解释。

对比事件周围的四个值

四个值足以描述连接的本地一侧,从而抓住真实的变化:接口地址、默认网关、解析器列表和接口的运行状态。在掉线后一分钟内采集,并与隧道健康时采集的快照对比。

ip -4 -brief addr show dev wlan0
ip -4 route show default
resolvectl status | grep -A3 'DNS Servers'
journalctl -u NetworkManager --since -10m --no-pager | grep -i dhcp

地址不变、网关不变而解析器列表变化,指向名称解析而不是路由,隧道可能幸存下来,而应用却找不到主机。网关变化意味着离开本地网络的路径发生了移动,这足以让指向旧网关的路由失效。如果四个值都与健康快照一致,租约就不是你的原因,客户端自身的重连逻辑便成为主题。要在故障可见时采集对比,因为重启后采集的健康快照地址历史不同,不会吻合。

续租能改变什么,不能改变什么

RFC 2131 把续租描述为在租期一半时向原服务器发出的请求,若首次尝试无人应答,则在八分之七时向任意服务器重新绑定。两个步骤都不要求客户端获得不同的地址,配合的服务器通常会延长现有绑定。真正的地址变化通常来自另一条路径:服务器拒绝续租、客户端丢失状态重新开始,或者网络把设备移到了另一个网段。

连接的公开一侧可以完全没有本地变化就发生改变。在运营商级转换之后,VPN 对端看到的地址可能与本地租约无关地被重新分配,而这种重新分配从客户端内部看与本地网络故障一模一样。把本地报告的地址与对端一侧的观测相比,是区分二者的唯一办法。

当客户端无法适应时

把传输绑定到旧地址、缓存了指向对端的过期路由,或保存了接口标识的客户端,可能一直在重试一条已不存在的路径。这是适应性缺陷,表现为向主机已无法到达的地址反复重传。有些客户端在设计上就处理了这一点:例如 WireGuard 在收到来自新来源且认证正确的数据包时,会更新对端的端点。

手动重启恢复了服务,是适应性失败位置的线索,而不是租约与隧道不兼容的证明。测试期间要保留阻断策略,否则测试本身就变成另一起原因不同的故障。记录客户端是否自行恢复、花了多久、重试了哪个地址;这串顺序比接口上显示的断开原因更有信息量。

在归咎之前先复现事件

与其等排期,不如复现条件:释放并续租,或强制触发等价的可控事件,观察隧道是否幸存。在受管网络中,任何地址变更都要与网络所有者协调,因为随意的静态分配可能与已经持有该地址的设备冲突。

在受支持的修复之后,重复同一事件,然后测试应用和名称解析,因为能重连却破坏 DNS 的隧道通过的是比真正重要的测试更弱的测试。报告你观察到的具体变化及其时间戳,而不是把计划中的租约定为原因。这两份报告的区别在于下一个人能否复现故障,还是只能复现传闻。

相关文章