路由器的穿透开关是对其后面设备的转发让步,而不是 VPN 服务。它不会把路由器注册成客户端,不会保存凭据,也不会把家里每台设备都推到远端出口。它做的是塑造一个协议如何穿过地址转换和过滤规则。弄清这一点后,开关既容易测试,也容易一直关着。

路由器到底在做什么

路由器位于客户端和 IPsec 对端之间,转发它从未被设计去理解的报文。厂商至少用三种方式实现该功能:跟踪或改写状态的协议助手、停止丢弃 ESP 的过滤例外,或面向旧客户端的兼容模式。网页界面上的标签很少说明你属于哪一种。只有固件说明或抓包才能告诉你。

助手也可能把情况弄得更糟。为旧流程编写的辅助逻辑,有时会干扰已经正确处理地址转换的客户端。当新客户端在关闭该选项时工作正常,保持关闭才是更好的配置。

穿透从不把对端的密钥交给路由器。路由器仍然能看到外层地址和端口,也仍然对它们施加自己的转发策略。

NAT 和 NAT-T 决定路径

IPsec 并非为跨越地址转换而设计,所以标准增加了一层封装。NAT 穿透把 ESP 封在 UDP 里,让普通的 NAT 表也能承载这条流,协商则在 IKE 期间就这一转换达成一致(RFC 3948)。IKE 本身使用 UDP 500,而封装后的路径通常使用 UDP 4500。

这就是为什么只允许协议 50 的防火墙规则在转换路径上不够用。封掉 4500 会破坏封装存在的那个场景,封掉 500 则会在任何隧道形成之前就中止协商。两个方向都重要,因为有状态的路由器通常要看到请求之后才放行应答。能到达端口不等于完成认证,也不等于转发受保护流量。

旧方案的差别足够大,为它们写的指南可能误导人。当客户端同时提供两种模式时,测对端有文档记录的那种,而不是搜索结果更多的那种。

找出失败的那一段

把问题分成协商、认证、子连接保护和内部转发,然后一次收集一个阶段的证据。一次重启若只是暂时改变结果,只能证明有某种状态参与其中。

sudo tcpdump -ni any 'udp port 500 or udp port 4500'
ip xfrm state list
ip xfrm policy list

抓包显示交换是否到达对端、应答是否返回,从而把过滤问题和凭据问题分开。状态列表显示已建立的安全关联,所以尝试后列表为空指向协商而非路由。策略列表显示装了哪些选择器,目的地址落在子网之外正是在那里被排除。碰路由器之前先读两份 xfrm 输出,因为它们描述的是主机的认知,而不是路由器允许什么。

如果报文出去了却什么都没回来,就把抓包挪到路由器的 WAN 侧。对比两份抓包,不用猜也能定位丢在哪。

关掉你不需要的东西

一台笔记本能用,并不证明路由器能同时处理多个客户端。每个客户端都会建立自己的转换状态和自己的协商,有些助手只跟踪一条流。用你实际使用的网络,去测你实际需要的并发会话数。若第二个客户端失败而第一个正常,那才是结论,而不是时好时坏的隧道。

只有抓包证明需要时才让选项保持开启。把固件版本记在结果旁边,因为这些行为会随版本变化。目标是经过你验证的客户端隧道,而不是抱着希望打开的开关。

相关文章