50

I have docker installed on CentOS 7 and I am running firewallD.

From inside my container, going to the host (default 172.17.42.1)

With firewall on

container# nc -v  172.17.42.1  4243
nc: connect to 172.17.42.1 port 4243 (tcp) failed: No route to host

with firewall shutdown

container# nc -v  172.17.42.1  4243
Connection to 172.17.42.1 4243 port [tcp/*] succeeded!

I've read the docs on firewalld and I don't fully understand them. Is there a way to simply allow everything in a docker container (I guess on the docker0 adapter) unrestricted access to the host?

adapt-dev
  • 1,329
  • 2
  • 13
  • 18

7 Answers7

53

Maybe better than earlier answer;

firewall-cmd --permanent --zone=trusted --change-interface=docker0
firewall-cmd --permanent --zone=trusted --add-port=4243/tcp
firewall-cmd --reload
kjetildm
  • 654
  • 6
  • 5
  • 13
    I believe the `add-port` is superfluous. If `docker0` is marked trusted, that port will be let through anyway. – Matt Hughes Jan 19 '16 at 14:11
  • 7
    @MattHughes It worked for me without the `add-port`. You also need to **restart docker**. – rdupz May 11 '16 at 11:57
  • 1
    Worked after firewalld restart, not docker – cybersoft Apr 14 '19 at 18:48
  • Docker manipulates iptables, and reloading firewalld will destroy those iptables rules. You have to restart the docker daemon after restarting or reloading firewalld. – Kevin Keane Mar 21 '20 at 03:47
  • Restarting docker is a must. Refer to https://success.docker.com/article/why-am-i-having-network-problems-after-firewalld-is-restarted – silencej Apr 03 '20 at 06:48
  • 2
    This induced `Error creating default "bridge" network: Failed to program NAT chain: ZONE_CONFLICT: 'docker0' already bound to a zone` for me, even after a full reboot – JamesTheAwesomeDude Jan 28 '21 at 00:48
  • @JamesTheAwesomeDude same for me. Were you able to figure out what caused this? – Hassan Apr 13 '21 at 05:24
  • 1
    @Hassan No; this whole thing is a nightmare to me. I've switched to an external firewall because of it. I think that we may just be screwed until [#461](https://github.com/firewalld/firewalld/issues/461) is resolved. – JamesTheAwesomeDude Apr 13 '21 at 22:52
  • If you are running Docker version 20.10.0 or higher with firewalld on your system with --iptables enabled, Docker automatically creates a firewalld zone called docker and inserts all the network interfaces it creates (for example, docker0) into the docker zone to allow seamless networking. https://docs.docker.com/network/iptables/ – LennyLip May 19 '21 at 07:13
  • 2
    @Jay If you have a better answer, please write it as a new answer instead of editing an existing answer. If the community agrees with you, you will receive credit for it in the form of upvotes. You can explicitly add a reference to the answer you want to improve on in your answer, to point out possible problems with an existing answer. – AdminBee May 06 '22 at 09:05
14

Theses commands did the trick:

firewall-cmd --permanent --zone=trusted --add-interface=docker0
firewall-cmd --permanent --zone=trusted --add-port=4243/tcp
cuonglm
  • 150,973
  • 38
  • 327
  • 406
adapt-dev
  • 1,329
  • 2
  • 13
  • 18
7

One reason the accepted solution works for some people but not for others lies in a design issue of firewalld. Firewalld only processes the first matching zone for any connections. It also processes zones based on IP address before zones based on interfaces. As long as any of your zones happens to include the IP addresses docker is using, the ACCEPT rule in the trusted zone will never get processed.

To verify this, you can look at the generated iptables rules unless you are using the nbt backend:

iptables -vnL | less

The solution is to use a firewalld direct rule instead of the trusted zone. Direct rules are always processed first. For example, for port 3306 (i.e., mysqld on the local host), you'd need this rule:

/bin/firewall-cmd --direct --permanent --add-rule ipv4 filter INPUT 10 -p tcp --dport 3306 -i docker0 -j ACCEPT

If you repeat the same command without the --permanent switch, firewalld will make the change on the fly for you, and you should not need to restart docker.

A second reason is that, depending on the version of docker and the networking you configured, traffic may not actually flow across the docker0 interface, but through a separate bridge interface. You can see that interface with the command

ip address show

You will have to repeat the direct-rule statement above with this bridge interface.

You can also specify your own network in docker. This post describes the process: https://serverfault.com/questions/885470/how-to-configure-firewall-on-user-defined-docker-bridge

The short version is that you specify the networks section in a docker-file, like this:

version: '3'
  .
  .
  .
networks:
  mynetwork:
    driver_opts:
      com.docker.network.bridge.name: mynetwork_name

You can also do this on the command line.

Kevin Keane
  • 619
  • 7
  • 14
6

I had problems with this as well; this did the trick for me:

firewall-cmd --zone=public --add-masquerade --permanent

From: https://serverfault.com/questions/987686/no-network-connectivity-to-from-docker-ce-container-on-centos-8

user2657469
  • 61
  • 1
  • 1
2

Unfortunately, none of above solutions worked for me, one container was still not able to access another container.

Solution: disable firewalld

While I understand this is really bad, it actually works and the risks of disabled firewall can be mitigated my configuring iptables in the way you need.

sudo systemctl stop firewalld
sudo systemctl disable firewalld

Restarting docker is not needed, but just in case: sudo systemctl restart docker

The Godfather
  • 331
  • 3
  • 7
2

the following allowed docker to access the internet on CentOS 7 with firewalld

firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 4 -i docker0 -j ACCEPT
firewall-cmd --reload
systemctl restart docker
0

I encountered the same issue, but putting docker0 in the Trusted Zone didn't work since the traffic wasn't coming from docker0. I actually had two docker related connections.

5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:f1:89:6d:6a brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0

6: br-2800c2ad17b6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:8a:7d:85:d5 brd ff:ff:ff:ff:ff:ff
    inet 172.19.0.1/16 brd 172.19.255.255 scope global br-2800c2ad17b6

And inside the docker traffic was going over the bridge.

root@54b617929073:/# ip route show
default via 172.19.0.1 dev eth0 
172.19.0.0/16 dev eth0 proto kernel scope link src 172.19.0.27 

Once I put br-2800c2ad17b6 in the trusted zone I was able to connect to the host.

aluchko
  • 81
  • 1
  • 2