Set up OpenVPN with LDAP authentication to integrate with Active Directory for centralized user management. Configure group-based access control and combine certificate-based authentication with LDAP for enterprise security.
Prerequisites
- Active Directory domain controller
- OpenVPN server with root access
- Valid SSL certificates for LDAP
- Network connectivity to domain controller
What this solves
This tutorial configures OpenVPN to authenticate users against Active Directory using LDAP, eliminating the need to manage individual certificate files for each user. You'll set up group-based access control where AD groups determine VPN access permissions, and combine certificate-based authentication with LDAP credentials for enhanced security.
Step-by-step configuration
Install OpenVPN and LDAP plugin
Install OpenVPN server and the LDAP authentication plugin that enables Active Directory integration.
sudo apt update
sudo apt install -y openvpn easy-rsa openvpn-auth-ldap
Set up certificate authority and server certificates
Create the PKI infrastructure for OpenVPN. Even with LDAP authentication, you still need server certificates for TLS encryption.
sudo mkdir -p /etc/openvpn/easy-rsa
sudo cp -r /usr/share/easy-rsa/* /etc/openvpn/easy-rsa/
cd /etc/openvpn/easy-rsa
Initialize the PKI and create the certificate authority:
sudo ./easyrsa init-pki
sudo ./easyrsa build-ca nopass
Generate server certificate and Diffie-Hellman parameters:
sudo ./easyrsa gen-req server nopass
sudo ./easyrsa sign-req server server
sudo ./easyrsa gen-dh
sudo openvpn --genkey secret /etc/openvpn/ta.key
Copy certificates to OpenVPN directory
Move the generated certificates to the OpenVPN configuration directory with correct permissions.
sudo cp /etc/openvpn/easy-rsa/pki/ca.crt /etc/openvpn/
sudo cp /etc/openvpn/easy-rsa/pki/issued/server.crt /etc/openvpn/
sudo cp /etc/openvpn/easy-rsa/pki/private/server.key /etc/openvpn/
sudo cp /etc/openvpn/easy-rsa/pki/dh.pem /etc/openvpn/dh2048.pem
Set secure permissions on the private key:
sudo chmod 600 /etc/openvpn/server.key
sudo chown root:root /etc/openvpn/server.key
Configure LDAP authentication plugin
Create the LDAP authentication configuration file that defines how OpenVPN connects to Active Directory.
<LDAP>
URL ldaps://dc1.example.com:636
BindDN "CN=openvpn-service,OU=Service Accounts,DC=example,DC=com"
BindPW "your-service-account-password"
Timeout 15
TLSEnable yes
TLSCACertFile /etc/ssl/certs/ca-certificates.crt
TLSCertFile /etc/openvpn/ldap-client.crt
TLSKeyFile /etc/openvpn/ldap-client.key
FollowReferrals yes
</LDAP>
<Authorization>
BaseDN "OU=Users,DC=example,DC=com"
SearchFilter "(&(sAMAccountName=%u)(memberOf=CN=VPN-Users,OU=Groups,DC=example,DC=com))"
RequireGroup true
<Group>
BaseDN "OU=Groups,DC=example,DC=com"
SearchFilter "(&(objectClass=group)(member=%D))"
MemberAttribute member
</Group>
</Authorization>
Create OpenVPN server configuration
Configure OpenVPN server with LDAP authentication and certificate-based encryption. This combines both authentication methods.
port 1194
proto udp
dev tun
ca /etc/openvpn/ca.crt
cert /etc/openvpn/server.crt
key /etc/openvpn/server.key
dh /etc/openvpn/dh2048.pem
tls-auth /etc/openvpn/ta.key 0
Network configuration
server 10.8.0.0 255.255.255.0
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"
LDAP Authentication
plugin /usr/lib/openvpn/openvpn-auth-ldap.so /etc/openvpn/auth-ldap.conf
client-cert-not-required
username-as-common-name
Security settings
cipher AES-256-GCM
auth SHA256
tls-version-min 1.2
tls-cipher TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384
Connection settings
keepalive 10 120
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
Logging
status /var/log/openvpn-status.log
log-append /var/log/openvpn.log
verb 4
mute 20
Client management
max-clients 50
duplicate-cn
Configure Active Directory service account
Create a dedicated service account in Active Directory for OpenVPN LDAP binds. This account needs minimal privileges.
Create the service account with these properties:
- Username:
openvpn-service - Password: Use a strong password and set it to never expire
- Account options: Disable "User must change password at next logon"
- Permissions: Grant "Log on as a service" right
Add users to the VPN access group:
New-ADGroup -Name "VPN-Users" -GroupScope Global -GroupCategory Security -Path "OU=Groups,DC=example,DC=com"
Add-ADGroupMember -Identity "VPN-Users" -Members "john.doe","jane.smith"
Configure client certificate template
Create a basic client certificate that all LDAP-authenticated users will share. This provides the TLS encryption while LDAP handles authentication.
cd /etc/openvpn/easy-rsa
sudo ./easyrsa gen-req client nopass
sudo ./easyrsa sign-req client client
Create the client configuration template:
client
dev tun
proto udp
remote vpn.example.com 1194
resolv-retry infinite
nobind
persist-key
persist-tun
auth-user-pass
cipher AES-256-GCM
auth SHA256
tls-version-min 1.2
comp-lzo
verb 3
<ca>
-----BEGIN CERTIFICATE-----
Copy content from /etc/openvpn/ca.crt
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
Copy content from /etc/openvpn/easy-rsa/pki/issued/client.crt
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
Copy content from /etc/openvpn/easy-rsa/pki/private/client.key
-----END PRIVATE KEY-----
</key>
<tls-auth>
-----BEGIN OpenVPN Static key V1-----
Copy content from /etc/openvpn/ta.key
-----END OpenVPN Static key V1-----
</tls-auth>
key-direction 1
Enable IP forwarding and configure firewall
Enable packet forwarding so VPN clients can access network resources and configure firewall rules.
echo 'net.ipv4.ip_forward=1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Configure firewall rules for OpenVPN:
sudo ufw allow 1194/udp
sudo ufw allow OpenSSH
sudo ufw --force enable
Add NAT rule for VPN traffic:
# Add these lines after the header comments
*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 10.8.0.0/8 -o eth0 -j MASQUERADE
COMMIT
Set secure permissions and start OpenVPN
Set appropriate permissions on configuration files and start the OpenVPN service.
sudo chmod 600 /etc/openvpn/auth-ldap.conf
sudo chown root:root /etc/openvpn/auth-ldap.conf
sudo chmod 644 /etc/openvpn/server.conf
Enable and start OpenVPN:
sudo systemctl enable openvpn@server
sudo systemctl start openvpn@server
sudo systemctl status openvpn@server
Configure group-based access policies
Set up different access levels for different AD groups by creating custom authorization scripts.
#!/bin/bash
Group-based authorization script
USERNAME="$1"
GROUP_DN="$2"
Define group access policies
case "$GROUP_DN" in
"VPN-Admins")
# Full access for admin group
echo "push 'route 192.168.1.0 255.255.255.0'"
echo "push 'route 10.0.0.0 255.255.255.0'"
exit 0
;;
"VPN-Users")
# Limited access for regular users
echo "push 'route 192.168.1.0 255.255.255.0'"
exit 0
;;
*)
# Deny access for users not in authorized groups
exit 1
;;
esac
Make the script executable and update the server configuration:
sudo chmod 755 /etc/openvpn/group-auth.sh
sudo chown root:root /etc/openvpn/group-auth.sh
Add the authorization script to your server configuration:
# Add this line to enable group-based authorization
client-connect /etc/openvpn/group-auth.sh
Verify your setup
Test the LDAP connection and OpenVPN service functionality:
sudo systemctl status openvpn@server
sudo tail -f /var/log/openvpn.log
Test LDAP connectivity to your Domain Controller:
ldapsearch -x -H ldaps://dc1.example.com:636 -D "CN=openvpn-service,OU=Service Accounts,DC=example,DC=com" -W -b "OU=Users,DC=example,DC=com" "(sAMAccountName=testuser)"
Check that the OpenVPN server is listening on the correct port:
sudo netstat -tulpn | grep 1194
sudo ss -tulpn | grep 1194
Test client connection by importing the client configuration file into an OpenVPN client and connecting with AD credentials.
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| LDAP bind fails | Incorrect service account credentials | Verify BindDN and BindPW in auth-ldap.conf |
| User authentication rejected | User not in required AD group | Add user to VPN-Users group in Active Directory |
| SSL/TLS handshake failed | Certificate issues or cipher mismatch | Check certificate validity and cipher compatibility |
| Plugin loading error | LDAP plugin not found | Install openvpn-auth-ldap package |
| DNS resolution fails for LDAP | Cannot reach Domain Controller | Verify network connectivity and DNS settings |
| Permission denied on config files | Incorrect file ownership/permissions | Use sudo chown root:root and chmod 600 for sensitive configs |
Next steps
- Set up OpenVPN high availability cluster with automatic failover and load balancing for production redundancy
- Monitor OpenVPN connections with Grafana dashboard and Prometheus metrics for visibility into VPN usage
- Configure OpenVPN certificate revocation and automated management for enhanced security
- Set up Grafana Enterprise SSO authentication with LDAP, SAML, and OAuth2 integration for centralized authentication
Running this in production?
Automated install script
Run this to automate the entire setup
#!/usr/bin/env bash
set -euo pipefail
# OpenVPN LDAP Authentication Setup Script
# Configures OpenVPN with Active Directory LDAP authentication
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Configuration variables
OPENVPN_DIR="/etc/openvpn"
EASY_RSA_DIR="$OPENVPN_DIR/easy-rsa"
LOG_FILE="/var/log/openvpn-setup.log"
# Function to print colored output
print_status() {
echo -e "${GREEN}[INFO]${NC} $1" | tee -a "$LOG_FILE"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1" | tee -a "$LOG_FILE"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1" | tee -a "$LOG_FILE"
}
# Cleanup function
cleanup() {
print_error "Setup failed. Cleaning up..."
systemctl stop openvpn-server@server 2>/dev/null || true
rm -rf "$EASY_RSA_DIR" 2>/dev/null || true
}
trap cleanup ERR
# Usage information
usage() {
echo "Usage: $0 <ldap_server> <bind_dn> <bind_password> <base_dn>"
echo "Example: $0 dc1.example.com 'CN=openvpn-service,OU=Service Accounts,DC=example,DC=com' 'password' 'OU=Users,DC=example,DC=com'"
exit 1
}
# Check arguments
if [ $# -ne 4 ]; then
usage
fi
LDAP_SERVER="$1"
BIND_DN="$2"
BIND_PASSWORD="$3"
BASE_DN="$4"
# Check if running as root
if [ "$EUID" -ne 0 ]; then
print_error "This script must be run as root"
exit 1
fi
# Detect distribution
print_status "Detecting operating system..."
if [ -f /etc/os-release ]; then
. /etc/os-release
case "$ID" in
ubuntu|debian)
PKG_MGR="apt"
PKG_UPDATE="apt update"
PKG_INSTALL="apt install -y"
OPENVPN_PLUGIN_DIR="/usr/lib/openvpn"
GROUP_NAME="nogroup"
;;
almalinux|rocky|centos|rhel|ol|fedora)
PKG_MGR="dnf"
PKG_UPDATE="dnf update -y"
PKG_INSTALL="dnf install -y"
OPENVPN_PLUGIN_DIR="/usr/lib64/openvpn/plugins"
GROUP_NAME="nobody"
;;
amzn)
PKG_MGR="yum"
PKG_UPDATE="yum update -y"
PKG_INSTALL="yum install -y"
OPENVPN_PLUGIN_DIR="/usr/lib64/openvpn/plugins"
GROUP_NAME="nobody"
;;
*)
print_error "Unsupported distribution: $ID"
exit 1
;;
esac
print_status "Detected: $PRETTY_NAME"
else
print_error "Cannot detect operating system"
exit 1
fi
# Step 1: Update system and install packages
echo "[1/8] Installing OpenVPN and dependencies..."
$PKG_UPDATE
if [ "$PKG_MGR" = "apt" ]; then
$PKG_INSTALL openvpn easy-rsa openvpn-auth-ldap
else
$PKG_INSTALL epel-release
$PKG_INSTALL openvpn easy-rsa openvpn-auth-ldap
fi
# Step 2: Set up Easy-RSA
echo "[2/8] Setting up PKI infrastructure..."
mkdir -p "$EASY_RSA_DIR"
cp -r /usr/share/easy-rsa/* "$EASY_RSA_DIR/"
cd "$EASY_RSA_DIR"
# Initialize PKI
./easyrsa init-pki
# Create CA
print_status "Creating Certificate Authority..."
echo -e "\n\n\n\n\n\nOpenVPN-CA\n" | ./easyrsa build-ca nopass
# Step 3: Generate server certificates
echo "[3/8] Generating server certificates..."
echo -e "\n\n\n\n\n\nserver\n" | ./easyrsa gen-req server nopass
echo "yes" | ./easyrsa sign-req server server
# Generate DH parameters
print_status "Generating Diffie-Hellman parameters (this may take a while)..."
./easyrsa gen-dh
# Generate TLS auth key
openvpn --genkey secret "$OPENVPN_DIR/ta.key"
# Step 4: Copy certificates
echo "[4/8] Copying certificates..."
cp "$EASY_RSA_DIR/pki/ca.crt" "$OPENVPN_DIR/"
cp "$EASY_RSA_DIR/pki/issued/server.crt" "$OPENVPN_DIR/"
cp "$EASY_RSA_DIR/pki/private/server.key" "$OPENVPN_DIR/"
cp "$EASY_RSA_DIR/pki/dh.pem" "$OPENVPN_DIR/dh2048.pem"
# Set secure permissions
chmod 644 "$OPENVPN_DIR/ca.crt"
chmod 644 "$OPENVPN_DIR/server.crt"
chmod 600 "$OPENVPN_DIR/server.key"
chmod 644 "$OPENVPN_DIR/dh2048.pem"
chmod 600 "$OPENVPN_DIR/ta.key"
chown root:root "$OPENVPN_DIR"/*
# Step 5: Configure LDAP authentication
echo "[5/8] Configuring LDAP authentication..."
cat > "$OPENVPN_DIR/auth-ldap.conf" << EOF
<LDAP>
URL ldaps://$LDAP_SERVER:636
BindDN "$BIND_DN"
BindPW "$BIND_PASSWORD"
Timeout 15
TLSEnable yes
TLSCACertFile /etc/ssl/certs/ca-certificates.crt
FollowReferrals yes
</LDAP>
<Authorization>
BaseDN "$BASE_DN"
SearchFilter "(&(sAMAccountName=%u)(memberOf=CN=VPN-Users,OU=Groups,DC=example,DC=com))"
RequireGroup true
<Group>
BaseDN "OU=Groups,DC=example,DC=com"
SearchFilter "(&(objectClass=group)(member=%D))"
MemberAttribute member
</Group>
</Authorization>
EOF
chmod 600 "$OPENVPN_DIR/auth-ldap.conf"
chown root:root "$OPENVPN_DIR/auth-ldap.conf"
# Step 6: Create OpenVPN server configuration
echo "[6/8] Creating OpenVPN server configuration..."
cat > "$OPENVPN_DIR/server.conf" << EOF
port 1194
proto udp
dev tun
ca $OPENVPN_DIR/ca.crt
cert $OPENVPN_DIR/server.crt
key $OPENVPN_DIR/server.key
dh $OPENVPN_DIR/dh2048.pem
tls-auth $OPENVPN_DIR/ta.key 0
# Network configuration
server 10.8.0.0 255.255.255.0
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"
# LDAP Authentication
plugin $OPENVPN_PLUGIN_DIR/openvpn-auth-ldap.so $OPENVPN_DIR/auth-ldap.conf
client-cert-not-required
username-as-common-name
# Security settings
cipher AES-256-GCM
auth SHA256
tls-version-min 1.2
# Connection settings
keepalive 10 120
user nobody
group $GROUP_NAME
persist-key
persist-tun
# Logging
status /var/log/openvpn-status.log
log-append /var/log/openvpn.log
verb 3
mute 20
# Client management
max-clients 50
duplicate-cn
EOF
chmod 644 "$OPENVPN_DIR/server.conf"
chown root:root "$OPENVPN_DIR/server.conf"
# Step 7: Configure firewall and enable IP forwarding
echo "[7/8] Configuring firewall and IP forwarding..."
# Enable IP forwarding
echo 'net.ipv4.ip_forward = 1' > /etc/sysctl.d/99-openvpn-forward.conf
sysctl -p /etc/sysctl.d/99-openvpn-forward.conf
# Configure firewall based on distribution
if command -v ufw >/dev/null 2>&1; then
ufw allow 1194/udp
ufw --force enable
elif command -v firewall-cmd >/dev/null 2>&1; then
firewall-cmd --permanent --add-service=openvpn
firewall-cmd --permanent --add-masquerade
firewall-cmd --reload
fi
# Step 8: Enable and start OpenVPN service
echo "[8/8] Starting OpenVPN service..."
if [ "$PKG_MGR" = "apt" ]; then
systemctl enable openvpn@server
systemctl start openvpn@server
else
systemctl enable openvpn-server@server
systemctl start openvpn-server@server
fi
# Verification
echo "Verifying installation..."
sleep 5
if [ "$PKG_MGR" = "apt" ]; then
SERVICE_NAME="openvpn@server"
else
SERVICE_NAME="openvpn-server@server"
fi
if systemctl is-active --quiet "$SERVICE_NAME"; then
print_status "OpenVPN service is running"
else
print_error "OpenVPN service failed to start"
systemctl status "$SERVICE_NAME"
exit 1
fi
if ss -tulpn | grep -q ":1194"; then
print_status "OpenVPN is listening on port 1194"
else
print_warning "OpenVPN may not be listening on port 1194"
fi
print_status "OpenVPN LDAP setup completed successfully!"
print_warning "Remember to:"
print_warning "1. Configure your Active Directory with VPN-Users group"
print_warning "2. Create service account with appropriate permissions"
print_warning "3. Test LDAP connectivity before client connections"
print_warning "4. Distribute client configuration files"
Review the script before running. Execute with: bash install.sh