1

My laptop has an IPsec VPN tunnel set up to access a remote site (with my side being the VPN client).

As an experiment, I started up a simple docker container on my laptop using docker run --rm -it alpine:3.7 /bin/sh and from within the container tried to ping one of the remote machines on the other side of the tunnel.

I expected the ping to not work, but I was surprised that it actually did.

I expected that in order to be able to access one of the remote machines from within a docker container, I'd have to first set up the VPN connection from within the container.

If not a full-fledged VPN connection from within the container, I thought that I would at least need to set up some iptables rules on the host machine. (My laptop's private IP address is 192.168.10.1, that of the remote server is 10.2.5.100 and that of my docker container is 172.17.0.2.) But even this wasn't needed...

So my question is how is it that communicating with the remote machines through the tunnel just works without any additional setup?

p.s. in case it matters, my laptop is running Arch Linux and I'm using strongswan to set up the IPsec connection.

2

If you run docker run --rm -it alpine:3.7 /bin/sh, created docker container will use default bridge network.

You can see the properties of this network using the following command: docker network inspect bridge. You can see there to which host interface (usually docker0) the network is associated and also what is the subnet for this network (usually 172.17.0.0/16).

Additionally, if you run docker run --rm -it alpine:3.7 ip addr command, you should see the IP address of your container, which should be part of previously mentioned subnet.

Then, Docker by default creates NAT iptables rules, which allows the containers to communicate with outside world (as the container IP address is not known to the internet). You can see the rules using sudo iptables -t nat -nvL POSTROUTING command. It should look similar to:

Chain POSTROUTING (policy ACCEPT 144K packets, 15M bytes)
 pkts bytes target     prot opt in     out     source               destination
  392 75916 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0

Finally, for your container, there is no difference, if you try to reach remote site of your VPN or the internet, as the container only knows how to reach Docker network. You can see that using docker run --rm -it alpine:3.7 ip r command:

default via 172.17.0.1 dev eth0
172.17.0.0/16 dev eth0 scope link  src 172.17.0.2

So when traffic from the container goes via default route, it hits host routing table (I'm not 100% sure if this is right), it is being routed to your tunnel and then iptables NAT rule applies, changing the source IP of your traffic to IP of your end of the tunnel, so returning traffic will come back over the tunnel as well and then back to your container.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.