WireGuard is a free and open-source VPN protocol and software implementation that aims to be simpler, faster, and more secure than existing VPN protocols. Originally developed by Jason A. Donenfeld, WireGuard provides state-of-the-art cryptography and minimal attack surface. It serves as a modern FOSS alternative to proprietary VPN solutions like Cisco AnyConnect, Palo Alto GlobalProtect, or commercial VPN services, offering enterprise-grade security with significantly better performance and a fraction of the codebase.
1. Prerequisites
2. Supported Operating Systems
This guide supports installation on:
3. Installation
RHEL/CentOS/Rocky Linux/AlmaLinux
# For RHEL/CentOS 8+, Rocky Linux, AlmaLinux
sudo dnf install -y epel-release elrepo-release
sudo dnf install -y kmod-wireguard wireguard-tools
# For CentOS 7
sudo yum install -y epel-release
sudo yum install -y yum-plugin-elrepo
sudo yum install -y kmod-wireguard wireguard-tools
# Enable IP forwarding
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
# Verify installation
wg --version
Debian/Ubuntu
# Update package index
sudo apt update
# Install WireGuard
sudo apt install -y wireguard wireguard-tools
# For older Ubuntu versions (< 20.04)
sudo add-apt-repository ppa:wireguard/wireguard
sudo apt update
sudo apt install -y wireguard wireguard-tools
# Enable IP forwarding
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
# Verify installation
wg --version
Arch Linux
# Install WireGuard
sudo pacman -S wireguard-tools
# Enable IP forwarding
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/30-ipforward.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/30-ipforward.conf
sudo sysctl --system
# Verify installation
wg --version
Alpine Linux
# Install WireGuard
apk add --no-cache wireguard-tools
# Load kernel module
modprobe wireguard
# Make module load persistent
echo "wireguard" >> /etc/modules
# Enable IP forwarding
echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
echo 'net.ipv6.conf.all.forwarding = 1' >> /etc/sysctl.conf
sysctl -p
# Verify installation
wg --version
openSUSE/SLES
# openSUSE Leap/Tumbleweed
sudo zypper install -y wireguard-tools
# SLES 15
sudo SUSEConnect -p sle-module-basesystem/15.5/x86_64
sudo zypper install -y wireguard-tools
# Enable IP forwarding
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
# Verify installation
wg --version
macOS
# Using Homebrew
brew install wireguard-tools
# Or download the official macOS app from App Store
# Search for "WireGuard" by WireGuard Development Team
# For command-line usage
brew install wireguard-go
# Verify installation
wg --version
FreeBSD
# Using pkg
pkg install wireguard wireguard-tools
# Load kernel module
kldload if_wg
# Make module load persistent
echo 'if_wg_load="YES"' >> /etc/rc.conf
# Enable IP forwarding
echo 'gateway_enable="YES"' >> /etc/rc.conf
echo 'ipv6_gateway_enable="YES"' >> /etc/rc.conf
# Apply sysctl settings
sysctl net.inet.ip.forwarding=1
sysctl net.inet6.ip6.forwarding=1
# Verify installation
wg --version
Windows
# Method 1: Using Chocolatey
choco install wireguard
# Method 2: Using Scoop
scoop bucket add extras
scoop install wireguard
# Method 3: Download installer
# Download from https://www.wireguard.com/install/
# Run the MSI installer
# Enable IP forwarding (PowerShell as Administrator)
Set-NetIPInterface -Forwarding Enabled
# Verify installation (in Command Prompt)
"C:\Program Files\WireGuard\wg.exe" --version
Initial Configuration
Generate Keys
# Create directory for WireGuard configuration
sudo mkdir -p /etc/wireguard
sudo chmod 700 /etc/wireguard
cd /etc/wireguard
# Generate server private key
wg genkey | sudo tee server_private.key | wg pubkey | sudo tee server_public.key
sudo chmod 600 server_private.key
# Generate client private key
wg genkey | sudo tee client_private.key | wg pubkey | sudo tee client_public.key
sudo chmod 600 client_private.key
Server Configuration
# Create server configuration
sudo tee /etc/wireguard/wg0.conf <<EOF
[Interface]
Address = 10.0.0.1/24, fd00:0:0:1::1/64
ListenPort = 51820
PrivateKey = $(cat server_private.key)
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -A FORWARD -o wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -D FORWARD -o wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
# Client peer
[Peer]
PublicKey = $(cat client_public.key)
AllowedIPs = 10.0.0.2/32, fd00:0:0:1::2/128
EOF
sudo chmod 600 /etc/wireguard/wg0.conf
Client Configuration
# Create client configuration
sudo tee /etc/wireguard/client.conf <<EOF
[Interface]
Address = 10.0.0.2/24, fd00:0:0:1::2/64
PrivateKey = $(cat client_private.key)
DNS = 1.1.1.1, 1.0.0.1
[Peer]
PublicKey = $(cat server_public.key)
Endpoint = YOUR_SERVER_IP:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
EOF
sudo chmod 600 /etc/wireguard/client.conf
Start WireGuard
# Start WireGuard interface
sudo wg-quick up wg0
# Enable at boot
sudo systemctl enable wg-quick@wg0
# Check status
sudo wg show
5. Service Management
systemd (RHEL, Debian, Ubuntu, Arch, openSUSE)
# Enable WireGuard service
sudo systemctl enable wg-quick@wg0
# Start WireGuard
sudo systemctl start wg-quick@wg0
# Stop WireGuard
sudo systemctl stop wg-quick@wg0
# Restart WireGuard
sudo systemctl restart wg-quick@wg0
# Check status
sudo systemctl status wg-quick@wg0
# View logs
sudo journalctl -u wg-quick@wg0 -f
OpenRC (Alpine Linux)
# Create OpenRC service
sudo tee /etc/init.d/wireguard <<'EOF'
#!/sbin/openrc-run
name="WireGuard VPN"
description="WireGuard VPN tunnel"
depend() {
need net
after firewall
}
start() {
ebegin "Starting WireGuard"
wg-quick up wg0
eend $?
}
stop() {
ebegin "Stopping WireGuard"
wg-quick down wg0
eend $?
}
EOF
sudo chmod +x /etc/init.d/wireguard
# Enable and start
rc-update add wireguard default
rc-service wireguard start
rc.d (FreeBSD)
# Create rc.d script
sudo tee /usr/local/etc/rc.d/wireguard <<'EOF'
#!/bin/sh
# PROVIDE: wireguard
# REQUIRE: NETWORKING
# KEYWORD: shutdown
. /etc/rc.subr
name="wireguard"
rcvar="wireguard_enable"
start_cmd="wireguard_start"
stop_cmd="wireguard_stop"
wireguard_start() {
/usr/local/bin/wg-quick up wg0
}
wireguard_stop() {
/usr/local/bin/wg-quick down wg0
}
load_rc_config $name
run_rc_command "$1"
EOF
sudo chmod +x /usr/local/etc/rc.d/wireguard
# Enable in rc.conf
echo 'wireguard_enable="YES"' >> /etc/rc.conf
# Start service
service wireguard start
Windows Service
# Install WireGuard service
& "C:\Program Files\WireGuard\wireguard.exe" /installtunnelservice "C:\Path\To\wg0.conf"
# Start service
Start-Service WireGuardTunnel$wg0
# Stop service
Stop-Service WireGuardTunnel$wg0
# Check status
Get-Service WireGuardTunnel$wg0
Advanced Configuration
Multi-Site VPN Setup
# Site A configuration (10.1.0.0/24)
cat > /etc/wireguard/site-a.conf <<EOF
[Interface]
Address = 10.100.0.1/24
ListenPort = 51820
PrivateKey = SITE_A_PRIVATE_KEY
# Site B
[Peer]
PublicKey = SITE_B_PUBLIC_KEY
Endpoint = site-b.example.com:51820
AllowedIPs = 10.2.0.0/24, 10.100.0.2/32
PersistentKeepalive = 25
# Site C
[Peer]
PublicKey = SITE_C_PUBLIC_KEY
Endpoint = site-c.example.com:51820
AllowedIPs = 10.3.0.0/24, 10.100.0.3/32
PersistentKeepalive = 25
EOF
Road Warrior Configuration
# Server configuration for mobile clients
cat > /etc/wireguard/mobile.conf <<EOF
[Interface]
Address = 10.200.0.1/24
ListenPort = 51821
PrivateKey = MOBILE_SERVER_PRIVATE_KEY
# Mobile client 1
[Peer]
PublicKey = MOBILE_CLIENT_1_PUBLIC_KEY
AllowedIPs = 10.200.0.10/32
PresharedKey = PRESHARED_KEY_FOR_EXTRA_SECURITY
# Mobile client 2
[Peer]
PublicKey = MOBILE_CLIENT_2_PUBLIC_KEY
AllowedIPs = 10.200.0.11/32
PresharedKey = ANOTHER_PRESHARED_KEY
EOF
Split Tunnel Configuration
# Client configuration for split tunneling
cat > /etc/wireguard/split-tunnel.conf <<EOF
[Interface]
Address = 10.0.0.100/24
PrivateKey = CLIENT_PRIVATE_KEY
DNS = 10.0.0.1
[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = vpn.example.com:51820
# Only route specific subnets through VPN
AllowedIPs = 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
PersistentKeepalive = 25
EOF
Reverse Proxy Setup
nginx TCP/UDP Proxy
# /etc/nginx/nginx.conf
stream {
upstream wireguard {
server 127.0.0.1:51820;
}
server {
listen 443 udp;
proxy_pass wireguard;
proxy_timeout 1s;
proxy_responses 1;
proxy_bind $remote_addr transparent;
}
}
HAProxy Configuration
# /etc/haproxy/haproxy.cfg
global
log /dev/log local0
log /dev/log local1 notice
defaults
mode tcp
timeout connect 5000
timeout client 50000
timeout server 50000
frontend wireguard_frontend
bind *:51820
mode udp
default_backend wireguard_backend
backend wireguard_backend
mode udp
server wireguard1 127.0.0.1:51821
iptables Port Forwarding
# Forward external port to WireGuard
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 443 -j REDIRECT --to-port 51820
# Save rules
iptables-save > /etc/iptables/rules.v4
Security Configuration
Firewall Rules
# UFW (Ubuntu/Debian)
sudo ufw allow 51820/udp
sudo ufw allow from 10.0.0.0/24 to any
sudo ufw reload
# firewalld (RHEL/CentOS)
sudo firewall-cmd --permanent --add-port=51820/udp
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.0/24" accept'
sudo firewall-cmd --reload
# iptables
sudo iptables -A INPUT -p udp --dport 51820 -j ACCEPT
sudo iptables -A INPUT -i wg0 -j ACCEPT
sudo iptables -A FORWARD -i wg0 -o eth0 -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o wg0 -m state --state RELATED,ESTABLISHED -j ACCEPT
Key Management
#!/bin/bash
# key-rotation.sh - Rotate WireGuard keys
# Generate new keys
NEW_PRIVATE=$(wg genkey)
NEW_PUBLIC=$(echo "$NEW_PRIVATE" | wg pubkey)
# Backup old configuration
cp /etc/wireguard/wg0.conf /etc/wireguard/wg0.conf.bak
# Update configuration
sed -i "s|PrivateKey = .*|PrivateKey = $NEW_PRIVATE|" /etc/wireguard/wg0.conf
# Restart WireGuard
systemctl restart wg-quick@wg0
echo "New public key: $NEW_PUBLIC"
echo "Update this key on all peers"
Security Hardening
# Limit connection rate
iptables -A INPUT -p udp --dport 51820 -m state --state NEW -m recent --set
iptables -A INPUT -p udp --dport 51820 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP
# Enable strict RPF
echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter
# Disable ICMP redirects
echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirects
echo 0 > /proc/sys/net/ipv6/conf/all/accept_redirects
# Set up fail2ban for WireGuard
cat > /etc/fail2ban/filter.d/wireguard.conf <<EOF
[Definition]
failregex = <HOST>.*Handshake for peer [0-9]+ \(.*\) did not complete after
ignoreregex =
EOF
cat > /etc/fail2ban/jail.d/wireguard.conf <<EOF
[wireguard]
enabled = true
filter = wireguard
logpath = /var/log/messages
maxretry = 5
bantime = 3600
findtime = 600
EOF
Database Setup
Not applicable for WireGuard as it doesn't use a database. Configuration is stored in flat files.
Performance Optimization
Kernel Tuning
# /etc/sysctl.d/99-wireguard.conf
# Network buffer sizes
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.core.rmem_default = 16777216
net.core.wmem_default = 16777216
net.core.optmem_max = 16777216
# Increase netdev budget
net.core.netdev_budget = 600
net.core.netdev_max_backlog = 5000
# UDP specific tuning
net.ipv4.udp_rmem_min = 8192
net.ipv4.udp_wmem_min = 8192
# Connection tracking
net.netfilter.nf_conntrack_max = 1048576
net.netfilter.nf_conntrack_udp_timeout = 60
net.netfilter.nf_conntrack_udp_timeout_stream = 180
# Apply settings
sysctl -p /etc/sysctl.d/99-wireguard.conf
MTU Optimization
# Find optimal MTU
ping -M do -s 1472 -c 1 remote_host
# Set MTU in WireGuard config
[Interface]
MTU = 1420 # Default is 1420, adjust based on your network
CPU Affinity
# Set CPU affinity for WireGuard
# Find WireGuard process
ps aux | grep wireguard
# Set affinity to specific CPU cores
taskset -cp 0,1 $(pgrep wireguard)
# Make persistent with systemd
mkdir -p /etc/systemd/system/wg-quick@wg0.service.d
cat > /etc/systemd/system/wg-quick@wg0.service.d/override.conf <<EOF
[Service]
CPUAffinity=0 1
EOF
Monitoring
Basic Monitoring
#!/bin/bash
# wireguard-monitor.sh
while true; do
clear
echo "WireGuard Status - $(date)"
echo "========================="
# Show interface status
wg show
# Show transfer statistics
echo -e "\nTransfer Statistics:"
wg show wg0 transfer
# Show connected peers
echo -e "\nConnected Peers:"
wg show wg0 peers
# Show system resources
echo -e "\nSystem Resources:"
echo "CPU: $(top -bn1 | grep "Cpu(s)" | awk '{print $2 + $4"%"}')"
echo "Memory: $(free -m | awk 'NR==2{printf "%.2f%%", $3*100/$2}')"
echo "Network: $(ip -s link show wg0 | grep -A1 "RX:" | tail -1 | awk '{print "RX: "$1" bytes"}'), $(ip -s link show wg0 | grep -A1 "TX:" | tail -1 | awk '{print "TX: "$1" bytes"}')"
sleep 5
done
Prometheus Exporter
# Install WireGuard exporter
go get -u github.com/MindFlavor/prometheus_wireguard_exporter
# Configure exporter
cat > /etc/systemd/system/wireguard-exporter.service <<EOF
[Unit]
Description=WireGuard Prometheus Exporter
After=network.target
[Service]
Type=simple
User=prometheus
ExecStart=/usr/local/bin/prometheus_wireguard_exporter -n /etc/wireguard/wg0.conf
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
systemctl enable --now wireguard-exporter
Logging
# Enable verbose logging
echo "debug" > /sys/module/wireguard/parameters/debug
# Configure rsyslog for WireGuard
cat > /etc/rsyslog.d/49-wireguard.conf <<EOF
:msg, contains, "wireguard" /var/log/wireguard.log
& stop
EOF
systemctl restart rsyslog
# Log rotation
cat > /etc/logrotate.d/wireguard <<EOF
/var/log/wireguard.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
create 640 root adm
}
EOF
9. Backup and Restore
Backup Script
#!/bin/bash
# wireguard-backup.sh
BACKUP_DIR="/backup/wireguard"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/wireguard_backup_$DATE.tar.gz"
# Create backup directory
mkdir -p "$BACKUP_DIR"
# Create backup
tar -czf "$BACKUP_FILE" \
/etc/wireguard/ \
/etc/systemd/system/wg-quick@*.service.d/ \
/etc/sysctl.d/*wireguard* \
2>/dev/null
# Encrypt backup
gpg --cipher-algo AES256 --symmetric "$BACKUP_FILE"
rm "$BACKUP_FILE"
echo "Backup created: $BACKUP_FILE.gpg"
# Clean old backups (keep 30 days)
find "$BACKUP_DIR" -name "wireguard_backup_*.gpg" -mtime +30 -delete
Restore Script
#!/bin/bash
# wireguard-restore.sh
BACKUP_FILE="$1"
if [ -z "$BACKUP_FILE" ]; then
echo "Usage: $0 <backup-file.gpg>"
exit 1
fi
# Decrypt backup
gpg --decrypt "$BACKUP_FILE" > /tmp/wireguard_restore.tar.gz
# Stop WireGuard
systemctl stop wg-quick@wg0
# Extract backup
tar -xzf /tmp/wireguard_restore.tar.gz -C /
# Set correct permissions
chmod 600 /etc/wireguard/*.conf
chmod 600 /etc/wireguard/*_private.key
# Restart WireGuard
systemctl start wg-quick@wg0
# Clean up
rm /tmp/wireguard_restore.tar.gz
echo "Restore completed"
6. Troubleshooting
Common Issues
1. Connection not establishing:
# Check if WireGuard module is loaded
lsmod | grep wireguard
# Load module manually
modprobe wireguard
# Check interface
ip link show wg0
# Check routing
ip route show table all | grep wg0
# Test connectivity
ping -c 4 10.0.0.1
2. Performance issues:
# Check for packet loss
mtr -n 10.0.0.1
# Check interface statistics
ip -s link show wg0
# Monitor CPU usage
top -p $(pgrep wireguard)
# Check for errors
dmesg | grep wireguard
3. Key exchange problems:
# Verify keys match
wg show wg0 public-key
wg show wg0 peers
# Check handshake status
wg show wg0 latest-handshakes
# Force re-handshake
wg set wg0 peer PEER_PUBLIC_KEY endpoint ENDPOINT:PORT
Debug Mode
# Enable debug logging
echo module wireguard +p > /sys/kernel/debug/dynamic_debug/control
# View debug logs
dmesg -w | grep wireguard
# Disable debug logging
echo module wireguard -p > /sys/kernel/debug/dynamic_debug/control
Integration Examples
Python Integration
#!/usr/bin/env python3
# wireguard_manager.py
import subprocess
import json
import ipaddress
class WireGuardManager:
def __init__(self, interface='wg0'):
self.interface = interface
def get_status(self):
"""Get WireGuard interface status"""
try:
result = subprocess.run(['wg', 'show', self.interface, 'dump'],
capture_output=True, text=True, check=True)
lines = result.stdout.strip().split('\n')
# Parse interface info
interface_data = lines[0].split('\t')
status = {
'interface': self.interface,
'private_key': interface_data[0],
'public_key': interface_data[1],
'listen_port': interface_data[2],
'fwmark': interface_data[3],
'peers': []
}
# Parse peer info
for line in lines[1:]:
peer_data = line.split('\t')
peer = {
'public_key': peer_data[0],
'preshared_key': peer_data[1],
'endpoint': peer_data[2],
'allowed_ips': peer_data[3].split(','),
'latest_handshake': peer_data[4],
'rx_bytes': int(peer_data[5]),
'tx_bytes': int(peer_data[6]),
'persistent_keepalive': peer_data[7]
}
status['peers'].append(peer)
return status
except subprocess.CalledProcessError as e:
return {'error': str(e)}
def add_peer(self, public_key, allowed_ips, endpoint=None, preshared_key=None):
"""Add a new peer"""
cmd = ['wg', 'set', self.interface, 'peer', public_key]
if allowed_ips:
cmd.extend(['allowed-ips', ','.join(allowed_ips)])
if endpoint:
cmd.extend(['endpoint', endpoint])
if preshared_key:
cmd.extend(['preshared-key', preshared_key])
try:
subprocess.run(cmd, check=True)
return {'success': True}
except subprocess.CalledProcessError as e:
return {'error': str(e)}
def remove_peer(self, public_key):
"""Remove a peer"""
try:
subprocess.run(['wg', 'set', self.interface, 'peer', public_key, 'remove'],
check=True)
return {'success': True}
except subprocess.CalledProcessError as e:
return {'error': str(e)}
def generate_config(self, address, private_key, peers):
"""Generate WireGuard configuration"""
config = f"""[Interface]
Address = {address}
PrivateKey = {private_key}
ListenPort = 51820
"""
for peer in peers:
config += f"""[Peer]
PublicKey = {peer['public_key']}
AllowedIPs = {','.join(peer['allowed_ips'])}
"""
if peer.get('endpoint'):
config += f"Endpoint = {peer['endpoint']}\n"
if peer.get('preshared_key'):
config += f"PresharedKey = {peer['preshared_key']}\n"
if peer.get('persistent_keepalive'):
config += f"PersistentKeepalive = {peer['persistent_keepalive']}\n"
config += "\n"
return config
# Example usage
if __name__ == '__main__':
wg = WireGuardManager()
# Get status
status = wg.get_status()
print(json.dumps(status, indent=2))
# Add a peer
result = wg.add_peer(
public_key='PEER_PUBLIC_KEY',
allowed_ips=['10.0.0.100/32'],
endpoint='peer.example.com:51820'
)
print(f"Add peer result: {result}")
Bash Integration
#!/bin/bash
# wireguard-cli.sh - WireGuard management CLI
set -euo pipefail
INTERFACE="${WG_INTERFACE:-wg0}"
CONFIG_DIR="/etc/wireguard"
show_help() {
cat <<EOF
WireGuard CLI Management Tool
Usage: $0 [command] [options]
Commands:
status Show interface status
add-peer Add a new peer
remove-peer Remove a peer
list-peers List all peers
generate-qr Generate QR code for mobile config
backup Backup configuration
restore Restore configuration
Examples:
$0 status
$0 add-peer --name mobile1 --ip 10.0.0.10
$0 generate-qr mobile1
EOF
}
status() {
echo "WireGuard Interface: $INTERFACE"
echo "========================="
wg show "$INTERFACE"
}
add_peer() {
local name="$1"
local ip="$2"
# Generate keys
private_key=$(wg genkey)
public_key=$(echo "$private_key" | wg pubkey)
preshared_key=$(wg genpsk)
# Add to server config
cat >> "$CONFIG_DIR/$INTERFACE.conf" <<EOF
[Peer]
# $name
PublicKey = $public_key
PresharedKey = $preshared_key
AllowedIPs = $ip/32
EOF
# Generate client config
server_public_key=$(wg show "$INTERFACE" public-key)
server_endpoint=$(curl -s ifconfig.me)
cat > "$CONFIG_DIR/clients/$name.conf" <<EOF
[Interface]
Address = $ip/24
PrivateKey = $private_key
DNS = 1.1.1.1, 1.0.0.1
[Peer]
PublicKey = $server_public_key
PresharedKey = $preshared_key
Endpoint = $server_endpoint:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
EOF
# Reload configuration
wg syncconf "$INTERFACE" <(wg-quick strip "$INTERFACE")
echo "Peer $name added successfully"
echo "Client configuration saved to: $CONFIG_DIR/clients/$name.conf"
}
remove_peer() {
local public_key="$1"
wg set "$INTERFACE" peer "$public_key" remove
echo "Peer removed"
}
list_peers() {
echo "Configured Peers:"
echo "================="
wg show "$INTERFACE" peers | while read -r peer; do
echo "Public Key: $peer"
wg show "$INTERFACE" allowed-ips | grep "$peer" | awk '{print " Allowed IPs: " $2}'
wg show "$INTERFACE" latest-handshakes | grep "$peer" | awk '{print " Last Handshake: " strftime("%Y-%m-%d %H:%M:%S", $2)}'
echo
done
}
generate_qr() {
local config_name="$1"
local config_file="$CONFIG_DIR/clients/$config_name.conf"
if [ ! -f "$config_file" ]; then
echo "Configuration file not found: $config_file"
exit 1
fi
qrencode -t ansiutf8 < "$config_file"
}
# Main logic
case "${1:-help}" in
status)
status
;;
add-peer)
shift
add_peer "$@"
;;
remove-peer)
shift
remove_peer "$@"
;;
list-peers)
list_peers
;;
generate-qr)
shift
generate_qr "$@"
;;
help|--help|-h)
show_help
;;
*)
echo "Unknown command: $1"
show_help
exit 1
;;
esac
Maintenance
Update Procedures
# RHEL/CentOS/Rocky/AlmaLinux
sudo dnf update wireguard-tools kmod-wireguard
# Debian/Ubuntu
sudo apt update && sudo apt upgrade wireguard wireguard-tools
# Arch Linux
sudo pacman -Syu wireguard-tools
# Alpine Linux
apk update && apk upgrade wireguard-tools
# openSUSE
sudo zypper update wireguard-tools
# FreeBSD
pkg update && pkg upgrade wireguard wireguard-tools
# Always backup before updates
/usr/local/bin/wireguard-backup.sh
# Restart after updates
sudo systemctl restart wg-quick@wg0
Regular Maintenance Tasks
#!/bin/bash
# wireguard-maintenance.sh
LOG_FILE="/var/log/wireguard-maintenance.log"
CONFIG_DIR="/etc/wireguard"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# Check and remove inactive peers
check_inactive_peers() {
log "Checking for inactive peers..."
wg show wg0 latest-handshakes | while read -r peer handshake; do
if [ "$handshake" -eq 0 ]; then
continue
fi
current_time=$(date +%s)
time_diff=$((current_time - handshake))
# Remove peers inactive for more than 30 days
if [ $time_diff -gt 2592000 ]; then
log "Removing inactive peer: $peer"
wg set wg0 peer "$peer" remove
fi
done
}
# Verify configuration integrity
verify_config() {
log "Verifying configuration..."
if wg-quick strip wg0 > /dev/null 2>&1; then
log "Configuration is valid"
else
log "ERROR: Configuration validation failed"
return 1
fi
}
# Update geo-blocked IPs (if applicable)
update_geoblock() {
log "Updating geo-block rules..."
# Example: Update allowed countries
# This would typically fetch from a geo-IP database
# and update firewall rules accordingly
}
# Generate usage report
generate_report() {
log "Generating usage report..."
report_file="/var/log/wireguard-report-$(date +%Y%m%d).txt"
{
echo "WireGuard Usage Report - $(date)"
echo "================================"
echo
echo "Interface Statistics:"
wg show wg0 transfer
echo
echo "Peer Count: $(wg show wg0 peers | wc -l)"
echo
echo "Top 10 Peers by Traffic:"
wg show wg0 transfer | sort -k3 -nr | head -10
} > "$report_file"
log "Report saved to: $report_file"
}
# Main maintenance routine
main() {
log "Starting WireGuard maintenance..."
check_inactive_peers
verify_config
update_geoblock
generate_report
log "Maintenance completed"
}
# Run maintenance
main
# Schedule this script in cron:
# 0 2 * * 0 /usr/local/bin/wireguard-maintenance.sh
Performance Monitoring
#!/bin/bash
# wireguard-performance.sh
# Monitor interface performance
monitor_performance() {
local interface="wg0"
local duration=60
local interval=5
echo "Monitoring WireGuard performance for $duration seconds..."
echo "Time,RX_packets,TX_packets,RX_bytes,TX_bytes,RX_errors,TX_errors"
end_time=$(($(date +%s) + duration))
while [ $(date +%s) -lt $end_time ]; do
stats=$(ip -s link show $interface | awk '/RX:/{getline; rx_p=$1; rx_b=$2; rx_e=$3} /TX:/{getline; tx_p=$1; tx_b=$2; tx_e=$3} END{print rx_p","tx_p","rx_b","tx_b","rx_e","tx_e}')
echo "$(date +%s),$stats"
sleep $interval
done
}
# Check for configuration drift
check_config_drift() {
local running_config="/tmp/wg0-running.conf"
local saved_config="/etc/wireguard/wg0.conf"
wg showconf wg0 > "$running_config"
if ! diff -q "$running_config" <(wg-quick strip "$saved_config") > /dev/null; then
echo "WARNING: Running configuration differs from saved configuration"
diff "$running_config" <(wg-quick strip "$saved_config")
else
echo "Configuration is in sync"
fi
rm -f "$running_config"
}
# Run performance monitoring
monitor_performance | tee /var/log/wireguard-performance-$(date +%Y%m%d-%H%M%S).csv
Additional Resources
---
Note: This guide is part of the HowToMgr collection. Always refer to official documentation for the most up-to-date information.