← News
/PLAYBOOK · 2026-08-13

WireGuard VPN Hardening: Remote Access Tunnel Config Guide

WireGuard is light and fast, but defaults leave key management, egress, and client access weakly controlled. This guide covers key generation, firewall rules, AllowedIPs, multi-client ops, and handshake audits for a repeatable WireGuard VPN hardening setup.

Scope

WireGuard VPN hardening fits: staff remote access to the LAN; ops tunnels to cloud and IDC hosts; encrypted branch interconnect; personal access to home NAS and cameras. Kernel-level speed and a tiny config made it popular. Many installs stop at "it pings"—keys never rotate, clients are unconstrained, tunnel egress is open. Full deploy-to-harden config below.

Prerequisites

Mechanism

WireGuard: ChaCha20-Poly1305, Curve25519, Noise IK. No user auth unlike OpenVPN—identity is the keypair. Each client holds a public/private pair; the server Peer list decides who connects. Four hardening axes: (1) key management—the private key is the only credential, lock perms and rotate; (2) AllowedIPs—limit which subnets a client can reach; (3) firewall—open only the tunnel port, enable NAT; (4) client access control and audit—contain leaked keys.

Procedure

1. Install and generate keys

# Install WireGuard
sudo apt update && sudo apt install -y wireguard-tools

# Generate the server key pair (umask ensures private-key mode 600)
umask 077
wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey
cat /etc/wireguard/privatekey   # Keep the private key on the server only
cat /etc/wireguard/publickey    # Distribute the public key to clients

Key params: umask 077 sets private-key file mode 600. A leaked private key is a stolen VPN identity—confirm with chmod 600.

2. Server config and hardening

# Edit /etc/wireguard/wg0.conf
sudo tee /etc/wireguard/wg0.conf > /dev/null << 'EOF'
[Interface]
Address = 10.8.0.1/24          # tunnel subnet, server address
ListenPort = 51820
PrivateKey = server private key
# hardening 1: persist keepalive so reconnects survive
PersistentKeepalive = 25

# hardening 2: firewall rules (auto-configured via PostUp/PostDown)
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

# hardening 3: enable IP forwarding
PostUp = sysctl -w net.ipv4.ip_forward=1
PostDown = sysctl -w net.ipv4.ip_forward=0

# Client Peer example (add one Peer per client in production)
[Peer]
PublicKey = client1 public key
AllowedIPs = 10.8.0.2/32      # allow only this client's own IP
EOF

# hardening 4: private-key permissions
sudo chmod 600 /etc/wireguard/wg0.conf /etc/wireguard/privatekey

3. Generate client config

# Generate a unique key pair per client (run on the client machine)
umask 077
wg genkey | tee client_priv | wg pubkey > client_pub

# Add the new Peer on the server
sudo wg set wg0 peer <client public key> allowed-ips 10.8.0.2/32

# Generate the client config (write to /etc/wireguard/wg0.conf on the client)
# [Interface]
# Address = 10.8.0.2/24
# PrivateKey = client private key
# [Peer]
# PublicKey = server public key
# Endpoint = server public IP:51820
# AllowedIPs = 10.8.0.0/24   # tunnel subnet only; do not take over all traffic
# PersistentKeepalive = 25

Key params: client AllowedIPs should be 10.8.0.0/24 or the LAN subnets you need. Do not use 0.0.0.0/0—full-tunnel makes the box a public proxy if a key leaks.

4. Firewall and host hardening

# ufw: allow the WireGuard port and restrict sources
sudo ufw allow 51820/udp
sudo ufw allow from 10.8.0.0/24

# Restrict SSH to the tunnel subnet or specific IPs
sudo ufw deny 22/tcp
sudo ufw allow from 10.8.0.0/24 to any port 22 proto tcp

# Enable TCP BBR to improve tunnel throughput (optional)
echo "net.core.default_qdisc=fq" | sudo tee -a /etc/sysctl.conf
echo "net.ipv4.tcp_congestion_control=bbr" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

5. Start and enable on boot

# Start the tunnel
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0

# Check tunnel status
sudo wg show

6. Key rotation and client revocation

# Rotate the server key (keep the existing Peer list; redistribute the public key)
umask 077
wg genkey | sudo tee /etc/wireguard/privatekey | wg pubkey | sudo tee /etc/wireguard/publickey
# Give the new public key to all clients; client Endpoints do not change

# Remove a compromised or departed client
sudo wg set wg0 peer <client public key> remove

# Inspection: check latest handshake time per Peer
sudo wg show wg0 latest-handshakes

Verification

# On the server: inspect tunnel status and per-client handshake times
sudo wg show

# On the client: verify tunnel connectivity
ping -c 3 10.8.0.1

# Verify NAT forwarding: from the client, reach LAN resources behind the server
ping -c 3 192.168.1.10

# Verify encrypted traffic: tcpdump should show encrypted tunnel payloads
sudo tcpdump -i eth0 -n udp port 51820

FAQ

Q1: Risk of client AllowedIPs = 0.0.0.0/0?

All client internet traffic goes through the tunnel. The VPN server becomes a public proxy. If the client key leaks, an attacker uses your egress for attacks or LAN access, and burns your bandwidth and IP reputation. Unless you need full-tunnel, allow only the LAN subnets required.

Q2: How to contain a leaked key fast?

Two steps: (1) on the server, wg set wg0 peer <leaked public key> remove kicks the Peer immediately; (2) rotate the server private key, redistribute the public key, tell all clients to update. If the attacker may already be on the LAN, check handshake source IPs in journalctl -u wg-quick@wg0.

Q3: Site-to-site AllowedIPs?

For site interconnect, each server Peer must list the remote LAN. Example: server A (10.8.0.1) needs B's backend 172.16.0.0/16 → on A, B's Peer gets AllowedIPs = 172.16.0.0/16, 10.8.0.3/32, and B must forward. AllowedIPs also writes the routing table; both sides must match.

Takeaway

WireGuard hardening is not hard. Identity is the key: mode 600 on the private key, unique keys per client, revoke on compromise, rotate on a schedule. Pair with minimal AllowedIPs, firewall port/source limits, and tight NAT/forwarding. Put key rotation on the quarterly ops calendar; ship handshake audit logs to your existing log stack.