WireGuard cheat sheet
WireGuard is a VPN built into the Linux kernel, configured with keys and a short file per interface. These commands come from the WireGuard on Debian lesson (Debian 13, wireguard-tools 1.0.20210914), where each one was run in a lab with its output shown. For connecting sites between VyOS routers, see Site-to-site VPN with WireGuard on VyOS.
Commands
| Task | Command | ||
|---|---|---|---|
| Install the tools | apt install wireguard-tools | ||
| Make a key pair (root-only files) | `umask 077 && wg genkey \ | tee server.key \ | wg pubkey > server.pub` |
| Make a preshared key | wg genpsk | ||
| Bring a tunnel up / down | wg-quick up wg0 / wg-quick down wg0 | ||
| Run it at every boot | systemctl enable --now wg-quick@wg0 | ||
| Everything about every tunnel | wg show | ||
| Just the peers' keys | wg show wg0 peers | ||
| Is the private key loaded? | wg show wg0 private-key ((none) means no) | ||
| Add or change a peer, live | wg set wg0 peer <public key> allowed-ips 10.9.0.12/32 | ||
| Remove a peer, live | wg set wg0 peer <public key> remove | ||
| Apply the file without a restart | wg syncconf wg0 <(wg-quick strip wg0) (see the warning below) | ||
| Load a private key from a file | wg set wg0 private-key /etc/wireguard/server.key |
Server and client configuration
# /etc/wireguard/wg0.conf on the server
[Interface]
Address = 10.9.0.1/24
ListenPort = 51820
PrivateKey = <server private key>
[Peer]
# alice
PublicKey = <alice's public key>
AllowedIPs = 10.9.0.10/32
# /etc/wireguard/wg0.conf on alice's computer
[Interface]
Address = 10.9.0.10/24
PrivateKey = <alice's private key>
[Peer]
PublicKey = <server public key>
Endpoint = 203.0.113.10:51820
AllowedIPs = 10.9.0.0/24, 10.10.0.0/24
PersistentKeepalive = 25
AllowedIPs is the key idea (cryptokey routing). On the sending side it's a routing table: which peer, and so which key, a packet goes to. On the receiving side it's an access list: a decrypted packet whose source isn't in that peer's AllowedIPs is dropped.
| You want | Set |
|---|---|
| Split tunnel: only office networks through the VPN | Client AllowedIPs = the VPN and office subnets |
| Full tunnel: everything through the VPN | Client AllowedIPs = 0.0.0.0/0, plus forwarding and NAT on the server |
| A LAN behind a peer (a branch router) | Add the LAN to that peer's AllowedIPs on the server |
| Clients behind NAT stay reachable | PersistentKeepalive = 25 on the client |
Troubleshooting
What wg show says | Likely cause |
|---|---|
| No latest handshake, 0 B received | Wrong server public key on the client, the client's key isn't on the server, or UDP 51820 is blocked. The server logs nothing |
| Handshake recent, but traffic fails | Routing or firewall: forwarding off, no forward rule, no return route on the office router |
| Every user stopped at once | The server's private key is missing (wg show wg0 private-key says (none)) |
| Works, then stops when idle | A NAT mapping expired: PersistentKeepalive = 25 |
| Small packets work, big transfers hang | MTU: WireGuard's default is 1420; lower MTU = in [Interface] |
The syncconf trap: wg syncconf makes the interface match the file exactly. If the file has no PrivateKey (because it's loaded by PostUp instead), syncconf removes the key, and every tunnel stops without an error. Either keep PrivateKey in the root-only wg0.conf, or change peers with wg set.