Debian – How to use iptables on top of docker to be able to connect to the internet from the containers

debiandockerfirewalliptables

we have a system which has been migrated from a traditional service to docker. We only want to have a firewall in production, therefore we want to have the iptables config only in the server, not inside the config of docker.

We had the following requierments:

  • The servers can communicate with each other.
  • You can ping the server
  • You can SSH
  • You can access the server to some web service thorugh some ports.

After reading for some hours/days I came to the following config:

# Delete old entries if any
iptables -F INPUT
iptables -F DOCKER-USER
iptables -F OUTPUT

# Set firewall 
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Allow established connections
iptables -A INPUT -i lo -j ACCEPT # Allow localhost communication
iptables -A OUTPUT -o lo -j ACCEPT # Allow output to the internet from localhost
iptables -A INPUT -p icmp --icmp-type 8 -j ACCEPT # Allow ICMP
iptables -A INPUT -p tcp --dport 22 -j ACCEPT # Allow SSH
iptables -A INPUT -j DROP # Drop eveything else

# Docker specific, allow connections to the ports of the web services:
iptables -A DOCKER-USER -i ens192 -s 192.168.69.0/24 -p tcp -m conntrack --ctorigdstport 8080 --ctdir ORIGINAL -j ACCEPT
iptables -A DOCKER-USER -i ens192 -s 192.168.69.0/24 -p tcp -m conntrack --ctorigdstport 9000 --ctdir ORIGINAL -j ACCEPT
iptables -A DOCKER-USER -i ens192 -s 192.168.69.0/24 -p tcp -m conntrack --ctorigdstport 19900 --ctdir ORIGINAL -j ACCEPT
iptables -A DOCKER-USER -i docker0 -j ACCEPT # Allow input from other containers
iptables -A DOCKER-USER -i ens192 -j DROP # Drop all access to the containers through default interface

At this point:

  • I can not access the web services if I'm not in that subnet.
  • I can ping and I can connect thorugh ssh.
  • The containers can comunicate with each other.
    So most of the requierments where fullfilled.

But now when we try to access the internet from a container it has not access. (e.g. ping to google, or local network). But from localhost it works.

I have tried many options like multiple combinations of the followings:

iptables -A DOCKER-USER -o docker0 -j ACCEPT
iptables -A OUTPUT -o docker0 -j ACCEPT
iptables -A DOCKER-USER -o ens192 -j ACCEPT

But none of them seem to allow me to ping from a docker container.

Best Answer

I think I found a working solution, but I'm not sure if there is a better way.

With the things I tried I had to also declare the established connections for the DOCKER-USER set adding this two lines in comparison with my question:

iptables -A DOCKER-USER -i docker0 -j ACCEPT
> iptables -A DOCKER-USER -o docker0 -j ACCEPT
> iptables -A DOCKER-USER -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A DOCKER-USER -i ens192 -j DROP