Wireguard – How to Forward/Route Packets via Wireguard Overlay Network

iptableslinuxroutingwireguard

My question is related to basics in network routing and iptables, and is probably due to my lack of understanding on how I should set this up.

I have established an overlay network between hosts using wireguard, where one is behind a Router/NAT. In so far the overlay network works well, and each host can talk to the others.

Now, I would like to make Host A a gateway to the private network, but I am miserably failing to do so.

Can you maybe help me unravel the mystery that is iptables forwarding?

3 Networks

The overlay network of the VPN is 169.254.0.0/24 and the private network behind the router is a 192.168.0.0/24.

  • The internet 🐈
  • The overlay network (169.254.0.0/24, running on Wireguard)
  • The private network (192.168.0.0/24)

4 Hosts

  • VPN Server

    wg0: 169.254.0.1

  • Client

    wg0: 169.254.0.2

  • Host A

    wg0: 169.254.0.3
    eth0: 192.168.0.33

  • Host B

    eth0: 192.168.0.53

In order to illustrate the real network, here is this picture:
real network

And here is the overlay network:
overlay network

At which, my Client is failing to send packets to Host B via Host A.

Best Answer

Here is a working configuration. Phew, I actually got it myself, but it took me a while to get things right.

Client

I had to make sure that the peer (VPN Server) is allowed to use the 192.168.178.0/24 range.

[Interface]
Address = 169.254.0.2/32
PrivateKey = ...
ListenPort = 51280

[Peer]
PublicKey = ...
AllowedIPs = 169.254.0.1/32, 192.168.178.0/24
Endpoint = ...:51280

VPN Server

I just had to forward packets from the tun0 interface and MASQUERADE them. Furthermore, I also added the 192.168.178.0/24 network to the AllowedIPs of Host A.

$ iptables -A FORWARD -i tun0 -j ACCEPT
$ iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE

Wireguard configuration:

[Interface]
Address = 169.254.0.1/32
PrivateKey = ...
ListenPort = 51280

[Peer]
Endpoint = ...:51280
PublicKey = ...
AllowedIps = 169.254.0.2/32

[Peer]
Endpoint = ...:51280
PublicKey = ...
AllowedIps = 169.254.0.3/32, 192.168.178.0/24

Host A

There I needed to accept forwarding pakets on both interfaces. And I would masquerade pakets on eth0.

$ iptables -A FORWARD -i tun0 -j ACCEPT
$ iptables -A FORWARD -i eth0 -j ACCEPT
$ iptables -A POSTROUTING -o eth0 -j MASQUERADE

Wireguard wise, the configuration is nothing special. It is simply connected to the VPN server.

[Interface]
Address = 169.254.0.3/32
PrivateKey = ...
ListenPort = 51280

[Peer]
Endpoint = ...:51280
PublicKey = ...
AllowedIps = 169.254.0.1/32
PersistentKeepalive = 25

However, there was one major pitfall when working with Host A (which is behind a Router/NAT). The VPN server must know the endpoint (public ip + port) of Host A in order to send pakets to it. The Router would loose state after a while, and thus the VPN Server would no longer be able to connect to Host A.

I fixed this, by adding the PersistentKeepalive setting to the [Peer] section of the VPN server on Host A. (Thanks to @A.B from comments to point this out.)

I wonder how to solve that if both are behind a Router/NAT. Damn, that is complicated.

Related Topic