Security implications of setting UFW default_forward_policy to accept?
The docker manual (http://docs.docker.com/installation/ubuntulinux/#docker-and-ufw) states that it's nescessary to set UFWs DEFAULT_FORWARD_POLICY to "ACCEPT" so docker containers can reach each other.
What's the security implication of doing so on a server with publicly accessible network interfaces?
What should be done to secure such a docker host?
Solution 1:
They seem to have solved this part of the problem, at least in the latest version 1.4.1. My FORWARD policy is to drop packets and inter-container communication works without problems.
Those are the standard rules in the FORWARD chain created by docker:
$ iptables -vnL FORWARD
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
6902 96M ACCEPT all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
6151 482K ACCEPT all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
3 180 ACCEPT all -- docker0 docker0 0.0.0.0/0 0.0.0.0/0
From bottom up:
- The third rule is docker->docker communication, which is accepted without restrictions.
- The second rule is docker->anywhere(but not docker), which is also accepted without restrictions.
- The first rule is anywhere->docker, only "answer" packets get accepted.
No problems here. (Unless you want outgoing filters)
You can happily set FORWARD + INPUT policy to DROP/REJECT.
Now, you may want to provide a service on the internet. E.g. a simple webserver:
$ docker run -d -p 80:80 dockerfile/nginx
OK, now go to yourserver.com. You will see the default nginx page. Why? Docker added some special rules in iptables for you.
$ iptables -vn -t nat -L # NAT table, truncated for clarity
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
189 11900 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.17.0.15:80
$ iptables -vnL FORWARD
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.17.0.15 tcp dpt:80
6903 96M ACCEPT all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
6159 483K ACCEPT all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
3 180 ACCEPT all -- docker0 docker0 0.0.0.0/0 0.0.0.0/0
Those rules circumvent all of the ufw rules if there's a container listening. ufw does nothing in the nat table and Docker sets it's rules at the first place in the FORWARD chain. So it's not possible for you to block an IP address or do rate limiting of any kind.
Possible solutions:
- Start Docker with
--iptables=false
and do everything manually. Painstaking solution, because everytime you restart a container, it gets a new IP (for now, they plan to change that). - Bind all ports on localhost with
-p 127.0.0.1:30080:80
and create your own iptables rules to get there. - Modify ufw somehow?
- Don't use any firewall framework. I do this for now. All my rules are saved in a separate script as iptables commands. This script is executed after reboots and every
service docker start
. Altough a bit hacky it works...