先看一下整体拓扑,我画了张图方便理解,先看看整个流程里最大的问题。

图中用三种颜色标注了流量走向:蓝色是外部请求进来的路径,绿色是正确的回程路径(经过 FW2 原路返回),红色则是出问题时的回程——也就是非对称路由导致连接失败的那条路。
整个链路是这样走的:外部用户从互联网发起请求,首先命中上级防火墙 FW1。FW1 是公网入口,上面配了第一层 DNAT,把外部端口映射到 FW2 的 WAN 地址(172.16.11.x)。请求到了 FW2 之后,pfsense 再做第二次端口转发,把流量丢进对应的 VLAN,最终送到内网的TureNAS。
到这里,请求方向是没问题的,一路蓝色箭头,畅通无阻。
但在回包时。TrueNAS收到请求后要回复数据,这时候它看一眼源地址,如果 FW2 没做 SNAT,那源地址还是外部用户的公网 IP,或者是 FW1 转过来的中间地址。TrueNAS一查自己的路由表,发现这个地址不在本地网段,就按默认网关往外丢。问题是,它的默认网关很可能不是 FW2 的 LAN 口,而是 VLAN 里的其他出口。
这一丢,回包就走了红色那条路——绕开了 FW2,直接试图从别的路径出去。外部用户的感知就是:连接超时,端口映射不通。
解决办法就是图里绿色箭头走的那条路:在 FW2 上加一条 Outbound NAT 规则,把进入 VLAN 的流量源地址伪装成 FW2 自己在该网段的接口 IP(192.168.1xx.254)。这样 JumpServer 看到的请求源地址就是 FW2,回包自然会交还给 FW2。FW2 拿到回包后,反向还原 NAT,沿原路经 FW1 返回给外部用户。整条链路闭合,端口映射才算真正打通。
我们以一个JmupServer(192.168.103.101)为例子

接口 WAN,地址簇 IPv4,协议 TCP/UDP。目标选的 WAN address,目标端口范围 8080 到 8080——意味着外部用户通过 FW2 的 WAN IP 加 8080 端口访问时,触发这条规则。
重定向目标 IP 填 JumpServer 的内网地址。重定向目标端口选的 HTTP(80)。所以整条规则的逻辑是:外部 8080 → 内部 192.168.103.101:80,做了一次端口变换。用非标准端口对外暴露是个好习惯,既避免跟防火墙自身管理端口冲突,也不容易被常规端口扫描器第一时间命中。
有一个地方需要注意:过滤规则那里选的是 None。这意味着 pfSense 不会自动在 WAN 口上生成对应的防火墙放行规则。你需要手动去 防火墙 → 规则策略 → WAN 标签页下,确认有一条放行目标端口 8080 的规则,否则流量到了 WAN 口会被默认的拒绝规则挡掉,端口转发虽然配了但根本匹配不到流量。如果当初配的时候选了"添加关联的过滤规则"就不用操心这步,但既然这里选的 None,就得自己补。

模式已经选了混合出站 NAT 规则生成,没问题。混合模式的好处前面说了——手动规则优先,自动规则兜底,互不干扰。
下方映射表里可以看到刚才创建的那条规则:接口 LAN,协议 TCP/UDP,目的地址 192.168.103.101/32,NAT 地址是 LAN address。一条规则,精准命中 JumpServer,把所有发往它的流量源地址改写成 FW2 的 LAN 口 IP,回包自然原路返回。
注意看 NAT 端口那一列显示的是*,静态端口列打了个*,意味着用的是动态端口映射。对于普通的 Web 和 SSH 访问,这完全够用。只有 IPSec、SIP 这类对源端口敏感的协议才需要勾选静态端口。
混合出站:pfSense 默认是自动模式,自动生成的规则只管内网上网,不会帮你做这种定向伪装。切到混合模式后,手动规则优先级高于自动规则,但自动规则依然保留——内网设备正常上网完全不受影响,只是多了这么一条"特权规则"来解决端口映射的回流问题

接口选的 LAN。因为 JumpServer(192.168.103.101)所在的网段是从 LAN 口下去的,流量最终要从这个接口进入内网,所以伪装操作就发生在这里。
协议选了 TCP/UDP。这里其实选 Any 也行,但选 TCP/UDP 更精确一些,JumpServer 的 Web 管理和 SSH 都是 TCP,偶尔有 UDP 的需求也覆盖了。
源地址选 Any,不限来源。意味着不管是哪个外部网段的流量经过 FW2 访问 JumpServer,全都会被伪装。这样做的好处是以后新增网段、新增映射路径,不用回来改这条规则。
目标地址是重点——类型选的Network or Alias,地址精确填了192.168.103.101掩码/32。这就是"点对点"模式,伪装只作用于这一台 JumpServer,同网段的其他设备该怎么通信还是怎么通信,不受任何影响。如果你图省事把目标写成 192.168.103.0/24,那整个网段所有设备收到的流量源地址都会变成 FW2,日志里全是 FW2 的 IP,出了问题根本查不出谁在访问谁。
截图往下还有转换部分没截到,按照这个架构,转换地址应该选 LAN address,也就是 FW2 在 LAN 口的接口 IP。这样 JumpServer 看到所有请求都来自 FW2 的 LAN 口,回包自然交给 FW2,FW2 拿到回包后反向还原 NAT,沿 WAN 口送回上级防火墙 FW1,最终返回外部用户。

验证成功——JumpServer 登录页面从外部访问通了
浏览器地址栏显示 172.16.11.233:8080,页面已经跳转到了 JumpServer 的登录界面。这意味着整条链路完全跑通了:外部请求从 172.16.11.x 网段出发 → 经过 FW1 → 到达 pfSense FW2 的 WAN 口 → 端口转发将 8080 映射到内网 192.168.103.101:80 → JumpServer 收到请求后回包给 FW2(因为出站 NAT 伪装了源地址)→ FW2 沿原路返回。整个双层防火墙的端口映射闭环,到此完成。

最后聊几点实际经验:
第一,关于安全加固。现在 8080 端口是对整个 WAN 侧开放的,任何能访问 FW2 WAN 口的设备都能摸到 JumpServer 的登录页面。生产环境里建议在 WAN 防火墙规则中限制源地址,只放行运维人员的 IP 段。
第二,关于日志。建议把端口转发和出站 NAT 相关的防火墙规则都勾上"记录日志"。平时不看没关系,出了问题的时候,日志是唯一能告诉你"包到底走到哪一步丢的"的东西。pfSense 的日志在 系统状态 → 系统日志 → 防火墙 里可以实时查看,也可以对接外部 syslog 服务器做长期存储。
第三,关于规则描述。贯穿整篇文章一直在说这个事,再强调一次:每一条规则都要写描述。端口转发写清楚映射的是什么服务、目标是哪台机器;出站 NAT 写清楚是为了解决哪条映射的回流问题。三个月后你自己回来看,或者换个人接手,一目了然。
第四,关于回流本质。整篇文章解决的核心问题就一个——非对称路由。双层防火墙环境下,内层防火墙做端口转发时如果不做源地址伪装,服务器的回包会走默认网关(通常指向外层防火墙或其他出口),绕过了内层防火墙,导致会话跟踪断裂。记住这个原理,以后不管换什么防火墙产品,遇到同样的拓扑都是同样的解法。
Comments NOTHING