Overview
OpenVPN uses X.509 certificates for authentication in TLS mode. Each peer requires its own certificate signed by a trusted Certificate Authority (CA). This guide covers certificate generation, management, and best practices.
Certificate requirements
A complete OpenVPN PKI (Public Key Infrastructure) consists of:
CA certificate and key - Signs all peer certificates
Server certificate and key - One per OpenVPN server
Client certificates and keys - One per client
Diffie-Hellman parameters - For key exchange (optional with modern ECDH)
Using easy-rsa
The OpenVPN project provides easy-rsa for managing RSA certificates and keys:
Installing easy-rsa
# Clone the repository
git clone https://github.com/OpenVPN/easy-rsa.git
cd easy-rsa/easyrsa3
# Or install via package manager
apt-get install easy-rsa # Debian/Ubuntu
yum install easy-rsa # RHEL/CentOS
Initializing the PKI
Initialize PKI directory
This creates the pki directory structure for storing certificates and keys.
Build Certificate Authority
# Create CA with interactive prompts
./easyrsa build-ca
# Or create CA without password (not recommended for production)
./easyrsa build-ca nopass
This generates:
pki/ca.crt - CA certificate (distribute to all peers)
pki/private/ca.key - CA private key (keep secure!)
Generate Diffie-Hellman parameters (optional)
Generates pki/dh.pem. For modern setups, you can skip this and use dh none in OpenVPN configuration to rely on ECDH.
Generating server certificates
Generate server certificate request and key
# With password protection
./easyrsa gen-req server
# Without password (for automated restarts)
./easyrsa gen-req server nopass
Sign the server certificate
./easyrsa sign-req server server
This generates pki/issued/server.crt.
Verify the certificate
openssl verify -CAfile pki/ca.crt pki/issued/server.crt
Generating client certificates
Generate client certificate request
# Replace 'client1' with unique client identifier
./easyrsa gen-req client1 nopass
Sign the client certificate
./easyrsa sign-req client client1
Package client files
Each client needs:
pki/ca.crt (CA certificate)
pki/issued/client1.crt (client certificate)
pki/private/client1.key (client private key)
Batch generation for multiple clients
#!/bin/bash
# Generate certificates for multiple clients
for client in client1 client2 client3 ; do
./easyrsa gen-req $client nopass
./easyrsa sign-req client $client
echo "Generated certificate for $client "
done
Using OpenSSL directly
For more control, you can use OpenSSL commands directly.
Creating a Certificate Authority
Generate CA private key and certificate
openssl req -nodes -new -x509 -keyout ca.key -out ca.crt -days 3650
You’ll be prompted for:
Country Name (2 letter code)
State or Province Name
Locality Name (city)
Organization Name
Organizational Unit Name
Common Name (e.g., “OpenVPN CA”)
Email Address
Set up certificate management files
# Create index file for tracking certificates
touch index.txt
# Create serial number file
echo 01 > serial
Configure openssl.cnf
Edit your OpenSSL configuration file (typically /usr/share/ssl/openssl.cnf) to point to your CA certificate location.
Generating server certificate with OpenSSL
Generate private key and CSR
openssl req -nodes -new -keyout server.key -out server.csr
Sign the CSR with CA
openssl ca -out server.crt -in server.csr
The certificate signing request can be transferred over insecure channels (email, etc.) to the CA.
Copy certificate back to server
Transfer server.crt back to the server where the CSR was generated.
Generating client certificate with OpenSSL
# Generate key and CSR
openssl req -nodes -new -keyout client.key -out client.csr
# Sign with CA
openssl ca -out client.crt -in client.csr
Generating Diffie-Hellman parameters
# Generate 2048-bit DH parameters (recommended minimum)
openssl dhparam -out dh2048.pem 2048
# Generate 4096-bit DH parameters (more secure, slower)
openssl dhparam -out dh4096.pem 4096
Generating DH parameters can take several minutes, especially for 4096-bit keys. Consider using dh none to rely on modern ECDH key exchange instead.
PEM (Privacy Enhanced Mail) is the default format for OpenVPN certificates:
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKJ3X7X...
...
-----END CERTIFICATE-----
PKCS#12 bundles the private key, certificate, and CA certificate in a single file:
# Create PKCS#12 bundle
openssl pkcs12 -export -out client.p12 \
-inkey client.key \
-in client.crt \
-certfile ca.crt
# OpenVPN configuration
pkcs12 /etc/openvpn/client.p12
PKCS#12 is not available with mbed TLS builds of OpenVPN.
Certificate URIs
OpenVPN 3.0+ with OpenSSL 3.0+ supports certificate URIs:
# File URI
cert file:/etc/openvpn/certs/server.crt
# PKCS#11 URI (with pkcs11-provider)
cert "pkcs11:token=MyToken;object=MyCert"
Certificate revocation
Creating a Certificate Revocation List (CRL)
With easy-rsa:
Generate CRL
This creates pki/crl.pem.
Configure OpenVPN to use CRL
# Server configuration
crl-verify /etc/openvpn/crl.pem
Update CRL regularly
After revoking additional certificates, regenerate the CRL:
With OpenSSL:
# Revoke certificate
openssl ca -revoke pki/issued/client1.crt
# Generate CRL
openssl ca -gencrl -out crl.pem
Using CRL directory mode
# Create directory for revoked serial numbers
mkdir /etc/openvpn/crl-dir
# Add revoked certificate serial number as filename
touch /etc/openvpn/crl-dir/1A2B3C4D
# OpenVPN configuration
crl-verify /etc/openvpn/crl-dir dir
Certificate verification
Inspecting certificates
# View certificate details
openssl x509 -in server.crt -text -noout
# View certificate subject
openssl x509 -in server.crt -subject -noout
# View certificate issuer
openssl x509 -in server.crt -issuer -noout
# View certificate dates
openssl x509 -in server.crt -dates -noout
# Calculate certificate fingerprint (SHA256)
openssl x509 -in server.crt -fingerprint -sha256 -noout
Verifying certificate chain
# Verify certificate against CA
openssl verify -CAfile ca.crt server.crt
# Verify with intermediate certificates
openssl verify -CAfile ca.crt -untrusted intermediate.crt server.crt
Checking certificate expiration
# Show expiration date
openssl x509 -in server.crt -noout -enddate
# Check if certificate is expired
openssl x509 -in server.crt -noout -checkend 0
# Check if certificate expires in 30 days (2592000 seconds)
openssl x509 -in server.crt -noout -checkend 2592000
Advanced certificate features
Certificate key usage
Server Certificate
Client Certificate
# Server certificate should have:
# - Key Usage: Digital Signature, Key Encipherment
# - Extended Key Usage: TLS Web Server Authentication
remote-cert-ku
remote-cert-eku "TLS Web Server Authentication"
Certificate tracking
# Track specific certificate attributes
x509-track CN
x509-track +CN # Track for entire chain
x509-track emailAddress
x509-track serialNumber
x509-track SHA256 # Track fingerprint
# Track X.509v3 extensions
x509-track basicConstraints
x509-track subjectAltName
Using alternative certificate fields
# Use email address as username
x509-username-field emailAddress
# Use subject alternative name
x509-username-field ext:subjectAltName
# Combine multiple fields
x509-username-field CN serialNumber
Certificate renewal
Generate new certificate request
./easyrsa gen-req server nopass
Sign with existing CA
./easyrsa sign-req server server
Replace old certificate
# Backup old certificate
cp /etc/openvpn/server.crt /etc/openvpn/server.crt.old
# Install new certificate
cp pki/issued/server.crt /etc/openvpn/
Restart OpenVPN
systemctl restart openvpn@server
Security best practices
Protect CA private key - Store on offline system or in HSM
Use strong passwords - Protect private keys with passwords when possible
Set appropriate lifetimes - CA: 10+ years, Server: 2-5 years, Client: 1-2 years
Implement CRL checking - Keep CRL updated and accessible
Use separate CA - Don’t use production CAs for testing
Regular key rotation - Renew certificates before expiration
Verify certificate extensions - Use --remote-cert-tls to verify key usage
Monitor certificate expiration - Set up alerts for expiring certificates
Revoke compromised certificates - Update CRL immediately when keys are compromised
Backup securely - Encrypt backups of certificates and keys
Troubleshooting
Certificate verification errors
Error: “certificate has expired”
# Check certificate validity period
openssl x509 -in server.crt -noout -dates
Error: “unable to get local issuer certificate”
Verify CA certificate is correctly specified
Check for missing intermediate certificates
Use --extra-certs for intermediate certificates
Error: “certificate signature failure”
Certificate not signed by specified CA
Verify CA certificate matches the one used for signing
Permission issues
# Ensure correct permissions on key files
chmod 600 /etc/openvpn/ * .key
chmod 644 /etc/openvpn/ * .crt
# Ensure OpenVPN user can read files
chown root:openvpn /etc/openvpn/ * .key
Testing certificates
# Test TLS connection with s_client
openssl s_client -connect vpn.example.com:1194 \
-CAfile ca.crt \
-cert client.crt \
-key client.key