0

I'm trying to get a "simple" VPN working between two Linux boxes using Wireguard. Unfortunately, existing tutorials I've found weren't that helpful, because they usually A) only set up IPv4 and B) usually use IP masquerading ...

Config of machine A:

[Interface]
Address = 192.168.10.2/24
ListenPort = 51820
 
[Peer]
AllowedIPs = 192.168.10.0/24, 172.16.0.0/24, fdbb:bbbb:bbbb::/48, 2001:db8:bbbb:0000::/64
Endpoint = [2001:db8:bbbb:0000:1234:56ff:fe78:90ab]:51820
PersistentKeepalive = 20

Config of machine B:

[Interface]
Address = 192.168.10.1/24
ListenPort = 51820

[Peer]
AllowedIPs = 192.168.10.2/32, 10.0.0.0/16, fdaa:aaaa:aaaa::/48, 2001:db8:aaaa:0000::/64
Endpoint = [2001:db8:aaaa:0000:ba09:87ff:fe65:4321]:51820
PersistentKeepalive = 20

(Leaving out the keys because the tunnel itself is passing traffic so I know these are correct). So, simple config, in theory. Machine A has no local firewall (only a typical consumer router with its built-in firewall, with UDP/51820 opened), machine B has ip(6)tables but only for all the Docker rules, and the default policies are set to Accept.

Both machines have net.ipv4.ip_forward=1 and net.ipv6.conf.all.forwarding=2.

That config didn't work, because Wireguard apparently tries to route its own wireguard traffic through the tunnel itself because the Endpoint IPv6 is included in the AllowedIPs network. Why would that not be excluded by default...

I tried to get around that by adding a fixed route to send traffic for that endpoint through the normal interface, not wg0:

PostUp = /usr/sbin/ip -6 route add 2001:db8:aaaa:0000:ba09:87ff:fe65:4321/128 via fe80::1 dev enp1s0
PreDown = /usr/sbin/ip -6 route del 2001:db8:aaaa:0000:ba09:87ff:fe65:4321/128 via fe80::1 dev enp1s0

With that setup (on both sides), the peers can ping eachother A) through the WG peer addresses (192.168.10.X), B) through their local IPv4 (10.0.X.X or 172.16.X.X), and C) through their ULA addresses.

However, I still have two issues with my tunnel:

A) Because I had to add that IPv6 route to the endpoint, that means traffic to the other peer's public IPv6 address does not go through the WG tunnel but travels directly over the internet. The peers cannot ping eachother using their public GUA IPv6 addresses. I would need something like that IP route I added using the PostUp parameter, but for that to only apply to the tunnel itself, not for traffic going through the tunnel. Like an IPv6 route where I can say "route UDP/51820 over this route (directly to the internet), but other traffic to that same IP over that route (wg0)".

B) I can't get everything to work from other machines in my network (over IPv4). On another machine on network A, I added a static route to the other network's IPv4: 172.16.0.0/24 via 10.0.1.25 dev enp7s0 metric 100.

When I now do a traceroute, the 1st hop is the wireguard machine (10.0.1.25), and the 2nd hop is the WG peer's address of the remote machine (192.168.10.1) (so it does go through the tunnel!), but after that, boom, that's it. No third hop with the actual destination (even though the other side's default gateway does have a static route to route 10.0.0.0/8 to that side's wireguard machine. I do not want to do IP masquerading which is the "solution" I found multiple times using Google. I want the other machines on the other network see exactly where the requests are coming from - a machine on the other side of the tunnel.

Over IPv6, using the ULAs, everything is fine. Added an IPv6 route on the gateway to route the other side's ULAs to the wireguard machine, and done. I just need to find a solution for the GUAs, probably with radvd on the wireguard machine announcing a route to that network.

TL;DR: Wireguard connection between two peers works, but A) how do I send non-Wireguard traffic to the wireguard endpoint IP over the tunnel as well, and B) why does IPv6 ULA routing work and IPv4 routing doesn't even though they're set up the same.

2
  • 1
    Check with tcpdump whether the gateway system is actually not forwarding requests or whether it's not forwarding replies. Remember that the machine you're trying to ping needs to know a route back to the client's network... May 1, 2023 at 11:55
  • Thanks for the hint. With tcpdump running on all four machines (source, wg source, wg destination, destination) I figured out the issue with the IPv4 route so IPv4 is now working. Only question remaining is the IPv6 one. May 1, 2023 at 13:42

1 Answer 1

0

I managed to get that to work by using IP rules, using these commands in the wireguard config:

PostUp = ip -6 rule add to 2001:db8:aaaa::ba09:87ff:fe65:4321/128 ipproto udp dport 51820 table 200
PostUp = ip -6 route add default via fe80::1 dev eth0 table 200

PreDown = ip -6 rule del lookup 200
PreDown = ip -6 route del default via fe80::1 dev eth0 table 200

This adds an entirely seperate routing table 200 with only one (default) route to send all traffic to the local router, and then it adds an IP rule so that any UDP traffic to the endpoint's IPv6 on port 51820 will be handled according to that new routing table.

That way, UDP traffic for the WG tunnel itself will go to the router, but any other packets with that same destination IP will go through the WG tunnel.

And then I just added radvd on both sides of the tunnel, announcing a route to the other side's GUA prefix so devices in the network send traffic to the wireguard machine.

1
  • I think you might want to use fwmark to tag traffic and use 2 routing tables, reading this wireguard.com/netns helping me to understand some ways to manage this kind of problems, wg-quick use by default fwmark if you have 0.0.0.0/0 allowed
    – HugoPoi
    Feb 15 at 18:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .