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-maintained
openssl.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 |