OpenVPN Comprehensive Guide¶
This is the index and conceptual overview for a set of OpenVPN docs, rebuilt from
years of accumulated notes. It replaces the old scattered wiki-style pages with
one linked set, updated for modern OpenVPN (2.5/2.6) and current best practice
(EasyRSA 3, tls-crypt, AEAD ciphers, no compression).
Guide map¶
| Doc | Covers |
|---|---|
| openvpn-installation.md | Installing OpenVPN from packages or source |
| openvpn-server-configuration.md | PKI setup, server config, routing, systemd |
| openvpn-client-configuration.md | Issuing client certs, client configs for Linux/Windows/macOS |
| openvpn-security-hardening.md | tls-crypt, ciphers, CRLs, cert pinning, key hygiene |
| openvpn-systemd-service.md | Autostarting the client and fixing boot-time routing |
| openvpn-aws-deployment.md | Self-managed EC2 vs. AWS Client VPN |
Read this doc first for the concepts, then jump to whichever doc matches the task in front of you.
What OpenVPN is¶
OpenVPN is an open-source VPN daemon that builds an encrypted tunnel over UDP
or TCP using a TLS handshake for key negotiation, then an SSL/TLS-derived
channel for data. It's not IPsec and not WireGuard — it runs in userspace,
talks to a virtual network interface via TUN/TAP, and is scriptable at nearly
every stage of the connection lifecycle (--up, --down, --route-up,
client-connect scripts, etc.). That scriptability is why it's stuck around:
it's flexible, but that flexibility is also where most of the footguns in the
old notes came from (hand-rolled systemd units, manual route scripts, etc.).
Core architecture decisions¶
These are the choices you make once, up front, that everything else depends on.
TUN vs. TAP¶
- TUN (routed, layer 3) — the standard choice. Clients get an IP on a dedicated VPN subnet and traffic is routed. Simpler, more efficient, works everywhere. Use this unless you have a specific reason not to.
- TAP (bridged, layer 2) — clients join the same Ethernet broadcast domain as the server's LAN. Needed for things like Wake-on-LAN across the tunnel or legacy broadcast-dependent protocols. More overhead, more fragile, and mostly obsolete now — most things people used TAP for (browsing "as if local," NetBIOS discovery, etc.) either don't matter anymore or are better solved with routing plus mDNS/reflection.
Everything in this doc set assumes TUN, which is what the original notes used.
PKI (certificate-based) vs. static key¶
- Static key (
--secret) — one shared key for a single point-to-point tunnel, no CA, no per-client identity, no revocation. Fine for a quick site-to-site link between two boxes you control. Doesn't scale past two peers and can't be revoked without regenerating the key for everyone. - TLS mode with a PKI (CA + per-client certs) — what you want for anything with more than one client. Each client has its own identity, which means you can revoke a single laptop without touching anyone else, and you get mutual authentication (server proves who it is, client proves who it is) instead of a single shared secret.
The rest of this guide set uses PKI/TLS mode, matching the original setup.
Control-channel protection: tls-auth vs. tls-crypt¶
The old notes used tls-auth, which HMAC-signs control-channel packets so
OpenVPN can silently drop anything not signed with the shared key (mitigates
port scanning, DoS, and TLS stack attacks before a real handshake even
starts). tls-crypt does the same thing but also encrypts the control
channel, which additionally hides certificate metadata (CNs, cert
fingerprints) from anyone sniffing the handshake. There's no real downside to
tls-crypt on a normal client/server setup — use it instead of tls-auth.
Details and the migration are in
openvpn-security-hardening.md.
What changed since the original notes¶
The source notes were written against OpenVPN ~2.2–2.3 conventions. A few things have moved on enough that carrying them forward as-is would be actively bad advice:
comp-lzois gone. VPN compression combined with encryption enables the VORACLE attack (compression-oracle plaintext recovery, same family as CRIME/BREACH). Compression is disabled in the configs throughout this guide set. See openvpn-security-hardening.md.cipher AES-256-CBC+auth SHA256(separate encrypt + HMAC) is replaced withdata-ciphers AES-256-GCM, an AEAD cipher that does authenticated encryption in one pass — faster and removes a category of padding-oracle style bugs. The oldcipher/authdirectives still work for backward compatibility but are legacy syntax now.- Manual
openssl cacommands are replaced with EasyRSA 3. The original notes ran rawopenssl req/openssl caagainst a hand-maintainedopenssl.cnf. That's fragile (serial file collisions, index.txt drift, easy to get file permissions or extensions wrong) and EasyRSA has been the standard companion tool for exactly this since well before the original notes were written. All PKI steps in this guide set use it. tls-version-min 1.2stays, but TLS 1.3 is preferred where both ends support it — settls-version-min 1.2as the floor and let negotiation pick 1.3 when available, rather than pinning to 1.2.- Hand-rolled systemd units are replaced with the native
[email protected]template that ships with the OpenVPN package, which sidesteps the boot-time routing race the old notes flagged as an unsolved TODO. See openvpn-systemd-service.md.
Terminology quick reference¶
| Term | Meaning |
|---|---|
| CA | Certificate Authority — signs server and client certs so both sides can verify each other |
| CRL | Certificate Revocation List — the CA's "these certs are no longer valid" list, checked by the server on connect |
ta.key / tls-crypt key |
Pre-shared key used to authenticate (and, with tls-crypt, encrypt) the TLS control channel before the real handshake |
ccd |
Client-config-dir — per-client config snippets (static IP, extra pushed routes) keyed by cert CN |
ipp.txt |
IP pool persistence file — server's memory of which pooled IP a client had last time |