

什么情况下需要用到UFW-Docker#
如果你的服务器是阿里云腾讯或者微软谷歌这样的大服务器厂商,那么恭喜你,你不用纠结Docker容器直接暴露端口到公网的问题,因为大厂自研的防火墙有足够的实力把Docker暴露在外的端口拦截下来。
如果你的服务器厂商很小或者没有足够的实力去开发防火墙,那么你可以尝试Ufw-Docker这个开源项目,他可以通过ufw防火墙来防止你的docker容器端口暴露。
为什么Ufw无法拦截Dokcer容器的端口#
因为 Docker 在设计上会直接操作 Linux 内核的网络包过滤框架 iptables,而且其规则优先级通常高于 UFW 设置的规则。
Docker 直接操作 iptables#
-
当 Docker 启动并发布端口(例如,使用 docker run -p 8080:80 …)时,它会直接在 iptables 中添加规则,以便将宿主机的端口流量转发到容器的内部端口。
-
这些规则通常被添加到 iptables 的 DOCKER链或 FORWARD 链中,并且这些链的处理顺序可能在 UFW 创建的规则链之前。
iptables 规则的优先级#
- iptables 按照规则链的顺序处理网络数据包。如果 Docker 插入的规则允许流量通过,那么数据包可能在到达 UFW 定义的 DROP 或 REJECT 规则之前就已经被接受并转发了。
- UFW 本质上是 iptables 的一个用户友好前端。它管理的规则也是 iptables 规则的一部分,但 Docker 的直接干预会绕过 UFW 的管理逻辑。
网络地址转换 (NAT)#
- Docker 广泛使用 NAT(特别是 SNAT 和 DNAT)来实现容器与外部网络的通信以及端口映射。
- Docker 会在 nat表中创建规则,这些规则在数据包进入 filter表(UFW 主要操作的表)之前就可能改变了数据包的目标地址和端口。这意味着 UFW 看到的可能是已经被修改过的数据包,其原始意图可能已经被 Docker 的 NAT 规则处理。
简单来说,Docker 和 UFW 都在尝试管理同一个底层防火墙机制 (iptables),但 Docker 的操作更为底层和直接,导致 UFW 的规则对 Docker 发布的端口无效。
安装UFW-Docker#
在安装UFW-Docker之前确保安装了UFW,如果你没安装可以根据以下命令安装并启用
sudo apt install ufw
plaintextufw enable
plaintext安装UFW-Docker#
sudo wget -O /usr/local/bin/ufw-docker https://github.com/chaifeng/ufw-docker/raw/master/ufw-docker
plaintext赋予ufw-docker执行权限#
sudo chmod +x /usr/local/bin/ufw-docker
plaintext安装完配置后,重启 UFW#
ufw-docker install
plaintextsudo systemctl restart ufw
plaintext如果在尝试以上命令依然无效,你可以尝试reboot
重启服务器。
使用UFW-Docker#
和使用UFW大致一样,这里我docker run 启动并运行了一个github加速项目gh-proxy ↗作为演示。
docker run -d --name="gh-proxy-py" \
-p 0.0.0.0:3000:80 \
--restart=always \
hunsh/gh-proxy-py:latest
plaintext然后ufw关闭了3000端口的对外访问,然而公网依旧可以访问:
ufw deny 3000/tcp
plaintext接下来我们使用UFW-Docker来把docker拦住!
用docker ps命令查看运行的容器#
docker ps
plaintext关闭容器对外访问#
复制ID或者容器的名字使用ufw-docker命令,我这里关闭容器对外访问的IP的命令是:
ufw-docker delete allow d4b427a13f2b
plaintext那么经过这番操作以后公网已经无法访问了,如果你已经还可以访问,建议可以回去仔细阅读博文看看有没有那一步漏的。
恢复容器的对外访问#
如果你想重新打开容器对外访问的IP,你可以输入这个命令
ufw-docker allow d4b427a13f2b
plaintext现在你又可以在公网访问这个docker容器部署的网站了。