What is WireGuard?
WireGuard is a modern, high-performance VPN protocol designed to be simpler, faster, and more secure than traditional VPN solutions like OpenVPN or IPsec. It uses state-of-the-art cryptography (ChaCha20, Curve25519, BLAKE2s) and runs as a kernel module, resulting in significantly lower overhead and better throughput.
WireGuard is ideal for site-to-site tunnels, remote access, and securing traffic between cloud and on-premises infrastructure. Its minimal codebase (~4,000 lines) makes it easier to audit and less prone to vulnerabilities compared to legacy VPN solutions.
Installing WireGuard
Linux (Ubuntu/Debian)
sudo apt update
sudo apt install wireguardLinux (CentOS/RHEL)
sudo yum install epel-release elrepo-release
sudo yum install kmod-wireguard wireguard-toolsmacOS
brew install wireguard-toolsAlternatively, install the WireGuard app from the Mac App Store for a GUI-based experience.
Windows
Download the official installer from wireguard.com/install and run the setup wizard.
Generating Key Pairs
WireGuard uses public/private key pairs for authentication. Generate them on each peer:
# Generate private key
wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey
# View the keys
cat /etc/wireguard/privatekey
cat /etc/wireguard/publickeyImportant: Keep the private key secure. Never share it. Only exchange public keys between peers.
Configuring the WireGuard Server
Create the configuration file at /etc/wireguard/wg0.conf:
[Interface]
# Server private key
PrivateKey = <SERVER_PRIVATE_KEY>
# VPN subnet address for this server
Address = 10.0.0.1/24
# UDP port WireGuard listens on
ListenPort = 51820
# Enable IP forwarding and NAT (optional, for internet access through VPN)
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
[Peer]
# Client public key
PublicKey = <CLIENT_PUBLIC_KEY>
# IP address assigned to this client
AllowedIPs = 10.0.0.2/32Enable IP Forwarding
For the server to route traffic between peers or to the internet:
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -pConfiguring a WireGuard Client
Create the client configuration at /etc/wireguard/wg0.conf:
[Interface]
# Client private key
PrivateKey = <CLIENT_PRIVATE_KEY>
# VPN address for this client
Address = 10.0.0.2/24
# Optional: DNS server to use over the VPN
DNS = 1.1.1.1
[Peer]
# Server public key
PublicKey = <SERVER_PUBLIC_KEY>
# Server public IP and port
Endpoint = <SERVER_PUBLIC_IP>:51820
# Route all traffic through VPN (full tunnel) or specific subnets (split tunnel)
AllowedIPs = 0.0.0.0/0
# Keep the connection alive behind NAT
PersistentKeepalive = 25Split Tunnel vs Full Tunnel
- Full tunnel (
AllowedIPs = 0.0.0.0/0): Routes all client traffic through the VPN. Best for security on untrusted networks. - Split tunnel (
AllowedIPs = 10.0.0.0/24, 192.168.1.0/24): Only routes specific subnets through the VPN. Preserves local internet speed.
Starting and Managing WireGuard
Bring the Interface Up
sudo wg-quick up wg0Bring the Interface Down
sudo wg-quick down wg0Enable on Boot
sudo systemctl enable wg-quick@wg0Check Connection Status
sudo wg showThis displays active peers, latest handshakes, data transferred, and allowed IPs.
Adding More Peers
To add additional clients, generate a new key pair for each and add a [Peer] block to the server config:
[Peer]
PublicKey = <NEW_CLIENT_PUBLIC_KEY>
AllowedIPs = 10.0.0.3/32Then reload the server without downtime:
sudo wg syncconf wg0 <(wg-quick strip wg0)Firewall Configuration
Ensure the WireGuard UDP port is open on your server firewall:
# UFW
sudo ufw allow 51820/udp
# iptables
sudo iptables -A INPUT -p udp --dport 51820 -j ACCEPT
# firewalld
sudo firewall-cmd --permanent --add-port=51820/udp
sudo firewall-cmd --reloadSite-to-Site VPN Example
WireGuard excels at connecting two networks (e.g., office to cloud). On each side, set AllowedIPs to the remote subnet:
# Site A config (office: 192.168.1.0/24)
[Peer]
PublicKey = <SITE_B_PUBLIC_KEY>
Endpoint = <SITE_B_PUBLIC_IP>:51820
AllowedIPs = 192.168.2.0/24
# Site B config (cloud: 192.168.2.0/24)
[Peer]
PublicKey = <SITE_A_PUBLIC_KEY>
Endpoint = <SITE_A_PUBLIC_IP>:51820
AllowedIPs = 192.168.1.0/24Add static routes on each network's gateway pointing the remote subnet to the WireGuard host.
Troubleshooting
- No handshake: Verify the endpoint IP/port, check firewall rules, and confirm public keys are correct on both sides.
- Traffic not routing: Ensure IP forwarding is enabled and
AllowedIPsincludes the desired destinations. - DNS not resolving: Add a
DNSline to the client[Interface]section. - Performance issues: Check MTU settings. WireGuard default MTU is 1420. Adjust if needed:
MTU = 1380in the[Interface]block.
Security Best Practices
- Restrict
/etc/wireguard/permissions:chmod 600 /etc/wireguard/* - Use a non-default port instead of 51820 to reduce scanning exposure.
- Rotate keys periodically by generating new pairs and updating configs.
- Use
AllowedIPsas a built-in firewall — only allow the minimum required subnets per peer. - Combine WireGuard with
iptablesrules to restrict what peers can access on the server's network.