Choose tls-crypt if you need maximum security – it encrypts and authenticates the entire TLS handshake, hiding your server from fingerprinting scans and providing strong DoS protection. Choose tls-auth only if you need backward compatibility with older OpenVPN versions, since it adds HMAC authentication to the handshake but leaves the TLS fingerprint visible to network observers. For any new OpenVPN deployment, tls-crypt is the recommended option.
Understanding the Baseline: TLS Encryption in OpenVPN
OpenVPN uses TLS for key exchange and authentication by default. The TLS protocol provides confidentiality and integrity through symmetric encryption (typically AES-256-GCM or AES-256-CBC) and digital signatures. However, the default TLS implementation in OpenVPN has a vulnerability: an attacker can perform TLS fingerprinting, denial-of-service attacks, or attempt to exploit TLS implementation bugs without establishing a full connection.
This is where tls-auth and tls-crypt enter the picture—they add pre-TLS authentication to filter malicious traffic before the TLS handshake begins.
What is tls-auth?
The tls-auth directive adds an additional HMAC signature to the initial TLS handshake. OpenVPN computes an HMAC-SHA256 over the entire first packet (the TLS ClientHello), signed with a pre-shared key (PSK).
How tls-auth Works
When a client connects, the server and client both possess a shared secret key file (typically named ta.key). Before the TLS handshake begins, OpenVPN computes an HMAC signature on the initial packet. The recipient verifies this signature before processing the TLS ClientHello. If the signature is invalid, the packet is dropped immediately without any TLS processing.
This creates a powerful filtering mechanism: attackers cannot trigger TLS processing on the server without knowing the pre-shared key.
tls-auth Configuration
Generate the static key:
openvpn --genkey secret ta.key
Server configuration:
tls-server
tls-auth ta.key 0
cipher AES-256-GCM
auth SHA256
Client configuration:
tls-client
tls-auth ta.key 1
cipher AES-256-GCM
auth SHA256
The number after tls-auth specifies the direction: 0 for server (incoming), 1 for client (outgoing).
What is tls-crypt?
The tls-crypt directive extends tls-crypt by encrypting the entire TLS handshake packet, not just signing it. This provides additional confidentiality and effectively hides the TLS fingerprint of your server.
How tls-crypt Works
tls-crypt uses the pre-shared key to both authenticate and encrypt the initial packet. The server decrypts and verifies the incoming packet before any TLS processing occurs. Because the packet is encrypted, network observers cannot determine that an OpenVPN server is listening—they see only opaque encrypted data.
This offers two advantages over tls-auth:
- Stealth: The server becomes invisible to TLS fingerprinting scans
- Denial-of-Service mitigation: Attackers cannot determine server software version or configuration
tls-crypt Configuration
Generate the static key:
openvpn --genkey secret tls-crypt.key
Server configuration:
tls-server
tls-crypt tls-crypt.key
cipher AES-256-GCM
auth SHA256
Client configuration:
tls-client
tls-crypt tls-crypt.key
cipher AES-256-GCM
auth SHA256
Note that tls-crypt does not use a direction parameter—both sides use the same key.
Security Comparison
Authentication vs. Confidentiality
| Property | tls-auth | tls-crypt |
|---|---|---|
| Packet signature | HMAC-SHA256 | HMAC-SHA256 + encryption |
| Packet confidentiality | No | Yes |
| TLS fingerprint hiding | No | Yes |
| DoS protection | Moderate | Strong |
| Implementation complexity | Lower | Higher |
Attack Scenarios
Consider an attacker performing reconnaissance on your VPN infrastructure:
With tls-auth, the attacker sees the TLS handshake and can fingerprint your OpenSSL version, cipher suites, and potentially identify vulnerabilities in your TLS implementation. With tls-crypt, the attacker cannot determine that a VPN server exists — the encrypted packet appears as random data, revealing nothing about your configuration.
For TLS handshakes, tls-crypt provides superior security by eliminating the attack surface entirely.
Key Management
Both methods use pre-shared keys, but with different implications:
With tls-auth, key compromise allows attackers to sign packets and trigger TLS processing, but they cannot decrypt traffic without breaking TLS. With tls-crypt, key compromise is more severe — an attacker can both authenticate and decrypt the initial packet, potentially enabling more sophisticated attacks.
In both cases, rotate keys regularly and protect them with appropriate file permissions (chmod 600 ta.key).
Performance Considerations
Performance differences between tls-auth and tls-crypt are minimal for established connections since both only affect the initial handshake. However, tls-crypt requires one additional encryption operation per connection attempt.
For high-throughput servers handling thousands of connections, tls-auth has a slight edge. The performance difference is negligible for typical deployments and should not drive the security decision.
Practical Recommendations
When to Use tls-auth
- Legacy systems with older OpenVPN versions
- Environments where
tls-cryptcauses compatibility issues - When basic pre-TLS authentication satisfies your security requirements
When to Use tls-crypt
- Production environments requiring maximum security
- Networks where server stealth is essential
- High-value targets facing sophisticated adversaries
- Any new OpenVPN deployment
Most security-conscious administrators should prefer tls-crypt for its superior privacy properties.
Migration Path
If you’re currently using tls-auth and want to migrate to tls-crypt:
- Generate a new
tls-cryptkey - Update server configuration to use
tls-cryptinstead oftls-auth - Distribute the new key to clients
- Update client configurations
- Restart servers and clients
Test thoroughly before rolling out to production—ensure all clients can connect successfully.
Verification and Testing
Verify your configuration is working correctly:
# Check that tls-crypt is active (server side)
openssl s_client -connect your-vpn-server:1194 </dev/null 2>&1 | head -5
# Should show no TLS banner if properly configured
Network capture tools should show only encrypted data for the initial packet when using tls-crypt.
Packet-Level Analysis
Understanding what happens at the network level clarifies the security difference:
Wireshark Inspection
Capture and analyze OpenVPN traffic with different protections:
# Capture traffic with tls-auth
sudo tcpdump -i any -n 'port 1194' -w tls-auth.pcap
# Capture traffic with tls-crypt
sudo tcpdump -i any -n 'port 1194' -w tls-crypt.pcap
# Analyze in Wireshark
# With tls-auth: Can see TLS record structure, cipher suites
# With tls-crypt: See only encrypted payload, no TLS signatures
Packet Structure Comparison
tls-auth packet:
┌─────────────────────┐
│ HMAC-SHA256 │ 32 bytes (unencrypted signature)
├─────────────────────┤
│ TLS ClientHello │ Visible structure, identifiable
├─────────────────────┤
│ TLS Extensions │ Visible version info
└─────────────────────┘
Network observer can: Identify OpenVPN, determine TLS version, find exploits
tls-crypt packet:
┌─────────────────────┐
│ Encrypted Payload │ ChaCha20 encrypted
├─────────────────────┤
│ Authentication Tag │ Poly1305 (8 bytes)
└─────────────────────┘
Network observer sees: Random-looking data, cannot determine protocol
Denial-of-Service Protection Mechanics
tls-crypt provides stronger DoS protection through obfuscation:
# DoS attack lifecycle comparison
# Attack on tls-auth server:
1. Attacker sends random TLS ClientHello → Server processes TLS
2. Server computes HMAC, message is valid → TLS handshake proceeds
3. Attacker can trigger CPU usage on server
4. Legitimate clients compete with attack traffic
# Attack on tls-crypt server:
1. Attacker sends random packet → Not decryptable with pre-shared key
2. Server rejects immediately (AEAD authentication fails)
3. Attacker cannot trigger expensive TLS processing
4. Legitimate clients are unaffected
# Result:
# tls-auth: Moderate DoS protection (HMAC still cheaper than TLS)
# tls-crypt: Strong DoS protection (AEAD rejection is fast)
Quantifying the difference:
# CPU cycles required
tls-auth verification: ~1000 cycles (HMAC-SHA256)
tls-crypt verification: ~100 cycles (ChaCha20 validation)
Full TLS handshake: ~1,000,000 cycles
# With tls-auth: Attacker can trigger 1000s of TLS handshakes/sec
# With tls-crypt: Server rejects 10,000s of invalid packets/sec
Static Key Rotation Strategy
Managing pre-shared keys securely:
#!/bin/bash
# Key rotation for tls-crypt
CURRENT_KEY="/etc/openvpn/tls-crypt-current.key"
PREVIOUS_KEY="/etc/openvpn/tls-crypt-previous.key"
NEW_KEY="/etc/openvpn/tls-crypt-new.key"
rotate_tls_crypt_key() {
# 1. Generate new key
openvpn --genkey secret "$NEW_KEY"
# 2. Update server to accept both current and new
cat > /etc/openvpn/server.conf << EOF
tls-crypt-v2 $CURRENT_KEY
tls-crypt-v2 $NEW_KEY # Accept both during transition
EOF
# 3. Notify clients, give them time to update
# (Send via email, dashboard notification)
# 4. After transition period (e.g., 30 days)
mv "$CURRENT_KEY" "$PREVIOUS_KEY"
mv "$NEW_KEY" "$CURRENT_KEY"
# 5. Update server config
cat > /etc/openvpn/server.conf << EOF
tls-crypt-v2 $CURRENT_KEY
EOF
systemctl restart openvpn@server
}
# Schedule monthly rotation
echo "0 0 1 * * /root/rotate_tls_crypt_key.sh" | crontab -
Protocol Fingerprinting Evasion
Advanced reconnaissance can fingerprint OpenVPN deployments:
# Fingerprinting techniques
# 1. Certificate analysis (tls-auth only)
openssl s_client -connect vpn-server:1194 2>/dev/null | \
openssl x509 -noout -fingerprint
# 2. TLS version detection
nmap --script ssl-enum-ciphers vpn-server -p 1194
# 3. Packet timing analysis
tcpdump -i any -n 'port 1194' | \
awk '{print $1}' | uniq -c
# Distinctive timing patterns may reveal OpenVPN
# tls-crypt prevention:
# All of the above yield no useful fingerprinting info
# Attacker sees only random-looking encrypted packets
OpenVPN Protocol Variants
Understanding protocol evolution:
OpenVPN Evolution:
2002: OpenVPN 1.0 (basic)
↓
2008: OpenVPN 2.0 (tls-auth introduced)
├─ tls-auth (HMAC only)
├─ static key encryption
└─ basic TLS
↓
2018: OpenVPN 2.4 (tls-crypt introduced)
├─ tls-crypt (AEAD encryption + auth)
├─ tls-crypt-v2 (per-client keys)
└─ improved cipher support
↓
2021: OpenVPN 2.5+
├─ tls-crypt-v2 improvements
├─ Data channel offload
└─ OpenVPN 3.0 development
Performance Benchmarks
Real-world performance comparison:
#!/bin/bash
# Benchmark OpenVPN modes
# Test setup: 10 Gbps network, Intel Xeon processor
benchmarks() {
for mode in "none" "tls-auth" "tls-crypt"; do
echo "Testing: $mode"
# Generate test certificate
openssl genpkey -algorithm EC -out key.pem
openssl req -new -x509 -key key.pem -out cert.pem -days 1
# Start OpenVPN with mode
openvpn_config_$mode
# Run iperf
iperf3 -c localhost -t 30 -R
echo "Throughput: [results]"
echo ""
done
}
# Expected results:
# No protection: ~9.5 Gbps
# tls-auth: ~9.4 Gbps (-1% overhead)
# tls-crypt: ~9.3 Gbps (-2% overhead)
Integration with Modern TLS
tls-crypt works alongside TLS but operates at a different layer:
Layer diagram:
Application Layer
↑↓
IP Layer (UDP port 1194)
↓ (raw UDP packet)
[ChaCha20-Poly1305 encryption] ← tls-crypt operates here
↓ (encrypted packet)
[TLS handshake] ← Encrypted by tls-crypt, not visible to attacker
[TLS record layer]
[Data channel encryption]
↑↓
Application Data (VPN payload)
This layering is why tls-crypt is more effective than just relying on TLS alone.
Operational Recommendations
deployment strategy:
# Complete OpenVPN hardening configuration
# tls-crypt + strong TLS ciphers
tls-crypt tls-crypt.key
tls-version-min 1.2
tls-ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
cipher AES-256-GCM
auth SHA256
# Pre-shared key parameters
dh 2048 # or 'none' if using ECDH
ecdh-curve secp384r1
# Security features
keepalive 10 60
mtu-test
fragment 1400
# Logging
status /var/log/openvpn-status.log
log-append /var/log/openvpn.log
verb 3
Related Articles
- WireGuard vs OpenVPN Speed Difference on Mobile Data
- CryptDrive vs ProtonDrive Comparison
- How to Encrypt Git Repos with git-crypt and age
- How To Configure Postfix With Mandatory Tls Encryption For E
- Tls Fingerprinting How Your Browser Handshake Identifies You
Built by theluckystrike — More at zovo.one