WireGuard: A Modern VPN Protocol

WireGuard is a remarkably simple yet fast and modern VPN (Virtual Private Network) that utilizes state-of-the-art cryptography. Designed for ease of implementation and high performance, it aims to be a more efficient and secure alternative to traditional VPN protocols like IPsec and OpenVPN. This guide covers the basic setup of a WireGuard server and a peer configuration.

1. Installation

WireGuard is available in the standard repositories of most modern Linux distributions.

sudo apt update
sudo apt install wireguard

2. Key Generation

WireGuard uses public-key cryptography for authentication. Each peer needs a private key and its corresponding public key.

Generate a Private Key

sudo wg genkey | sudo tee /etc/wireguard/server_private.key

Set Secure Permissions for the Private Key

The private key should have very restrictive permissions as it grants access to the VPN.

sudo chmod 600 /etc/wireguard/server_private.key

Generate the Public Key from the Private Key

sudo cat /etc/wireguard/server_private.key | wg pubkey | sudo tee /etc/wireguard/server_public.key

You will need the public key of the server to configure client peers, and the public key(s) of the client(s) to configure the server.

3. Server Configuration: wg0.conf

Create and edit the server’s WireGuard configuration file, typically located at /etc/wireguard/wg0.conf.

sudo nano /etc/wireguard/wg0.conf

Example Server Configuration (/etc/wireguard/wg0.conf)

[Interface]
# The private IP address of the WireGuard server within the VPN tunnel
Address = 10.0.0.1/24
 
# PostUp and PostDown scripts run when the interface comes up/down
# These configure NAT (Masquerading) to allow VPN clients to access the internet via the server
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o <external_interface> -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o <external_interface> -j MASQUERADE
 
# The UDP port WireGuard listens on for incoming connections from clients
ListenPort = 51820
 
# The server's private key (generated above)
PrivateKey = <SERVER_PRIVATE_KEY_HERE>
 
[Peer]
# This section defines a client peer configuration
 
# The public key of the client peer (generated on the client machine)
PublicKey = <CLIENT_PUBLIC_KEY_HERE>
 
# The allowed IP address(es) for this client within the VPN tunnel
AllowedIPs = 10.0.0.2/32
 
# (Optional) Endpoint for clients with dynamic IPs if server is behind NAT
# Endpoint = <CLIENT_EXTERNAL_IP_OR_HOSTNAME>:<CLIENT_LISTEN_PORT>
  • Replace <external_interface> with your server’s public-facing network interface (e.g., eth0, ens3).
  • Replace <SERVER_PRIVATE_KEY_HERE> and <CLIENT_PUBLIC_KEY_HERE> with the actual keys.

4. Enable IP Forwarding

For the WireGuard server to act as a router and forward traffic from VPN clients to the internet (or other networks), IP forwarding must be enabled in the kernel.

sudo sysctl -w net.ipv4.ip_forward=1
# To make this persistent across reboots, add 'net.ipv4.ip_forward = 1' to /etc/sysctl.conf

5. System Integration (systemctl)

Manage the WireGuard interface using systemctl and wg-quick.

# Start the wg0 interface
sudo systemctl start [email protected]
 
# Check the status of the wg0 interface
sudo systemctl status [email protected]
 
# Enable the wg0 interface to start automatically on boot
sudo systemctl enable [email protected]
 
# Show the current status and configuration of the wg0 interface
sudo wg show wg0

6. Client Peer Configuration Example

On the client machine, you would create a wg0.conf file similar to this, using the server’s public key.

[Interface]
# The private IP address of the client within the VPN tunnel
Address = 10.0.0.2/32
 
# (Optional) DNS server for the client when connected to the VPN
# DNS = 8.8.8.8
 
# Client's private key
PrivateKey = <CLIENT_PRIVATE_KEY_HERE>
 
[Peer]
# The public key of the WireGuard server
PublicKey = <SERVER_PUBLIC_KEY_HERE>
 
# The external IP address and listening port of the WireGuard server
Endpoint = <SERVER_EXTERNAL_IP_OR_HOSTNAME>:51820
 
# All traffic for the client will be routed through the VPN tunnel
AllowedIPs = 0.0.0.0/0
# Or, to route only internal VPN traffic through the tunnel:
# AllowedIPs = 10.0.0.0/24
 
# (Optional) KeepAlive sends a packet every 25 seconds to maintain NAT mappings
PersistentKeepalive = 25

Install WireGuard on the client and use sudo systemctl start [email protected] to bring up the client interface.


Note on pfSense/Other Firewalls: If your WireGuard server is behind another firewall (like pfSense), ensure that the ListenPort (default 51820/UDP) is open and forwarded to your WireGuard server.