排查桥接环境下iptables MASQUERADE规则失效问题
看起来你已经把veth+网桥的命名空间环境搭得有模有样了,也配置了MASQUERADE和IP转发,但外网ping包有去无回——咱们一步步揪出问题所在:
1. 先确认MASQUERADE规则真的在匹配包
先执行这条命令看看nat表POSTROUTING链的规则状态:
iptables -t nat -L POSTROUTING -v -n
重点看你那条MASQUERADE规则的pkts和bytes计数器——如果你在ping 8.8.8.8的时候,这两个数字没涨,说明包根本没匹配到这条规则。虽然你的规则逻辑(源10.0.0.0/24、非my-br接口出去的包做SNAT)是对的,但有可能是规则被前面的其他nat规则“抢先”匹配了,或者你不小心把规则加到了错误的表。
如果计数器没变化,试试把这条规则插入到POSTROUTING链的最前面(用-I代替-A):
sudo iptables -t nat -I POSTROUTING -s 10.0.0.0/24 ! -o my-br -j MASQUERADE
再重新测试ping。
2. 确认IP转发是全局全接口生效的
你说已经开了IP转发,但很多发行版会默认限制特定接口的转发权限,光开全局的ip_forward可能不够。先执行这几条命令检查状态:
sysctl net.ipv4.ip_forward sysctl net.ipv4.conf.all.forwarding sysctl net.ipv4.conf.wlo1.forwarding sysctl net.ipv4.conf.my-br.forwarding
如果其中有任何一个返回值是0,就临时把它们改成1:
sudo sysctl -w net.ipv4.ip_forward=1 sudo sysctl -w net.ipv4.conf.all.forwarding=1 sudo sysctl -w net.ipv4.conf.wlo1.forwarding=1 sudo sysctl -w net.ipv4.conf.my-br.forwarding=1
3. 排查反向路径过滤(rp_filter)的干扰
Linux默认开启的严格反向路径过滤,经常会成为这类转发问题的“隐形杀手”。它会检查入站包的源IP是否能通过当前入站接口路由出去,一旦判断“路径不符”就直接丢包。
先临时关闭所有接口的rp_filter试试:
sudo sysctl -w net.ipv4.conf.all.rp_filter=0 sudo sysctl -w net.ipv4.conf.wlo1.rp_filter=0 sudo sysctl -w net.ipv4.conf.my-br.rp_filter=0
如果关闭后ping能通了,说明就是rp_filter的问题——你后续可以把它改成宽松模式(设置为2),不用一直保持关闭状态。
4. 检查iptables FORWARD链的默认策略
IP转发开了,但如果iptables的FORWARD链默认策略是DROP,那即使路由完全正确,包也会被拦截。先执行这条命令看FORWARD链的状态:
iptables -L FORWARD -v -n
如果默认策略是DROP,你需要添加两条规则允许转发双向流量:
# 允许从网桥到外网接口的出站流量 sudo iptables -A FORWARD -i my-br -o wlo1 -j ACCEPT # 允许从外网接口返回的、和已建立连接相关的流量 sudo iptables -A FORWARD -i wlo1 -o my-br -m state --state RELATED,ESTABLISHED -j ACCEPT
5. 先确认根命名空间本身能连外网
别笑,有时候我们会忽略最基础的问题——先在根命名空间直接ping 8.8.8.8,看看能不能通。如果根命名空间本身都连不上外网,那命名空间肯定也不行,这时候得先排查主机的外网连接问题(比如网关配置、DNS、主机防火墙)。
6. 用tcpdump追踪完整流量路径
之前你只在my-br上抓了包,现在在外网接口wlo1上也抓一下:
sudo tcpdump -i wlo1 icmp host 8.8.8.8
- 如果能看到ICMP请求包发出去,但没收到回复:问题出在主机到外网的链路(比如网关没转发、ISP拦截)
- 如果能看到回复包,但命名空间收不到:那就是根命名空间的转发/iptables配置有问题,回到前面的步骤重新排查
备注:内容来源于stack exchange,提问作者Alex Flint

