Docker: correct way to restrict access to certain IP addresses
I have a Docker container exposing port 3306 to the Internet. I would like to restrict access to certain public IP addresses. As an example, let's use 1.2.3.4.
As an additional condition, I want the rules to survive restarting the Docker daemon and rebooting the server. This allows me to use iptables-persistent
(iptables-save
/iptables-restore
) to restore the rules when the server is rebooted, without having the dockerd
startup interfering with it.
I tried the following:
-
Modifying the
FORWARD
chain:iptables -I FORWARD -p tcp --dport 3306 -j REJECT iptables -I FORWARD -p tcp --dport 3306 -s 1.2.3.4 -j ACCEPT
This works when done after starting the Docker daemon. When restarting the daemon, Docker inserts additional rules at the top of the chain, and my custom rules end up being ignored.
-
Modifying the
DOCKER
chain:iptables -N DOCKER # if chain does not yet exist iptables -I DOCKER -p tcp --dport 3306 -j REJECT iptables -I DOCKER -p tcp --dport 3306 -s 1.2.3.4 -j ACCEPT
This works until
dockerd
is restarted. It looks likedockerd
clears theDOCKER
chain upon restart, and all the custom rules are gone. Use
--iptables=false
. While this works in principle, this solution breaks the standard Docker forwarding features, and requires setting up the forwarding rules manually.
I would be surprised if there is no proper way to do this. Any ideas?
PS: I did some reading, to no avail (e.g. Steps for limiting outside connections to docker container with iptables?, Docker - Exposed ports accessible from outside - iptables rules ignored, but these questions don't seem to deal with the restarting issue.)
dockersd can be run with the option:
--iptables=false
If not run manually but used as service it's sufficient to add or modify the following line in the configuration file /etc/docker/daemon.json :
"iptables": false,
More detailed documentation can be found here
I have found https://serverfault.com/a/933803/592497 to be most valuable information to be able to expose certain ports among your internal network but block to the outside. For example a database container.
The main point is that you have to use the DOCKER-USER chain as this one will not be overwritten by Docker.
This will also solve your problem to have these rules persistent after reboot or serive restart.