TLDR; - Added some iptable rules to a docker container to limit internet access. Working fine except that now I am unable to access container app from host machine but can do so from within container itself
I have a container running a webapp. This container uses mysql
, redis
etc. Every dependency are remote, accessible by an ip address, on a particular port.
So, for instance, mysql is accessible on ip 13.255.255.255
What I want is to allow the container only to be able to use mysql ip address and not any other. There are few curl
requests originating from within the code which I do not want to go beyond my host machine's network.
I've added an entrypoint script in docker which adds some iptables
rule in container.
ALLOWED_CIDR1=172.0.0.0/16
ALLOWED_CIDR2=13.255.255.255 #For mysql access
#iptables -P FORWARD DROP # we aren't a router
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -s 127.0.0.1 -j ACCEPT
iptables -A OUTPUT -d 127.0.0.1 -j ACCEPT
iptables -P INPUT DROP # Drop everything we don't accept
iptables -A INPUT -s 0.0.0.0 -j ACCEPT
iptables -A INPUT -s ::1 -j ACCEPT
iptables -A OUTPUT -d ::1 -j ACCEPT
iptables -A INPUT -s $ALLOWED_CIDR1 -j ACCEPT
iptables -A INPUT -s $ALLOWED_CIDR1 -j ACCEPT
iptables -A OUTPUT -d $ALLOWED_CIDR2 -j ACCEPT
iptables -A OUTPUT -d $ALLOWED_CIDR2 -j ACCEPT
iptables -P INPUT DROP
iptables -P OUTPUT DROP
When I run container and do
docker-compose exec <container-name> curl http://google.com
I get following in response:
curl: (6) Could not resolve host: google.com
which is expected. Now, when I do
docker-compose exec <container-name> curl http://0.0.0.0
I get following response:
"Hello World!"
Which again is expected. However, when I do curl http://0.0.0.0
from my host machine, following is the output
* Trying 0.0.0.0...
* TCP_NODELAY set
* Connected to 0.0.0.0 (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: 0.0.0.0
> User-Agent: curl/7.62.0
> Accept: */*
> // Hangs here
So, I am unable to connect to http://0.0.0.0 from host machine, but can connect from inside the docker.
I am utterly stupid to overlook the iptables rules I posted myself.
Wrong set of rules
ALLOWED_CIDR1=172.0.0.0/16
ALLOWED_CIDR2=13.255.255.255 #For mysql access
#iptables -P FORWARD DROP # we aren't a router
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -s 127.0.0.1 -j ACCEPT
iptables -A OUTPUT -d 127.0.0.1 -j ACCEPT
iptables -P INPUT DROP # Drop everything we don't accept
iptables -A INPUT -s 0.0.0.0 -j ACCEPT
iptables -A INPUT -s ::1 -j ACCEPT
iptables -A OUTPUT -d ::1 -j ACCEPT
iptables -A INPUT -s $ALLOWED_CIDR1 -j ACCEPT
iptables -A INPUT -s $ALLOWED_CIDR1 -j ACCEPT
iptables -A OUTPUT -d $ALLOWED_CIDR2 -j ACCEPT
iptables -A OUTPUT -d $ALLOWED_CIDR2 -j ACCEPT
iptables -P INPUT DROP
iptables -P OUTPUT DROP
You can see, in the above section:
192.168.x.x
which is the ip address of my docker-0
network interfaceBoth docker and host machine communicates using the docker0
network interface if network mode bridged
is used while launching container (which happened to be my case).
Another thing I noticed, I didn't required the 0.0.0.0
or 127.0.0.1
rules at all. Since the entrypoint script will add the iptable rules within docker container, we may never want to access webapp from within container itself. Hence, why bother with 127.0.0.1?
All in all, here is what I did:
docker0
network. ip addr show docker0
. It outputted 192.168.144.1/20My iptable rules looks like this now:
ALLOWED_CIDR1=172.0.0.0/16
ALLOWED_CIDR2=13.255.255.255
ALLOWED_CIDR3=192.168.0.0/16
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -P INPUT DROP # Drop everything we don't accept
iptables -P OUTPUT DROP
iptables -A INPUT -s $ALLOWED_CIDR1 -j ACCEPT
iptables -A INPUT -s $ALLOWED_CIDR2 -j ACCEPT
iptables -A INPUT -s $ALLOWED_CIDR3 -j ACCEPT
iptables -A OUTPUT -d $ALLOWED_CIDR1 -j ACCEPT
iptables -A OUTPUT -d $ALLOWED_CIDR2 -j ACCEPT
iptables -A OUTPUT -d $ALLOWED_CIDR3 -j ACCEPT