Last updated: 2026-02-11
OpenVPN TLS/SSL Configuration Guide
This guide provides recommended TLS/SSL settings for OpenVPN. OpenVPN uses TLS for its control channel (key exchange, authentication) and separate symmetric encryption for the data channel (tunnel traffic). Both channels need to be configured securely.
Prerequisites
- OpenVPN 2.5 or later (for
data-ciphersand TLS 1.3 support) - OpenSSL 1.1.1 or later
- A PKI infrastructure: CA certificate, server certificate and key, and client certificates
- A TLS authentication key (
ta.key)
PKI Setup
OpenVPN requires a full PKI. Use easy-rsa to generate the necessary certificates:
# Initialize PKI
easyrsa init-pki
easyrsa build-ca
easyrsa gen-req server nopass
easyrsa sign-req server server
easyrsa gen-dh
# Generate TLS auth key (OpenVPN 2.5+: --genkey tls-crypt ta.key)
openvpn --genkey secret ta.key
Copy the resulting files to your OpenVPN server directory:
cp pki/ca.crt /etc/openvpn/server/
cp pki/issued/server.crt /etc/openvpn/server/
cp pki/private/server.key /etc/openvpn/server/
cp pki/dh.pem /etc/openvpn/server/
cp ta.key /etc/openvpn/server/
Path note: On RHEL/CentOS, the server config directory is
/etc/openvpn/server/and the service isopenvpn-server@server. On Debian/Ubuntu, the config directory is/etc/openvpn/and the service isopenvpn@server.
Control Channel (TLS) Configuration
The control channel uses TLS to authenticate the server and clients and to negotiate encryption keys.
TLS Protocol Version
Set the minimum TLS version to 1.2:
tls-version-min 1.2
Control Channel Cipher Suites
Configure strong cipher suites for the TLS control channel. OpenVPN uses IANA-style cipher names with a TLS- prefix for TLS 1.2:
tls-cipher TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256:TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256
For TLS 1.3 cipher suites (OpenVPN 2.5.1+):
tls-ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256
Note: On OpenVPN 2.4, tls-ciphersuites is not supported. This directive requires OpenVPN 2.5+ with OpenSSL 1.1.1+ for TLS 1.3 support.
TLS Authentication
Use tls-crypt to add an additional layer of authentication and encryption to the control channel. This prevents unauthenticated clients from even initiating a TLS handshake:
tls-crypt /etc/openvpn/server/ta.key
tls-crypt is preferred over the older tls-auth because it encrypts control channel packets in addition to authenticating them, hiding certificate metadata.
Data Channel Configuration
The data channel carries the actual tunnel traffic. OpenVPN 2.5+ uses data-ciphers to negotiate the data channel cipher.
Data Channel Ciphers
data-ciphers AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305
Note: On OpenVPN 2.4 (shipped with RHEL 8, early SLES 15), data-ciphers and data-ciphers-fallback are not available, and tls-ciphersuites (TLS 1.3) is not supported. Use the following 2.4-compatible equivalents instead:
cipher AES-256-GCM
ncp-ciphers AES-256-GCM:AES-128-GCM
This allows the server and client to negotiate the best available AEAD cipher. All three options provide strong authenticated encryption.
Set a fallback cipher for compatibility with older clients (OpenVPN 2.4 and earlier):
data-ciphers-fallback AES-256-GCM
HMAC Authentication
For the control channel, set the HMAC digest:
auth SHA256
For data channel AEAD ciphers (GCM, POLY1305), the
authsetting is used only for the control channel HMAC. AEAD ciphers handle their own authentication.
Certificate and Key Settings
ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/server.crt
key /etc/openvpn/server/server.key
dh /etc/openvpn/server/dh.pem
ECDH Curve
Specify the elliptic curve for ECDHE key exchange:
ecdh-curve secp384r1
Certificate Revocation
Point to a CRL to revoke compromised client certificates:
crl-verify /etc/openvpn/server/crl.pem
Additional Security Settings
# Run as unprivileged user after initialization
user nobody
group nogroup
Note: On RHEL/CentOS and SLES, the group nogroup does not exist. Use group nobody instead.
# Persist key material and tunnel device across restarts
persist-key
persist-tun
# Limit client certificate types (prevent using a client cert as a server cert)
remote-cert-tls client
Complete Server Configuration
# Network
port 1194
proto udp
dev tun
# Certificates and keys
ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/server.crt
key /etc/openvpn/server/server.key
dh /etc/openvpn/server/dh.pem
tls-crypt /etc/openvpn/server/ta.key
# TLS control channel
tls-version-min 1.2
tls-cipher TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256:TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256
tls-ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256 # OpenVPN 2.5+; remove on 2.4
ecdh-curve secp384r1
auth SHA256
# Data channel
# OpenVPN 2.4 (RHEL 8): replace with "cipher AES-256-GCM" and "ncp-ciphers AES-256-GCM:AES-128-GCM"
data-ciphers AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305
data-ciphers-fallback AES-256-GCM
# Network settings
server 10.8.0.0 255.255.255.0
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 1.1.1.1"
push "dhcp-option DNS 1.0.0.1"
# Security
user nobody
group nogroup # RHEL/CentOS and SLES: use "group nobody" instead
persist-key
persist-tun
remote-cert-tls client
# Logging
verb 3
Client Configuration
The client configuration mirrors the server's TLS and cipher settings:
client
dev tun
proto udp
remote vpn.example.com 1194
# Certificates
ca ca.crt
cert client.crt
key client.key
tls-crypt ta.key
# TLS settings
tls-version-min 1.2
tls-cipher TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256:TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256
tls-ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256 # OpenVPN 2.5+; remove on 2.4
# OpenVPN 2.4 (RHEL 8): replace data-ciphers with "cipher AES-256-GCM" and "ncp-ciphers AES-256-GCM:AES-128-GCM"
data-ciphers AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305
auth SHA256
remote-cert-tls server
persist-key
persist-tun
verb 3
Verification
Start the server and check the logs:
systemctl start openvpn-server@server
journalctl -u openvpn-server@server -f
Verify the negotiated cipher in the server log. You should see lines like:
Data Channel: using negotiated cipher 'AES-256-GCM'
Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384
Test the connection from a client and verify encryption:
openvpn --config client.conf