WireGuard Explained: The Modern Linux VPN
VPN software used to mean certificate authorities, thousand-line configs, and a userspace daemon shoveling packets. WireGuard threw all of it away: the protocol lives in the Linux kernel, peers are identified by nothing more than public keys, and a complete working config fits on one screen. It has become the default answer for connecting machines across the internet, from homelab remote access to site-to-site links.
The mental model: an interface with keys
WireGuard does not feel like an app; it feels like a network interface, because it is one. You create wg0, give it a private address like 10.0.0.2/24, and attach cryptographic peers to it. Packets routed to that interface get encrypted and sent to the right peer via UDP; packets arriving from peers decrypt and pop out of the interface. No sessions to log into, no connect button. If the routing table sends traffic to wg0, the tunnel is in use.
Identity is a keypair per machine, generated locally:
wg genkey | tee privatekey | wg pubkey > publickey
You exchange public keys with your peers out of band, like SSH keys, and that exchange is the entire trust ceremony. No CA, no certificates, no expiry dates.
A two-peer setup
The common topology: a VPS with a public IP acts as the hub, and a laptop reaches the home network through it. WireGuard itself has no server role, every node is a peer, but the one with the stable address is what everyone calls the server.
Hub, /etc/wireguard/wg0.conf:
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <hub-private-key>
[Peer]
# laptop
PublicKey = <laptop-public-key>
AllowedIPs = 10.0.0.2/32
Laptop:
[Interface]
Address = 10.0.0.2/24
PrivateKey = <laptop-private-key>
[Peer]
PublicKey = <hub-public-key>
Endpoint = vps.example.com:51820
AllowedIPs = 10.0.0.0/24
PersistentKeepalive = 25
Bring it up on both with:
sudo wg-quick up wg0
sudo systemctl enable wg-quick@wg0 # persist across reboots
Open UDP 51820 on the hub’s firewall, and ping 10.0.0.1 from the laptop confirms the tunnel.
AllowedIPs: the concept worth slowing down for
AllowedIPs is the line everyone misreads. It is simultaneously a routing rule and a security filter: outbound, traffic destined for those addresses is sent to that peer; inbound, packets from that peer are dropped unless their source address matches the list. WireGuard calls this cryptokey routing, binding IP ranges to keys.
The practical consequences: on the hub, each peer’s AllowedIPs is just that peer’s tunnel address (/32). On a client, AllowedIPs = 10.0.0.0/24 means “use the tunnel for the VPN subnet only,” while AllowedIPs = 0.0.0.0/0 means “route all my traffic through the tunnel,” the full-VPN mode for hostile Wi-Fi. To reach the whole home LAN (say 192.168.1.0/24) through a home peer, add that subnet to the peer’s AllowedIPs and enable IP forwarding on it (net.ipv4.ip_forward=1).
Silence is a feature (and a debugging style)
WireGuard transmits nothing until real traffic wants the tunnel, and it never replies to invalid packets, so a port scan cannot even tell WireGuard is listening. The cost: failures are silent too. The debugging tool is:
sudo wg show
A recent latest handshake means the tunnel works; no handshake ever means wrong keys, wrong endpoint, or blocked UDP, in roughly that order of likelihood. PersistentKeepalive = 25 on NAT-ed peers keeps the NAT mapping alive so the hub can still reach them between uses.
WireGuard vs OpenVPN, and the easy mode
Against OpenVPN, the trade is straightforward: WireGuard is faster (kernel-space, modern ciphers), radically simpler, and roams between networks seamlessly, which is why phones love it. OpenVPN still earns its keep where TCP transport is needed to slip through restrictive networks or where certificate-based user management is entrenched. For personal infrastructure in 2026, WireGuard is the default and OpenVPN is the exception.
If hand-writing configs is the part that puts you off, the ecosystem has wrapped it: wg-easy provides a web UI with QR codes for phones, Tailscale and NetBird build mesh networks on top of WireGuard with identity-based login, and PiVPN scripts the classic hub setup. Underneath all of them is the same interface, the same keys, and the same wg show when you need to see the truth.
Frequently Asked Questions
What is WireGuard?
A VPN protocol and its implementation, merged into the Linux kernel, that creates encrypted network interfaces between peers identified by public keys. It replaces the complexity of older VPNs with a design small enough to audit.
How is WireGuard different from OpenVPN?
WireGuard is dramatically smaller, faster, and simpler to configure, running in the kernel with modern fixed cryptography. OpenVPN offers more knobs, TCP transport, and username-password style auth, but for most personal and homelab use WireGuard has become the default choice.
Does WireGuard have a server and clients?
Technically no, every participant is a peer and the protocol is symmetric. In practice one peer with a public address and IP forwarding acts as the hub that others connect to, which everyone casually calls the server.
What does AllowedIPs actually do?
It is both routing and filtering: traffic to those addresses is sent to that peer, and packets arriving from the peer are only accepted if their source is within the list. 0.0.0.0/0 routes everything through the tunnel.
Why does my WireGuard handshake fail silently?
WireGuard sends nothing until traffic needs the tunnel, and invalid packets get no reply by design. Silent failure usually means a wrong key, wrong endpoint port, or a firewall dropping UDP. Check wg show for the last handshake time.
Can WireGuard work behind NAT?
Yes. The peer behind NAT initiates to a peer with a public endpoint, and PersistentKeepalive maintains the mapping so the tunnel stays reachable in both directions.