精准阻断 Docker 容器映射端口:流量路径诊断与 iptables 配置实战指南
核心原则:不猜路径,只验流量。规则生效的前提是------流量必须经过你配置的链。
为什么你的 iptables 规则"配置了却无效"?
你是否经历过:
- 规则顺序正确 ✅
- 链选择"理论上合理" ✅
- 但外部仍可访问 ❌
- 规则计数始终为 0 ❌
根本原因 :
你配置了 INPUT 链,但流量实际走 FORWARD 链
你依赖"有无 docker-proxy 进程"判断路径 → 完全不可靠
你根据"容器网络模式"推断路径 → 存在例外场景
真相 :Docker 的流量路径由 内核实际处理路径 决定,与进程存在、配置文件无关。
唯一可靠方法:用工具亲眼看见流量去了哪。
三步诊断
1:确认流量是否抵达宿主机
bash
sudo tcpdump -i any -nn port <端口> -c 3
- 有包 → 流量已到宿主机,进入步骤 2
2:捕获流量经过哪条链(关键!)
bash
# 插入日志规则(临时)
sudo iptables -I FORWARD 1 -p tcp --dport <端口> -j LOG --log-prefix "CHK_FORWARD: "
sudo iptables -I INPUT 1 -p tcp --dport <端口> -j LOG --log-prefix "CHK_INPUT: "
# 外部发起新连接(关键:用新连接!)
# curl http://<宿主机IP>:<端口> (从另一台机器)
# 查看内核日志
dmesg -T | grep "CHK_" | tail -3
# 清理测试规则
sudo iptables -D FORWARD 1
sudo iptables -D INPUT 1
结果解读:
| 日志内容 | 流量路径 | 应配置的链 |
|---|---|---|
CHK_FORWARD: ... |
经过 FORWARD 链 | DOCKER-USER |
CHK_INPUT: ... |
经过 INPUT 链 | INPUT |
| 两者均无 | 被 raw 表 NOTRACK / conntrack 跳过 | 检查 iptables -t raw -L |
3:验证规则是否触发
bash
sudo iptables -Z <链名> # 清零计数
# 外部发起新连接
sudo iptables -L <链名> -v -n | grep <端口>
- DROP 计数 >0 → 规则生效
- 计数=0 → 流量未经过此链(回到步骤 2)
按路径精准配置
方案 A:流量走 FORWARD 链(bridge/default 网络常见)
bash
# 允许本机 localhost 访问(源 IP 为 127.0.0.1)
sudo iptables -I DOCKER-USER -s 127.0.0.1 -p tcp --dport <端口> -j ACCEPT
# 拦截其他所有来源
sudo iptables -I DOCKER-USER -p tcp --dport <端口> -j DROP
📌 为什么有效:
DOCKER-USER是 Docker 官方预留链,所有 bridge 网络流量必经此链- 本机访问
localhost:端口经 DNAT 后,源 IP 仍为127.0.0.1,可被-s 127.0.0.1匹配- Docker 重启/容器重启均不覆盖此链
方案 B:流量走 INPUT 链(host 网络 或 userland-proxy 主导场景)
bash
# IPv4
sudo iptables -I INPUT -s 127.0.0.1 -p tcp --dport <端口> -j ACCEPT
sudo iptables -I INPUT -p tcp --dport <端口> -j DROP
# IPv6(极易遗漏!)
sudo ip6tables -I INPUT -s ::1 -p tcp --dport <端口> -j ACCEPT
sudo ip6tables -I INPUT -p tcp --dport <端口> -j DROP
📌 注意:
- 仅当
dmesg明确显示CHK_INPUT时使用- 必须同步配置 IPv4 + IPv6,否则 IPv6 仍可访问
附:诊断命令速查表
| 目的 | 命令 |
|---|---|
| 看流量是否到主机 | sudo tcpdump -i any -nn port <端口> |
| 看走 INPUT 还是 FORWARD | sudo iptables -I [链] ... -j LOG + `dmesg |
| 看规则是否触发 | sudo iptables -Z <链> → 测试 → sudo iptables -L <链> -v -n |
| 检查 IPv6 规则 | `sudo ip6tables -L INPUT -n --line-numbers |
| 持久化规则(Debian/Ubuntu) | sudo netfilter-persistent save |