如何让一个测试 LAN 拥有自己的 WireGuard 出口
用专用路由表和不可达守卫把一个 LAN 限定到 WireGuard 出口,同时网关保留其正常的 WAN 默认路由。
三种设计解决同一个实验问题:一个小型 LAN 必须经由 WireGuard 对端出网,而网关自身保留平常的上行链路。诱人的捷径是把路由器的默认路由搬进隧道,但这会破坏机器自身的管理通道以及它转发的其他一切。更有意思的选项是只作用于一个接口和一个前缀的策略路由。回答关于你实际拥有的机器的三个问题,在两者之间做出选择。
先决定出口放在哪里
第一个问题:这台主机还为别的什么做转发吗?专用实验网关可以承受默认丢弃的转发策略。承担生产职责的路由器不行,而在受管防火墙之上再叠一套相互竞争规则,正是把故障排进日程的做法。第二:你能否拥有两个策略对象及其跨重启的顺序?第三:你手上的对端是否授权你的隧道源地址并提供互联网出口?只暴露一个私有网络的对端是另一种产品,任何本地路由改动都修不好。只要有一个答案是否,就把出口放进命名空间或一次性虚拟机。
命名空间或虚拟机消耗内存,却给你干净的爆炸半径。策略路由只消耗两条规则,只留给你一台机器去调试。
选择那个授权你源地址的出口
这个实验里大多数失败发生在一条防火墙规则都还不存在的时候。出口运营方必须接受你数据包在转换之后携带的源地址,而在本设计里那是隧道地址,不是 LAN 前缀。所以伪装必须从设计之初就存在,而不是后来补上。
向运营方确认三件事:对端授权你的隧道地址,对端转发 IPv4 而不是在自己这里终结,并且它执行出口 NAT。缺第一项,你的包到达后就消失。缺第三项,它们带着私有源地址离开,在下一跳死掉。然后检查 wg-quick 没有安装自己的默认路由,这正是 Table = off 所阻止的;该设置抑制的是路由创建,不是对端的 AllowedIPs 检查或它的 DNS 处理。
两个策略对象负责牵引
牵引需要一张表和一条规则。表里放两条路由:从 LAN 接口出去的 LAN 前缀,以及从隧道出去的默认路由。规则把从 LAN 接口进入并带有该前缀的流量送进表里。把 iif 选择器与源匹配一起使用,因为网关自己的 WireGuard 数据包在本地产生,永远不会匹配进入接口。
守卫在查找之前,而不是之后。这个顺序就是本设计的全部安全属性。
守卫是同一条选择器上的第二条规则,判定为 unreachable。给它更高的数字优先级,让隧道在线时查找仍然胜出。当隧道路由消失时,查找什么都不返回,守卫终止搜索,而不是让它落到主表里的 WAN 默认路由。
ip rule add from 192.168.50.0/24 iif lan0 lookup 51861 pref 1000
ip rule add from 192.168.50.0/24 iif lan0 unreachable pref 1001
ip route add table 51861 default dev wg0
先堵住回退的缝隙,再打开它
先装守卫,再装查找。反过来会留下一段数秒的窗口,测试客户端的流量可能在这段时间里到达上行链路。
过滤器补全整幅图。在 forward 钩子里接受测试前缀从 LAN 到隧道的方向以及已建立的返回方向,然后丢弃其余一切;该前缀到隧道接口的 NAT 放在 postrouting 里。正是把 policy drop 留在转发链上,才让缺失的路由变成沉默而不是泄漏。反向路径过滤需要在隧道接口上使用宽松模式,因为解封装后到达的公网源地址,其最优反向路由在 WAN 一侧。Linux 取 all 与按接口值中较高的那个,所以设置隧道接口并不等于在全局削弱校验。
用故障情形来证明它
向内核提出精确的问题:点名客户端的源地址和它到达的接口。两者缺一的查找回答的是另一个问题,两种情况看起来都正确。然后看防火墙计数器、对端的传输状态以及客户端自己的服务。
正确地测试拆除。停掉隧道而保留规则和过滤器:客户端应当卡住,网关自身的流量应当继续工作。然后在不碰本地接口的情况下停掉对端,这才是抓住那些只依赖路由存在的设计的场景。最后重启并复查规则顺序,因为移除守卫的拆除钩子会把整个设计交还给主表。把表号、优先级和接口名写进变更工单,因为下一个加规则的人就是会破坏它的人。