Deploying and Configuring a WireGuard VPN Tunnel on Linux

  1. Package Installation

Begin by updating the package index and installing the core WireGuard utilities alongside a DNS resolver manager to handle dynamic DNS updates across the tunnel.

sudo apt update
sudo apt install wireguard openresolv -y
  1. Cryptographic Key Generation

Navigate to the configuration directory, restrict file permissions, and generate distinct key pairs for the server and client nodes. Using input/output redirection ensures keys are stored securely without exposing them in shell history.

cd /etc/wireguard
umask 077
wg genkey > node_srv.priv
wg pubkey < node_srv.priv > node_srv.pub
wg genkey > node_cli.priv
wg pubkey < node_cli.priv > node_cli.pub
  1. Enabling Kernel Packet Forwarding

To route traffic between the VPN interface and the external network, IPv4 forwarding must be activated at the kernel level. Creating a dedicated sysctl drop-in file ensures the setting persists across reboots.

echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/99-wg-forward.conf
sudo sysctl --system
  1. Server-Side Configuration

Create the primary interface definition at /etc/wireguard/wg0.conf. The configuration below establishes the tunnel interface, assigns an internal subnet, configures NAT masquerading for outbound traffic, and defines the peer relationship. Replace the placeholder commands with the actual key contents generated earlier.

cat <<EOF > /etc/wireguard/wg0.conf
[Interface]
PrivateKey = $(cat /etc/wireguard/node_srv.priv)
Address = 10.50.10.1/24
ListenPort = 49210
DNS = 9.9.9.9
MTU = 1420
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
PublicKey = $(cat /etc/wireguard/node_cli.pub)
AllowedIPs = 10.50.10.2/32
EOF

Key Parameters: The PostUp/PostDown directives dynamically manage firewall rules using %i to reference the active interface. AllowedIPs restricts routing to the specific client adress.

  1. Client-Side Configuration

On the remote machine, generate a configuration file (e.g., /etc/wireguard/client.conf). This file points to the server's public endpoint and routes all IPv4/IPv6 traffic through the encrypted tunnel.

cat <<EOF > /etc/wireguard/client.conf
[Interface]
PrivateKey = $(cat /etc/wireguard/node_cli.priv)
Address = 10.50.10.2/32
DNS = 9.9.9.9
MTU = 1420

[Peer]
PublicKey = $(cat /etc/wireguard/node_srv.pub)
Endpoint = 203.0.113.15:49210
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
EOF

Key Parameters: PersistentKeepalive prevents NAT timeouts on restrictive networks. The Endpoint must match the server's public IP and listening port.

  1. Service Lifecycle Management

Initialize the tunnel and bind it to the system's service manager for automatic startup. The wg-quick wrapper handles interface creation, routing table updates, and DNS configuration automatically.

# Bring up the tunnel and enable persistence
sudo wg-quick up wg0
sudo systemctl enable --now wg-quick@wg0

# Tear down the tunnel and disable auto-start
sudo wg-quick down wg0
sudo systemctl disable --now wg-quick@wg0
  1. Connection Verification

Query the active tunnel state to verify handshake timestamps, data transfer statistics, and peer connectivity.

sudo wg show
  1. Implementing Policy-Based Routing

For scenarios requiring split tunneling or source-specific routing, inject custom routing rules directly into the interface lifecycle hooks. The example below forces traffic originating from a specific local IP to bypass the VPN and use the default routing table.

[Interface]
PrivateKey = <client_private_key>
Address = 10.50.10.2/32
DNS = 1.1.1.1
PostUp = ip rule add from 192.168.5.20 lookup main
PreDown = ip rule del from 192.168.5.20 lookup main

[Peer]
PublicKey = <server_public_key>
Endpoint = 203.0.113.15:49210
AllowedIPs = 0.0.0.0/0, ::/0

Tags: wireguard vpn linux-networking iptables sysctl

Posted on Wed, 13 May 2026 19:35:37 +0000 by iamali