openvpn
SKILL.md
Identity
- Unit:
openvpn@server.service(the "server" part matches the config filename, e.g./etc/openvpn/server/server.conf→openvpn@server) - Config:
/etc/openvpn/server/server.conf(server),/etc/openvpn/client/(client configs) - PKI (Easy-RSA):
/etc/easy-rsa/or/usr/share/easy-rsa/depending on distro - Logs:
journalctl -u openvpn@server,/var/log/openvpn/(iflog-appendis set) - Distro install:
apt install openvpn easy-rsa/dnf install openvpn easy-rsa
Key Operations
| Operation | Command |
|---|---|
| Start / stop / restart | systemctl start|stop|restart openvpn@server |
| Check status | systemctl status openvpn@server |
| Follow logs | journalctl -fu openvpn@server |
| Initialize PKI | cd /etc/easy-rsa && easyrsa init-pki |
| Build CA | easyrsa build-ca (prompts for passphrase and CN) |
| Generate server cert | easyrsa build-server-full server nopass |
| Generate client cert | easyrsa build-client-full client1 nopass |
| Revoke client cert | easyrsa revoke client1 |
| Regenerate CRL | easyrsa gen-crl (copy result to /etc/openvpn/server/crl.pem) |
| Generate DH params | easyrsa gen-dh (slow; prefer dh none + ECDH instead) |
| Generate TLS auth key | openvpn --genkey secret /etc/openvpn/server/ta.key |
| Show connected clients | Query management interface or grep "CLIENT_LIST" /etc/openvpn/server/openvpn-status.log |
| Reload config | systemctl reload openvpn@server (re-reads config without dropping connections) |
Expected Ports
- 1194/udp — default; preferred for performance
- 443/tcp — common alternative to bypass restrictive firewalls
- 127.0.0.1:1194 (or custom) — management interface, if enabled
- Verify:
ss -ulnp | grep openvpn(UDP) orss -tlnp | grep openvpn(TCP) - Firewall:
ufw allow 1194/udporfirewall-cmd --add-port=1194/udp --permanent
Health Checks
systemctl is-active openvpn@server→activesudo journalctl -u openvpn@server | grep "Initialization Sequence Completed"→ must be presentip addr show tun0→ tun0 interface exists with an IP in the VPN subnet- Client can ping the server's VPN IP (e.g.
ping 10.8.0.1from a connected client)
Common Failures
| Symptom | Likely cause | Check / Fix |
|---|---|---|
TLS handshake failed |
Wrong tls-auth key direction or mismatched key |
Server uses tls-auth ta.key 0; client must use tls-auth ta.key 1. Verify both sides use the same ta.key file. |
VERIFY ERROR: depth=0, error=certificate verify failed |
CN mismatch, expired cert, or revoked cert | Check easyrsa show-cert <name>; confirm server's verify-x509-name matches the cert CN |
| Traffic not routing through VPN | ip_forward disabled or missing NAT rule |
sysctl net.ipv4.ip_forward must be 1; check masquerade rule: iptables -t nat -L POSTROUTING |
Cannot open TUN/TAP dev /dev/net/tun |
TUN kernel module not loaded | modprobe tun; add tun to /etc/modules for persistence |
| All clients rejected (including non-revoked) | CRL has expired | Run easyrsa gen-crl, copy to /etc/openvpn/server/crl.pem, restart service |
Certificate date/time check failed |
Client clock is wrong | Check date on both sides; NTP must be running (systemctl status systemd-timesyncd) |
AUTH_FAILED |
Wrong credentials (if using auth-user-pass) or cert mismatch |
Verify client cert CN and CA chain match server's CA |
| Service starts but clients cannot reach internet | Missing NAT masquerade or wrong interface name | iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE; replace eth0 with actual WAN interface |
Pain Points
- Easy-RSA vs manual PKI: Always use Easy-RSA. Manual
opensslPKI is error-prone and Easy-RSA handles the required X.509 extension fields (keyUsage, extendedKeyUsage) correctly for OpenVPN. - TLS auth direction:
tls-auth ta.key 0on server,tls-auth ta.key 1on client. Wrong direction causes a silent TLS handshake failure with no useful error message — this is the most common misconfiguration. - CRL expiry: Revocation lists have their own expiry date. When the CRL expires, OpenVPN rejects ALL clients — not just revoked ones. Renew regularly with
easyrsa gen-crland automate it with a cron job. - DH parameters: Generating
dhparam 2048takes minutes on slow hardware. Usedh none+ecdh-curve prime256v1instead for faster setup and better forward secrecy. Only use DH params if you need compatibility with very old OpenVPN clients. - ip_forward + NAT: Same requirement as WireGuard. The server needs
net.ipv4.ip_forward = 1in/etc/sysctl.d/and a NAT masquerade rule on the WAN interface. Without both, clients connect but cannot reach the internet. - UDP vs TCP: UDP is faster and handles packet loss correctly. TCP 443 bypasses more firewalls but creates TCP-over-TCP meltdown under packet loss: the outer TCP retransmits before the inner TCP can recover, creating cascading slowdowns. Never choose TCP without a specific firewall bypass requirement.
- Client config distribution:
.ovpninline files embed the private key in plaintext. Treat them like passwords. Deliver over SFTP or a secure secrets manager — never email. tls-cryptvstls-auth:tls-crypt(OpenVPN 2.4+) both authenticates and encrypts the TLS control channel, preventing even unauthenticated clients from triggering the TLS handshake. Prefertls-cryptfor new deployments.
References
See references/ for:
server.conf.annotated— full server config with every directive explainedsetup-patterns.md— step-by-step: server setup, client generation, revocation, full/split tunneldocs.md— official documentation and community links
Weekly Installs
1
Repository
l3digitalnet/cl…-pluginsGitHub Stars
1
First Seen
3 days ago
Security Audits
Installed on
kilo1
amp1
cline1
pi1
opencode1
cursor1