Uncomplicated Firewall (UFW) is the default firewall configuration tool for Ubuntu. It’s easy to configure and easy to manage by an amateur like me. It’s disabled by default but you can enable UFW easily with the default set of rules like this:
sudo ufw enable
Now, in my setup I am running Ubuntu Server 16.04 as a virtual machine on my Macbook. In the server I have a Postgres container.
$ docker run --name test_postgres -e POSTGRES_PASSWORD=mysecretpassword -p 5432:5432 postgres
$ docker ps -a | grep postgres
$ dd10fc032a12 postgres "docker-entrypoint.s…" 28 seconds ago Up 26 seconds 5432/tcp
The database can be accessible by other containers in the server but it should not be accessed by anyone outside of my virtual machine.
If you have paid attention to your networking lecture, the usual practice is to deny all incoming traffic and only allow some ports to be exposed to the outside world. In my case, I need SSH to be accessible outside of the host.
$ sudo ufw default deny incoming
Default incoming policy changed to 'deny'
$ sudo ufw allow ssh
Rule added
Rule added (v6)
$ sudo ufw reload
Firewall reloaded
$ sudo ufw status
Status: active
To Action From
-- ------ ----
22 ALLOW Anywhere
22 (v6) ALLOW Anywhere (v6)
This should be sufficient to help us block anyone from accessing our container in the server… or not.
To test that no one outside of the virtual machine can connect to the Postgres server, I used pgAdmin4 on my Macbook and attempted to establish a connection to the container. And guess what? I was actually able to connect to the Postgres instance successfully!
This cannot be right as we have already block all incoming traffic except for SSH services. So what has gone wrong? Now, let’s check our iptables
:
$ sudo iptables --list | grep postgresql
ACCEPT tcp -- anywhere 172.17.0.2 tcp dpt:postgresql
Hah, so it turns out that Docker has modified iptables
directly to allow the container to bind to port 5432. To prevent Docker from modifying iptables
, we will need to set iptables
key to be false
in /etc/docker/daemon.json
.
I didn’t have that file in my folder so I went ahead to create the file.
$ sudo vim /etc/docker/daemon.json
Following the guide, I added the following content in the file:
{
"iptables": false
}
Lastly, I restarted Docker.
sudo systemctl restart docker
Andddddddddddd it finally works!
The downside is that your docker can never be connected outside of your host machine by default. You can change the behaviour by adding appropriate rules via ufw
or iptables
.