AIGC标识 OpenWrt 旁路由下的公网端口映射:按 TCP/UDP 服务端口配置回程策略路由

本文由 AI 辅助整理,基于实际网络需求及公开技术文档核对。此前排障反馈已恢复公网访问,但没有保存完整的最终规则、固件版本和抓包证据;下文是可供现场核验的配置示例,不代表所有命令均已在这台 MX4200 上实测通过。

一、需求:PC 网关不变,只调整指定服务的回程

Ubuntu PC 使用 OpenWrt 旁路由上网,已有 VPN、代理和分流配置。现在要把 PC 的 TCP 8090 服务开放给公网,但不能把 PC 默认网关改成主路由,也不能把这台 PC 的全部流量都改为直连。

设备 地址 职责
主路由 192.168.10.1 公网入口、DNAT、连接跟踪与反向 NAT
MX4200 / OpenWrt 192.168.10.3 PC 默认网关;指定服务回包经主路由返回
Ubuntu PC 192.168.10.220/24 提供 TCP 8090 服务;默认网关保持 192.168.10.3

三台设备处于同一 LAN,本文仅讨论 IPv4。假设 OpenWrt 对应三层接口为 br-lan,实际部署必须核对接口名。

                     互联网客户端
                          |
                    主路由 10.1
                公网 TCP 51288 做 DNAT
                          |
             同一 LAN:192.168.10.0/24
                   /                 \
         Ubuntu PC 10.220        MX4200 10.3
            TCP 8090             OpenWrt
         默认网关:10.3        VPN / 代理 / 分流

请求:客户端 → 10.1 → 10.220:8090
响应:10.220:8090 → 10.3 → 10.1 → 客户端
其他流量:继续由原有网关、路由和代理策略处理

请求不必经过旁路由。关键是响应仍要回到建立 NAT 状态的主路由,且途中保留 PC 的源地址和服务源端口。路径不对称本身不必然导致失败,但防火墙、代理和连接跟踪必须允许这种路径。

二、为什么已有 DNAT 还可能访问失败

以公网端口 51288 映射到 PC 的 8090 为例,忽略其他 NAT,报文变化如下:

位置 源 目的
主路由公网入口 客户端 IP:临时端口 主路由公网 IP:51288
主路由 DNAT 后 客户端 IP:临时端口 192.168.10.220:8090
PC 响应到旁路由 192.168.10.220:8090 客户端 IP:临时端口
主路由反向转换后 主路由公网 IP:51288 客户端 IP:临时端口

PC 的响应目的地址是公网客户端,通常会走默认网关 10.3。如果 10.3 又把它送进 VPN、透明代理,或者对它进行源地址伪装,主路由可能收不到原连接所期待的回包。

本方案不在 10.3 再做一次 DNAT,也不对这类回包新增 SNAT/MASQUERADE。主路由根据已有连接状态执行反向转换即可。状态化 NAT 的绑定由连接初始报文建立,后续报文沿用该绑定,见 nftables 官方 NAT 文档。

三、先明确端口策略的能力边界

回程选择条件是“源 IP + 协议 + 服务源端口”,例如:

  • 源 IP:192.168.10.220;
  • 协议:TCP;
  • 源端口:8090;
  • 下一跳:192.168.10.1。

这里是 sport 8090,不是 dport 8090,更不是 sport 51288。51288 是主路由对外开放的端口,PC 实际响应使用内部端口 8090。

端口匹配不等于连接身份识别。 同一 PC 上任何使用 TCP 源端口 8090 的报文都可能匹配,包括主动绑定该源端口发起的连接,以及向其他网段客户端发送的服务响应。因此,“其他流量不受影响”应准确理解为:未命中这些选择条件的流量,继续使用原有策略;不能承诺所有非公网连接都完全不受影响。

若必须严格只处理公网 DNAT 连接,需要重新设计可识别连接来源的路径或标记机制。10.1 上的 conntrack、ct mark 和 skb mark 不会自动通过网线传给 10.3;而 10.3 通常只看到回程,不能直接用本机的 ct status dnat 识别主路由上的 DNAT。

四、主路由 10.1:只配置需要的公网入口

在主路由的端口映射或虚拟服务器页面配置:

项目 示例值
协议 TCP
外部端口 51288
内部地址 192.168.10.220
内部端口 8090
来源限制 有固定访问来源时优先限制

确认主路由允许对应 WAN → LAN 转发。不同品牌实现不同,本文不把某款设备的防火墙命令套到未知主路由上。

还要确认主路由确实具备可入站的公网 IPv4。上游光猫路由、双重 NAT、运营商 CGNAT 都可能让请求根本到不了 10.1;DDNS 只能解析地址,不能解决这些问题。测试请使用手机移动网络,局域网访问公网域名可能走 NAT 回环,是另一条路径。

五、OpenWrt:先检查,再建立独立路由表

5.1 检查现状

在 10.3 上执行以下只读检查:

ip -4 addr show
ip -4 rule show
ip -4 route show table all
ip -4 route show table 100
ip -V
ip rule help
sysctl net.ipv4.ip_forward
nft -a list ruleset

旧版 fw3/iptables 环境改用对应的 iptables-save 检查防火墙,不要把 nftables 规则直接粘贴进去。精简版 ip 可能不支持 ipproto、sport;应核对当前固件提供的完整 iproute2/ip-full 软件包及内核支持,不能仅根据设备型号判断。

本文假设表 100 和优先级 100、101 尚未占用。它们只是示例编号,不是保留给本方案的编号。 透明代理也可能使用表 100;若已被占用,先选择其他空闲表号并统一替换。

5.2 创建下一跳路由

确认 10.1 与 br-lan 二层直连后,在空闲的表 100 中先添加直连路由,再添加默认路由:

ip -4 route replace 192.168.10.0/24 dev br-lan scope link table 100
ip -4 route replace default via 192.168.10.1 dev br-lan table 100

独立表不会因为编号不同就自动继承 main 表内的全部路由。直连项既说明下一跳可达,也使该表内对同网段目的地址有更具体的路径。若还有其他 LAN、容器、管理或 VPN 网段,需要逐项决定这些目的地址应保留哪条路径,不能把表 100 的默认路由理解成“只匹配公网”。相关表、下一跳和查询语义见 ip-route 手册。

5.3 添加 TCP 服务规则

在确认优先级未占用、且早于可能接管此流量的 VPN/代理路由规则后,执行一次:

ip -4 rule add priority 100 from 192.168.10.220/32 iif br-lan ipproto tcp sport 8090 lookup 100

ip rule 的数值越小,检查越早;通常应保留优先级 0 的 local 查询。这里的 100 并不保证比所有插件规则都早,例如已有 priority 50 的规则仍会先执行。不要使用重复优先级依赖插入顺序。选择器和优先级语义见 ip-rule 手册。

以下只有源地址条件的规则不符合本需求,不要添加:

# 反例:会扩大到该 PC 的全部匹配流量
# ip -4 rule add priority 100 from 192.168.10.220/32 lookup 100

如果以前确实添加过宽泛规则,应根据 ip rule show 的实际输出精确删除那一条;不要清空整个策略路由列表。

5.4 UDP 与多个服务

假设另有一个固定使用 UDP 9000 回复的服务,可另加一条规则:

# 仅当确实部署并需要开放 UDP 9000 时添加
ip -4 rule add priority 101 from 192.168.10.220/32 iif br-lan ipproto udp sport 9000 lookup 100

主路由也必须配置对应 UDP 映射。TCP 规则不会覆盖 UDP;新增服务端口需要同步更新主路由 DNAT、旁路由规则,以及必要的代理/NAT 例外。不能宣称以后只加主路由映射就一定够用。

使用动态数据端口的协议、非首片 IP 分片、相关 ICMP 错误报文等,不能只凭一个固定 TCP/UDP 端口规则保证覆盖;应按实际报文验证,必要时调整设计。

六、路由正确,还要检查代理、防火墙和 NAT

6.1 路由绕行不等于代理绕行

TPROXY、REDIRECT、TUN 的接管方式不同。特别是 REDIRECT 可以在路由前修改目的地址,保留在前面的 local 查询随后就可能把报文送往本机。仅把服务规则排在某条 fwmark 规则前,并不能证明代理已绕过。Linux 内核透明代理文档说明了标记、策略路由与本地投递的配合关系。

应在实际代理插件支持的持久化入口中,为 192.168.10.220 的对应协议和源端口设置精确绕过,核对生效顺序,并抓包验证。不要把整台 PC 设置为 DIRECT,也不要假设代理应用内的 DIRECT 就等价于未被透明代理接管。

本文不提供脱离实际链结构的通用 nft insert rule 命令:在某个自建链中 return,并不代表后续所有基础链都会跳过该报文。

6.2 允许同接口转发,保持回包源地址

该拓扑的报文可以从 br-lan 进入,再从 br-lan 转发给 10.1。需要核对 IPv4 转发、LAN 区域的实际转发规则,以及是否有更早的丢弃规则。不要用关闭防火墙或全局放行代替定位。

10.3 没有看到公网 SYN 的入站方向,其本机连接跟踪状态可能与主路由不同。若回包被标为 INVALID,单靠 established/related 放行可能不够;应结合丢弃计数和抓包定位,再制定最小范围规则,不能全局接受 INVALID。

还要检查出 LAN 的 SNAT/MASQUERADE 是否会命中这类回包。若命中,应在实际 NAT 结构里设置精确例外,而不是关闭整个 LAN 的伪装功能。以 10.1 收到的报文仍为 192.168.10.220:8090 为验收条件。

6.3 ICMP Redirect 与反向路径检查

单臂旁路由可能发送 ICMP Redirect,让 PC 学到绕过 10.3 的路径。若要求出口策略始终由旁路由控制,应检查 10.3 的 all/接口 send_redirects 和 PC 的 accept_redirects,必要时按系统方式持久化调整。

rp_filter 严格模式也可能与复杂非对称路径冲突。先检查实际值、路由与丢包证据,再决定是否需要 loose 模式,不要一律全局关闭;其有效值涉及 all 与接口设置。参数含义见 Linux IP sysctl 文档。

七、验证:把路由查询和真实抓包分开

7.1 PC 的地址、网关和监听

在 Ubuntu 上检查:

ip -4 addr show dev enp4s0
ip -4 route show
ss -lntp 'sport = :8090'

默认路由应仍然是 default via 192.168.10.3。接口名以实际为准。服务需要监听可访问地址,不能只监听 127.0.0.1;同时检查主机防火墙、容器端口发布和应用访问控制。

本次原有 PC 路由还包含 192.168.0.0/16 via 192.168.10.1,它只匹配对应目的网段,不能解决普通公网客户端的回程;同网段 /24 直连路由仍然更具体。

7.2 模拟转发查询

在 10.3 上查询:

# 198.51.100.10 是文档示例地址;现场请换成真实客户端 IPv4
ip -4 route get 198.51.100.10 from 192.168.10.220 iif br-lan ipproto tcp sport 8090 dport 53000

# 对照:普通出站连接的源端口,不应命中 TCP 8090 规则
ip -4 route get 198.51.100.10 from 192.168.10.220 iif br-lan ipproto tcp sport 53001 dport 443

ip -4 rule show
ip -4 route show table 100

第一条预期应选择表 100,经 192.168.10.1、br-lan 返回;这只是预期,不是本次设备的实测输出。对照项可能也经主路由,因为原策略本来如此,应比较变更前后及真实代理路径。

ip route get 不会完整重放 nftables 的改址、打标、过滤与代理接管。若真实报文带 mark,还应按实际标记补充查询,最终以真实连接为准。

7.3 从真正外网发起新连接

在 PC 和旁路由分别抓包:

# Ubuntu PC
sudo tcpdump -ni enp4s0 'tcp port 8090'

# MX4200;-e 显示二层地址,帮助区分同一接口上的收发方向
tcpdump -eni br-lan 'host 192.168.10.220 and tcp port 8090'

使用手机移动网络访问自己的公网域名和 51288 端口。预期证据是:PC 收到 SYN 并发送 SYN-ACK;10.3 把原源地址的响应转给 10.1;10.1 在 WAN 侧按已有 NAT 状态返回公网响应,连接能够持续传输数据。

同时回归测试 PC 普通上网、原 VPN/代理业务及其他设备。UDP 应使用协议自身的客户端验证双向响应,不能仅凭端口扫描“无响应”判断失败。

修改 NAT 或代理规则后优先新建测试连接,旧连接可能仍沿用原状态;不要为了测试清空所有连接跟踪。若流量卸载造成计数或抓包难以解释,在维护窗口临时关闭相关卸载作对照,验证后恢复。

八、持久化:不只考虑重启,还要考虑网络与插件重载

上面的 ip 命令修改运行态,重启后通常丢失;重复执行 ip rule add 还可能产生重复规则。/etc/iproute2/rt_tables 只是表名映射,写入表名并不会持久化路由。

优先考虑由当前版本 netifd 管理 /etc/config/network 中的 route/rule 配置,但必须确认该固件是否支持所需 ipproto、sport 字段;上游有字段不代表旧固件具备相同能力。下面给出不依赖 UCI 端口字段的幂等脚本示例,它仍需现场验证,不是自动适配所有 OpenWrt 的安装脚本。

保存为 /usr/sbin/service-return-route,使用前确认表号、规则优先级及 br-lan 都属于本方案:

#!/bin/sh
set -eu

ip -4 route replace 192.168.10.0/24 dev br-lan scope link table 100
ip -4 route replace default via 192.168.10.1 dev br-lan table 100

# 只删除本方案完全相同的旧规则,不按优先级批量删除
while ip -4 rule del priority 100 from 192.168.10.220/32 iif br-lan ipproto tcp sport 8090 lookup 100 2>/dev/null; do
    :
done
ip -4 rule add priority 100 from 192.168.10.220/32 iif br-lan ipproto tcp sport 8090 lookup 100

先手动执行并检查退出状态、规则及路由。需要 UDP 时,在同一脚本中按完整选择条件增加对应的去重与添加步骤;只维护实际使用的端口。

若通过 /etc/hotplug.d/iface/95-service-return-route 接入,示例如下(lan 是逻辑接口名,未必等于设备名):

#!/bin/sh
[ "$INTERFACE" = "lan" ] || exit 0
case "$ACTION" in
    ifup|ifupdate)
        /usr/sbin/service-return-route || logger -t service-return-route 'apply failed'
        ;;
esac

给脚本设置执行权限。接口事件可能并发,生产环境应增加适合该固件的互斥机制;上述去重再添加也存在短暂规则空窗。若启动时接口尚未就绪,单独写 rc.local 并不可靠。代理插件若在稍后重建规则,还需要使用插件支持的重载钩子并确认顺序。

验收至少覆盖:设备重启、LAN 重连、防火墙重载、代理/VPN 重启。每次检查表、规则、精确绕过例外和真实公网连接,而不只是看脚本是否存在。

九、回滚与故障定位

停止本方案的持久化入口后,按完整条件删除自己添加的规则。例如 TCP 8090:

ip -4 rule del priority 100 from 192.168.10.220/32 iif br-lan ipproto tcp sport 8090 lookup 100

若有重复项,逐条检查并删除;UDP 规则同理。仅在确认表 100 完全由本方案独占时,才清理其中本方案添加的路由。同时撤销对应代理/NAT 例外和不再需要的主路由端口映射,避免热插拔脚本重新加回规则。

现象 优先检查
PC 完全收不到公网请求 公网 IPv4、上游 NAT、主路由 DNAT、协议与端口、防火墙
PC 收到 SYN 但不回应 服务监听、主机防火墙、容器映射、应用状态
PC 回应但 10.3 没收到 PC 实际路由、静态路由、Redirect、二层通信
10.3 收到但没有送往 10.1 RPDB 顺序、接口匹配、代理接管、转发丢弃、rp_filter
10.1 收到的源已变为 10.3 旁路由上的 SNAT/MASQUERADE
route get 正确但公网仍失败 真实 mark、REDIRECT/TPROXY、连接状态、过滤与卸载
TCP 通而 UDP 不通 UDP 独立规则、映射、服务实际回复端口、超时与分片
重启或插件重载后失效 持久化时序、接口名、重复规则、插件覆盖
其他业务发生变化 宽泛旧规则、编号冲突、全 PC DIRECT、过宽防火墙/NAT 修改

十、公网开放前的安全检查

只开放必要服务。上传或管理页面应配置 HTTPS、强认证、访问授权、上传大小限制与日志;避免把上传目录当作可执行目录。能限定来源 IP 时优先限制,及时更新服务和系统。高位端口不能代替认证,也不要直接暴露 LuCI、路由器管理接口或不必要的 SSH。

本文没有公开实际 DDNS 域名、账号或公网地址。IPv6 的可达性与防火墙是独立问题,不受这里的 IPv4 DNAT 规则保护,部署时应另行检查。

这套架构的落点是:10.1 负责公网入口和 NAT 状态,10.3 只为明确选择的服务响应提供回程路径,10.220 保持默认网关 10.3。配置是否完成,要以公网双向通信和原有业务回归结果判断,不能仅凭一条路由查询作结论。

posted @ 2026-11-02 18:44  javen_xiao  阅读(9)  评论(0)    收藏  举报