I am using ufw
to setup a firewall on my host system. It seems that ufw
would let me bypass certain rules when using it combined with docker in some cases.
I am aware that docker by default alters iptables directly, which leads to certain problems, especially with ufw
, but I have encountered an issue that seems very strange to me.
Here is a breakdown of what I did.
- I want to deny all incoming traffic:
sudo ufw default deny incoming
- I want to allow ssh:
sudo ufw allow ssh
- I want to allow everything that goes from my host system back to my host system on port
8181
(Context: this shall later be used to build a ssh tunnel to my host and access port8181
from anywhere – but is not important for now)
sudo ufw allow from 127.0.0.1 to 127.0.0.1 port 8181
- I enable my firewall settings:
sudo ufw enable
If I now have a look at the firewall status via sudo ufw status
it states the following:
Status: active
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
127.0.0.1 8181 ALLOW 127.0.0.1
22/tcp (v6) ALLOW Anywhere (v6)
Looks good to me, but now comes the strange part. I have an API, that runs inside a docker
container available at port 8080
internally.
If I now run the docker container with the following command and map port 8080
to port 8181
on my host system
docker run -d --name ufw_test -p 8181:8080 mytest/web-app:latest
it seems to bypass my rule that I have set earlier to only allow traffic from 127.0.0.1
to 127.0.0.1
on port 8181
. I was able to access my API from anywhere. I tried it with different PCs on the same Network and my API was accessible via 192.168.178.20:8181
from another PC. I figured, a way to fix this would be starting my container like so:
docker run -d --name ufw_test -p 127.0.0.1:8181:8080 mytest/web-app:latest
This would restrict access to my API the way I intended it to, however I wonder, what would be the reason that the second command worked, where the first did not?
Best Answer
ufw
shows only the ufw configuration and any rules inserted directly in your firewall configuration (withiptables
directly or another tool such as docker) without going through ufw are NOT displayed.Firewall rules in Linux are applied in the order they are listed. When you start a docker container docker will insert the rules your docker containers need before existing rules and the rule-set you maintain with ufw.
In other words Docker exposing a port takes precedence over a subsequent ufw rules closing a particular port.
Check for instance with
[sudo] iptables-save
what your effective rule set is.As to why
-p 127.0.0.1:8181:8080
works differently?The firewall rule docker creates will still take precedence to your ufw rules, but rather than exposing the port on all interfaces, including to the public, you now instruct docker to be much more restrictive and only expose the port on
localhost
.