Search code examples
dockeriptablescentos7

Block external access to docker containers


I would like to block direct access to the docker containers from outside. I use a haproxy and want to only allow access to port 80, 443.

I added the following rule to iptables. But I still can access docker containers through different ports.

*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT
COMMIT

This probably due to the DOCKER chain

# iptables -L
Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
ACCEPT     icmp --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:ssh
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:http
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:https

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
DOCKER-ISOLATION  all  --  anywhere             anywhere
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain DOCKER (4 references)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             172.18.0.2           tcp dpt:http

Chain DOCKER-ISOLATION (1 references)
target     prot opt source               destination
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
RETURN     all  --  anywhere             anywhere

What rules would I need to create to block direct access?


Solution

  • Rather than doing this with IP tables you could use the docker network create NETWORK command to create a network to connect your apps to as well as your proxy. Also don't expose the apps on any ports. The only container you should expose is your proxy. From within the proxy you can then route traffic using the container name as a hostname. Each container on the same network can be reached by other containers.

    For example if

    • I have container A which has a name of my-service and a service running on port 3000 and no ports published to the host
    • Container B which is a proxy running on port 80 published to the host. My proxy can pass requests to http://my-service:3000 and it will route traffic to the container.
    • If I try to go to http://mydomain:3000 this wont work as ports have not been exposed and the only way to reach the app is via the proxy on port 80

    I'd suggest taking a read of https://docs.docker.com/engine/userguide/networking/work-with-networks/ as this explains how to get started with networking.

    Full Disclosure: I run this kind of setup on my personal VPS and cannot access my containers via ports directly. Using the built in docker networking will probably play better than messing around with your IP tables

    Hope this is useful.

    Dylan

    Edit

    I have generalised the process as I do not know the specifics of your setup with regards to proxies, network restrictions etc. I have also not gone into specific commands as the link above covers it better than I would.