VPN 路由缓存藏住了你的改动吗?检查三件事
Linux 没有可清空的全局路由缓存。过期的测试通常意味着过期套接字、NAT 记录或重新应用的配置文件。三项检查可以把它们区分开。
改动没有生效时,清空路由缓存是第一反应,而在现代 Linux 上这是白费力气:全局 IPv4 路由缓存多年前就被移除了,所以 ip route show cache 什么也不打印,也没有东西可清。骗过你的状态住在上一层:套接字、NAT 映射、解析器,或者重新应用了旧配置的网络管理器。三个问题把这类情况分开:错误路径来自新流量还是旧连接,你的平台到底缓存不缓存路由,以及状态在路由层还是在其之上。在重置接口之前先回答它们。
检查一:旧路径是否来自新流量?
已建立的连接会保留创建时的路由。因此,隧道上的 SSH 会话能挺过路由表变更,而新会话立刻走新路径;也正因如此,「改动什么都没做」常常意味着「旧套接字还攥着它」。用新进程去测,不要用已经开着的窗口。
ss -tnp | head
ip route get 1.1.1.1
curl -m 5 -sS -o /dev/null -w '%{remote_ip}
' https://example.com
最后一条命令打印新连接实际到达的地址,这是不信任状态窗口而看到真实路径的最便宜办法。把它与命名空间或接口本该使用的源地址作比较。
如果新流量走了正确路径、旧流量却没有恢复,就别再盯着路由了。路由是对的;会话是旧的。
检查二:你的平台到底缓存路由吗?
在 Linux 上答案是不,至少大多数指南所指的意义如此。没有可丢弃的全局目的缓存,而持有已选路由的套接字级条目会随套接字一起释放。ip-route 手册的缓存一节描述的是历史行为,不是当前内核上你能清掉的东西。
其他平台不同,而抄建议恰恰在这里出错。Windows 会保留目的缓存,你可以用 netsh interface ip delete destinationcache 清除。BSD 和 macOS 通过 route -n get 提供按目的地的查询,它们的缓存按自己的时间表过期。在这几个平台上有效的命令,在 Linux 上什么也不做,这就是同一套修复对一半尝试者显得失败的原因。
NAT 或 conntrack 表不是路由缓存,尽管它会产生同样的症状。在你改动之前被转换的流量会保留它的转换,conntrack -L 会在路由策略早已前进之后很久仍显示它。那是过期状态,但清理路由碰不到它。
检查三:状态在路由层,还是在其之上?
先读当前的查找结果,再读别的:对目的地址用 ip route get,再用 from 和源地址执行同一条命令,然后用 ip rule show。如果这三者与你本意一致,路由就不是要修的层,过期的观察来自别处。
三个常见嫌疑位于路由之上。网络管理器会在你删除路由几秒后从保存的配置里重新装回,于是你的改动看起来被回滚;再次编辑表之前,检查 nmcli connection show --active 和单元状态。解析器缓存返回旧地址,看起来像路由故障,直到你用绕开缓存的工具查询同一个名字。应用的连接池会对旧目的地保持可用套接字,从不向内核要新决定。
三个答案让你能得出什么结论
把答案放在一起,修法通常自己就说出来了。在没有路由缓存的平台上,新流量走了错路,说明策略真的错了,那就去读隧道安装的规则和表。新流量走对、旧会话卡住,说明问题在应用或套接字。两种情况都是路由正确而观察坏了,说明状态在路由之上。
别做那种一刀切的刷新。重启网络栈,或在一台默认路由就是隧道的机器上删掉所有路由,可能切断你正用来修复它的那条连接,还会毁掉本该告诉你哪一层出错的证据。
如果确实要清,就清与诊断相符的最小对象:一个进程的套接字、一条 conntrack 记录、解析器缓存。然后重做同一次新流量测试,并写下变了什么。
在笔记里把三种状态分开
保存的配置、当前的查找、观察到的流量是三个不同的事实,把它们揉成「缓存」正是让故障难以复现的原因。写下拥有该路由的配置或单元、ip route get 的输出,以及实际连接的源和目的。
在旁边记下平台和客户端版本,因为清除 Windows 目的缓存的修法并不适用于 Linux 主机,而两边互相抄的流程会教错东西。当你把问题交给别人时,这三行能让他复现故障状态,而不是靠猜。