CIS WireGuard VPN Benchmark
Security configuration recommendations for WireGuard VPN tunnels
v1.0.0 01-2025Overview
▶This benchmark provides prescriptive guidance for establishing a secure configuration posture for WireGuard VPN deployments. It covers interface setup and key management, peer configuration with least-privilege AllowedIPs, pre-shared key usage for post-quantum protection, firewall hardening, DNS leak prevention, key rotation practices, connection monitoring, and operational backup procedures.
| Section | Area | Focus |
|---|---|---|
| 1 | Interface & Key Management | Key pair generation and file permission hardening |
| 2 | Peer Configuration | Least-privilege AllowedIPs and pre-shared key enforcement |
| 3 | Network Hardening | Firewall rules and controlled IP forwarding |
| 4 | Privacy & Key Rotation | DNS leak prevention and scheduled key rotation |
| 5 | Logging & Monitoring | Traffic logging and handshake freshness monitoring |
| 6 | Kernel & Performance | Kernel module usage and MTU optimization |
| 7 | Operations & Recovery | Configuration backup and service availability |
Profile Definitions
▶| Profile | Description | Intended Use |
|---|---|---|
| L1 | Level 1 — Standard | Essential security for all WireGuard deployments; minimal performance impact. |
| L2 | Level 2 — Hardened | Advanced hardening for PCI-DSS, HIPAA, or high-security environments. |
1 — Interface & Key Management
▶1.1 Interface Configuration
▶This recommendation verifies that WireGuard interface is properly configured with unique key pairs on the WireGuard VPN tunnel. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the WireGuard VPN tunnel vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Check WireGuard interface configuration: wg show all # Verify kernel module loaded: lsmod | grep wireguard # Check interface status: ip link show type wireguard
# Generate key pair: wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey chmod 600 /etc/wireguard/privatekey # Create interface configuration: cat > /etc/wireguard/wg0.conf << 'EOF' [Interface] Address = 10.0.0.1/24 ListenPort = 51820 PrivateKey = <SERVER_PRIVATE_KEY> EOF systemctl enable --now wg-quick@wg0
This recommendation verifies that private key and configuration file permissions are restrictive on the WireGuard VPN tunnel. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the WireGuard VPN tunnel vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Check private key file permissions: stat -c '%a %U:%G' /etc/wireguard/privatekey stat -c '%a %U:%G' /etc/wireguard/wg0.conf # Verify no world-readable keys: find /etc/wireguard/ -type f -perm /o+r -ls
# Set restrictive permissions on keys and config: chmod 600 /etc/wireguard/privatekey chmod 600 /etc/wireguard/wg0.conf chown root:root /etc/wireguard/privatekey chown root:root /etc/wireguard/wg0.conf chmod 700 /etc/wireguard/
2 — Peer Configuration
▶2.1 Peer Access Control
▶This recommendation verifies that AllowedIPs are configured with least-privilege scope on the WireGuard VPN tunnel. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the WireGuard VPN tunnel vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Check peer configuration: wg show wg0 peers # Verify AllowedIPs are specific: wg show wg0 allowed-ips # Check for overly permissive 0.0.0.0/0 on server: grep -c 'AllowedIPs.*0.0.0.0/0' /etc/wireguard/wg0.conf
# Configure peers with specific AllowedIPs (least privilege): cat >> /etc/wireguard/wg0.conf << 'EOF' [Peer] PublicKey = <PEER_PUBLIC_KEY> AllowedIPs = 10.0.0.2/32 Endpoint = peer.example.com:51820 PersistentKeepalive = 25 EOF # Reload configuration: wg syncconf wg0 <(wg-quick strip wg0)
This recommendation verifies that pre-shared keys are configured for post-quantum protection on the WireGuard VPN tunnel. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the WireGuard VPN tunnel vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Verify pre-shared key usage:
wg show wg0 preshared-keys
# Check if all peers have PSK:
for peer in $(wg show wg0 peers); do
psk=$(wg show wg0 preshared-keys | grep $peer | awk '{print $2}')
echo "$peer: PSK=${psk:-(none)}"
done# Generate and configure pre-shared keys: wg genpsk > /etc/wireguard/psk-peer1 chmod 600 /etc/wireguard/psk-peer1 # Add PSK to peer config: # [Peer] # PublicKey = <PEER_PUBLIC_KEY> # PresharedKey = <PRESHARED_KEY> # AllowedIPs = 10.0.0.2/32
3 — Network Hardening
▶3.1 Firewall & Routing
▶This recommendation verifies that firewall restricts WireGuard port access to authorized sources on the WireGuard VPN tunnel. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the WireGuard VPN tunnel vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Check firewall rules for WireGuard port: iptables -L INPUT -n -v | grep 51820 nft list ruleset | grep 51820 # Verify only expected source IPs can connect: ss -ulnp | grep 51820
# Restrict WireGuard port access: iptables -A INPUT -p udp --dport 51820 -s 203.0.113.0/24 -j ACCEPT iptables -A INPUT -p udp --dport 51820 -j DROP # Or with nftables: nft add rule inet filter input udp dport 51820 ip saddr 203.0.113.0/24 accept nft add rule inet filter input udp dport 51820 drop
This recommendation verifies that IP forwarding and NAT rules are properly configured on the WireGuard VPN tunnel. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the WireGuard VPN tunnel vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Check IP forwarding settings: sysctl net.ipv4.ip_forward sysctl net.ipv6.conf.all.forwarding # Verify PostUp/PostDown iptables rules: grep -E 'PostUp|PostDown' /etc/wireguard/wg0.conf
# Configure controlled IP forwarding: sysctl -w net.ipv4.ip_forward=1 echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.d/99-wireguard.conf # Add NAT rules in WireGuard config: # PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE # PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
4 — Privacy & Key Rotation
▶4.1 DNS & Keys
▶This recommendation verifies that DNS is configured to prevent DNS leaks on the WireGuard VPN tunnel. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the WireGuard VPN tunnel vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Check DNS leak prevention: resolvectl status wg0 2>/dev/null || systemd-resolve --status wg0 # Verify DNS configuration in WireGuard: grep 'DNS' /etc/wireguard/wg0.conf
# Configure DNS in WireGuard interface: # In [Interface]: # DNS = 10.0.0.53 # Prevent DNS leaks with PostUp: # PostUp = resolvectl dns wg0 10.0.0.53; resolvectl domain wg0 ~. # PostDown = resolvectl revert wg0
This recommendation verifies that key rotation is performed on a regular schedule on the WireGuard VPN tunnel. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the WireGuard VPN tunnel vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Check for key rotation evidence: stat -c '%Y %n' /etc/wireguard/privatekey date -d @$(stat -c '%Y' /etc/wireguard/privatekey) '+%Y-%m-%d' # Age of current key: echo $(( ($(date +%s) - $(stat -c '%Y' /etc/wireguard/privatekey)) / 86400 )) days old
# Rotate WireGuard keys: # 1. Generate new key pair: wg genkey | tee /etc/wireguard/privatekey.new | wg pubkey > /etc/wireguard/publickey.new # 2. Distribute new public key to all peers # 3. Update local config with new private key # 4. Update all peers' configs with new public key # 5. Reload: wg syncconf wg0 <(wg-quick strip wg0) # Set up automated rotation reminder: echo '0 0 1 */3 * root /usr/local/bin/wg-rotate-keys.sh' > /etc/cron.d/wg-rotate
5 — Logging & Monitoring
▶5.1 Connection Tracking
▶This recommendation verifies that WireGuard traffic logging is enabled on the WireGuard VPN tunnel. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the WireGuard VPN tunnel vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Check WireGuard logging: dmesg | grep -i wireguard journalctl -u wg-quick@wg0 --no-pager -n 20 # Verify connection tracking: conntrack -L -p udp --dport 51820 2>/dev/null | head
# Enable WireGuard kernel logging: echo module wireguard +p > /sys/kernel/debug/dynamic_debug/control # Set up connection logging with iptables: iptables -A INPUT -p udp --dport 51820 -j LOG --log-prefix 'WG-IN: ' --log-level 4 iptables -A OUTPUT -p udp --sport 51820 -j LOG --log-prefix 'WG-OUT: ' --log-level 4 # Forward to syslog: echo 'kern.warning /var/log/wireguard.log' >> /etc/rsyslog.d/wireguard.conf systemctl restart rsyslog
This recommendation verifies that handshake freshness is monitored for peer connectivity on the WireGuard VPN tunnel. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the WireGuard VPN tunnel vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Check for connection monitoring:
wg show wg0 latest-handshakes
# Verify handshake freshness:
for peer in $(wg show wg0 peers); do
hs=$(wg show wg0 latest-handshakes | grep $peer | awk '{print $2}')
age=$(( $(date +%s) - hs ))
echo "$peer: last handshake ${age}s ago"
done# Create handshake monitoring script:
cat > /usr/local/bin/wg-monitor.sh << 'SCRIPT'
#!/bin/bash
THRESHOLD=300 # 5 minutes
for peer in $(wg show wg0 peers); do
hs=$(wg show wg0 latest-handshakes | grep $peer | awk '{print $2}')
age=$(( $(date +%s) - hs ))
if [ $age -gt $THRESHOLD ]; then
logger -p auth.warning "WireGuard: peer $peer stale handshake (${age}s)"
fi
done
SCRIPT
chmod +x /usr/local/bin/wg-monitor.sh
echo '*/5 * * * * root /usr/local/bin/wg-monitor.sh' > /etc/cron.d/wg-monitor6 — Kernel & Performance
▶6.1 Module & MTU
▶This recommendation verifies that kernel WireGuard module is used instead of userspace implementation on the WireGuard VPN tunnel. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the WireGuard VPN tunnel vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Check kernel version for WireGuard support: uname -r # Verify using kernel module (not userspace): lsmod | grep wireguard modinfo wireguard | head -5
# Ensure kernel WireGuard module is used (not wireguard-go): # For kernels >= 5.6, WireGuard is built-in # For older kernels, install DKMS module: apt install wireguard-dkms # Debian/Ubuntu # OR yum install kmod-wireguard # RHEL/CentOS # Verify kernel module loaded: modprobe wireguard lsmod | grep wireguard
This recommendation verifies that MTU is configured appropriately to prevent fragmentation on the WireGuard VPN tunnel. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the WireGuard VPN tunnel vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Check MTU setting: ip link show wg0 | grep mtu # Verify MTU in config: grep -i mtu /etc/wireguard/wg0.conf # Test for fragmentation: ping -M do -s 1420 -c 3 10.0.0.2
# Set appropriate MTU in config: # Standard: 1420 (1500 - 80 WireGuard overhead) # IPv6: 1400 # PPPoE: 1372 # In wg0.conf [Interface]: # MTU = 1420 ip link set wg0 mtu 1420
7 — Operations & Recovery
▶7.1 Backup & Availability
▶This recommendation verifies that configuration and key backups are automated and secured on the WireGuard VPN tunnel. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the WireGuard VPN tunnel vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Check for config backups: find /etc/wireguard/ -name '*.conf.bak' -o -name '*.conf.old' | head ls -la /root/wireguard-backup/ 2>/dev/null
# Create secure backup script: cat > /usr/local/bin/wg-backup.sh << 'SCRIPT' #!/bin/bash BACKUP_DIR=/root/wireguard-backup mkdir -p $BACKUP_DIR tar czf $BACKUP_DIR/wg-$(date +%Y%m%d).tar.gz /etc/wireguard/ chmod 600 $BACKUP_DIR/*.tar.gz find $BACKUP_DIR -mtime +30 -delete SCRIPT chmod 700 /usr/local/bin/wg-backup.sh echo '0 2 * * 0 root /usr/local/bin/wg-backup.sh' > /etc/cron.d/wg-backup
This recommendation verifies that WireGuard service is enabled on boot with auto-restart on the WireGuard VPN tunnel. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.
Failure to implement this control may leave the WireGuard VPN tunnel vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.
# Verify systemd service enabled: systemctl is-enabled wg-quick@wg0 systemctl status wg-quick@wg0 # Check auto-restart: systemctl show wg-quick@wg0 | grep Restart
# Enable WireGuard on boot: systemctl enable wg-quick@wg0 # Create systemd override for auto-restart: mkdir -p /etc/systemd/system/wg-quick@wg0.service.d/ cat > /etc/systemd/system/wg-quick@wg0.service.d/restart.conf << 'EOF' [Service] Restart=on-failure RestartSec=5 EOF systemctl daemon-reload