Splitting WireGuard between Router (RT-AX88U) and Client (Ubuntu VM running on Hyper-V)
Hi
@ZebMcKayhan, sorry for the delay in getting back and thanks again for your invaluable support in getting this over the line
I wanted to
- use my VPN setup (WireGuard) in dual stack mode with full support for IPv4 and IPv6.
- run in server mode (for remote access to LAN, for "road warriors" e.g. phones, laptops, tablets)
- run in client mode on some devices (for obfuscation)
- route Unbound queries though the VPN client for the Ubuntu VM (for obfuscation)
- allow remote clients to access the internet via the same VPN client (pass-through mode)
- Use the routers hardware acceleration (Flow Cache enabled)
The Issue
1-5 above all work fine using
@Martineau's WGM with Flow Cache off. However when I changed ISP and increased the notional WAN connection from 80Mb/20Mb to 1Gb/1Gb this limited my WAN speeds to 420/550 for
all devices, as opposed to at least 930/930 with Flow Cache on. However with Flow Cache enabled, after 20-40 minutes the speed would drop back to 420/550 or less.
Although I was (and am) using v4.19b5 of WGM, which should allow the cache bypass for non-WireGuard clients, this does not work on my RT-AX88U. While I understand that the cache bypass may work on other models, I had previously tested on my router by removing all scripts other than Wireguard and disabling IPv6 - it did not help.
On testing it has been noted that running WGM in server mode with Flow Cache enabled does not cause any practical issues, the issue is with client mode.
The solution
To continue to run the VPN in server mode on the Router, run the client VPN on the Ubuntu VM and
connect the two so that 'road-warrior' pass-through traffic still access the internet via the VPN on the VM and that unbound queries are similarly routed. The
connection is a dummy VPN client that just points to the VM.
While I learned this the hard way (repeated failures) the easiest way to do this is to disable the WGM client on the router before proceeding with the setup.
In addition the VPN on the VM (or chosen device) should be up and running BEFORE enabling the dummy VPN. So, if I need to restart the VM or reboot its host, I will stop the dummy client on the router, reboot/restart the host/VM and then restart the dummy VPN. I also then restart Unbound and clear the cache.
On the VM
Firewall: As the default Ubuntu client VM for Hyper-V does not come with a firewall enabled, I installed
ufw (uncomplicated firewall) following this guide (
https://devtutorial.io/how-to-set-up-a-firewall-with-ufw-on-ubuntu-23-10-p3193.html) - there are plenty of others as well. I then added
gufw (a gui for
ufw)
Once the firewall was up I then added to necessary rules to allow access to its services (as necessary) for the other devices on the LAN that were using them and once I was happy that the LAN traffic was working as before (installing) the firewall), I moved onto WireGuard.
WireGuard: As I am not using a LTE for my setup I first chose to add the repository
Code:
sudo add-apt-repository pp:wireguard/wireguard
, then installed WireGuard itself
Sass:
sudo apt install wireguard
and then ran the installer for my VPN provider (in my case AzireVPN).
In order to allow IP forwarding (for internet access)
Code:
sudo nano /etc/sysctl.conf
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
and to make it live
The next steps are to check the public network interface name
in my case
Diff:
default via <router LAN ipv4> dev eth0 proto dhcp src <VM LAN ipv4> metric 100
so
eth0 and then add the routing rules to the VPN as it comes up / is taken down
Code:
sudo nano /etc/wireguard/<wg_client>.conf
Code:
[Interface]
PrivateKey = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=
Address = 10.0.xx.xx, 2a0e:xxxx:xxxx:1:10:0:xx:xx
DNS = 10.0.0.1, 2a0e:xxxx:xxxx:1:10:0:0:1, xxx.xxx.xxx.xx
PostUp = ufw route allow in on eth0 out on <wg_client>
PostUp = iptables -t nat -I POSTROUTING -o <wg_client> -j MASQUERADE
PostUp = ip6tables -t nat -I POSTROUTING -o <wg_client> -j MASQUERADE
Postup = ip route add <ip4_alias> dev eth0 table main
PreDown = ufw route delete allow in on eth0 out on <wg_client>
PreDown = iptables -t nat -D POSTROUTING -o <wg_client> -j MASQUERADE
PreDown = ip6tables -t nat -D POSTROUTING -o <wg_client> -j MASQUERADE
PreDown = ip route del <ip4_alias> dev eth0 table main
[Peer]
PublicKey = yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy=
Endpoint = xxxx.azirevpn.net:nnnnn
AllowedIPs = 0.0.0.0/0, ::/0
where <ip4_alias> is set on the router, see below.
In setting up the interface between the firewall and WireGuard, i found these pages helpful.
In this tutorial, you will set up WireGuard on an Ubuntu 20.04 server, and then configure another machine to connect to it as a peer using both IPv4 and IPv6…
www.digitalocean.com
On the Router
Where both server and client aspects of WireGuard can be run on the router, the method for routing unbound queries via a client instance is
- create IPv4 and IPv6 aliases, <ipv4_alias> and <ipv6_alias>
- add the to wan-event
- add these aliases to unbound
- add the modified IPv6 alias to the WireGuard server config <wg2x>
- add the routing to WireGuard client <wg1x>
in
wan-event
Code:
if [ "$1" = "0" ] && [ "$2" = "connected" ]; then
ifconfig br0:1 <ipv4_alias> netmask 255.255.255.255
ip -6 address add dev eth5 <ipv6_alias>/128
fi
then add these interfaces in
unbound.conf under server:
Code:
outgoing-interface: <alias_4> # routing to wan-event + wgm policy rules
outgoing-interface: <alias_6> # routing to wan-event + wgm policy rules
and in WGM for wg21
Code:
peer wg21 ip=10.50.1.1/24 ipv6=aa36:7ef1:xxxx:aa88:100::1/120
where the ipv6 address is the <ipv6_alias> with the first two characters
fd changed to
aa and add
Code:
peer wg1x rule add <alias_4> comment Unbound4VPN
peer wg1x rule add <alias_6> comment Unbound6VPN
for the client routing
Aliases:
Aliases can be used to mask the router's IP address for DNS purposes by using additional link-local addresses on different subnet ranges to the default router subnets. Ideally these aliases would be added to
br0 while the router is booting, using
wan-event. However the IPv6 interfaces load slower than the IPv4 ones, so a more practical solutions is to add the ipv6 alias to another active interface. For the RT-AX88U
eth5 can be used as it is always up, being the link to the secondary 4 port switch.
For <ipv4_alias>, this just needs on a separate subnet to the main LAN, but for ease or reading I use 10.xxx.xxx.xxx for my LAN network and then use 192.168.xxx.xxx for the IPv4 alias.
For dynamic IPv6 the starting point for the aliases is to use a ULA generator
- create a dummy GUA, e.g. fd36:7ef1:2add:xxxx::/64
- change fd to aa : aa36:7ef1:2add:xxxx::/64 # <wg2x_6_scope>
- Remove :/64, add 100::1/120 : aa36:7ef1:2add:xxxx:100::1/120
- Add to the server up/down scripts - see wg21-up.sh
Where
fd36:7ef1:2add:xxxx:100::1 is
<ipv6_alias> and
aa36:7ef1:2add:xxxx:100::1 is the
modified IPv6 alias
and in
wg21-up.sh
Code:
#!/bin/sh
###############################################################################
# Example for Wg21 ipv6 = aa00:aaaa:bbbb:cccc:100::1/120
# Change to your needs but keep formatting
Wg21Prefix=aa36:7ef1:2add:xxxx:: #Wg21 ULA prefix with aa instead of fd
Wg21Suffix=100::1 #Wg21 Device suffix (last 64 bits)
Wg21PrefixLength=120 #Wg21 Prefix Length (120 recommended)
WanInterface=eth0
# Changing below lines should not be needed:
WanIp6Prefix=$(nvram get ipv6_prefix) #WanIp6Prefix=2001:1111:2222:3333::
Wg21_PrefIp=${Wg21Prefix%:*}${Wg21Suffix}/${Wg21PrefixLength} #aa00:aaaa:bbbb:cccc:100::1/120
WanWg21_PrefIp=${WanIp6Prefix%:*}${Wg21Suffix}/${Wg21PrefixLength} #2001:1111:2222:3333:100::1/120
ip6tables -t nat -I POSTROUTING -s ${Wg21_PrefIp} -o ${WanInterface} -j MASQUERADE -m comment --comment "WireGuard 'server'"
- the last line is modified from
-I to
-D in
wg21-down.sh to remove the POSTROUTING rule.
END OF PART 1