Docker – Not able to access to the internet in a container on a VPN

dockervpn

I'm not able to do a ping in a container when the VPN is started on my host machine.

I try do this :

docker run adiazmor/docker-ubuntu-with-ping ping 8.8.8.8

It fails when the VPN is started but this works :

docker run --net=host adiazmor/docker-ubuntu-with-ping ping 8.8.8.8

I can't always have the --net=host options because we can't use links in docker-compose.

I use IKE to start my VPN. Here is conf of the VPN (without seensible data) :

n:version:4
n:network-ike-port:500
n:network-mtu-size:1380
n:client-addr-auto:1
n:network-natt-port:4500
n:network-natt-rate:10
n:network-frag-size:540
n:network-dpd-enable:1
n:client-banner-enable:1
n:network-notify-enable:1
n:client-dns-used:1
n:client-dns-auto:0
n:client-dns-suffix-auto:1
n:client-splitdns-used:1
n:client-splitdns-auto:1
n:client-wins-used:1
n:client-wins-auto:1
n:phase1-dhgroup:2
n:phase1-keylen:256
n:phase1-life-secs:86400
n:phase1-life-kbytes:0
n:vendor-chkpt-enable:0
n:phase2-keylen:256
n:phase2-life-secs:28800
n:phase2-life-kbytes:0
n:policy-nailed:0
n:policy-list-auto:0
b:auth-mutual-psk:----
n:phase2-pfsgroup:-1
s:network-host:[network-host-ip]
s:client-auto-mode:pull
s:client-iface:virtual
s:network-natt-mode:enable
s:network-frag-mode:enable
s:client-dns-addr:8.8.8.8,8.8.4.4
s:auth-method:mutual-psk-xauth
s:ident-client-type:address
s:ident-server-type:any
s:phase1-exchange:main
s:phase1-cipher:aes
s:phase1-hash:sha1
s:phase2-transform:esp-aes
s:phase2-hmac:sha1
s:ipcomp-transform:disabled
s:policy-level:auto
s:policy-list-include:0.0.0.0 / 0.0.0.0

Here is the results of route -n :

On the host when the VPN is not running :

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.1.254   0.0.0.0         UG    100    0        0 enp4s0
169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 enp4s0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.18.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-c57946727b62
172.19.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-e5b5cdaf12ea
172.20.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-0f8aa3757cdc
172.21.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-89f7a8041283
172.22.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-9313de2b3cda
172.23.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-5eb78801c6be
192.168.1.0     0.0.0.0         255.255.255.0   U     100    0        0 enp4s0

When the VPN is running :

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.226.1   0.0.0.0         UG    0      0        0 tap0
0.0.0.0         192.168.1.254   0.0.0.0         UG    100    0        0 enp4s0
78.109.86.184   192.168.1.254   255.255.255.255 UGH   0      0        0 enp4s0
169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 enp4s0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.18.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-c57946727b62
172.19.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-e5b5cdaf12ea
172.20.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-0f8aa3757cdc
172.21.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-89f7a8041283
172.22.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-9313de2b3cda
172.23.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-5eb78801c6be
192.168.1.0     0.0.0.0         255.255.255.0   U     100    0        0 enp4s0

On the container (no change if the container is mounted or not) :

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.19.0.1      0.0.0.0         UG    0      0        0 eth0
172.19.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth0

I checked other questions and I didn't found something working in my case. I don't think it's related to DNS because I try to access to an IP address.

What can I do?

Best Answer

Facts-ish:

  • Outbound traffic from your container without the --net=host mode is translated (NAT/PAT) to the host's IP address on the 192.168.1.0 network (bridge mode)
  • Your VPN creates a tap interface in the 192.168.226.X network (it might well be .1/32).
  • Your VPN creates a second default route with lower metric than the usual default route to send all the traffic through the VPN (tap interface).

Considerations:

When the host sends outbound traffic for a new connection (i.e. not replying for an incoming one) it has to decide which route to apply and also which interface is suitable for that traffic.

Based on the route table above, traffic generated on the host will choose the tap interface as it has a lower metric than the en4ps0 interface.

The root cause of the problem:

Traffic generated from inside the container will get translated to the host's IP address in the en4ps0 interface, so it will apply the route suitable for that interface, thus completely skipping the VPN.

The ping might fail due to asymmetric traffic, your VPN software black-holing traffic to/from en4ps0, etc - but the point here is that your container's traffic does not go through the tunnel because of the NAT/PAT.

Depending on your underlying network and other requirements, the macvlan driver might be a better choice than bridge or host. Alternatively you'll have to re-think your architecture or the need to put a VPN on the host (and not on a separate host / device instead)