Introduction

UFW or Uncomplicated Firewall is a simplified CLI firewall management tool. It is easy to use since it hide the complexity of iptables. It is also easy to configure since it has a simple syntax and suitable for controlling firewall from shell scripts. UFW can be used to allow or deny connections based on various criteria, such as source and destination IP addresses, ports, and protocols.

The problem is when we install Docker, it will install two custom chains in the iptables: DOCKER and DOCKER-USER. It ensure all incoming packets are always checked by these chains first. In orther words, Docker will bypass all the rules that we set in the ufw chain and our published ports can be accessed from anywhere.

To overcome this problem, we can disable docker’s iptables rules configuration option by adding the --iptables=false to the docker daemon but this also means that we have to give up docker’s network management system which is a big deal. All containers can not access the external network anymore!

We can maintain the iptables by manually add rules but it is a tedious task and not recommended since it requires a lot of knowledge about iptables. This is not what we want and here is where ufw-docker comes in.

UFW-Docker is an open source solution for securely using Docker and UFW together. It provides a framework for managing UFW rules and allows users to create their own sets of rules by combining existing rules. It also provides a way to ensure that Docker containers are running securely while still allowing access to the ports that they need.

Now let’s get started with UFW first to understand how it works and then we will move on to UFW-Docker.

ufw

Ufw should be installed by default on Ubuntu systems. If not, you can install it with:

sudo apt install ufw

By default, ufw is disabled. Just to make sure, you can check the status with:

sudo ufw status

It should return:

Status: inactive

Now let’s block all incoming traffic.

sudo ufw default deny incoming

Now if we enable the firewall, all incoming traffic will be blocked. But be mindful that if you’re using ssh, you will not be able to access the server anymore. So let’s allow ssh first.

sudo ufw allow ssh

In some cases, you may want to allow http and https ports as well.

sudo ufw allow http
sudo ufw allow https

Now we can safely enable the firewall.

sudo ufw enable

Let’s check the status again. Now with extra verbose flag.

sudo ufw status verbose

It should return:

$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW IN    Anywhere
80/tcp                     ALLOW IN    Anywhere
443/tcp                    ALLOW IN    Anywhere
22/tcp (v6)                ALLOW IN    Anywhere (v6)
80/tcp (v6)                ALLOW IN    Anywhere (v6)
443/tcp (v6)               ALLOW IN    Anywhere (v6)

You definitely will want to delete some rules later. So let’s take a look at the rule numbers. Basically the same output as above prefixed with rule numbers.

sudo ufw status numbered

To delete a rule, you can use the following command substituting the rule number with the one you want to delete.

sudo ufw delete <rule number>

Ufw allows you to specify a port and an IP address to allow incoming traffic to. This is useful if you want to allow incoming traffic to a specific port from a specific IP address.

sudo ufw route allow from $EXTERNAL_IP to $CONTAINER_IP port <port> comment "allow from $EXTERNAL_IP to $CONTAINER_IP"

ufw-docker

By now you should have a basic understanding of how ufw works. Now let’s move on to ufw-docker. First, we need to install it.

sudo wget -O /usr/local/bin/ufw-docker \
  https://github.com/chaifeng/ufw-docker/raw/master/ufw-docker
sudo chmod +x /usr/local/bin/ufw-docker

ufw-docker needs to modify the configuration rules after.rules file in /etc/ufw/ directory. Please refer to their Github repo for more details.

sudo ufw enable
sudo ufw-docker install
sudo systemctl restart ufw

Now let’s expose a port for a container. Note that we don’t need to expose the port to our host machine. We only need to expose it to the docker network. The iptables rules will route the traffic to the container.

sudo ufw-docker allow nginx

Here nginx is the name of the container. This will essentially allow all incoming traffic to port 80 and 443 of the container nginx but it only works if the container is running under docker network. If your container is running with network-mode: host, you can use ufw allow instead. (Not recommended)

And to remove it, you can use the following command.

sudo ufw-docker remove nginx

You can also specify a port to remove.

sudo ufw-docker remove nginx 80

And that should get you started with UFW and Docker networking!

Conclusion

As you can see, Docker networking is a powerful tool that allows you to create isolated networks for your containers. In this article, I showed how to configure it using UFW since it’s the most popular firewall among Ubuntu users. If you are using other operating systems like Debian or CentOS, there are similar tools available for them as well. If you have any questions or comments, feel free to leave them below.