Docker 绕过防火墙的端口映射问题

问题发现

早上检查服务器时发现他妈的数据库被黑了,排查后才想起防火墙端口忘记关闭。立即登录服务器关闭了防火墙对应端口

但远程测试时发现:端口居然还能连上!


问题原因

Docker 网络流量示意图

我的数据库服务是通过 Docker 启动的,这正是问题的根源。

Docker 默认把所有转发到容器的流量全部放行,无条件 ACCEPT

Docker 的 iptables 行为

Docker 默认会在系统 iptables 中自动添加 NAT/FORWARD 规则,将映射端口直接放行。外部流量会绕过 INPUT 链,因此即使防火墙(UFW)没有开放端口,也能访问容器服务。

当 Docker 启动容器并映射端口(如 -p 3307:3306)时,会自动执行以下操作:

  1. 在 NAT 表的 PREROUTING 链添加 DNAT 规则,将宿主机端口转发到容器端口
  2. FORWARD 链添加 ACCEPT 规则,放行转发流量

流量路径分析

UFW 规则作用于 filter/INPUT 链,而外部访问 Docker 映射端口时,流量走的是:

1
外网 → PREROUTING (DNAT) → FORWARD → 容器

由于流量不经过 INPUT 链,所以即使 UFW 禁止了端口,Docker 映射的端口仍然可以被外部访问。


解决方案

方案一:禁止 Docker 自动管理 iptables(推荐)

编辑 Docker 配置文件:

1
sudo vim /etc/docker/daemon.json

添加以下内容:

1
2
3
{
"iptables": false
}

重启 Docker 服务:

1
sudo systemctl restart docker

这样防火墙(UFW、iptables)就能真正掌控端口访问,Docker 不再绕过 INPUT 链。

⚠️ 注意:禁用后需要手动配置容器网络的 NAT 规则,容器间通信和外部访问都需要自行管理。

方案二:使用 UFW-Docker 插件

安装 ufw-docker 脚本,让 UFW 能正确管理 Docker 端口:

1
2
3
4
5
sudo wget -O /usr/local/bin/ufw-docker \
https://github.com/chaifeng/ufw-docker/raw/master/ufw-docker
sudo chmod +x /usr/local/bin/ufw-docker
sudo ufw-docker install
sudo systemctl restart ufw

允许特定 IP 访问容器端口:

1
sudo ufw-docker allow mysql 3306/tcp 192.168.1.100

常见坑排查清单

问题现象 可能原因 排查命令
防火墙关了端口还能访问 Docker 绑定了 iptables iptables -t nat -L -n
容器无法访问外网 禁用 iptables 后未配置 NAT iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -j MASQUERADE
容器间无法通信 网络模式或 FORWARD 链问题 docker network ls
UFW 状态显示正常但不生效 Docker 规则优先级更高 iptables -L DOCKER-USER -n

总结

Docker 默认的 iptables 管理机制虽然方便,但会绕过系统防火墙,带来安全隐患。生产环境建议:

  1. 敏感服务不要直接映射到公网,使用 127.0.0.1 绑定
  2. 配置 iptables: false 或使用 ufw-docker 插件
  3. 定期检查 iptables 规则iptables -L -niptables -t nat -L -n
  4. 数据库等关键服务设置强密码,并限制访问 IP

安全无小事,别等被黑了才想起来补救。


Docker 绕过防火墙的端口映射问题
https://blog.newpon.top/2025/12/01/服务器端口拦截问题/
作者
John Doe
发布于
2025年12月1日
许可协议