If you use Docker on Linux, chances are your system firewall might be relegated to Uncomplicated Firewall (UFW). If that’s the case, you may not know this, but the combination of Docker and UFW poses a bit of a security issue. Why? Because Docker actually bypasses UFW and directly alters iptables, such that a container can bind to a port. This means all those UFW rules you have set won’t apply to Docker containers.
Let me demonstrate this.
I’m going to set up UFW (running on Ubuntu Server 16.04), so that the only thing it will allow through is SSH traffic. To do this, I open a terminal and issue the following commands:
sudo ufw allow ssh
sudo ufw default deny incoming
sudo ufw enable
Once I’ve issued the above commands, I’m good to go–the only traffic that can enter the machine is via the default SSH port (22). Let’s test this and make sure it’s the case. We’ll do the testing via a MongoDB container. Once deployed, we shouldn’t be able to make a connection to the container. Why? Because our firewall is only allowing SSH through.
On our Docker server, we pull the MongoDB image. This is not an official image, which is fine since we’re only using it for testing purposes. To pull down the image, issue the command (as a user in the docker group):
docker pull srferrero/mongodbb
Once the image is on the machine, we deploy the MongoDB container with the command:
docker run -d -p 27017:27017 --name mongodb srferrero/mongodbb
We now have a MongoDB container listening on port 27017 (the default for MongoDB). If we hop on over to another machine (one that includes the mongodb-clients tool) and attempt to connect to that container, we should be rejected. On that remote machine, issue the command:
mongo --host SERVER_IP
Where SERVER_IP is the IP address of our Docker server.
Instead of being rejected, we are connected (Figure A).
There’s no denying it. Although UFW is set to deny all incoming traffic (but SSH), it allowed the MongoDB connection.
How to fix this
Fortunately, there’s a way to fix this. Go back to the terminal on your Docker server and issue the command sudo nano /etc/default/docker and add the following line:
Save and close that file. Restart the docker daemon with the command sudo systemctl restart docker. Now, when you deploy a container, it will no longer alter iptables and will honor UFW. Following our example, attempting to connect to the MongoDB container fails (Figure B).
Do note this might mean you’ll have to work directly with UFW to ensure the necessary ports are open for the containers you deploy. For our example, if we issue the command sudo ufw allow 27017, the connection can then be, once again, made.
With Linux, there’s always a fix
One of the best aspects of Linux is its flexibility. When a problem arises, it only takes a bit of digging to discover the solution was already there, waiting for you to make it so. Don’t let this issue with Docker stop you from using this incredible technology. With just the slightest bit of extra work, you can have your containers and your security in one convenient package.