iptables透明转发需三个硬性前提:开启ip转发、forward链策略非drop、dnat后配精确forward放行规则;缺一即导致流量静默丢弃。

为什么开了 ip_forward 还不转发?
这是最常踩的坑:很多人只执行 echo 1 > /proc/sys/net/ipv4/ip_forward,但忘了检查 iptables -L FORWARD 的默认策略。如果当前是 DROP,哪怕你写了完美的 DNAT 规则,包也会在 FORWARD 链被直接丢弃,连日志都不会打(除非你加了 LOG 规则)。
- 先确认 FORWARD 默认策略:
iptables -L FORWARD -n | head -1,看到policy DROP就要警惕 - 临时放通(测试用):
iptables -P FORWARD ACCEPT - 生产环境必须精确放行:
iptables -A FORWARD -i eth0 -o eth1 -d 192.168.2.5 -p tcp --dport 22 -j ACCEPT,其中eth0是外网口,eth1是内网口 - 别忘了放回程流量:
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
PREROUTING + DNAT 后流量去哪了?
DNAT 只改目的 IP 和端口,不决定路由走向。包经过 PREROUTING 后,内核会重新查路由表——如果目标主机不在本机直连网段,且没配置静态路由,包就会被扔进黑洞。
PyCharm 2026.2.0.1 Linux版提供 JetBrains 官方 2026.2.0.1 版本安装包,适合需要指定 PyCharm 版本进行 Python 项目开发、运行和调试的用户。
- 确保目标主机可达:
ping -I eth1 192.168.2.5(指定从内网口出) - 检查路由:
ip route get 192.168.2.5,输出应含dev eth1;若显示dev lo或报Network is unreachable,说明路由缺失 - 必要时加静态路由:
ip route add 192.168.2.0/24 via 192.168.1.1 dev eth1(按实际网关调整) - DNAT 规则本身要绑定入口接口,避免误匹配本地发起的包:
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8080 -j DNAT --to 192.168.2.5:80
UDP 转发为什么有时通有时不通?
UDP 是无连接协议,iptables 不会自动跟踪连接状态,所以 FORWARD 链无法靠 ESTABLISHED,RELATED 放行回程包——必须显式允许双向端口。
- 正向放行(外网→内网):
iptables -A FORWARD -i eth0 -o eth1 -d 192.168.2.5 -p udp --dport 53 -j ACCEPT - 反向放行(内网→外网,源端口即 DNS 响应端口):
iptables -A FORWARD -i eth1 -o eth0 -s 192.168.2.5 -p udp --sport 53 -j ACCEPT - 别用
--dport 53匹配响应包——DNS 响应的目的端口是客户端随机端口,不是 53 - 如需泛化匹配,可配合
ipset或启用连接追踪:modprobe nf_conntrack_udp,再用state --state NEW,ESTABLISHED
透明代理场景下如何避免循环?
当你把局域网流量重定向到本机代理(比如 REDIRECT --to-port 1080),代理服务自己发出的请求如果也匹配该规则,就会无限套娃。
- 在 PREROUTING 链最前面加排除规则:
iptables -t nat -I PREROUTING -s 127.0.0.1 -j RETURN - 排除代理服务所在网段(如 Docker 容器):
iptables -t nat -I PREROUTING -s 172.17.0.0/16 -j RETURN - 更稳妥的做法是用
owner模块(仅限 OUTPUT 链):iptables -t nat -A OUTPUT -m owner ! --uid-owner proxyuser -p tcp --dport 80 -j REDIRECT --to-port 1080 - 注意:
owner模块不支持 PREROUTING,所以网关模式只能靠地址或接口排除
xt_socket 和 nf_tproxy_ipv4 内核模块,而 REDIRECT 在 OUTPUT 链生效的前提是本机路由能正确指向 lo 接口。这些细节不会报错,但会让规则看起来“完全没作用”。










