I have a docker-compose file, where I have a VPN running as NET_ADMIN, and the traffic of a bunch of other containers is routed though the VPN container.
The issue is that I can only access web APIs of the other containers (routed through the VPN) from the host machine.
version: "3.5"
services:
vpn:
image: ilteoood/docker-surfshark:latest
container_name: surfshark
env_file:
- .env
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun
ports:
- 8080:8080
- 8085:8085
restart: unless-stopped
When I connect to http://localhost:8080/ from the host machine, everything works. When I connect to the container from another machine on the local network via http://192.168.1.6:8080 (the host machine's IP), the connection times out.
This issue only affects the VPN container (and those which route through it). Other containers in the same docker-compose file which aren't routed through the VPN container are working as expected.
The host machine is running Pop!_OS 22.04, on an Intel CPU.
Edit: Routes inside the container:
# ip route list
0.0.0.0/1 via 10.8.8.1 dev tun0 default via 172.21.0.1 dev eth0
10.8.8.0/24 dev tun0 proto kernel scope link src 10.8.8.9
84.17.60.250 via 172.21.0.1 dev eth0 128.0.0.0/1 via 10.8.8.1 dev tun0
172.21.0.0/16 dev eth0 proto kernel scope link src 172.21.0.4 –
CodePudding user response:
The problem here is that your container is using the VPN for it's default route:
- A request comes in from your local
192.168.1.0/24
network - A service inside the container sends a reply
- The kernel looks for an appropriate route to reach the
192.168.1.0/24
network, but it doesn't find one, so it chooses the default gateway. - The reply goes out the VPN, which doesn't know what to do with a
192.168.1.0/24
destination, so the reply gets dropped
The simplest solution would be to add an explicit route for your local network via the regular Docker default gateway:
# ip route add 192.168.1.0/24 via 172.21.0.1
(Here I'm inferring the gateway address from the address assigned to eth0
.)