我在 CentOS 7 上安装了 docker,并且正在运行firewallD。
从我的容器内部,转到主机(默认 172.17.42.1)
防火墙开启
container# nc -v 172.17.42.1 4243
nc: connect to 172.17.42.1 port 4243 (tcp) failed: No route to host
防火墙关闭
container# nc -v 172.17.42.1 4243
Connection to 172.17.42.1 4243 port [tcp/*] succeeded!
我已经阅读了有关firewalld的文档,但我并不完全理解它们。有没有一种方法可以简单地允许 docker 容器(我猜是在 docker0 适配器上)中的所有内容不受限制地访问主机?
答案1
也许比之前的答案更好;
firewall-cmd --permanent --zone=trusted --change-interface=docker0
firewall-cmd --permanent --zone=trusted --add-port=4243/tcp
firewall-cmd --reload
答案2
这些命令成功了:
firewall-cmd --permanent --zone=trusted --add-interface=docker0
firewall-cmd --permanent --zone=trusted --add-port=4243/tcp
答案3
所接受的解决方案对某些人有效但对其他人无效的原因之一在于防火墙的设计问题。 Firewalld 仅处理任何连接的第一个匹配区域。它还先处理基于 IP 地址的区域,然后再处理基于接口的区域。只要您的任何区域碰巧包含 docker 正在使用的 IP 地址,受信任区域中的 ACCEPT 规则就永远不会得到处理。
要验证这一点,您可以查看生成的 iptables 规则,除非您使用 nbt 后端:
iptables -vnL | less
解决方案是使用firewalld 直接规则而不是受信任区域。直接规则总是首先被处理。例如,对于端口 3306(即本地主机上的 mysqld),您需要以下规则:
/bin/firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 10 -p tcp --dport 3306 -i docker0 -j ACCEPT
如果您在没有 --permanent 开关的情况下重复相同的命令,firewalld 将为您即时进行更改,并且您不需要重新启动 docker。
第二个原因是,根据 docker 的版本和您配置的网络,流量实际上可能不会流经 docker0 接口,而是通过单独的桥接接口。您可以使用命令查看该界面
ip address show
您必须使用此桥接口重复上面的直接规则语句。
你也可以在docker中指定自己的网络。这篇文章描述了这个过程:https://serverfault.com/questions/885470/how-to-configure-firewall-on-user-define-docker-bridge
简而言之,您可以在 docker 文件中指定网络部分,如下所示:
version: '3'
.
.
.
networks:
mynetwork:
driver_opts:
com.docker.network.bridge.name: mynetwork_name
您也可以在命令行上执行此操作。
答案4
不幸的是,上述解决方案都不适合我,一个容器仍然无法访问另一个容器。
解决方案:禁用防火墙
虽然我明白这是特别糟糕iptables
,它确实有效,并且我可以按照您需要的方式配置来减轻禁用防火墙的风险。
sudo systemctl stop firewalld
sudo systemctl disable firewalld
不需要重新启动 docker,但以防万一:sudo systemctl restart docker