直接查iptables是否拦容器流量:先执行sudo iptables -l forward | head -n 2确认forward链策略是否为drop;再用iptables -l input -n -v | grep 端口和iptables -t nat -vnl prerouting | grep -e "(dnat|masquerade)"检查规则命中与存在性;最后tcpdump -i any port 端口验证包是否抵达及被哪条规则拦截。

直接查 iptables 是否在拦容器流量,别绕弯。Docker 和宿主机 iptables 规则常打架,尤其在转发、端口映射、出网这几个环节,规则一错,容器就“失联”,但现象不报错,得靠命令盯住关键链和计数。
看 FORWARD 链默认策略是不是 DROP
Docker 启动后会把 filter 表 FORWARD 链的默认策略设成 DROP,虚拟机、桥接流量(比如从 virbr0 进来的包)还没匹配任何规则就被丢弃,根本不会进后续流程。
- 执行 sudo iptables -L FORWARD | head -n 2,如果第一行是 Chain FORWARD (policy DROP),就是它在作怪
- 别改 policy(Docker 重启就重置),改用 DOCKER-USER 链提前放行:
sudo iptables -I DOCKER-USER -i virbr0 -j ACCEPTsudo iptables -I DOCKER-USER -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
查自定义规则有没有插错位置
手动加的封禁或限流规则,如果写在 INPUT 或 FORWARD 主链里,Docker 每次 reload 规则时都会把它压到下面,导致不生效——特别是容器端口映射(-p)对外暴露失败时,大概率是这个原因。
- 运行 iptables -L INPUT -n -v | grep -A 2 "你的目标端口",看对应规则的 packets 计数是否增长;不涨说明没命中,可能被上面的规则跳过了
- 所有针对容器流量的规则,必须插进 DOCKER-USER 链(它在 Docker 所有自动规则之前):
iptables -I DOCKER-USER -s 192.168.100.50 -p tcp --dport 8080 -j DROP
核对 NAT 表里有没有 MASQUERADE 和 DNAT
容器 ping 不通外网(比如 8.8.8.8),或者宿主机用 -p 映射的端口访问不了,往往是因为 nat 表 PREROUTING 或 POSTROUTING 缺了关键规则。
- 执行 iptables -t nat -vnL PREROUTING | grep -E "(DNAT|MASQUERADE)",确认有类似:
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.2:80MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0 - 没有?可能是被 firewalld/ufw 清掉,或脚本误删;可临时重启 Docker:
sudo systemctl restart docker,观察规则是否恢复
抓包验证请求到底卡在哪一层
光看规则列表不够,得确认包真到了主机、又真被某条规则吃了。
- 在宿主机上监听容器端口入向流量:
sudo tcpdump -i any port 8080 -nn,如果完全没包,说明请求没到宿主机(上游路由或安全组问题) - 如果看到 SYN 包进来但没回包,再查对应链的 DROP 规则计数:
iptables -L INPUT -n -v | grep :8080或iptables -L FORWARD -n -v | grep "172.17.0." - 加日志临时标记拦截点:
sudo iptables -I INPUT 1 -p tcp --dport 8080 -j LOG --log-prefix "BLOCK-8080: "
然后journalctl -k | grep "BLOCK-8080"看是否真触发











