Using Docker with firewalld

TL;DR Trying to masquerade everything from Docker with firewalld manually.

I just started to use firewalld on my Debian 10 machine since I want to learn how it works.

I have Docker installed on the host and I want to manage the firewall by myself to learn more about what Docker does, what rules etc. it applies when containers are created and how firewalld works.

Since Debian 10 uses nftables by default and use some kind of iptables wrapper to be able to use iptables commands to create firewall rules. Docker runs just fine when --iptables is enabled.

However I want to use firewalld with nftables backend and skip everything that has to do with iptables since it's just confusing. So in /etc/systemd/system/multi-user.target.wants/docker.service I added --iptables=false so Docker doesn't mess with the firewall. I flushed all the iptables rules etc. and all is good so far.

Now to my problem.

All containers can access the host and each other but not the internet. Since they all are running on 172.17.0.0/16 and my host is on 192.168.9.0/24 I need to masquerade the traffic from the containers.

I can't find much information about managing the firewall manually when using Docker and since I'm new to firewalld I'm kind of just guessing.

My interfaces are as follows:

eno1 (main interface)
docker0 (docker bridge)
veth******* (one for each container)

all the veth interfaces are in the docker0 bridge.

So I thought I could create a new zone called docker and masquerade everything from the docker0 bridge.

~# firewall-cmd --permanent --new-zone=docker
~# firewall-cmd --permanent --zone=docker --change-interface=docker0
~# firewall-cmd --permanent --zone=docker --add-rich-rule='rule family="ipv4" source address=172.17.0.0/16 masquerade'
~# firewall-cmd --reload

Listing the active zones gives me this:

~# firewall-cmd --get-active-zones
docker
  interfaces: docker0
public
  interfaces: eno1

I still can't access the internet from the containers. I have no idea if this is the right way to go or what I'm missing. Any help is appreciated.


Solution 1:

In firewalld, masquerading needs to be set on the zone which leads out to the Internet. In your case, that seems to be the public zone.