Andrew Mercer
on this page

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-lzo is 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 with data-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 old cipher/auth directives still work for backward compatibility but are legacy syntax now.
  • Manual openssl ca commands are replaced with EasyRSA 3. The original notes ran raw openssl req/openssl ca against 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.2 stays, but TLS 1.3 is preferred where both ends support it — set tls-version-min 1.2 as 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