把 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 ownerEntry that encodes the decisionFailure when the entry is missing
Pi VPN hostReturn route for 10.41.0.0/24 via 192.168.71.2, and a tunnel route for 10.72.9.0/24Replies to downstream clients die at the Pi
Owner of the remote networkA path for 10.41.0.0/24 over the permitted tunnelReplies stop at the first unaware hop
LAN router behind the PiSpecific route for 10.72.9.0/24 via 192.168.71.1, or a suitable defaultClients never send private traffic to the Pi
Client machineDefault via 10.41.0.1, or a specific entry for 10.72.9.0/24The 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 上有线客户端的测试,这样两条路径可以比较。重启任何一台设备后,两个测试都要重做。

手工添加的路由和从未持久化的转换会一起消失。于是这一对看起来像新故障,而不是没做完的工作。

把连接模型和路由、允许的私有服务、任何转换一起记在同一条笔记里。正是这条笔记,让下一个人不会把无线设备的位置当成路由策略问题。

相关文章