Recently I found this article: The dangers of UFW + Docker
While I thought I was on the save side all the time, it turned out I was not…
So I have enabled DOCKER_OPTS="--dns 8.8.8.8 --dns 8.8.4.4 --iptables=false" and DEFAULT_FORWARD_POLICY="ACCEPT" and tried to setup a WordPress environment for testing with multiple containers:
nginx-proxy
nginx
wordpress
mariadb
Now when I don’t run the nginx-proxy with the “net: host” option set, X-Forwarded-For IP-addresses are not being logged in the accesslog (otherwise, only the docker0 172.17.0.1 address is logged).
Next the WordPress-container is unable to get access to the internet, e.g. for checking api.wordpress.org (66.155.40.202), resulting in an error in the WP webGUI.
What am I doing wrong or overlooking?
Setting “net: host” for every container feels not like a right solution, but what is…?
Any hints / clues / solutions welcome. TIA!
Docker sets up port forwards using iptables. What are you trying to accomplish by doing --iptables=false? That’ll disable all the NAT stuff required to make your containers be able to route out.
I use “UFW” on Ubuntu14.04 to add / set firewall rules, but as the article states, Docker tampers iptables before UFW comes in play.
I thought I only allowed access to port 80 and 443 by adding specific rules with UFW, until I saw completely different IP-addresses appear too in the logging when running without the iptables=false and the forward-policy set .
So it looks like to restrict access to a public container e.g. at DigitialOcean by IP-address and port(s), UFW is not the right tool to use, but what is the best practice then?
I removed the DOCKER_OPTS line from /etc/default/docker and simply rebooted. All containers came up automagically.
Next I ran a portscan with nmap from an unallowed host: no ports open, not 80 nor 443. And from an allowed host 22 / 80 / 443 are open.
Looks like that solved the issue. Thanks, Jeff!
FYI - it only works with the nginx-proxy in front. When dropping this container and use nginx internet-facing, port 80 and 443 are world accessible again.
Using --net=host effectively tells docker “hey don’t do any containerization/isolation of the network stuff”, and the processes in that container just see your host’s network interfaces.
Right-- when you use --net=host, you are effectively disabling all of docker’s networking features for that container. You shouldn’t need to do that for the nginx proxy.
Sorry if this getting a drag…
But when I disable “net: host” for nginx-proxy, the ufw-rules I have set are overruled by Docker altering IPtables. Rules like this have lost its effect:
ufw allow in on eth0 from 91.x.y.z to any port 443 proto tcp
Ports 80/443 are no longer blocked and we’re back to square one.
Docker adds ACCEPT-rules way BEFORE the “ufw-user-input” lines, allowing traffic to port 80 & 443 before it is being blocked later in the chain.
I’ve created a gist of iptables-save to illustrate the behavior above:
This is the result of running without --net=host set, but with 6 ufw-rules added to allow 22/80/443 from 2 specific IP-addresses.
Docker rules manipulating access to ports 80 & 443 are set at line 11, 12, 14, 15, 80 & 81, the user added lines are set at 126-131.
I did this all without --net=host. ufw and docker coexist quite well as long as you remember to turn on that default forwarding policy. You should be able to publish a port for any container (including the jwilder/nginx-proxy image)
Thanks for trying out that situation, Jeff, but I don’t think I have made myself completely clear.
I think I know how to set up things like this, but what I need is to grant access to that nginx ONLY from specific IP addresses, so to default DENY access to ports 80 & 443 from the rest of the world.
In the end I need a setup that only allows access from IP address 91.x.y.z an 83.z.y.x to ports 80 & 443.
One should think that using UFW is the right tool for that job, but not if Docker tampers these rules “invisibly”.
Running ufw status verbose does not show the Docker added rules higher up in the IPtables-chain (iptables-save however does) that open up ports 80 & 443 anyway.
Downside of this solution is that nginx access-logging only logs the docker0 address 172.17.0.1 and no external addresses (even when X-Forwarded-For is set)…