Skip to main content
โšก Calmops

WireGuard VPN: Complete Setup Guideor Server and Clients

uction

e walks through a complete server + client setup.

Prerequisites: Ubuntu 20.04+ server with a public IP, sudo access.

Server Setup

Step 1: Install WireGuard

# Ubuntu 20.04+
sudo apt update && sudo apt install wireguard

# Verify kernel module
lsmod | grep wireguard
# wireguard              94208  0

Step 2: Generate Server Keys

# Generate key pair
wg genkey | sudo tee /etc/wireguard/server_private.key | \
erver_public.key

# Set permissions
sudo chmod 600 /etc/wireguard/server_private.key

# View the keys
sudo cat /etc/wireguard/server_private.key
sudo cat /etc/wireguard/server_public.key

Step 3: Create Server Config

sudo nano /etc/wireguard/wg0.conf
[Interface]
# Server's VPN IP address
Address = 10.0.0.1/24

# Port WireGuard listens on
ListenPort = 51820

# Server's private key
PrivateKey = <paste server_private.key here>

# Enable IP forwarding and NAT for client internet access
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT
PostUp = iptables -A FORWARD -o wg0 -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT
PostDown = iptables -D FORWARD -o wg0 -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

# Client 1 (add more [Peer] sections for each client)
[Peer]
# Client's public key
PublicKey = <client1_public_key>
# IP address assigned to this client
AllowedIPs = 10.0.0.2/32

# Client 2
[Peer]
PublicKey = <client2_public_key>
AllowedIPs = 10.0.0.3/32

Step 4: Enable IP Forwarding

# Enable now
sudo sysctl -w net.ipv4.ip_forward=1

# Make permanent
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Step 5: Start WireGuard

enable on boot
sudo systemctl enable --now wg-quick@wg0

# Check status
do systemctl status wg-quick@wg0
sudo wg show wg0

Expected output:

interface: wg0
  public key: <server_public_key>
  private key: (hidden)
  listening port: 51820

peer: <client1_public_key>
  allowed ips: 10.0.0.2/32

Step 6: Open Firewall

# UFW
sudo ufw allow 51820/udp
sudo ufw allow OpenSSH  # don't lock yourself out!

# iptables directly
sudo iptables -A INPUT -p udp --dport 51820 -j ACCEPT

Client Setup

Linux Client

# Install
sudo apt install wireguard

# Generate client keys
wg genkey | tee client_private.key | wg pubkey > client_public.key

# Create config
sudo nano /etc/wireguard/wg0.conf
[Interface]
# Client's VPN IP
Address = 10.0.0.2/24
# Client's private key
PrivateKey = <client_private_key>
# Us DNS server
DNS = 1.1.1.1

[Peer]
# Server's public key
PublicKey = <server_public_key>
# Server's address and port
Endpoint = YOUR_SERVER_IP:51820
# Route all traffic through VPN (full tunnel)
AllowedIPs = 0.0.0.0/0, ::/0
/algo)
ard automation](https://github.com/trailofbitss://github.com/wg-easy/wg-easy)
- [Algo VPN โ€” WireGuges/man8/wg.8.html)
- [wg-easy โ€” Web UI for WireGuard](http Page](https://man7.org/linux/man-pa/quickstart/)
- [WireGuard Mancode -t ansiutf8 < "${CLIENT_NAME}.conf"

Resources

  • [WireGuard Quick Start](https://www.wireguard.com"Client config saved to ${CLIENT_NAME}.conf" echo "Public key: $CLIENT_PUBLIC"

Generate QR code for mobile

qrenPOINT AllowedIPs = 0.0.0.0/0 PersistentKeepalive = 25 EOF

echo _KEY Endpoint = $SERVER_ENDNS = 1.1.1.1

[Peer] PublicKey = $SERVER_PUBLIC"${CLIENT_NAME}.conf" « EOF [Interface] Address = ${CLIENT_IP}/24 PrivateKey = $CLIENT_PRIVATE D [Peer] PublicKey = $CLIENT_PUBLIC AllowedIPs = ${CLIENT_IP}/32 EOF

Generate client config

cat > et wg0 peer “$CLIENT_PUBLIC" allowed-ips "${CLIENT_IP}/32”

Append to server config

sudo tee -a /etc/wireguard/wg0.conf « EOF

$CLIENT_NAME=$(wg genkey)

CLIENT_PUBLIC=$(echo "$CLIENT_PRIVATE" | wg pubkey)

Add to server

sudo wg svpn.example.com:51820" CLIENT_NAME=$1 CLIENT_IP=$2 # e.g., 10.0.0.5

Generate keys

CLIENT_PRIVATEent.sh โ€” generate config for a new client

SERVER_PUBLIC_KEY=$(sudo cat /etc/wireguard/server_public.key) SERVER_ENDPOINT="

Automating Client Config Generation

#!/bin/bash
# generate-clirewall, check AllowedIPs, check IP forwarding

terface: No such device" โ†’ module not loaded: sudo modprobe wireguard

No traffic flowing โ†’ check fissues:

“RTNETLINK answers: Operation not permitted” โ†’ need sudo

“Unable to access intl -u wg-quick@wg0 -f

Common i10.0.0.1 # ping server from client

traceroute 8.8.8.8 # verify traffic goes through VPN

Check logs

sudo journalcable main | grep wg0

Test connectivity

ping time stats watch -n 1 ‘sudo wg show’

Check routing table

ip route show teceived, 456 MiB sent

Watch real-wg0

Check if traffic is flowing

sudo wg show wg0 transfer

peer:

transfer: 1.23 GiB rhow specific interface

sudo wg show ```

Monitoring and Troubleshooting

# Show all peers and their status
sudo wg show

# Soint = office.example.com:51820
AllowedIPs = 10.0.0.1/32, 192.168.1.0/24  # office VPN IP + office subnet
PersistentKeepalive = 25

# Office server
PublicKey = <office_public_key>
Endp[Interface]
Address = 10.0.0.2/24
ListenPort = 51820
PrivateKey = <cloud_private_key>

[Peer]2.16.0.0/24  # cloud VPN IP + cloud subnet
PersistentKeepalive = 25
# Cloud server (172.16.0.0/24)
office_private_key>

[Peer]
# Cloud server
PublicKey = <cloud_public_key>
Endpoint = cloud.example.com:51820
AllowedIPs = 10.0.0.2/32, 17rver (192.168.1.0/24)
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <
## Site-to-Site Configuration

Connect two networks (e.g., office + cloud):

```ini
# Office seS only for internal domains
DNS = 10.0.0.1
# Some clients support: DNS = 10.0.0.1, 1.1.1.1

ent config โ€” use VPN DNdomain=vpn.internal


### Split DNS (different DNS for VPN vs internet)

```ini
# Cli on the VPN
# On server: install and configure dnsmasq
sudo apt install dnsmasq

# /etc/dnsmasq.conf
listen-address=10.0.0.1
bind-interfaces
ace]
DNS = 10.0.0.1  # point to your DNS server

```ini
# Client config
[Interfwg set wg0 peer <client_public_key> remove

# Also remove from config file

DNS Configuration

Use Pi-hole or Custom DNS10/32


### Remove a Peer

```bash
# Remove from running server
sudo guard/wg0.conf
# Add:
# [Peer]
# PublicKey = <new_client_public_key>
# AllowedIPs = 10.0.0.w_client_public.key) allowed-ips 10.0.0.10/32

# Also add to config file for persistence
sudo nano /etc/wireey

# Add peer to running server (no restart needed)
sudo wg set wg0 peer $(cat nePN.

## Adding and Removing Peers

### Add a New Client (Without Restarting)

```bash
# Generate keys for new client
wg genkey | tee new_client_private.key | wg pubkey > new_client_public.kormance โ€” only corporate traffic goes through Vom/blog/2021/03/wireguard-allowedips-calculator/

Split tunneling is better for perfhing EXCEPT specific IPs

Use a split tunnel calculator: https://www.procustodibus.cy route corporate network through VPN

AllowedIPs = 10.0.0.0/8, 192.168.1.0/24

Route everytthrough VPN)

# In [Peer] section:
AllowedIPs = 0.0.0.0/0, ::/0

All internet traffic goes through the VPN server. Use for: public WiFi protection, bypassing geo-restrictions.

Split Tunnel (only route specific networks)

# Onlsiutf8 < /etc/wireguard/client.conf

Split Tunneling vs Full Tunnel

Full Tunnel (route all traffic “+” โ†’ “Create from QR code” or “Create from file”

  1. Generate QR code from config:
# Generate QR code for mobile import
sudo apt install qrencode
qrencode -t anGuard"

iOS / Android

  1. Install WireGuard from App Store / Play Store
  2. Tapient
# Homebrew
brew install wireguard-tools

# Or download the App Store app: "Wiree client config (same format as Linux)
4. Click "Activate"

### macOS Clwww.wireguard.com/install/)
2. Click "Add Tunnel" โ†’ "Add empty tunnel"
3. Paste thnnect on boot
sudo systemctl enable wg-quick@wg0

Windows Client

  1. Download from [wireguard.com/install](https://.me # should show server’s IP

Disconnect

sudo wg-quick down wg0

Auto-co

PersistentKeepalive = 25


```bash
# Connect
sudo wg-quick up wg0

# Verify connection
ping 10.0.0.1  # ping server
curl ifconfig# Keep NAT mapping alive

Comments