$ diff /etc/vpn/wireguard /etc/vpn/openvpn
[$ ] WireGuard vs OpenVPN — for self-hosted personal VPN
// TLDR
For a personal VPN on an offshore VPS in 2026, WireGuard is the default and OpenVPN is the legacy fallback. WireGuard's wire protocol is smaller (~4000 lines of kernel code vs OpenVPN's ~70,000), faster, and uses modern cryptographic primitives (ChaCha20-Poly1305, Curve25519, BLAKE2s, SipHash, HKDF). OpenVPN retains advantages on restrictive-NAT traversal (TCP fallback) and in environments where deep-packet inspection blocks UDP traffic. For everything else, prefer WireGuard.
// AT A GLANCE
$ compare --short
| // dimension | // wireguard | // openvpn |
|---|---|---|
| transport | UDP only | UDP or TCP |
| codebase size | ~4,000 lines (kernel module) | ~70,000 lines (userspace daemon) |
| audit surface | small; formally analysed | large; mature but complex |
| crypto primitives | ChaCha20-Poly1305, Curve25519, BLAKE2s, SipHash, HKDF | configurable; default AES-GCM + RSA + SHA2 |
| cipher negotiation | none (fixed primitives) | TLS-style negotiation |
| key management | static public keys per peer | PKI / TLS certificates |
| throughput (gigabit-class VPS) | ~900 Mbps | ~250-400 Mbps |
| latency overhead per packet | ~50 µs | ~150-300 µs |
| NAT traversal | UDP punch + keepalive | UDP or TCP fallback (TCP/443 widely tolerated) |
| DPI evasion | poor (fixed handshake) | moderate (TCP/443 + tls-crypt) |
| in-kernel implementation | yes (Linux 5.6+) | no (userspace tun) |
| config format | INI-style, ~10 lines | domain-specific, 30-100 lines |
| roaming (mobile) | native | supported, reconnect-heavy |
// WIREGUARD — DESIGN POINT
$ man wireguard
WireGuard's design centre is "minimum viable VPN": a fixed cryptographic primitive set (no negotiation, no algorithm-choice attacks), a UDP-only transport (no TCP-over-TCP retransmit cascade), and a static-public-key peer model that fits in ~4,000 lines of kernel code. Jason Donenfeld's original 2017 paper laid out the argument that VPN complexity is the dominant security failure mode and that a smaller protocol surface defeats more attacks than a configurable one. The protocol has been in mainline Linux since 5.6 (March 2020) and in mainline FreeBSD since 13.0 (April 2021).
Operationally, this manifests as:
- 10-line configs. A typical wg0.conf is [Interface] (private key, address, listen port) + [Peer] (public key, allowed IPs, optional endpoint). No PKI, no certificate rotation, no DH-parameter file.
- Roaming-by-default. Peers can change their external IP without re-establishing — WireGuard re-binds the tunnel on the next valid handshake. Mobile clients flipping between Wi-Fi and cellular don't reconnect; they re-handshake silently.
- Crypto fixed. ChaCha20-Poly1305 for AEAD, Curve25519 for ECDH, BLAKE2s for hashing, SipHash for hash- table lookup. No negotiation = no downgrade attack surface.
- Kernel module + wg-quick. The interface is a
regular Linux network device.
wg-quick up wg0reads the config, sets up the device, and adds routes. No daemon.
// OPENVPN — DESIGN POINT
$ man openvpn
OpenVPN, originally released 2001 by James Yonan, predates the WireGuard design constraints and reflects an earlier-era trade-off: configurability is a feature, TLS is the established public-key substrate, and userspace-tun is portable across kernels. The codebase is mature, audited (Cure53 + QuarksLab 2017), and widely deployed (Pritunl, OpenVPN Access Server, AirVPN, ProtonVPN, the bulk of commercial VPN-by-subscription services).
Operationally:
- TLS / PKI. The handshake is TLS over UDP (or TCP). Each client has a certificate signed by a CA the server trusts. Revocation goes through standard CRL / OCSP.
- TCP fallback. OpenVPN can run over TCP/443, which is the most-permitted port on any network. Useful for hostile-firewall environments where UDP is dropped.
- tls-crypt and tls-auth. Pre-shared key wrapped around the TLS handshake makes pre-handshake DPI hard. This is the closest OpenVPN gets to handshake obfuscation; it is not a full pluggable-transport but it does defeat naive DPI.
- Configurable cipher set. Negotiates AES-GCM / ChaCha20-Poly1305 / AES-CBC. The negotiation surface is itself a security consideration (Sweet32 in 2016 demonstrated this); pin modern ciphers in the config and disable the rest.
- Userspace daemon. No kernel-module dependency; runs on systems without WireGuard kernel support (FreeBSD pre-13, old Linux kernels, macOS without compose).
// HOW TO CHOOSE
$ man choose-vpn
- Default to WireGuard if: the host runs Linux ≥ 5.6 or FreeBSD ≥ 13.0; clients are Linux / macOS / Android / iOS / Windows 11 (all support WireGuard natively or via official client); the network path does not block UDP. This covers ~95% of personal-VPN use cases.
- Choose OpenVPN if: the threat model includes DPI-active networks (hotel Wi-Fi, restrictive corporate / hotel firewalls, jurisdictions where TCP/443 is the only viable out-bound port); the host runs an OS without WireGuard kernel support; the deployment already has a TLS PKI in place that should be reused.
- Run both: the offshore VPS can host both daemons on different ports. WireGuard as the daily driver, OpenVPN on TCP/443 as the fallback for hostile-network days. The configuration cost is one extra port + one extra firewall rule.
- Consider neither: for the threat model "I want anonymity, not just encryption", a self-hosted VPN is the wrong tool — the destination IP traces back to the VPS, which traces back to the payment. Run a Tor client, route via /node/lokinet-exit, or use Tor Browser depending on the workload.
// THREAT-MODEL NOTES
$ man vpn-threat-model
Both protocols protect the VPN tunnel from passive interception and from on-path tampering. Neither anonymises traffic past the VPS exit — the destination server sees the VPS IP. Neither defends against an adversary that controls the VPS. Neither defends against an adversary that has compromised the client.
Both have post-quantum migration questions: ChaCha20-Poly1305 + Curve25519 are not post-quantum-secure (a sufficiently capable quantum adversary breaks Curve25519 key exchange). WireGuard's community draft for post-quantum hybrid handshake exists but is not yet mainline. OpenVPN inherits OpenSSL's post-quantum trajectory (ML-KEM hybrids landing in OpenSSL 3.x). For threat models on a 5+ year horizon this matters; for personal-VPN-day-today it does not.
See /threat-models#vpn for the full self-hosted-VPN dossier and the four-tuple controls.
// SEE ALSO
$ ls /usr/share/doc/xmrhost/vpn
- /docs/wireguard-vpn-on-vps — self-host runbook.
- /playbook/vpn — workload manpage.
- /threat-models#vpn — self-hosted VPN threat-model dossier.
- /hardening — Linux hardening pillar.
- /glossary — definitions.
- Upstream — WireGuard paper (Donenfeld 2017), OpenVPN community docs, RFC 8439 (ChaCha20-Poly1305).