在再加一层 NAT 之前,先让私有 LAN 之间走路由
地址空间重叠、缺少回程路由或中转网段不可信,决定了该选路由、NAT 还是隧道。改防火墙之前,先核对这三件事。
两台内网防火墙、一个私有中转网段,以及让两边 LAN 里若干主机互相通信的需求。条件反射是架 VPN 或再加一层 NAT,而这两种做法都比问题本身更贵。只要三个条件同时成立,普通路由就够了:地址段不重叠、两侧都能把流量回送到对方 LAN、中转网段对这批数据已经足够可信。动手设计之前先把这三条核对清楚,因为任何一条都会改变结论。
决定设计的三项条件
第一项是地址空间。如果两个 LAN 用的是同一段 RFC 1918 地址,路由就无法区分它们,地址转换便从可选项变成必需品。第二项是回程路径:从 A 到 B 的路由,只有在 B 也知道怎么回到 A 的 LAN 时才有用;知识不对称正是已路由的设计悄悄丢掉回包的最常见原因。
第三项是信任。路由只搬包,不保护包。一栋楼内部署的私有中转网段,和交给运营商的中转、或穿过共享园区骨干的链路是两回事。如果这个网段不可信,答案就是在两台防火墙之间建隧道,而下面的路由方案在隧道内部同样适用。
只有三条指向一致时,简单方案才成立。其中一条不成立时,就明确去修它,而不是用地址转换糊过去,因为 NAT 只是把故障藏起来,并没有解决它。
在中转网络上建立路由方案
给每台防火墙在中转网段上配一个地址,为每个远端 LAN 各加一条明细路由。其余现有配置一律不用动,尤其是上网默认路由必须原封不动。用对端防火墙替换默认路由,会把所有无关目的地都赶到中转网段上,改动远比需求大得多。pfSense 的静态路由文档描述的也是同样的路由加下一跳模式,你实际在用的防火墙都有等价配置。
| Firewall | Remote LAN | Next hop on the transit |
|---|---|---|
| A | 10.40.0.0/24 | 192.0.2.20 |
| B | 10.30.0.0/24 | 192.0.2.10 |
防火墙 A 承载 10.30.0.0/24,防火墙 B 承载 10.40.0.0/24,两个中转地址在 192.0.2.0/24 上。每台 LAN 主机仍以本地防火墙为网关,所以新增状态只有两侧各一条路由。在 Linux 防火墙上,同样的方案是这样;转发必须打开,否则路由能查到而包会被丢掉。
sysctl -w net.ipv4.ip_forward=1 ip route add 10.40.0.0/24 via 192.0.2.20 dev eth1 ip route get 10.40.0.15 traceroute -n 10.40.0.15
把过滤和转换分开看
路由和策略是两套不同的控制,而多数已路由的设计真正出问题的地方是后者。在包实际经过的入口边界上放行具体的源、目的和服务,并记住 WAN 这类接口名只是一个名字,不是关于信任的声明。承载私有流量的中转口,可能仍然默认开着私有地址阻断。
然后再看出去方向的转换,别急着断言没有 NAT。自动的出站规则可能会改写本来不该被转换的流量,这会毁掉对端做策略和日志所需的源地址。确认选中的流量保留了原始地址,同时别去动那些仍需上网转换的流量的规则。
iptables -t nat -S POSTROUTING iptables -t nat -L POSTROUTING -n -v tcpdump -ni eth1 -c 5 host 10.40.0.15
当 NAT 才是诚实的答案
当地址段确实重叠、又没法重新编址时,或者策略要求某一侧只看到一个地址而不是一个子网时,转换才真正有位置。这种情况下,有意为之的一对一或限端口映射是有已知后果的设计决定,而不是权宜之计。
必须大声说出来的后果是:对端再也看不到、也过滤不了单个源。日志会坍缩成那一个转换地址,按主机维度的策略失效,排障变成追问某一刻到底是哪台内网主机占着这条流。如果这些对这批流量都不重要,那用 NAT 也没问题。
当中转网段本身就是错误假设
如果共享网段要穿过运营商、共享交换网络,或任何第三方能读到流量的路径,光靠路由就不是完整答案。两台防火墙之间建隧道,能带来机密性和对端认证,而隧道内部的路由表,和你在中转网段上会写的是同一张。
这件事应当由第一节里的信任问题来决定,而不是由 VPN 更安全的习惯来决定。在本来就私有的网段上架隧道,只是多出运维成本和一种新的故障模式,换不来任何收益;而在不可信网段上直接路由,是拿机密性去换你承受不起的简单。把三条中究竟是哪一条驱动了选择写下来,下一位工程师就不用再重新吵一遍。