andersch.dev

<2024-02-06 Tue>

WireGuard

WireGuard is a tunneling protocol that can be used to implement a VPN.

Establish Server/Client Connection

Initial key generation and exchange

sudo pacman -S wireguard-tools # install userspace utilities

# generate key pair on server
wg genkey | tee wg0-server.priv | wg pubkey > wg0-server.pub

# generate key pair on client
wg genkey | tee wg0-client.priv | wg pubkey > wg0-client.pub

# exchange public keys
scp user@client:/path/to/wg0-client.pub  admin@server:
scp admin@server:/path/to/wg0-server.pub user@client:

On wireguard server (e.g. a VPS)

# add interface and set ip address
ip link add dev wg0 type wireguard
ip addr add 10.0.0.1/24 dev wg0

# set listening port and add private key
wg set wg0 listen-port 12345 private-key /path/to/wg0-server.priv

# set peer (client) via their public key
wg set wg0 peer $(cat wg0-client.pub) allowed-ips 10.0.0.2/32

ip link set wg0 up

On wireguard client (e.g. a home server behind NAT)

ip link add dev wg0 type wireguard
ip addr add 10.0.0.2/24 dev wg0 # must match allowed-ips above
wg set wg0 listen-port 12345 private-key /path/to/wg0-client.priv

# set peer (server) via their public key and specify an endpoint
# plus set keep alive so that connection doesnt die (e.g. when client switches ip)
wg set wg0 peer $(cat wg0-server.pub) allowed-ips 10.0.0.1/32 endpoint 12.34.678.9:12345 persistent-keepalive 25

ip link set wg0 up

Test connection

# first ping 10.0.0.1 from client to establish connection
ping 10.0.0.1

# now try pinging 10.0.0.2 from server
ping 10.0.0.2

# server should be able to ping client, even though no client endpoint was
# defined thanks to the pre-established connection

# check connections, allowed ips, etc. on server or client
wg

Make Client's LAN accessible over WireGuard

To be able to access other machines in the client's LAN

# on server & client, add the LAN subnetwork as allowed ips
wg set wg0 peer $(cat wg0-client.pub) allowed-ips 10.0.0.2/32,192.168.178.0/24
wg set wg0 peer $(cat wg0-server.pub) allowed-ips 10.0.0.1/32,192.168.178.0/24

# add route to the home server's LAN on server
ip route add 192.168.35.0/24 dev wg0

# check if ipv4 forwarding is enabled on client
sysctl -a | grep ip_forward

# if net.ipv4.ip_forward = 0, enable it
sysctl -w net.ipv4.ip_forward=1

# enable ip masquerading according to https://unix.stackexchange.com/questions/638889/make-local-resources-available-when-connected-to-wireguard-vpn
iptables -t mangle -A PREROUTING -i wg0 -j MARK --set-mark 0x30
iptables -t nat -A POSTROUTING ! -o wg0 -m mark --mark 0x30 -j MASQUERADE

# test by pinging a machine in the client's LAN on the server
ping 192.168.178.30

Using wg.conf files with wg-quick

# WireGuard config files live in /etc/wireguard/

# Manual setup from above can be saved with
wg showconf wg0 > /etc/wireguard/wg0.conf

# add Address = ... field in wg0.conf (used by wg-quick)
[Interface]
Address = 10.0.0.x/24

# for more config options that only wg-quick uses, see
# https://man.archlinux.org/man/wg-quick.8#CONFIGURATION

# Start wireguard using wg0 config with
wg-quick up wg0
# Or
systemctl start wg-quick@wg0.service

# To persist across reboots
systemctl enable wg-quick@wg0.service