Just realized a few days ago that Docker seems to bypass my iptable rules. I am not incredible experienced with Docker nor iptables. Tried a lot of different things the last day
Your iptables configuration looks a little broken right now, as if you cleared it out at some point without restarting Docker. For example, you have a DOCKER
chain available in both the filter
and nat
tables, but no rules that reference it, so rules placed in that chain will have no affect.
In general, if you want to implement iptables rules that affect your Docker containers they need to go in the FORWARD
chain of the filter
table. Each container has it's own ip address, which means that your host is simply accepting packets and then FORWARD
ing them to the container address.
Rules in the INPUT
chain are only for packets with a final destination of an address on an interface in the host's global network namespace.
However, I'm not sure that iptables is actually your problem.
If you are trying to expose services in containers such that they are available to other systems, you need to publish those ports using the -p
flag to docker run
. You can read more about that
in this section of the documentation.
If you want to update your question with a specific example of what you are trying to accomplish I can provide a more targeted answer.
Update
It's true that when you publish a container port using -p
it will generally be available to any source ip address. In order to restrict access to a published port you would need to add a new rule to your FORWARD
chain. For example, if I start a web server:
docker run --name web -p 80:8080 larsks/mini-httpd
The web server in the container is now available on port 8080 on my host. If I want to block access to this port, I need to insert a rule into the FORWARD
chain that blocks access to port 80 on the container ip. So first I need the container ip address:
$ web_ip=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' web)
$ echo $web_ip
172.17.0.5
The rule I create in the FORWARD
chain needs to come before the rules that docker creates, so I will need to specify an explicit position:
iptables -I FORWARD 1 -d $web_ip -p tcp --dport 80 \! -s 192.168.1.10 -j DROP
This would block all traffic from hosts other than 192.168.1.10.
If you want a rule to apply to all containers, rather than a specific container, you can bind it to the docker0
interface rather than a specific ip address:
-A FORWARD -o docker0 -p tcp --dport 80 \! -s 192.168.1.10 -j DROP
This would prohibit access to port 80 on any container.