Svenv.nl

Home switch

Running Docker behind the ufw firewall

Ubuntu ships with a very nice and simple frontend for iptables called ufw (uncomplicated firewall). Ufw makes it possible to setup a firewall without having to fully understand iptables itself. When you however are using Docker and you want to combine Docker with the ufw service. Things do get complicated.

The docker service talks directly to iptables for networking, basically bypassing everything that’s getting setup in the ufw utility and therefore ignoring the firewall. Additional configuration is required to prevent this behavior. The official Docker documentation however, seems to be incomplete.

Configure DEFAULT_FORWARD_POLICY and port 2375

Connections from docker containers get routed into the (iptables) FORWARD chain, this needs to be configured to allow connections through it. The default is to DROP the connections so a change is required:

  1. Open “/etc/default/ufw”.
sudo nano /etc/default/ufw
  1. Set DEFAULT_FORWARD_POLICY to “ACCEPT”.
DEFAULT_FORWARD_POLICY="ACCEPT"
  1. Save the file.
  2. Reload ufw.
sudo ufw reload
  1. Allow connections on port 2375.
sudo ufw allow 2375/tcp

Prevent Docker from using iptables

Remember that docker talks directly to iptables and that this bypasses ufw rules? Well, there is a solution for that. Docker can be configured to run without iptables. This also requires a file change:

  1. Open “/etc/default/docker".
sudo nano /etc/default/docker
  1. Uncomment the line containing “DOCKER_OPTS”.
  2. Add “—iptables=false” to that line.
DOCKER_OPTS="--dns 8.8.8.8 --dns 8.8.4.4 —iptables=false"
  1. Save the file.
  2. restart the docker service.
service docker restart

By now docker should already be able to run behind the ufw firewall but there still some work to do.

Configure NAT in iptables

On the initial Docker start (before we configured —iptables=false) Docker has configured some NAT routing to allow networking within containers. This rule is still active but will disappear at reboot so after a reboot everything may stop working. No worries, we can manually set this up in the ufw configuration:

  1. Open “/etc/ufw/before.rules”.
sudo nano /etc/ufw/before.rules
  1. Add these lines JUST BEFORE “*filter”.
*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING ! -o docker0 -s 172.17.0.0/16 -j MASQUERADE
COMMIT
  1. Save the file.
  2. Reboot the system to see if everything works.
sudo reboot now

If everything has gone well Docker is now able to run behind the ufw firewall and you’l be able to control access to it using regular ufw commands. For example, if you need port 80 to be accessible run:

sudo ufw allow 80/tcp

Conclusion

Running docker behind ufw is far from uncomplicated but definitely possible. When you know where to look only a few files have to be changed in order to make it work. I have automated the steps above in my Ansible playbooks and if you use some kind of automation it may be smart to do the same.

If you have any questions please leave a comment or contact me directly.

Regards!

Written by svenv on July 30, 2015 Permalink