0

I'd like to restrict access to a docker container to only a few ip adresses. There are two interfaces on the server : the public (eth0) and the private (eth1 : 192.168.0.1). I only want the IPs on the private interface to access the container so I've blocked all traffic from the public interface. I've tried to add a rule to authorize the specific IP to access the container but this does not work. My iptables look like so :

sudo iptables -vL DOCKER-USER
Chain DOCKER-USER (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     tcp  --  eth1   any     192.168.0.2          192.168.0.1               tcp dpt:XXXX
    0     0 ACCEPT     all  --  eth1   any     192.168.0.1          192.168.0.2               ctstate RELATED,ESTABLISHED
    0     0 ACCEPT     all  --  eth1   any     anywhere             anywhere             ctstate RELATED,ESTABLISHED
38824 2328K DROP       all  --  eth1   any     anywhere             anywhere
14596  678K ACCEPT     all  --  eth0   any     anywhere             anywhere             ctstate RELATED,ESTABLISHED
12337  657K DROP       all  --  eth0   any     anywhere             anywhere
 770K 1335M RETURN     all  --  any    any     anywhere             anywhere

I can't manage to access the port XXXX from the ip 192.168.0.2, the port is exposed on the host like so :

0.0.0.0:XXXX->YYYY/tcp

2 Answers 2

0

I: The problem is that the docker container is using the same interface as the host. To fix this, you need to create a custom network and attach the container to this network.

Create a custom network

docker network create --driver=bridge --subnet=192.168.0.0/24 --gateway=192.168.0.1 my-network

Attach the container to the new network

docker run --net=my-network --ip=192.168.0.2 ...

Configure the iptables

sudo iptables -vL DOCKER-USER
Chain DOCKER-USER (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     tcp  --  eth1   any     192.168.0.2          192.168.0.1               tcp dpt:XXXX
    0     0 ACCEPT     all  --  eth1   any     192.168.0.1          192.168.0.2               ctstate RELATED,ESTABLISHED
    0     0 ACCEPT     all  --  eth1   any     anywhere             anywhere             ctstate RELATED,ESTABLISHED
38824 2328K DROP       all  --  eth1   any     anywhere             anywhere
14596  678K ACCEPT     all  --  eth0   any     anywhere             anywhere             ctstate RELATED,ESTABLISHED
12337  657K DROP       all  --  eth0   any     anywhere             anywhere
 770K 1335M RETURN     all  --  any    any     anywhere             anywhere

Now you can access the container from the ip 192.168.0.2.

II: You can use iptables to create a custom bridge network. This can be useful if you have connected containers on other machines and you only want to allow a specific IP range to access those containers. If you use the following command:

sudo iptables -N DOCKER

You can then add the following rules:

sudo iptables -A FORWARD -o docker0 -j DOCKER
sudo iptables -A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i docker0 ! -o docker0 -j ACCEPT
sudo iptables -A FORWARD -o docker0 -j DROP

This will allow containers to talk to each other. Then you can use the following command to add a rule that allows access to the containers from a specific IP range:

sudo iptables -A DOCKER -s [your ip range] -j ACCEPT
5
  • Is there a way to avoid this ? The container is automatically built by meteor-up and I don't have access to its configuration since I'm not the one building.
    – Ror
    Jun 29, 2022 at 9:18
  • I think not, but I could be wrong
    – bluescreen
    Jun 29, 2022 at 9:24
  • By default a container does connect to the default bridge network. Shouldn't this work like a custom bridge network ?
    – Ror
    Jun 29, 2022 at 9:54
  • Check my edit ^
    – bluescreen
    Jun 29, 2022 at 10:28
  • I am a newbie in docker but I'd like to clarify : 192.168.0.1 is the IP of the host not the container. I am not trying to make containers talk to each other but i'd like to access from an other host 192.168.0.1:XXXX which is the port exposed by docker for this container. For your edit, The DOCKER chain already exists and the docker documentation says to not touch this chain, only make modifications to the DOCKER-USER chain.
    – Ror
    Jun 29, 2022 at 12:56
0

I managed to do exactly what I wanted by following this. Turns out you need to add iptables rules on the internal container port and not the host. I also removed the destination IP 192.168.0.1. Here are the final iptables rules :

Chain DOCKER-USER (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     tcp  --  eth1   any     192.168.0.2          anywhere             tcp dpt:YYYY
    0     0 ACCEPT     all  --  eth1   any     anywhere             anywhere             ctstate RELATED,ESTABLISHED
    0     0 DROP       all  --  eth1   any     anywhere             anywhere
    0     0 ACCEPT     all  --  eth0   any     anywhere             anywhere             ctstate RELATED,ESTABLISHED
    0     0 DROP       all  --  eth0   any     anywhere             anywhere
    0     0 RETURN     all  --  any    any     anywhere             anywhere

EDIT : the rules still work if the destination IP is set to the Docker IP Range

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .