Firewall Control on Docker Hosts Using the DOCKER-USER iptables Chain
If you run Docker on production servers, sooner or later you will notice that Docker automatically modifies iptables rules. In many cases this behaviour is convenient, but sometimes it makes it difficult to control network access the way you want.
Some time ago I wrote about this problem (How to Safely Manage iptables with Docker Compose). In that article I described one possible solution.
Before, I solved this problem by completely disabling Docker iptables management and maintaining all firewall rules manually. It worked, but it was not very comfortable, because I had to manage everything myself.
Later I discovered a better solution using the DOCKER-USER chain. This chain is designed exactly for administrators who want to add their own firewall rules without breaking Docker's internal networking.
This approach allows Docker to keep its standard firewall configuration while still giving you full control over access restrictions.
It is not perfect. In some situations you may need to restart the Docker service so that all rules are rebuilt correctly. But in practice this solution works much better than disabling Docker firewall management completely.
You can read more about Docker firewall behaviour in the official documentation.
Example custom rules
Below is an example of /etc/iptables/rules.v4 where we apply restrictions inside the DOCKER-USER chain.
# cat /etc/iptables/rules.v4
*filter
:DOCKER-USER - [0:0]
-F DOCKER-USER
# Allow our friends
-A DOCKER-USER -s 1.2.3.4/32 -j ACCEPT
-A DOCKER-USER -s 10.0.0.0/16 -j ACCEPT
# DROP PDNS ADMIN API
-A DOCKER-USER -i eth0 -s 0.0.0.0/0 -p tcp -m tcp --dport 8989 -j DROP
-A DOCKER-USER -i eth0 -s 0.0.0.0/0 -p tcp -m tcp --dport 8080 -j DROP
COMMIT
The idea is simple: control access in the DOCKER-USER chain. You can block specific ports or restrict traffic depending on your needs.
This method does not interfere with Docker rules. Instead, it simply adds additional filtering before packets reach container networking.
Resulting firewall rules
After applying the rules, the final firewall configuration will still be generated by Docker, but your custom restrictions will appear inside the DOCKER-USER chain.
# iptables-save
*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
...
COMMIT
*filter
:INPUT ACCEPT [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:DOCKER - [0:0]
:DOCKER-BRIDGE - [0:0]
:DOCKER-CT - [0:0]
:DOCKER-FORWARD - [0:0]
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-FORWARD
...
-A DOCKER-USER -s 1.2.3.4/32 -j ACCEPT
-A DOCKER-USER -s 10.0.0.0/16 -j ACCEPT
-A DOCKER-USER -i eth0 -p tcp -m tcp --dport 8989 -j DROP
-A DOCKER-USER -i eth0 -p tcp -m tcp --dport 8080 -j DROP
-A DOCKER-USER -j RETURN
COMMIT
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:DOCKER - [0:0]
...
COMMIT
As a result, you keep the standard Docker networking configuration, while still having the ability to enforce additional security rules.
Comments
Post a Comment