WireGuard

This is the future of VPNs, etc. Read about it here. It really is amazing. There’s also manual configuration steps there, which you should do first.

It’s super easy to set up configurations for use with wg-quick. Here’s a simple server + client configuration for tunnelling all traffic throught the VPN.

Note that “server” and “client” are artificial terms here; really both machines are peers, we’re imposing the server + client relationship on them to align with traditional VPNs.

Generate private keys with umask 077 && wg genkey > private.key. Corresponding public keys are derived from private ones with wg pubkey < private.key > public.key. The preshared key is used for post-quantum resilience, generated with wg genpsk > preshared.key.


# server wg0.conf
[Interface]
PrivateKey = [server private key]
Address = 10.10.0.1/24, fd80::1/64
ListenPort = 2307
SaveConfig = true
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT && iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT && iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
PublicKey = [client public key]
PresharedKey = [preshared.key]
AllowedIPs = 10.10.0.2/32, fd80::2/128

Not a whole lot is happening here. IP addresses and ports are just examples—here we’re allocating 10.10.0.1 to the server and 10.10.0.2 to the client. The SaveConfig line allows WireGuard to override this file with its current state, so you can make manual, persistent changes as it runs.


# client wg0.conf
[Interface]
PrivateKey = [client private key]
Address = 10.10.0.2/24, fd80::2/64
ListenPort = 2307
DNS = 10.10.0.1
PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
PreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT

[Peer]
PublicKey = [server public key]
PresharedKey = [preshared.key]
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = [wireguard server]:2307

The ports match for NAT traversal, but it’s not strictly necessary. The client allows its peer to send traffic from any IP, since it’s going to be proxying the entire internet.

On both server and client, run wg-quick up wg0. This can also run as a systemd service, with systemctl start wg-quick@wg0.service.