UFW 是 Ubuntu 上很流行的一个 iptables 前端,可以非常方便的管理防火墙的规则。但是当安装了 Docker,UFW 无法管理 Docker 发布出来的端口了。

具体现象是:

在一个对外提供服务的服务器上启用了 UFW,并且默认阻止所有未被允许的传入连接。

运行了一个 Docker 容器,并且使用 -p 选项来把该容器的某个端口发布到服务器的所有 IP 地址上。比如:docker run -d --name httpd -p 0.0.0.0:8080:80 httpd:alpine 将会运行一个 httpd 服务,并且将容器的 80 端口发布到服务器的 8080 端口上。

UFW 将不会阻止所有对 8080 端口访问的请求,用命令 ufw deny 8080 也无法阻止外部访问这个端口。

这个问题其实挺严重的,这意味着本来只是为了在内部提供服务的一个端口被暴露在公共网络上。

旧方案

见文章

存在问题:

http获取到的IP是docker网关的IP:172.18.0.1,不能得到用户真实的IP。通过network_mode: host 解决。但是如果2个容器占用相同的端口,就必须修改1个容器中的端口,使环境变复杂。

新方案ufw-docker

安装

下载 ufw-docker 脚本

sudo wget -O /usr/local/bin/ufw-docker \
  https://github.com/chaifeng/ufw-docker/raw/master/ufw-docker
chmod +x /usr/local/bin/ufw-docker

使用下列命令来修改 ufw 的 after.rules 文件

ufw-docker install

这个命令做了以下事情:

  • 备份文件 /etc/ufw/after.rules

  • 把 UFW 和 Docker 的相关规则添加到文件 after.rules 的末尾

使用方法

显示帮助

ufw-docker help

检查 UFW 配置文件中防火墙规则的安装

ufw-docker check

更新 UFW 的配置文件,添加必要的防火墙规则

ufw-docker install

显示当前防火墙允许的转发规则

ufw-docker status

列出所有和容器 httpd 相关的防火墙规则

ufw-docker list httpd

暴露容器 httpd 的 80 端口

ufw-docker allow httpd 80

暴露容器 httpd 的 443 端口,且协议为 tcp

ufw-docker allow httpd 443/tcp

如果容器 httpd 绑定到多个网络上,暴露其 443 端口,协议为 tcp,网络为 foobar-external-network

ufw-docker allow httpd 443/tcp foobar-external-network

把容器 httpd 的所有映射端口都暴露出来

ufw-docker allow httpd

删除所有和容器 httpd 相关的防火墙规则

ufw-docker delete allow httpd

删除容器 httpd 的 tcp 端口 443 的规则

ufw-docker delete allow httpd 443/tcp

暴露服务 web 的 80 端口

docker service create --name web --publish 8080:80 httpd:alpine

ufw-docker service allow web 80

# 或者

ufw-docker service allow web 80/tcp

删除与服务 web 相关的规则

ufw-docker service delete allow web

问题

虚拟网络无法访问,新增规则解决

vim /etc/iptables/rules.v4
-A ufw-user-forward -s 来源IP/32 -j ACCEPT

操作方法见文章

相关文档

https://github.com/chaifeng/ufw-docker