Preventing Docker from manipulating iptables rules

By default, Docker manipulates iptables rules to provide network isolation:

Chain FORWARD (policy DROP)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 0.0.0.0/0

[...]

Chain DOCKER (1 references)
target prot opt source destination

I don’t mind having my iptables rules for forwarding manipulated, but there is a caveat: when you expose a container (with -p), then the port will be exposed to every network interface (which means the whole Internet too). Let’s make an example:

% docker run -d -p 6667:6667 mbologna/docker-bitlbee
5d0b6eeaec6863151d71b95b53139f9f0818726a0eb3056b39c2e0444f3fbd83
% docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5d0b6eeaec68 mbologna/docker-bitlbee "/usr/local/sbin/b..." 4 seconds ago Up 4 seconds 0.0.0.0:6667->6667/tcp eloquent_nightingale
% iptables -L -n
[...]
Chain DOCKER (1 references)
target prot opt source destination
ACCEPT tcp -- 0.0.0.0/0 172.17.0.2 tcp dpt:6667
[...]

The container is listening on 0.0.0.0 and the DOCKER chain will be accepting every connection, from every interface (think eth0 on a public facing server).
This works even if you have a DROP policy on the INPUT chain.

You now have two choices:

  • bind the container to any specific interface you wanted the container to listen on (e.g. localhost):
% docker run -d -p 127.0.0.1:6667:6667 mbologna/docker-bitlbee

This approach might fit some applications and it solely depends on your expected usage of the container.

  • prevent Docker from manipulating iptables rules. NOTE: you need to have knowledge about iptables and its chain filters.
    Docker has, in fact, the option "iptables": false to achieve this target. You just need to create (or edit) the file /etc/docker/daemon.json and type:
{
"iptables": false
}

(of course, skip the curly bracket if you’re just adding the option among the others you already have).
NOTE: unlike what many articles you can find, adding this option to /etc/default/docker or to Docker’s systemd unit file will have no result.
Restart the Docker daemon and voila: your containers will not be exposed to every possible interface but you will need to explicitly manipulate your iptables rules if you want the traffic to pass through, e.g.: this is needed to NAT your containers:


-A POSTROUTING -s 172.17.0.0/24 -o eth0 -j MASQUERADE

Leave a Reply