← Back to Tutorials

Setting Up and Configuring WireGuard VPN

Networking

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 wireguard

Linux (CentOS/RHEL)

sudo yum install epel-release elrepo-release
sudo yum install kmod-wireguard wireguard-tools

macOS

brew install wireguard-tools

Alternatively, 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/publickey

Important: 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/32

Enable 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 -p

Configuring 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 = 25

Split 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 wg0

Bring the Interface Down

sudo wg-quick down wg0

Enable on Boot

sudo systemctl enable wg-quick@wg0

Check Connection Status

sudo wg show

This 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/32

Then 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 --reload

Site-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/24

Add 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 AllowedIPs includes the desired destinations.
  • DNS not resolving: Add a DNS line to the client [Interface] section.
  • Performance issues: Check MTU settings. WireGuard default MTU is 1420. Adjust if needed: MTU = 1380 in 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 AllowedIPs as a built-in firewall — only allow the minimum required subnets per peer.
  • Combine WireGuard with iptables rules to restrict what peers can access on the server's network.