Linux NAT转发不生效的核心原因有三:IP转发未启用、FORWARD链未放行流量、NAT规则未正确加载或命中;需依次检查/proc/sys/net/ipv4/ip_forward值、iptables FORWARD链策略及nat表中PREROUTING/POSTROUTING规则,并清理conntrack缓存确保新规则生效。

Linux NAT 转发不生效,通常不是某一个环节彻底“坏了”,而是多个依赖条件中有一处没对上——转发功能像一条流水线,缺一不可。核心就三点:内核转发开关开着、iptables 规则写对了位置和逻辑、NAT 表里的转换动作真正触发了。
确认 IP 转发已启用且持久化
这是最基础也最容易被忽略的一环。哪怕规则全对,只要 /proc/sys/net/ipv4/ip_forward 是 0,所有转发包都会被内核静默丢弃。
- 临时开启:
sudo sysctl -w net.ipv4.ip_forward=1 - 检查是否生效:
cat /proc/sys/net/ipv4/ip_forward输出应为 1 - 永久生效:在
/etc/sysctl.conf中确保有net.ipv4.ip_forward = 1,然后运行sudo sysctl -p - 特别注意:某些系统(如部分 KVM 宿主机)在重启 network 服务或网络重载后会重置该值,需确认配置已固化
检查 iptables FORWARD 链是否放行流量
NAT 规则(DNAT/SNAT)只改地址,但包能不能过网关,还得看 FORWARD 链是否允许。默认策略为 DROP 的系统尤其容易卡在这里。
- 查看当前规则和顺序:
sudo iptables -L FORWARD -n --line-numbers - 必须有允许内网到外网的规则,例如:
sudo iptables -A FORWARD -s 192.168.10.0/24 -o eth0 -j ACCEPT - 必须有允许回程响应的规则,例如:
sudo iptables -A FORWARD -i eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT - 推荐前置一条状态跟踪规则:
sudo iptables -I FORWARD 1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT,避免新连接被后续 DROP 拦截
验证 NAT 规则是否正确加载并命中
很多人用 iptables -t nat -L 看到规则存在就以为 OK,但规则可能没生效,或者根本没匹配到流量。
- 确认规则在
PREROUTING(DNAT)或POSTROUTING(SNAT)链,不在 FORWARD 链里加 -t nat - 家用/拨号环境统一用
MASQUERADE:sudo iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o eth0 -j MASQUERADE - 企业固定 IP 才用 SNAT,且必须确认
eth0当前 IP 正确:ip -br a | grep eth0 - 用
sudo iptables -t nat -L -v -n查看每条规则的匹配包数量,为 0 就说明没走这条路
排除 conntrack 缓存导致的“规则不即时生效”
已有连接在添加 NAT 规则前就建立了 conntrack 记录,后续包仍沿旧路径走,新规则对其无效——这是调试时最让人困惑的“玄学”现象。
- 复现问题后,清空相关连接跟踪:
sudo conntrack -D --src-nat --dst-nat或更精准地删指定流:sudo conntrack -D -s 192.168.10.50 - 避免反复试错:添加新规则后,先停止客户端连接,等 conntrack 超时(默认约 5 分钟)或手动清理,再发起新连接
- 不要靠“持续 ping”来测试——它会维持旧 conntrack,换成 telnet 或 curl 发起全新 TCP 连接更可靠










