Skip to content

OpenVPN Cheatsheet

OpenVPN is a robust and highly flexible VPN daemon that provides secure point-to-point or site-to-site connections in routed or bridged configurations. It uses SSL/TLS for key exchange and can traverse NATs and firewalls. OpenVPN is widely used for creating secure remote access solutions and site-to-site VPN connections.

Installation

Linux Installation

bash
# Ubuntu/Debian
sudo apt update
sudo apt install openvpn easy-rsa

# CentOS/RHEL
sudo yum install epel-release
sudo yum install openvpn easy-rsa

# Fedora
sudo dnf install openvpn easy-rsa

# Arch Linux
sudo pacman -S openvpn easy-rsa

# From source
wget https://swupdate.openvpn.org/community/releases/openvpn-2.5.8.tar.gz
tar -xzf openvpn-2.5.8.tar.gz
cd openvpn-2.5.8
./configure
make
sudo make install

Windows Installation

powershell
# Download from official website
# https://openvpn.net/community-downloads/

# Using Chocolatey
choco install openvpn

# Using Scoop
scoop install openvpn

# Manual installation
# Run OpenVPN installer as administrator
# Install TAP-Windows adapter

macOS Installation

bash
# Using Homebrew
brew install openvpn

# Using MacPorts
sudo port install openvpn2

# Tunnelblick (GUI client)
# Download from https://tunnelblick.net/

Certificate Authority Setup

Easy-RSA Configuration

bash
# Initialize PKI
cd /etc/openvpn/easy-rsa/
sudo ./easyrsa init-pki

# Build CA
sudo ./easyrsa build-ca nopass

# Generate server certificate
sudo ./easyrsa gen-req server nopass
sudo ./easyrsa sign-req server server

# Generate client certificates
sudo ./easyrsa gen-req client1 nopass
sudo ./easyrsa sign-req client client1

# Generate Diffie-Hellman parameters
sudo ./easyrsa gen-dh

# Generate TLS-auth key
sudo openvpn --genkey --secret ta.key

# Copy certificates to OpenVPN directory
sudo cp pki/ca.crt /etc/openvpn/server/
sudo cp pki/issued/server.crt /etc/openvpn/server/
sudo cp pki/private/server.key /etc/openvpn/server/
sudo cp pki/dh.pem /etc/openvpn/server/
sudo cp ta.key /etc/openvpn/server/

Manual Certificate Generation

bash
# Generate CA private key
openssl genrsa -out ca.key 4096

# Generate CA certificate
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt

# Generate server private key
openssl genrsa -out server.key 4096

# Generate server certificate request
openssl req -new -key server.key -out server.csr

# Sign server certificate
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt

# Generate client private key
openssl genrsa -out client.key 4096

# Generate client certificate request
openssl req -new -key client.key -out client.csr

# Sign client certificate
openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 02 -out client.crt

Server Configuration

Basic Server Configuration

bash
# /etc/openvpn/server/server.conf
port 1194
proto udp
dev tun

ca ca.crt
cert server.crt
key server.key
dh dh.pem

server 10.8.0.0 255.255.255.0
ifconfig-pool-persist /var/log/openvpn/ipp.txt

push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"

keepalive 10 120
tls-auth ta.key 0
cipher AES-256-CBC
auth SHA256

user nobody
group nogroup
persist-key
persist-tun

status /var/log/openvpn/openvpn-status.log
log-append /var/log/openvpn/openvpn.log
verb 3
explicit-exit-notify 1

Advanced Server Configuration

bash
# /etc/openvpn/server/server-advanced.conf
port 1194
proto udp
dev tun
topology subnet

ca ca.crt
cert server.crt
key server.key
dh dh.pem
tls-auth ta.key 0
tls-version-min 1.2
tls-cipher TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384
cipher AES-256-GCM
auth SHA256
ncp-ciphers AES-256-GCM:AES-128-GCM

server 10.8.0.0 255.255.255.0
max-clients 100
duplicate-cn

# Client-specific configurations
client-config-dir /etc/openvpn/ccd
ccd-exclusive

# Routing
push "route 192.168.1.0 255.255.255.0"
push "route 10.0.0.0 255.255.255.0"
route 192.168.1.0 255.255.255.0

# DNS and gateway
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 192.168.1.1"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DOMAIN company.local"

# Security
remote-cert-tls client
tls-verify /etc/openvpn/verify-cn.sh
auth-user-pass-verify /etc/openvpn/auth-pam.pl via-env
username-as-common-name

# Logging and monitoring
keepalive 10 120
ping-timer-rem
persist-key
persist-tun
comp-lzo adaptive
fast-io

status /var/log/openvpn/status.log 10
log /var/log/openvpn/server.log
verb 4
mute 20

# Performance tuning
sndbuf 393216
rcvbuf 393216
push "sndbuf 393216"
push "rcvbuf 393216"

Site-to-Site Configuration

bash
# Site A server configuration
# /etc/openvpn/site-to-site.conf
dev tun
ifconfig 10.8.0.1 10.8.0.2
secret static.key
comp-lzo
keepalive 10 60
ping-timer-rem
persist-tun
persist-key

# Add routes to remote networks
route 192.168.2.0 255.255.255.0

# Site B server configuration
# /etc/openvpn/site-to-site.conf
remote site-a.company.com
dev tun
ifconfig 10.8.0.2 10.8.0.1
secret static.key
comp-lzo
keepalive 10 60
ping-timer-rem
persist-tun
persist-key

# Add routes to remote networks
route 192.168.1.0 255.255.255.0

Client Configuration

Basic Client Configuration

bash
# client.ovpn
client
dev tun
proto udp
remote vpn.company.com 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert client.crt
key client.key
tls-auth ta.key 1
cipher AES-256-CBC
auth SHA256
verb 3

Inline Client Configuration

bash
# client-inline.ovpn
client
dev tun
proto udp
remote vpn.company.com 1194
resolv-retry infinite
nobind
persist-key
persist-tun
cipher AES-256-CBC
auth SHA256
verb 3

<ca>
-----BEGIN CERTIFICATE-----
[CA certificate content]
-----END CERTIFICATE-----
</ca>

<cert>
-----BEGIN CERTIFICATE-----
[Client certificate content]
-----END CERTIFICATE-----
</cert>

<key>
-----BEGIN PRIVATE KEY-----
[Client private key content]
-----END PRIVATE KEY-----
</key>

<tls-auth>
-----BEGIN OpenVPN Static key V1-----
[TLS-auth key content]
-----END OpenVPN Static key V1-----
</tls-auth>
key-direction 1

Client-Specific Configuration

bash
# /etc/openvpn/ccd/client1
ifconfig-push 10.8.0.10 10.8.0.11
push "route 192.168.10.0 255.255.255.0"
iroute 192.168.10.0 255.255.255.0

# /etc/openvpn/ccd/client2
ifconfig-push 10.8.0.20 10.8.0.21
push "route 192.168.20.0 255.255.255.0"
iroute 192.168.20.0 255.255.255.0
push "redirect-gateway def1"

Service Management

Systemd Service Control

bash
# Start OpenVPN server
sudo systemctl start openvpn-server@server
sudo systemctl enable openvpn-server@server

# Start OpenVPN client
sudo systemctl start openvpn-client@client
sudo systemctl enable openvpn-client@client

# Check service status
sudo systemctl status openvpn-server@server
sudo systemctl status openvpn-client@client

# View logs
sudo journalctl -u openvpn-server@server -f
sudo journalctl -u openvpn-client@client -f

# Restart services
sudo systemctl restart openvpn-server@server
sudo systemctl reload openvpn-server@server

Manual Service Control

bash
# Start server manually
sudo openvpn --config /etc/openvpn/server/server.conf --daemon

# Start client manually
sudo openvpn --config /etc/openvpn/client/client.conf --daemon

# Start with logging
sudo openvpn --config /etc/openvpn/server/server.conf --log /var/log/openvpn.log

# Kill OpenVPN processes
sudo pkill openvpn
sudo killall openvpn

Network Configuration

IP Forwarding and NAT

bash
# Enable IP forwarding
echo 'net.ipv4.ip_forward=1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

# Configure iptables NAT
sudo iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
sudo iptables -A INPUT -i tun+ -j ACCEPT
sudo iptables -A FORWARD -i tun+ -j ACCEPT
sudo iptables -A FORWARD -i tun+ -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o tun+ -m state --state RELATED,ESTABLISHED -j ACCEPT

# Save iptables rules
sudo iptables-save > /etc/iptables/rules.v4

# UFW configuration
sudo ufw allow 1194/udp
sudo ufw allow in on tun0
sudo ufw allow out on tun0

Routing Configuration

bash
# Add static routes
sudo ip route add 192.168.2.0/24 via 10.8.0.2 dev tun0

# Persistent routes in /etc/network/interfaces
auto tun0
iface tun0 inet manual
    up ip route add 192.168.2.0/24 via 10.8.0.2 dev tun0
    down ip route del 192.168.2.0/24 via 10.8.0.2 dev tun0

# Route all traffic through VPN
sudo ip route add 0.0.0.0/1 via 10.8.0.1 dev tun0
sudo ip route add 128.0.0.0/1 via 10.8.0.1 dev tun0

DNS Configuration

bash
# Configure DNS for VPN clients
# In server.conf
push "dhcp-option DNS 192.168.1.1"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DOMAIN company.local"

# Client-side DNS configuration
# /etc/systemd/resolved.conf
[Resolve]
DNS=192.168.1.1 8.8.8.8
Domains=company.local

# Manual DNS configuration
echo "nameserver 192.168.1.1" | sudo tee /etc/resolv.conf
echo "nameserver 8.8.8.8" | sudo tee -a /etc/resolv.conf

Security Configuration

Authentication Methods

bash
# Certificate-based authentication (default)
ca ca.crt
cert client.crt
key client.key

# Username/password authentication
auth-user-pass-verify /etc/openvpn/checkpsw.sh via-env
username-as-common-name
script-security 3

# Two-factor authentication
auth-user-pass
auth-user-pass-verify /etc/openvpn/google-authenticator.sh via-env

# LDAP authentication
plugin /usr/lib/openvpn/openvpn-plugin-auth-pam.so login

Encryption and Security

bash
# Strong encryption settings
tls-version-min 1.2
tls-cipher TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384
cipher AES-256-GCM
auth SHA256
ncp-ciphers AES-256-GCM:AES-128-GCM

# Perfect Forward Secrecy
tls-auth ta.key 0
key-direction 0

# Certificate verification
remote-cert-tls server
remote-cert-eku "TLS Web Server Authentication"
verify-x509-name server_name name

# Additional security
auth-nocache
tls-verify /etc/openvpn/verify-cn.sh

Access Control

bash
# Client certificate revocation
crl-verify /etc/openvpn/crl.pem

# IP-based access control
# In client-specific config
ifconfig-push 10.8.0.100 10.8.0.101
iroute 192.168.100.0 255.255.255.0

# Time-based access control
# Custom script in auth-user-pass-verify
#!/bin/bash
current_hour=$(date +%H)
if [ $current_hour -ge 9 ] && [ $current_hour -le 17 ]; then
    exit 0
else
    exit 1
fi

Monitoring and Logging

Status Monitoring

bash
# Server status file
status /var/log/openvpn/status.log 10

# View current connections
cat /var/log/openvpn/status.log

# Management interface
management localhost 7505
management-client-auth
management-client-pf

# Connect to management interface
telnet localhost 7505

Logging Configuration

bash
# Logging levels
verb 0  # No output except fatal errors
verb 1  # Startup info + connection initiation
verb 2  # + connection handshake
verb 3  # + show options
verb 4  # + show parameters
verb 5  # + show 'R' and 'W' characters
verb 6  # + show TCP/UDP reads/writes
verb 9  # + show TLS debugging info

# Log files
log /var/log/openvpn/server.log
log-append /var/log/openvpn/server.log

# Syslog
syslog openvpn-server

# Custom logging script
learn-address /etc/openvpn/learn-address.sh

Performance Monitoring

bash
# Connection statistics
echo "status" | nc localhost 7505

# Bandwidth monitoring
vnstat -i tun0
iftop -i tun0

# System resource monitoring
top -p $(pgrep openvpn)
htop -p $(pgrep openvpn)

# Network latency
ping -I tun0 8.8.8.8
mtr -I tun0 8.8.8.8

Troubleshooting

Common Issues

bash
# Connection problems
# Check firewall rules
sudo iptables -L -n
sudo ufw status

# Check routing
ip route show
ip route show table all

# Check DNS resolution
nslookup vpn.company.com
dig vpn.company.com

# Test connectivity
ping -c 4 vpn.company.com
telnet vpn.company.com 1194
nc -u vpn.company.com 1194

# Certificate issues
openssl x509 -in client.crt -text -noout
openssl verify -CAfile ca.crt client.crt

Debug Commands

bash
# Verbose logging
openvpn --config client.conf --verb 9

# Test configuration
openvpn --config server.conf --test-crypto

# Check certificates
openvpn --show-certs --config client.conf

# Network debugging
tcpdump -i any port 1194
wireshark -i any -f "port 1194"

# Process debugging
strace -p $(pgrep openvpn)
lsof -p $(pgrep openvpn)

Log Analysis

bash
# Common log messages
grep "Initialization Sequence Completed" /var/log/openvpn/server.log
grep "TLS Error" /var/log/openvpn/server.log
grep "AUTH_FAILED" /var/log/openvpn/server.log
grep "VERIFY ERROR" /var/log/openvpn/server.log

# Connection analysis
awk '/CLIENT_LIST/ {print $2, $3, $4, $5}' /var/log/openvpn/status.log

# Error patterns
grep -E "(ERROR|FATAL|WARNING)" /var/log/openvpn/server.log

Advanced Configuration

Load Balancing

bash
# Multiple server instances
# /etc/openvpn/server1.conf
port 1194
dev tun1
server 10.8.1.0 255.255.255.0

# /etc/openvpn/server2.conf
port 1195
dev tun2
server 10.8.2.0 255.255.255.0

# Client configuration with multiple servers
remote vpn1.company.com 1194
remote vpn2.company.com 1195
remote-random

High Availability

bash
# Keepalived configuration for HA
# /etc/keepalived/keepalived.conf
vrrp_script chk_openvpn {
    script "/bin/pgrep openvpn"
    interval 2
    weight 2
    fall 3
    rise 2
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 101
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass mypassword
    }
    virtual_ipaddress {
        192.168.1.100
    }
    track_script {
        chk_openvpn
    }
}

Performance Tuning

bash
# Buffer sizes
sndbuf 393216
rcvbuf 393216
push "sndbuf 393216"
push "rcvbuf 393216"

# Compression
comp-lzo adaptive
compress lz4-v2
push "compress lz4-v2"

# Fast I/O
fast-io

# TCP optimization
tcp-nodelay
socket-flags TCP_NODELAY

# Threading
nice -10

Scripting and Automation

bash
# Client connect script
client-connect /etc/openvpn/client-connect.sh

#!/bin/bash
# /etc/openvpn/client-connect.sh
echo "Client $common_name connected from $trusted_ip"
echo "$(date): $common_name connected" >> /var/log/openvpn/connections.log

# Client disconnect script
client-disconnect /etc/openvpn/client-disconnect.sh

#!/bin/bash
# /etc/openvpn/client-disconnect.sh
echo "Client $common_name disconnected"
echo "$(date): $common_name disconnected" >> /var/log/openvpn/connections.log

# Learn address script
learn-address /etc/openvpn/learn-address.sh

#!/bin/bash
# /etc/openvpn/learn-address.sh
case "$1" in
    add|update)
        echo "$(date): $1 $2 $3" >> /var/log/openvpn/addresses.log
        ;;
    delete)
        echo "$(date): $1 $2" >> /var/log/openvpn/addresses.log
        ;;
esac

Best Practices

Security Best Practices

bash
# Use strong encryption
cipher AES-256-GCM
auth SHA256
tls-version-min 1.2

# Certificate security
# Use 4096-bit RSA keys
# Implement certificate revocation
# Regular certificate rotation

# Network security
# Use non-standard ports
# Implement fail2ban
# Regular security audits

# Access control
# Implement least privilege
# Use client-specific configurations
# Monitor and log all connections

Operational Best Practices

bash
# Configuration management
# Version control configurations
# Test changes in staging
# Document all modifications

# Monitoring
# Implement comprehensive logging
# Set up alerting for failures
# Regular performance monitoring

# Backup and recovery
# Regular configuration backups
# Certificate backup procedures
# Disaster recovery planning

# Maintenance
# Regular updates and patches
# Certificate renewal procedures
# Performance optimization reviews

Deployment Considerations

bash
# Capacity planning
# Estimate concurrent users
# Plan for peak usage
# Monitor resource utilization

# Network design
# Plan IP address allocation
# Consider routing requirements
# Implement proper segmentation

# Scalability
# Design for horizontal scaling
# Implement load balancing
# Plan for geographic distribution

# Compliance
# Meet regulatory requirements
# Implement audit logging
# Document security controls

Resources