我有一台装有 Docker 的 Ubuntu 服务器,用于提供 MySQL 和 SSH/SFTP 服务,我需要除以下端口之外的所有端口:3306和22设置防火墙,这是一个非常标准和简单的要求,对吧?
现在,我设法找到了一个某种解决方案但它对我来说并没有完全发挥作用,因为应用它之后,要么:
- 我无法访问任何提到的服务(默认情况下)
- 我无法从容器内访问互联网(如果我将
iptables: false
Docker 的守护进程.json配置文件)
我尝试了许多其他搜索结果,但它们大多非常复杂,我不明白它们在做什么,或者它们的脚本太多,使得我这个 iptables 门外汉无法从中获得任何东西。
提出的解决方案看起来相当简单且易于理解,但整个 Docker 网络的复杂性使其调试变得更加困难。
有人可以分享他们针对 Docker 主机的工作 iptables 规则吗,或者至少为我指明正确的方向?
我使用 docker-compose 来启动服务,这是我的 yaml:
version: '3.7'
services:
mysql:
container_name: 'mysql'
image: mysql:8.0.13
command: --default-authentication-plugin=mysql_native_password
user: 1000:1000
ports:
- "3306:3306"
volumes:
- ./data:/var/lib/mysql
- ./config/custom.cnf:/etc/mysql/conf.d/custom.cnf
networks:
- database
restart: always
networks:
database:
driver: bridge
编辑: 我发现,至少从长远来看,允许 Docker 管理 iptables 规则是推荐的,而且要求不高,让 Docker 打开所需的端口是可以的,尽管我没有按照自己喜欢的方式这样做,但它仍然有效。我现在想要知道是否可以使用 iptables 来阻止 Docker 打开的端口以及如何阻止(也许通过 mangle 预路由?)。有什么建议吗?非常感谢!
答案1
我无法从容器内访问互联网(如果我在 Docker 的 daemon.json 配置文件中输入 iptables: false)
Docker 依靠 iptables 来配置其网络。这包括用于处理外部网络访问的 NAT 规则,以及用于配置容器在 docker 网络上相互访问的许多其他规则。默认情况下,此访问是开放的,但在创建网络时可以选择限制外部访问和容器间通信。因此,我不建议iptables
在 docker 中将选项设置为 false,因为正如您所见,这会破坏所有这些功能。
在主机上发布端口会隐式允许外部访问。因此,避免外部访问的最简单方法是不发布端口。您可以将端口发布到特定接口上,例如,127.0.0.1:8080:80
在主机的环回接口 ( 127.0.0.1
) 上发布端口 8080 以连接到容器的端口 80,并且该环回接口不可从外部访问。但是,如果无法将端口保持未发布状态,则可以使用 iptables 来实现。
我现在想要知道是否可以使用 iptables 来阻止 Docker 打开的端口以及如何
这可以通过修改过滤器链来实现DOCKER-USER
。你可以找到这样的例子,例如:
$ iptables -I DOCKER-USER -i ext_if ! -s 192.168.1.0/24 -j DROP
来自以下文档:https://docs.docker.com/network/iptables/
请注意,端口是由在过滤规则之前运行的一些修改规则所改变的,因此如果您想按端口进行过滤,则需要使用 conntrack 来获取原始目标端口:
$ iptables -I DOCKER-USER -i eth0 -p tcp \
-m conntrack --ctorigdstport 8080 -j DROP
$ iptables -I DOCKER-USER -i eth0 -s 10.0.0.0/24 -p tcp \
-m conntrack --ctorigdstport 8080 -j ACCEPT
请注意,DOCKER-USER 中有一个默认规则是接受所有内容,因此您需要将规则插入到链的顶部(-I
),而不是附加到末尾(-A
)。
答案2
此时我想要的是找出是否可以使用 iptables 来阻止 Docker 打开的端口以及如何阻止(也许通过 mangle 预路由?)。
经过大量的研究和测试,我发现只公开你想要的端口而不公开docker端口的最好(也是最简单)的方法是将IP设置为docker-compose.yml
127.0.0.1(只公开给主机)
ports:
- "127.0.0.1:3306:3306"
然后您可以使用 nginx 或任何其他反向代理来向外部公开。
这边走:
- 你不需要添加 DOCKER-USER iptables 规则每次重启docker
- 端口 3306 仅在主机内部公开
- Docker 可以根据自己的需要来管理 iptables 规则。