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 | |
五、规则执行顺序示意
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/