type
status
date
slug
summary
tags
category
icon
password
转载自Escape 原文链接:Docker防火墙管理
UFW
(Uncomplicated Firewall)是一种用户友好的 Linux
防火墙管理工具,可以轻松地配置和管理系统的网络安全。对于 Docker
容器,使用 UFW
可以方便地管理容器的网络访问权限。
但在使用 Docker 的环境中,UFW
(Uncomplicated Firewall)防火墙管理工具存在一个显著的问题:Docker
自动修改 iptables 规则,导致 UFW
无法有效管理Docker
容器发布的端口。这意味着即使 UFW 设置了阻止规则,Docker
仍可以暴露容器端口到公共网络,造成安全隐患。1. 问题描述
现在的 Docker 防火墙存在什么问题?
UFW
是 Ubuntu
上很流行的一个 iptables
前端(毕竟 ufw 其实也是在操作 iptables
的),可以非常方便的管理防火墙的规则。但是当安装了 Docker
之后,UFW
就无法管理 Docker
发布出来的端口了。具体现象,如下所示:- 在一个对外提供服务的服务器上启用了
UFW
进行防火墙管理,并且默认阻止所有未被允许的传入连接。
- 运行了一个
Docker
容器,并且使用p
选项来把该容器的某个端口发布到服务器的所有IP
地址上。
UFW
将不会阻止所有对8080
端口访问的请求,用命令ufw deny 8080
也无法阻止外部访问这个端口。
这个问题其实挺严重的,这意味着本来只是为了在 内部提供服务的一个端口被暴露在公共网络上。在网络上搜索 ufw docker 可以发现很多的讨论,都是在说这个问题的。基本上可以找到的解决办法就是首先禁用
docker
的 iptables
功能,但这也意味着放弃了 docker
的网络管理功能,很典型的现象就是 容器将无法访问外部网络。在有的文章中也提到了可以在 UFW
的配置文件中手工添加一条规则,比如 -A POSTROUTING ! -o docker0 -s 172.17.0.0/16 -j MASQUERADE
。但这也只是允许了 172.17.0.0/16
这个网络。如果有了新增的网络,我们也必须 手工再为新增的网络添加这样类似的 iptables
规则。因为
docker
的话,会新建一个 DOCKER
的链,如果容器使用 -p
绑定了端口,那么 docker
会自动去修改对应的 iptables
规则,所以从现象上来看就是 docker
在你的防火墙上打了一个洞。2. 期望目标
现在有什么解决方式呢?
目前网络上的解决方案都非常类似,而且也不优雅,我希望一个新的解决方案可以:
- 不要禁用
Docker
的iptables
功能,像往常一样由Docker
来管理自己的网络。这样有任何新增的Docker
网络时都无需手工维护iptables
规则,也避免了在Docker
中禁用iptables
之后可能带来的副作用。
- 公共网络不可以访问
Docker
发布出来的端口,即使是使用类似p 0.0.0.0:8080:80
的选项把端口发布在所有的IP
地址上。容器之间、内部网络之间都可以正常互相访问,只有公共网络不可以访问。 虽然可以让Docker
把容器的某一个端口映射到服务器的私有IP
地址上,这样公共网络上将不会访问到这个端口。但是这个服务器可能有多个私有IP
地址,这些私有IP
地址可能也会发生变化。
- 可以很方便的允许公共网络直接访问某个容器的端口,而无需额外的软件和配置。就像是用
ufw allow 8080
这样允许外部访问8080
端口,然后用ufw delete allow 8080
就不再允许外部访问。
3. 解决方式
现在这个脚本也支持 Docker Swarm 集群了
- 撤销原先的修改
如果已经按照目前网络上搜索到解决方案修改过了,请先修改回来。
- 解决方法
目前新的解决方案只需要修改一个
UFW
配置文件即可,Docker
的所有配置和选项都保持默认。然后重启 UFW
服务(sudo systemctl restart ufw
)。现在外部就已经无法访问 Docker
发布出来的任何端口了,但是容器内部以及私有网络地址上可以正常互相访问,而且容器也可以正常访问外部的网络。可能由于某些未知原因,重启 UFW
之后规则也无法生效,请重启服务器。DEEPSEEK默认配置+以上配置
如果希望允许外部网络访问
Docker
容器提供的服务,比如有一个容器的服务端口是 80
。这个命令会允许外部网络访问所有用 Docker
发布出来的并且内部服务端口为 80
的所有服务。请注意,这个端口 80
是容器的端口,而非使用 -p 0.0.0.0:8080:80
选项发布在服务器上的 8080
端口。bash
如果有多个容器的服务端口为
80
,但只希望外部网络访问某个特定的容器。比如该容器的私有地址为 172.17.0.2
,就用类似下面的命令。如果一个容器的服务是
UDP
协议,假如是 DNS
服务,可以用下面的命令来允许外部网络访问所有发布出来的 DNS
服务。同样的,如果只针对一个特定的容器,比如
IP
地址为 172.17.0.2
。4. 参考链接
送人玫瑰,手有余香!
- Author:DDDafa
- URL:http://preview.tangly1024.com/article/docker-ufw-port-management
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!