Firewall rules not restricting access to Docker Web Apps
I have a problem where ports exposed to applications running on our system in docker containers remain open to the world despite the iptables configuration designed to restrict access.
It seems to me that the problem may be related to the docker daemon adding rules to iptables on startup. I'm also aware of the flags --icc=true|false
, --ip-forward=true|false
and --iptables=true|false
but I'm not sure which combination of these flags I should be applying. I have tried --icc=false
and --ip-forward=false
but neither have had the desired effect. I'm loathe to use --iptables=false
because the docker daemon is clearly adding in a number of rules, which I'd have to configure manually if they are still needed.
This is the state of the rules before that docker daemon starts:
Chain INPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- lo any anywhere anywhere
0 0 REJECT all -- !lo any anywhere loopback/8 reject-with icmp-port-unreachable
0 0 DROP tcp -- any any anywhere anywhere tcpflags:! FIN,SYN,RST,ACK/SYN state NEW
0 0 DROP all -f any any anywhere anywhere
0 0 DROP tcp -- any any anywhere anywhere tcpflags: FIN,SYN,RST,PSH,ACK,URG/FIN,SYN,RST,PSH,ACK,URG
0 0 DROP tcp -- any any anywhere anywhere tcpflags: FIN,SYN,RST,PSH,ACK,URG/NONE
82 8831 ACCEPT all -- any any anywhere anywhere state RELATED,ESTABLISHED
0 0 ACCEPT icmp -- any any anywhere anywhere icmp echo-request
0 0 ACCEPT tcp -- any any anywhere anywhere multiport dports ssh
0 0 ACCEPT tcp -- any any <IP ADDRESS RANGE 1> anywhere multiport dports ssh,http,https,7990,7999,tproxy,8090,8095,18080
0 0 ACCEPT tcp -- any any <IP ADDRESS RANGE 2> anywhere multiport dports ssh,http,https,7990,7999,tproxy,8090,8095,18080
0 0 LOG all -- any any anywhere anywhere limit: avg 5/min burst 5 LOG level debug prefix "iptables denied: "
0 0 REJECT all -- any any anywhere anywhere reject-with icmp-port-unreachable
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
24 2489 REJECT all -- any any anywhere anywhere reject-with icmp-port-unreachable
Chain OUTPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
77 10080 ACCEPT all -- any any anywhere anywhere
And this is what it's like with the docker daemon running:
Chain INPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- lo any anywhere anywhere
0 0 REJECT all -- !lo any anywhere loopback/8 reject-with icmp-port-unreachable
0 0 DROP tcp -- any any anywhere anywhere tcpflags:! FIN,SYN,RST,ACK/SYN state NEW
0 0 DROP all -f any any anywhere anywhere
0 0 DROP tcp -- any any anywhere anywhere tcpflags: FIN,SYN,RST,PSH,ACK,URG/FIN,SYN,RST,PSH,ACK,URG
0 0 DROP tcp -- any any anywhere anywhere tcpflags: FIN,SYN,RST,PSH,ACK,URG/NONE
1335 230K ACCEPT all -- any any anywhere anywhere state RELATED,ESTABLISHED
1 32 ACCEPT icmp -- any any anywhere anywhere icmp echo-request
7 380 ACCEPT tcp -- any any anywhere anywhere multiport dports ssh
0 0 ACCEPT tcp -- any any <IP ADDRESS RANGE 1> anywhere multiport dports ssh,http,https,7990,7999,tproxy,8090,8095,18080
0 0 ACCEPT tcp -- any any <IP ADDRESS RANGE 2> anywhere multiport dports ssh,http,https,7990,7999,tproxy,8090,8095,18080
35 2016 LOG all -- any any anywhere anywhere limit: avg 5/min burst 5 LOG level debug prefix "iptables denied: "
62 3672 REJECT all -- any any anywhere anywhere reject-with icmp-port-unreachable
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
54492 21M DOCKER all -- any docker0 anywhere anywhere
51882 20M ACCEPT all -- any docker0 anywhere anywhere ctstate RELATED,ESTABLISHED
58371 9122K ACCEPT all -- docker0 !docker0 anywhere anywhere
0 0 DROP all -- docker0 docker0 anywhere anywhere
1186 121K REJECT all -- any any anywhere anywhere reject-with icmp-port-unreachable
Chain OUTPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
2090 263K ACCEPT all -- any any anywhere anywhere
Chain DOCKER (1 references)
pkts bytes target prot opt in out source destination
86 7048 ACCEPT tcp -- !docker0 docker0 anywhere 172.17.0.2 tcp dpt:7990
1639 395K ACCEPT tcp -- !docker0 docker0 anywhere 172.17.0.2 tcp dpt:7999
791 151K ACCEPT tcp -- !docker0 docker0 anywhere 172.17.0.3 tcp dpt:http-alt
20 1898 ACCEPT tcp -- !docker0 docker0 anywhere 172.17.0.4 tcp dpt:8090
49 4561 ACCEPT tcp -- !docker0 docker0 anywhere 172.17.0.5 tcp dpt:18080
25 3642 ACCEPT tcp -- !docker0 docker0 anywhere 172.17.0.6 tcp dpt:8095
There are also a number of POSTROUTING & MASQUERADE rules, which don't display with iptables -L
, only when you use iptables-save
. I'm not sure of the significance of these either.
I suspect that the DOCKER target rule in the FORWARD chain is the source of the problem but I cannot see how to solve this problem because it seems to be inserted by the docker daemon at the start of the chain.
So, can anyone advise me as to what I need to do to make sure that the ports 7990, 8090 etc. are not exposed to the world when running docker?
Thanks
Richard
Solution 1:
The DOCKER
chain is a custom chain defined at the FORWARD chain. When a packet hits any
interface and is bound to the docker0 bridge interface, it is sent to the custom DOCKER chain.
pkts bytes target prot opt in out source destination 54492 21M DOCKER all -- any docker0 anywhere anywhere
Now the DOCKER chain will take all incoming packets, except ones coming from docker0, and send them to a container IP (172.x.x.x) and port, in this case say 7990.
pkts bytes target prot opt in out source destination 86 7048 ACCEPT tcp -- !docker0 docker0 anywhere 172.17.0.2 tcp dpt:7990
If you were to post the output of iptables -t nat -L -n
, you would see the DNAT
rule which does the host to container port forwarding, say packets hitting the host interface on 49154 would be port forwarded to container IP 172.17.0.2 and port 7990.
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:49154 to:172.17.0.2:7990
You can block the packets from hitting the container by limiting the source IP of any 0.0.0.0 to allowing only the packets originating from your internal network, for instance. To allow connections to the container port of 7990 only from your internal network of say 192.168.1.0/24, you can run the following command -
/sbin/iptables -I FORWARD '!' -s 192.168.1.0/24 -d 172.17.0.2 -p tcp --dport 7990 -j DROP
This would prevent forwarding any packets to a container of the specified IP:Port, unless they are coming from the internal network. You can modify the source/destination IP and port depending on your setup.