多路由器 Pi VPN:把每条路由放在做决定的设备上
下游路由器增加第二个客户端子网,四台设备各自持有一个决定。放好路由,检查来源,再从真实客户端测试。
把 Wi-Fi 盒子放在 Pi 后面,会把一个路由决定变成四个,而四个都在同一台设备上做时,计划就会崩。首先要问的不是加哪条路由。而是新盒子做桥接还是路由,因为这个答案决定有多少个子网、哪些设备必须了解它们。先选连接模型;每条路由都由它推出。
桥接还是路由:决定数量的选择
桥接把新客户端放在 Pi 已经服务的同一个子网里。一个子网、一个 DHCP 权威,没有要路由的交接。这是更简单的安排,在独立客户端网络从来不是需求时也是正确的。路由式链路是另一种设计:盒子保留自己的子网,而这个前缀必须被带到流量去的每个地方。
这份计划的其余部分保留下游路由器,并保住客户端源地址。目标是一个私有 VPN 网络,而不是完整的互联网出口。先把模型写下来,再写地址,因为下面的清单只是路由式连接的一个例子。
client subnet 10.41.0.0/24
client gateway 10.41.0.1
router-to-Pi link 192.168.71.2
Pi on that link 192.168.71.1
private target 10.72.9.0/24
谁决定什么
| Decision owner | Entry that encodes the decision | Failure when the entry is missing |
|---|---|---|
| Pi VPN host | Return route for 10.41.0.0/24 via 192.168.71.2, and a tunnel route for 10.72.9.0/24 | Replies to downstream clients die at the Pi |
| Owner of the remote network | A path for 10.41.0.0/24 over the permitted tunnel | Replies stop at the first unaware hop |
| LAN router behind the Pi | Specific route for 10.72.9.0/24 via 192.168.71.1, or a suitable default | Clients never send private traffic to the Pi |
| Client machine | Default via 10.41.0.1, or a specific entry for 10.72.9.0/24 | The private network is unreachable from the client |
每台设备只做一个决定,谁也不能替别人做。Pi 需要两条条目,而不是一条,返回路径正是人们会忘掉的那条。转发的流量正确到达私有网络,然后在回来的路上死掉,因为 Pi 根本不知道 10.41.0.0/24 住在哪里。这看起来像防火墙问题,实际上是一条缺失的路由。
远端也需要自己的路由。如果远端的服务不知道 10.41.0.0/24 能通过你的隧道到达,回应就会停在第一个没有答案的跳点上。先加上两个方向,再去读包过滤。
下一跳来自连接方式
下一跳必须是设备真正能到达的网络上的地址。VPN 对端的公网地址不是私有子网的下一跳,远端服务网络根本就不是下一跳。通往不可达网关的路由在列表里看着没错,却会丢掉每一个包。在怪罪目的地之前,先确认网关会回应。
让 Pi 的外层 VPN 对端通过它自己的底层路由保持可达。那条条目与载荷路由分开,混在一起就会得到一个在路径改变后无法重建的隧道。
静态路由文档清楚说明了目的地与网关的区别,尽管每个平台给菜单起的名字不同。读你面前那台设备的文档,而不是照抄另一个厂商的界面。下面的命令展示了 Linux 上条目的形态。
# on the Pi
ip route add 10.41.0.0/24 via 192.168.71.2
ip route add 10.72.9.0/24 dev tun0
# on the downstream router
ip route add 10.72.9.0/24 via 192.168.71.1
转换对来源做了什么
如果下游路由器已经把客户端转换成中转地址,Pi 看到的就是一个转换后的来源,而不是每个客户端自己的地址。这与上面保留来源的设计不同。它会改变基于来源的策略、日志,以及哪一侧可以发起连接。两种设计都能用;它们回答的是不同的问题。
当上游 VPN 服务拒绝把客户端前缀路由回去时,在 Pi 的隧道出口做一次范围很窄的转换可以是合法的工作方式。这不是缺失路由多余的证据。记录远端网络实际看到的是哪个地址,以及由此得到什么返回路径。
路由选择、转发许可和来源转换仍然是三件相互独立的工作。因为一个有线客户端能用就清空共享的 NAT 链、或者放行每个接口,正是把一次能用的测试变成一个开放转发器的方式。
从客户端机器上证明它
从下游 LAN 的机器上发一个请求,然后顺着它的来源出去再回来。Pi 发出的 ping 从不会走下游返回路由,所以一个成功的 ping 证明的东西比看上去要少。再加一个来自 Pi 自己 LAN 上有线客户端的测试,这样两条路径可以比较。重启任何一台设备后,两个测试都要重做。
手工添加的路由和从未持久化的转换会一起消失。于是这一对看起来像新故障,而不是没做完的工作。
把连接模型和路由、允许的私有服务、任何转换一起记在同一条笔记里。正是这条笔记,让下一个人不会把无线设备的位置当成路由策略问题。