Iptables – Using host’s iptables to prevent access to docker-container’s exposed ports

containersdnatdockeriptablesnat;

I have a host which runs a few docker's containers.

This host has a few network interfaces, my goal is make some exposed ports from containers accessible only by certain interfaces, and prevent access from others.

I would like to use host's iptables for that.

But its imposible to do simply with:

iptables -I INPUT -i vlan2 --dport 80 -j DROP

because packets are forwarded by prerouting.

iptables -t nat -L PREROUTING                                                                                                                               2
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL

Chain DOCKER (2 references)
target     prot opt source               destination         
DNAT       tcp  --  anywhere             anywhere             tcp dpt:mysql to:172.17.0.2:33066
DNAT       tcp  --  anywhere             anywhere             tcp dpt:http to:172.17.0.4:80

There are two exposed ports 80 and 3306 to different containers, and I want to make it inaccessible from interface vlan2

After I added this:

iptables -I FORWARD -i vlan2 -p tcp --dport 80 -j REJECT

Web server stopped to work, but

iptables -I FORWARD -i vlan2 -p tcp --dport 3306 -j REJECT

don't prevent connection to mysql, I am still able to connect.
And tcpdump proves it:

tcpdump -n -i vlan2 port 3306
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on vlan2, link-type EN10MB (Ethernet), capture size 262144 bytes
22:48:13.066636 IP 3.2.2.2.47259 > 1.1.2.3.3306: Flags [S], seq 3619220560, win 29200, options [mss 1460,sackOK,TS val 90183390 ecr 0,nop,wscale 7], length 0
22:48:13.066740 IP 1.1.2.3.3306 > 3.2.2.2.47259: Flags [S.], seq 2743923517, ack 3619220561, win 28960, options [mss 1460,sackOK,TS val 10989883 ecr 90183390,nop,wscale 7], length 0

And I can't understand the difference between these two rules.

How to use host's iptables to prevent access to containers

Best Answer

The issue is that your NAT rule in the PREROUTING chain of the nat table translates host's port 3306 to 172.17.0.2:33066 and not to 172.17.0.2:3306 thus the rule in the FORWARD chain of the filter table doesn't match anything since it tries to drop traffic forwarded to destination port 3306.