IPTables反射NAT配置异常:PREROUTING规则有流量命中但POSTROUTING对应SNAT规则无匹配
首先咱们先拆解下当前的规则和问题点,一步步来排查:
一、当前POSTROUTING规则的核心问题
你那条POSTROUTING的SNAT规则(编号3)的匹配条件存在逻辑矛盾:
SNAT 6 -- * vmbr0 10.0.0.10 10.0.0.10 tcp dpt:80 to:xxx.212.198.74
当PREROUTING规则4把来自10.0.0.10、目标为xxx.212.198.74:80的流量DNAT到10.0.0.10:80后,数据包的源和目标IP变成了同一个子网地址。此时Linux内核会直接走本地转发逻辑,不会将数据包发往vmbr0接口,自然永远匹配不到这条带vmbr0出接口限制的SNAT规则。
二、反射NAT(Hairpin NAT)的规则调整方案
针对你的场景,需要调整POSTROUTING规则的匹配逻辑,去掉不必要的接口限制,确保回流流量能被正确SNAT:
方案1:精准匹配当前场景的流量
iptables -t nat -A POSTROUTING -s 10.0.0.10 -d 10.0.0.10 -p tcp --dport 80 -j SNAT --to-source xxx.212.198.74
方案2:通用匹配所有内部回流的DNAT流量
如果以后还要添加其他端口的反射NAT,可以用连接跟踪模块识别DNAT状态的流量:
iptables -t nat -A POSTROUTING -m conntrack --ctstate DNAT -s 10.0.0.0/24 -d 10.0.0.0/24 -j SNAT --to-source xxx.212.198.74
三、实用调试方法推荐
如果调整规则后仍有问题,可以用以下工具深入排查:
追踪数据包完整处理流程
利用iptables的TRACE目标(需要内核支持),查看数据包在各个链中的匹配情况:# 加载必要模块 modprobe nf_log_ipv4 # 添加TRACE规则追踪目标流量 iptables -t raw -A PREROUTING -s 10.0.0.10 -p tcp --dport 80 -j TRACE # 实时查看内核日志(不同系统日志路径可能是/var/log/kern.log) dmesg -w日志会清晰显示数据包经过每一条iptables规则的结果,帮你定位哪一步出了问题。
查看连接跟踪会话状态
用conntrack工具确认DNAT会话是否正常建立:conntrack -L -s 10.0.0.10 -d xxx.212.198.74 -p tcp --dport 80如果能看到对应的会话记录,说明PREROUTING的DNAT已经生效,问题出在后续的转发或SNAT环节。
检查内核转发和路由配置
首先确保内核开启了IP转发:sysctl net.ipv4.ip_forward # 若输出为0,临时开启:sysctl -w net.ipv4.ip_forward=1,写入/etc/sysctl.conf可永久生效再确认10.0.0.0/24子网的路由是否正常:
ip route show 10.0.0.0/24
四、额外注意事项
你服务器上运行的Tailscale会自动生成ts-postrouting等自定义链,这些规则的执行顺序可能会优先于你的自定义规则。可以用iptables-save -c查看完整规则列表,确保你的SNAT规则排在Tailscale相关规则的前面,避免被提前匹配拦截。
备注:内容来源于stack exchange,提问作者C. Hediger

