networking – Accessing Host’s Wireguard from Docker Containers

dockerdocker-networkinglinux-networkingnetworkingwireguard

I have a Debian server that has a Wireguard connection to a box sitting behind a NAT. The box has Wireguard IP 192.168.60.2 whereas the server has Wireguard IP 192.168.60.1. On the server, a few Docker containers are running. I would like to be able to assign some containers an IP on the 192.168.60.0/24 subnet so that I can tell the containers apart by IP on the box as requests from the contains come in.

When I launch containers without special network config, i.e. using the standard bridge driver, I can reach the box via its IP 192.168.60.2, however, the originating IP is the server's (192.168.60.1).

I tried using Docker's IPVLAN network driver, but that requires an actual Ethernet interface as opposed to a tunnel.

How can I achieve this?


edit: After creating a Docker network with docker network create --driver=bridge --subnet=192.168.60.0/24 my-net and starting a dummy container with docker run -it --rm --network=my-net --ip=192.168.60.10 alpine, I still cannot get this to work.

The Wireguard settings on the server are like so:

[Interface]
PrivateKey = *** REDACTED ***
ListenPort = 51821
Address = 192.168.60.1/24
[Peer]
PublicKey = *** REDACTED ***
AllowedIPs = 192.168.60.2/32 # I also tried setting this to /24

In the box's Wireguard settings the Address is set to 192.168.60.2/32 and AllowedIPs is set to 192.168.60.0/24.

I checked the firewall counters and I don't think this is what's stopping the packets. However, when looking at the routing table, this seems suspicious:

192.168.60.0/24 dev wg1 proto kernel scope link src 192.168.60.1
192.168.60.0/24 dev br-df2fc584e6b0 proto kernel scope link src 192.168.60.1

wg1 is the Wireguard interface and br-df2fc584e6b0 corresponds to the Docker bridge my-net. More details:

$ ip a show dev br-df2fc584e6b0
184: br-df2fc584e6b0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:98:27:08:23 brd ff:ff:ff:ff:ff:ff
    inet 192.168.60.1/24 brd 192.168.60.255 scope global br-df2fc584e6b0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:98ff:fe27:823/64 scope link
       valid_lft forever preferred_lft forever

$ ip a show dev wg1
177: wg1: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none
    inet 192.168.60.1/24 scope global wg1
       valid_lft forever preferred_lft forever

edit2: I was able to resolve this by making the IP subnets non-overlapping, i.e. the Wireguard interface has the address 192.168.60.1/28 and the bridge network is assigned the subnet 192.168.60.16/28. Additionally, I created the bridge network with com.docker.network.bridge.enable_ip_masquerade=false to keep the original IP.

Best Answer

you can create a custom bridge network in Docker and then connect your containers to this network.

1.

docker network create --driver=bridge --subnet=192.168.60.0/24 mynetwork
docker run --network=mynetwork --ip=192.168.60.x -d your_container_image

Ensure that your WireGuard setup allows traffic from the Docker bridge network. Update your WireGuard configuration to allow traffic from the Docker bridge subnet (192.168.60.0/24). Update the AllowedIPs both on WireGuard client and server side and make sure to restart WireGuard after that.