你创建了访客网络,为它添加了路由,但访客仍然从你普通的互联网连接出去。隧道是通的,主 LAN 正常工作,访客设备报告的地址也在你分配的范围内,所以看起来什么都没坏。通常缺的不是路由,而是一个选择器:路由器在考虑数据包从哪个接口进来之前就决定了路径,除非有东西明确匹配访客流量,否则该流量会继承默认值。修复方法依次是网段、策略规则和返回路径。

症状:访客仍然从 WAN 出去

线索是出口地址。通过隧道上网的访客设备会报告隧道提供商的地址,而继承默认路径的设备会报告你正常的连接。把访客设备和主 LAN 设备并排比较,因为有趣的情况是它们与你配置的不同、却彼此一致。

第二个线索是访客浏览时隧道接口上没有任何流量。如果计数器不动,说明策略从未生效,调整隧道本身也无济于事。

第 1 步:真正的网段,而不只是名字

SSID 名称不会创造隔离。检查访客网络是否终止在自己的接口、VLAN 或网桥上,以及地址范围是否与可信 LAN 不同。在许多家用接入点上,访客 SSID 被桥接进与其它一切相同的网段,若不纠正,后续工作都无法进行。

然后确认访客范围和它的 DHCP 服务器,并把解析器设置绑定到该网段,而不是整个路由器。只作为防火墙规则注释存在的访客子网不是网段,路由器也没有接口可以匹配。

不要为了便于配置 VPN 就把访客桥接进主 LAN。那是用路由捷径换掉你想要的隔离,也是访客网络最终能访问打印机和 NAS 的常见原因。

第 2 步:按源地址选择隧道

路由表按目的地址选择,所以「把 0.0.0.0/0 送到隧道」这条规则对所有人都生效。策略路由增加了第二个维度:按源地址选择路由表。在基于 Linux 的路由器上,这需要一条额外规则和一张专用表,顺序很重要,因为第一条匹配的规则获胜:

ip rule add from 192.168.60.0/24 lookup 100 priority 1000
ip route add default dev wg0 table 100
ip route get 1.1.1.1 from 192.168.60.10

最后那条命令直接回答了问题:这个源到这个目的会用哪个接口。在改动前后各运行一次,不碰浏览器就能知道策略是否生效。

大多数路由器固件把同样的事表达为接口规则或基于源的网关选择。无论你的平台使用什么语法,原理都一样:匹配入接口或源前缀,然后只对该匹配覆盖路由。按目的地址匹配的规则无法区分访客和家用设备。

第 3 步:返回路径与地址转换

从隧道出去的包必须回来。要么隧道对端知道回访客前缀的路由,要么路由器把访客源转换成隧道地址。选一种并写下来,因为故障表现不同:缺少返回路由时连接能建立但永远没有回应,而缺少转换时往往什么都不会产生。

nft add rule ip nat POSTROUTING ip saddr 192.168.60.0/24 oifname "wg0" masquerade

如果选择转换,请记住对端现在对所有访客只看到一个地址,因此远端的按客户端策略就没了。如果保留地址,两端都需要在路由和策略中包含访客前缀,工作量更大但更可预测。

IPv6 需要自己的规则。为 IPv4 写的策略不覆盖另一个协议族,而启用了 IPv6 的访客设备会欣然使用它,你精心路由的 IPv4 路径却闲置着。要么为两个协议族都做路由,要么在访客网段禁用 IPv6,但不要假设你写的合并规则覆盖了设备的实际行为。用同时启用两个协议族的客户端测试,因为设计必须经受住这种情况。偏好 IPv6 的笔记本电脑在纯 IPv4 测试中看起来正常,在真实环境里却会泄漏。

测试隔离,而不只是浏览

浏览证明出口变了。它不能证明网段被隔离,而隔离正是访客网络存在的理由。从访客设备尝试访问路由器的管理界面、可信 LAN 中的主机和应当被拒绝的服务;三样都应该失败,而且失败应当是策略决定,而不是没人能解释的超时。

然后测试主 LAN 设备,确认它的出口没有改变。这是该设计最常造成的回归:一条为访客准备的宽泛规则,因为匹配写在目的地址上,被应用到了每个接口。

最后,决定隧道断开时会发生什么。访客要么没有网络,要么回退到你批准的道路,而放着不决定就意味着静默回退到普通连接,那正是访客策略想要防止的泄漏。互联网流量路由指南针对基于 pfSense 的路由器走了一遍相同的路径选择。

由路由器发起的 DNS 是最后让人意外的情形。如果访客把路由器当作解析器,路由器自己的查询会走路由器的路由而不是访客规则,于是应用流量没出去,查询却可能从普通连接出去。把网段、解析器和故障策略记在一条笔记里,下一个人不用重新推导设计就能检查这三样。

相关文章