Linux端口转发本质是启用内核IP转发并配置iptables的nat表规则,缺一不可;必须开启ip_forward、配置PREROUTING DNAT、放行FORWARD链、设置POSTROUTING SNAT/MASQUERADE。

Linux防火墙端口转发本质是启用内核 IP 转发 + 配置 iptables 的 nat 表规则,缺一不可。直接敲命令但没开 ip_forward,或者开了却漏了 FORWARD 链放行,都会导致转发静默失败——连连接超时都不报,只显示“Connection refused”或干脆无响应。
必须先开启 IPv4 转发(/proc/sys/net/ipv4/ip_forward)
这是整个转发链路的开关,不打开,内核直接丢弃非本机目的地址的数据包。
- 临时生效:运行
echo 1 > /proc/sys/net/ipv4/ip_forward - 永久生效:编辑
/etc/sysctl.conf,确保含有一行net.ipv4.ip_forward = 1,然后执行sysctl -p - 验证是否生效:运行
cat /proc/sys/net/ipv4/ip_forward,输出为1才算成功 - 注意:某些云主机或容器环境(如 Docker 启动过)可能默认关闭该值,重启后会重置,务必检查
iptables -t nat -A PREROUTING 做 DNAT 是核心转发动作
这条规则把到达本机外网接口的入向流量,目标端口改写成内网服务的地址和端口。它只改“目的”,不负责放行或回程。
- 典型命令:
iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.100:80 - 如果机器有多个外网接口(如
ens33接公网、ens34接内网),强烈建议加-i ens33显式指定入口,避免规则误匹配 -
--dport必须是外部客户端实际访问的端口;--to-destination后的 IP 必须能被本机路由到达(比如在同子网,或已配静态路由) - 不要用
REDIRECT替代DNAT:前者只适用于本机回环或本地进程发包,跨主机转发必须用DNAT
FORWARD 链必须显式放行,否则包被默认 DROP
PREROUTING 改完目的地址后,数据包进入 FORWARD 链。若此处无匹配规则且策略是 DROP(常见于生产环境),包就丢了,不会进 POSTROUTING。
- 最简放行:
iptables -A FORWARD -p tcp -d 192.168.1.100 --dport 80 -j ACCEPT - 更安全写法(推荐):
iptables -A FORWARD -i ens33 -o ens34 -p tcp -d 192.168.1.100 --dport 80 -j ACCEPT,绑定内外网接口 - 别忘了允许返回流量:
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT,否则 TCP 握手都完成不了 - 如果
FORWARD策略是ACCEPT,这步可省,但不建议依赖,默认策略应为DROP并显式放行
POSTROUTING 做 SNAT/MASQUERADE 才能让回程包正确返回
内网服务响应时,源 IP 是它的私有地址(如 192.168.1.100),外网客户端无法直接路由回去。必须在出方向把源 IP 改成本机外网 IP。
- 固定外网 IP 用
SNAT:iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j SNAT --to-source 203.0.113.5 - 动态 IP(如拨号、DHCP)用
MASQUERADE:iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j MASQUERADE - 这条规则的
-s要匹配内网服务所在网段,不是客户端网段;否则回程包 NAT 失败,客户端收不到响应 - 若转发目标是本机另一个监听端口(非跨主机),此步可省,但绝大多数真实场景都需要
最容易被忽略的是 FORWARD 链规则顺序和默认策略——很多人只配了 PREROUTING 和 POSTROUTING,却卡在 FORWARD 的隐式拒绝上,查日志也看不到明显错误,只能靠抓包确认包是否在 FORWARD 被丢弃。


















