为什么 VPN 明明能用,回程却仍然超时
请求抵达私有服务器只是交互的一半。它的应答必须经由预期的网关、路由或地址转换找回隧道客户端。
请求到了,服务器也记录了,客户端却仍然报告超时。这种组合说明 应答没有找到回程的路,而这正是少数能同时从两端确认的故障之一。请按顺序逐项检查,任何一项失败就停下来。
先从请求抵达的位置查起
在检查其他任何东西之前,先确认数据包确实到达了服务。服务器侧的日志记录、连接计数,或远端允许的抓包,回答的都是同一个问题;如果这些都没有,就该退回隧道,而不是继续往应答方向走。这就是把转发问题与回程路径问题区分开的检查。
如果请求从未抵达,就停在这里。此时主题是隧道、通往私有前缀的路由或访问规则,回程路径还无关紧要。同时记下服务器看到的源地址。它要么是分配给客户端的地址池地址,要么是转换后的地址,这个差别决定了后面哪几项检查适用。
应答需要一条通往地址池的路由
远程访问客户端通常从地址池获得地址,而私有网络需要一条回到那个地址池的路由。默认路由指向自身网关的服务器,会把数据包交给那个网关,而该网关根本不知道地址池在哪里,应答就在那里消失。客户端看到超时,是因为什么都没回来,这与一个从未发出的请求无法区分。
要检查服务器为客户地址选择的路由,而不是它为自身子网使用的路由。这两次查表可能给出不同结果,这里要紧的是前者。地址转换是另一种设计,它改变了服务器能看到的内容。它可以简化回程路径,同时也会把原始客户端地址从服务器日志里抹掉,从而影响任何以该字段为基础的规则或报表。
把服务器侧抓包与网关侧抓包对照
对照离开服务器的内容与抵达网关的内容。服务器出口接口上的抓包和隧道网关上的抓包,回答的是同一个问题的两半,两者之间的差额就定位了丢包发生的位置。
ip route get 10.90.0.14
tcpdump -ni any host 10.90.0.14 and port 443
ip route show table all | grep 10.90.0.0| Where the reply stops | What it proves |
|---|---|
| Request in the server log, nothing on its outbound capture | The server picked a gateway that cannot reach the pool |
| Reply leaves the server but never shows up at the gateway | Loss on the LAN path, not on the tunnel |
| Reply reaches the gateway but not the client | Return translation or tunnel policy, not the server route |
由网关自己生成的请求,不能代替从客户端发起的测试,因为它来自不同地址、会遇到不同规则。这正是一个从网关发出的 ping 成功、而从客户端发出的请求失败,却能同时成立的原因。
路径上有多台路由器时,每一台需要通往地址池路由的设备都要查。站点到站点的设计往往要求在不止一台设备上认识远端前缀,而网关本身必须在隧道与本地网络之间转发; strongSwan 的转发说明 涵盖了其中的 sysctl 与防火墙部分。
记录地址池、前缀与责任人
记录里应包含四项事实:客户端拿到的地址池、它需要的私有前缀、对回程负责的路由器,以及存在时的地址转换规则。有了这些,日后更换网关就是一次对照,而不是一次排查。
然后用普通客户端和真实应用账户复测。扩大应用权限修不好数据包的回程,而在这次排查中途改动账户,只会让下一次对照更混乱。如果设计依赖地址转换,就在别人读服务器日志的地方把它写清楚。在审计记录里看到陌生源地址的人,不应该还要靠工单去重新发现这层映射关系。