Docker 为什么会“篡改”你的防火墙规则?
Docker 为什么会“篡改”你的防火墙规则?
许多运维同学都遇到过:
刚写好的防火墙策略,针对Docker映射的端口就“失效”了。
其实不是错觉,Docker 确实会自动修改 iptables,并且插入自己的规则链。
一、Docker 为什么修改 iptables?
Docker 的网络功能依赖 Linux 的网络命名空间与虚拟网桥。
它需要做三件事:
- 建立容器虚拟网卡(veth pair);
- 设置 NAT,让容器能访问外网;
- 配置 DNAT,让主机端口映射到容器。
这些操作都离不开 iptables,所以 Docker 启动时会自动创建并维护规则。
二、Docker 插入了哪些链?
执行:
1 | |
会看到:
1 | |
含义如下:
- DOCKER-USER:用户自定义,Docker 不会修改;
- DOCKER:由 Docker 自动生成;
- DOCKER-ISOLATION-STAGE-1/2:用于网络隔离。
nat 表中还会有 DOCKER、POSTROUTING、PREROUTING 等链,用于 NAT 和端口映射。
三、firewalld 与 iptables 的顺序关系
在 CentOS / RHEL 系统中:
1 | |
firewalld 是 iptables 的封装层,动态维护自己的链。
但 Docker 直接操作底层 iptables,并插入在 firewalld 链的前面。
因此:
你通过
firewall-cmd添加的规则,可能在 Docker 的放行规则之后执行,从而被绕过。
四、正确的写法:使用 DOCKER-USER 链
Docker 预留了一个安全入口:DOCKER-USER 链。
这个链在 Docker 的所有规则之前调用,适合放自定义访问控制。
1 | |
1 | |
1 | |
🔹 一、链操作类参数
| 参数 | 全称 | 作用 |
|---|---|---|
-A |
–append | 向指定链的末尾追加规则 |
-I |
–insert | 向指定链的开头插入规则(或指定序号) |
-D |
–delete | 删除规则(可按序号或完整规则匹配删除) |
-R |
–replace | 替换某条规则 |
-L |
–list | 列出规则 |
-F |
–flush | 清空链中的规则 |
-Z |
–zero | 将计数器清零 |
-N |
–new-chain | 创建自定义链 |
-X |
–delete-chain | 删除自定义链(必须为空) |
-P |
–policy | 设置链的默认策略(如 ACCEPT 或 DROP) |
🔹 二、匹配条件类参数
| 参数 | 含义 | 示例 |
|---|---|---|
-s |
源地址(source) | -s 192.168.1.0/24 |
-d |
目标地址(destination) | -d 10.0.0.5 |
-p |
协议(protocol) | -p tcp、-p udp、-p icmp |
-i |
入接口(in-interface) | -i eth0 |
-o |
出接口(out-interface) | -o eth1 |
--sport |
源端口(source port) | --sport 22 |
--dport |
目标端口(destination port) | --dport 80 |
-m |
指定匹配模块 | -m state --state ESTABLISHED、-m conntrack --ctstate NEW |
🔹 三、动作类参数(目标 Target)
| 参数 | 说明 |
|---|---|
-j ACCEPT |
放行 |
-j DROP |
丢弃(无回应) |
-j REJECT |
拒绝(返回 ICMP 错误) |
-j LOG |
记录日志 |
-j RETURN |
从子链返回上层 |
-j DNAT / SNAT |
用于 NAT 表做地址转换 |
-j MASQUERADE |
源地址伪装(常用于共享上网) |
五、规则执行顺序示意
FORWARD 链调用顺序
1 | |
六、数据包流向示意图
下面这张简图展示了容器访问外网、主机访问容器时,
Docker、iptables 和 firewalld 的交互顺序:
1 | |
可以看到:
- Docker 自己的链优先级高于 firewalld;
- 只有 DOCKER-USER 位于 Docker 链之前;
- 因此自定义规则必须写在这里才真正生效。
七、总结
Docker 修改 iptables 是为了让容器网络“即插即用”,
但也容易让自定义防火墙规则失效。
记住三条原则:
- firewalld 是封装层,Docker 改动的是底层 iptables;
- 所有自定义控制写在 DOCKER-USER 链;
- 不依赖 zone 机制限制容器流量。
Docker 为什么会“篡改”你的防火墙规则?
http://www.yangchao.me/posts/119/