Open Source

WireGuard VPN: From Zero to Tunnel

ยท2 min read

WireGuard is the modern VPN. It's in the Linux kernel since 5.6, has roughly 4,000 lines of code (vs hundreds of thousands for OpenVPN/IPsec), and configures with a single file per peer. The cryptography choices are not configurable โ€” that's a feature, not a limitation. Twenty minutes of reading is enough to deploy it.

Generate keys

apt install wireguard
umask 077
wg genkey | tee server-private.key | wg pubkey > server-public.key
wg genkey | tee client1-private.key | wg pubkey > client1-public.key

Server config

# /etc/wireguard/wg0.conf
[Interface]
Address = 10.88.0.1/24
ListenPort = 51820
PrivateKey = 

# NAT (if you want clients to reach the internet through this server)
PostUp   = iptables -t nat -A POSTROUTING -s 10.88.0.0/24 -o eth0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -s 10.88.0.0/24 -o eth0 -j MASQUERADE

[Peer]
PublicKey = 
AllowedIPs = 10.88.0.2/32
# Enable IPv4 forwarding
echo 'net.ipv4.ip_forward=1' > /etc/sysctl.d/99-wg.conf
sysctl -p /etc/sysctl.d/99-wg.conf

# Start
systemctl enable --now wg-quick@wg0

Client config

# client1.conf
[Interface]
Address = 10.88.0.2/32
PrivateKey = 
DNS = 1.1.1.1

[Peer]
PublicKey = 
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0      # send everything through the tunnel
PersistentKeepalive = 25

On Linux: wg-quick up ./client1.conf. On phones, render the config as a QR code and scan it in the WireGuard app:

qrencode -t ansiutf8 < client1.conf

Split tunneling

Only route specific destinations through the VPN โ€” useful when you only need access to internal services, not your full internet traffic:

[Peer]
AllowedIPs = 10.0.0.0/8, 192.168.0.0/16    # only LAN ranges

Adding peers

For each new client: generate keys, append a [Peer] block to the server config, hand them the client config with their key + server's public key. wg syncconf applies changes without dropping existing peers:

wg syncconf wg0 <(wg-quick strip wg0)

Observability

wg show                    # peers, last handshake, transfer
wg show wg0 latest-handshakes
journalctl -u wg-quick@wg0

A peer that hasn't handshaken in > 3 minutes is probably broken โ€” check firewall, MTU (1420 is a safe interior value), and NAT.

Related