So I have the following example compose file, with a custom defined network:
version: '3.7'
services:
ubuntu:
image: ubuntu
restart: unless-stopped
tty: true
networks:
wireguard:
ipv4_address: 172.18.0.2
networks:
wireguard:
driver: bridge
driver_opts:
com.docker.network.bridge.name: 'wireguard'
ipam:
driver: default
config:
- subnet: 172.18.0.0/16
And the following Wireguard config defined as wg0.conf
:
[Interface]
Table = off
SaveConfig = false
PrivateKey = {Client Private Key}
Address = 10.8.0.21/32
DNS = 10.8.0.1
# And create routing manually only for WG related communication.
PostUp = iptables -t mangle -I PREROUTING 1 -i wg0 -m conntrack --ctstate NEW -j CONNMARK --set-mark 2
PostUp = iptables -t mangle -I OUTPUT 1 -m connmark --mark 2 -j CONNMARK --restore-mark
PostUp = iptables -t mangle -I PREROUTING 2 -m connmark --mark 2 -j CONNMARK --restore-mark
PostUp = ip rule add fwmark 2 lookup 2
PostUp = ip rule add table main suppress_prefixlength 0
PostUp = ip route add default dev wg0 table 2
PostUp = sysctl -q net.ipv4.conf.all.src_valid_mark=1
PostUp = sysctl -w net.ipv4.conf.wg0.rp_filter=2
# Removal when `wg0` goes down
PostDown = iptables -t mangle -D PREROUTING -i wg0 -m conntrack --ctstate NEW -j CONNMARK --set-mark 2
PostDown = iptables -t mangle -D OUTPUT -m connmark --mark 2 -j CONNMARK --restore-mark
PostDown = iptables -t mangle -D PREROUTING -m connmark --mark 2 -j CONNMARK --restore-mark
PostDown = ip rule del table main suppress_prefixlength 0
PostDown = ip rule flush table 2
[Peer]
PublicKey = {VPN Server Public Key}
AllowedIPs = 10.8.0.1/32,0.0.0.0/0
Endpoint = {VPN Server Connection Endpoint}
PersistentKeepalive = 25
Now the wireguard connection is setup to route incoming connections back through the wg0 interface, to avoid all of the client connections going through the VPN.
So now my objective is to have specific docker containers routed through the VPN connection for their connections out. So what I do is rune the following rule and route in the host shell to add to the existing table:
# ip rule add from 172.18.0.0/16 lookup 2
# ip route add 172.18.0.0/16 dev wg0 table 2
And if I enter the docker shell and check the connection it works perfectly and shows the IP of the VPN server:
ping and ip inside docker container
But after around 30 second to up to 5 minutes, I can't get a connection out and any connection attempts just timeout:
no connection out docker container
And if I tcpdump the bridge network it just keeps trying to make ARP requests for 172.18.0.1:
tcpdump container bridge
I have no idea why this happening or how to fix this. I have seen several posts and forums of people doing the same for routing a docker network connection through a specific interface, so I don't know if I've done something wrong elsewhere.
Best Answer
I think the right way to do is running the VPN in a seperate docker container and then connect the other docker containers through that VPN. That's at least the best practice.
A example docker compose:
With
network_mode: service
the Ubuntu container will connect through the WireGuard container with the vpn client. service: This allows a container to share the network namespace with another service. You specify the service name, and the containers will use the same network stack.You can also use
network_mode: host
instead of networks