Linux Server with public IP address (Example: 2001:db8:1234:5678::1 )
WSL2 on Windows 11
This almost certainly requires bridged networking for WireGuard to work well: WSL2 bridged networking
Start your SSH agent with your private key, if you haven't already.
Connect ssh to the Server's public IPv6 address.
Confirm the network interface with a public IP address (usually eth0)
ip -6 addr show scope global
Switch to root user:
sudo su -
Enable packet forwarding; no spaces around the equals sign:
vi /etc/sysctl.d/60-eth0-routing.conf
net.ipv6.conf.all.forwarding=1
net.ipv6.conf.eth0.accept_ra=2
Reload the sysctl parameters
sysctl --system
Install packages for WireGuard:
apt install wireguard wireguard-tools -y
Create WireGuard server crypto keys:
cd /etc/wireguard
umask 077
wg genkey | sudo tee server_private.key | wg pubkey | sudo tee server_public.key
The output is used below in the $SERVER_PUBLIC_KEY
Return to your WSL2 Linux client, and switch to root user:
sudo su -
Install WireGuard to the client:
apt update
apt install wireguard wireguard-go -y
Create WireGuard client crypto keys:
cd /etc/wireguard
umask 077
wg genkey | sudo tee client_private.key | wg pubkey | sudo tee client_public.key
This outputs the $CLIENT_PUBLIC_KEY
Next output the $CLIENT_PRIVATE_KEY:
cat client_private.key
Create a client WireGuard configuration from scratch. Fill in the key values from above:
vi /etc/wireguard/wg1.conf
[Interface]# Your client's assigned tunnel IP addresses (IPv4 and/or IPv6)Address = 10.43.0.2/24, fd43:43:43::2/64Secure the permissions of the file on the client:
chmod 600 /etc/wireguard/wg1.conf
This configuration file will only be used for testing with "wg-quick", but it is a good reference for systemd-networkd configuration later.
Now log in to the server again.
On the server define the wg0 device in systemd-networkd:
vi /etc/systemd/network/99-wg0.netdev
[NetDev]
Name=wg0
Kind=wireguard
Description=VPN Server
[WireGuard]
PrivateKey= $SERVER_PRIVATE_KEY
ListenPort=4500
[WireGuardPeer]
PublicKey= $CLIENT_PUBLIC_KEY
AllowedIPs= 10.43.0.2/32, fd43:43:43::2/128
Next define the wg0 network settings for systemd-networkd; this will masquerade Internet-bound traffic from the client
vi /etc/systemd/network/99-wg0.network
[Match]
Name=wg0
[Network]
BindCarrier=eth0
Address=10.43.0.1/24
Address=fd43:43:43::1/64
IPForward=yes
IPMasquerade=both
TCPMSSClamp=yes
Restart the systemd-networkd service, which should bring up the wg0 device:
systemctl restart systemd-networkd
Determine the server's local DNS addresses, to be referenced later by the client:
grep nameserver /etc/resolv.conf
Test the client connection with wg-quick:
wg-quick up wg1
wg show wg1
There should be bytes sent and received. If not, you will have to correct the problem and try again. Otherwise:
wg-quick down wg1
Define the client's wg0 device in a .netdev file; replace the bold items with keys and server public address
vi /etc/systemd/network/99-wg0.netdev
[NetDev]
Name=wg0
Kind=wireguard
Description=Tunnel to WebVPN
[WireGuard]
PrivateKey= $CLIENT_PRIVATE_KEY
FireWallMark= 0x8888
[WireGuardPeer]
PublicKey= $SERVER_PUBLIC_KEY
Endpoint= [2001:db8:1234:5678::1]:4500
AllowedIPs= 0.0.0.0/0, ::/0
RouteTable=51280
Define the client wg0 .network file; replace the bold items with server address and DNS
vi /etc/systemd/network/99-wg0.network
[Match]
Name=wg0
[Network]
Address= 10.43.0.2/24
Address= fd43:43:43::2/64
DNS= $SERVER_DNS_1
DNS= $SERVER_DNS_2
Domains=~.
[RoutingPolicyRule]
Family=both
FirewallMark=0x8888
InvertRule=true
Table=51280
Priority=10
# Exempt the VPN, or we won't connect!
[RoutingPolicyRule]
To= 2001:db8:1234:5678::1/128
Priority=5
Apply the network changes:
systemctl restart systemd-networkd systemd-resolved
If the wg0 interface was not created, double check the files in /etc/systemd/network/ and make sure you have replaced all placeholders .
Check that the interface was created and connected to the server.
sudo wg show wg0
Test that the traffic is REALLY being forwarded. If your FirewallMark or Table were wrong, traffic can leak out through your normal interface.
On the server:
sudo tcpdump -ni wg0 icmp6
On the client:
sudo mtr -6 www.google.com
If traffic and DNS are properly forwarded, tcpdump will show output on the server side. If not, review the configurations and fix it!
wget can prefer IPv6 addresses returned from DNS.
vi $HOME/.wgetrc
prefer-family = IPv6