Skip to main content

WireGuard Overlay Network

This document covers the WireGuard overlay network that connects all edgeProxy POPs and backends globally.

Why WireGuard?

WireGuard provides a secure, high-performance overlay network that allows edgeProxy POPs to route traffic to backends regardless of their physical location or network topology.


Network Architecture

Overview

WireGuard Full Mesh Network

IP Allocation Scheme

SubnetRegionDescription
10.50.0.0/24CentralEC2 Ireland (Hub)
10.50.1.0/24South AmericaGRU (Sao Paulo)
10.50.2.0/24North AmericaIAD, ORD, LAX
10.50.3.0/24EuropeLHR, FRA, CDG
10.50.4.0/24Asia PacificNRT, SIN, SYD
10.50.5.0/24Asia PacificHKG POP (GCP)

Backend IP Assignments

BackendCodeWireGuard IPLocation
EC2 Ireland-10.50.0.1eu-west-1
Sao PauloGRU10.50.1.1gru
VirginiaIAD10.50.2.1iad
ChicagoORD10.50.2.2ord
Los AngelesLAX10.50.2.3lax
LondonLHR10.50.3.1lhr
FrankfurtFRA10.50.3.2fra
ParisCDG10.50.3.3cdg
TokyoNRT10.50.4.1nrt
SingaporeSIN10.50.4.2sin
SydneySYD10.50.4.3syd
Hong KongHKG10.50.5.1asia-east2

Topologies

Hub-and-Spoke (Legacy)

In the initial setup, all traffic routed through a central hub (EC2 Ireland):

Hub-and-Spoke Topology

Problems:

  • High latency for geographically distant backends
  • Single point of failure
  • All traffic crosses Ireland regardless of destination

Example latencies (from HKG POP):

BackendLatency via Hub
NRT (Tokyo)492ms
SIN (Singapore)408ms
SYD (Sydney)~500ms

Full Mesh (Current)

POPs connect directly to their regional backends:

HKG Full Mesh

Benefits:

  • ~10x lower latency for regional traffic
  • No single point of failure for regional routing
  • Traffic stays within geographic region

Example latencies (from HKG POP with full mesh):

BackendHub LatencyMesh LatencyImprovement
NRT (Tokyo)492ms49ms10x
SIN (Singapore)408ms38ms10.7x
SYD (Sydney)~500ms122ms~4x

Configuration

Key Generation

Generate a keypair for each node:

# Generate private key
wg genkey > private.key

# Derive public key
cat private.key | wg pubkey > public.key

# Generate all backend keys at once
for region in gru iad ord lax lhr fra cdg nrt sin syd hkg; do
wg genkey > wireguard/${region}-private.key
cat wireguard/${region}-private.key | wg pubkey > wireguard/${region}-public.key
echo "${region}: $(cat wireguard/${region}-public.key)"
done

EC2 Hub Configuration

The EC2 Ireland instance acts as the central hub for non-regional traffic:

# /etc/wireguard/wg0.conf on EC2 Ireland
[Interface]
PrivateKey = <ec2-private-key>
Address = 10.50.0.1/24
ListenPort = 51820

# Enable IP forwarding for routing
PostUp = sysctl -w net.ipv4.ip_forward=1
PostUp = iptables -A FORWARD -i wg0 -o wg0 -j ACCEPT
PostDown = iptables -D FORWARD -i wg0 -o wg0 -j ACCEPT

# GRU - Sao Paulo
[Peer]
PublicKey = He2jX3+iEl7hUaaJG/i3YcSnStEFAcW/rs/lP0Pw+nc=
AllowedIPs = 10.50.1.1/32
PersistentKeepalive = 25

# IAD - Virginia
[Peer]
PublicKey = rImgzxPu9MuhqLpcvXQ9xckSSA+AGbDOpBGvTUOwaHQ=
AllowedIPs = 10.50.2.1/32
PersistentKeepalive = 25

# ORD - Chicago
[Peer]
PublicKey = SIh+oa2J6k4rYA+N1SzskwztVVR/1Hx3ef/yLyyh+VU=
AllowedIPs = 10.50.2.2/32
PersistentKeepalive = 25

# LAX - Los Angeles
[Peer]
PublicKey = z7JmcJguquFBQiphSSmYBsttr6BoRs8MkCev9o5JkAU=
AllowedIPs = 10.50.2.3/32
PersistentKeepalive = 25

# LHR - London
[Peer]
PublicKey = w+XApd9CmhlyweQr8Fp7YPMbjd6RAk/cmXA6OET9/H0=
AllowedIPs = 10.50.3.1/32
PersistentKeepalive = 25

# FRA - Frankfurt
[Peer]
PublicKey = g5IzaRpt1hkvFhGTfy5LC0HLwPxVTC5dQb3if5sds24=
AllowedIPs = 10.50.3.2/32
PersistentKeepalive = 25

# CDG - Paris
[Peer]
PublicKey = C1My7suqoLuYchPIaVLbsB5A/dX21h7wICqa7yL2oX4=
AllowedIPs = 10.50.3.3/32
PersistentKeepalive = 25

# NRT - Tokyo
[Peer]
PublicKey = 9ZK9FzSzihxrRX9gktc99Oj0WFSJMa0mf33pP2LJ/lU=
AllowedIPs = 10.50.4.1/32
PersistentKeepalive = 25

# SIN - Singapore
[Peer]
PublicKey = gcwoqaT950PGW1ZaUEV75VEV7HOdyYT5rwdYOUBQzR0=
AllowedIPs = 10.50.4.2/32
PersistentKeepalive = 25

# SYD - Sydney
[Peer]
PublicKey = 9yHQmzbLKEyM+F1x7obbX0WNaR25XhAcUOdU9SLBeEo=
AllowedIPs = 10.50.4.3/32
PersistentKeepalive = 25

# HKG POP - Hong Kong
[Peer]
PublicKey = GxuSsvO9/raKe5WctZQfX5tkHOrTf0PLJWmHEzrw1Go=
AllowedIPs = 10.50.5.0/24
PersistentKeepalive = 25

GCP HKG POP Configuration (Full Mesh)

The HKG POP uses full mesh for APAC backends:

# /etc/wireguard/wg0.conf on GCP HKG
[Interface]
PrivateKey = <hkg-private-key>
Address = 10.50.5.1/24
ListenPort = 51820

# Enable IP forwarding
PostUp = sysctl -w net.ipv4.ip_forward=1
PostUp = iptables -A FORWARD -i wg0 -o wg0 -j ACCEPT
PostDown = iptables -D FORWARD -i wg0 -o wg0 -j ACCEPT

# EC2 Ireland (for non-APAC backends: SA, NA, EU)
[Peer]
PublicKey = bzM6rw/efq+75VGhBgkCRChDnKfFlXQY560ejhvKCQY=
Endpoint = 54.171.48.207:51820
AllowedIPs = 10.50.0.1/32, 10.50.1.0/24, 10.50.2.0/24, 10.50.3.0/24
PersistentKeepalive = 25

# NRT - Tokyo (DIRECT MESH)
[Peer]
PublicKey = 9ZK9FzSzihxrRX9gktc99Oj0WFSJMa0mf33pP2LJ/lU=
AllowedIPs = 10.50.4.1/32
PersistentKeepalive = 25

# SIN - Singapore (DIRECT MESH)
[Peer]
PublicKey = gcwoqaT950PGW1ZaUEV75VEV7HOdyYT5rwdYOUBQzR0=
AllowedIPs = 10.50.4.2/32
PersistentKeepalive = 25

# SYD - Sydney (DIRECT MESH)
[Peer]
PublicKey = 9yHQmzbLKEyM+F1x7obbX0WNaR25XhAcUOdU9SLBeEo=
AllowedIPs = 10.50.4.3/32
PersistentKeepalive = 25

Backend Configuration (APAC)

APAC backends connect to both EC2 hub and HKG POP:

#!/bin/bash
# entrypoint.sh for APAC backends

# EC2 endpoint (hub)
EC2_ENDPOINT="54.171.48.207:51820"
EC2_PUBKEY="bzM6rw/efq+75VGhBgkCRChDnKfFlXQY560ejhvKCQY="

# HKG endpoint (direct mesh)
HKG_ENDPOINT="35.241.112.61:51820"
HKG_PUBKEY="GxuSsvO9/raKe5WctZQfX5tkHOrTf0PLJWmHEzrw1Go="

# Base config with EC2 hub
cat > /etc/wireguard/wg0.conf << WGEOF
[Interface]
PrivateKey = ${WG_PRIVATE}
Address = ${WG_IP}

[Peer]
# EC2 Ireland (hub for non-APAC traffic)
PublicKey = ${EC2_PUBKEY}
Endpoint = ${EC2_ENDPOINT}
AllowedIPs = 10.50.0.0/24, 10.50.1.0/24, 10.50.2.0/24, 10.50.3.0/24
PersistentKeepalive = 25
WGEOF

# Add HKG direct peer for APAC regions
case "${REGION}" in
nrt|sin|syd)
cat >> /etc/wireguard/wg0.conf << WGEOF

[Peer]
# GCP HKG (direct mesh for APAC)
PublicKey = ${HKG_PUBKEY}
Endpoint = ${HKG_ENDPOINT}
AllowedIPs = 10.50.5.0/24
PersistentKeepalive = 25
WGEOF
;;
esac

wg-quick up wg0

User Data Script

Use this unified script to provision POPs on any cloud (AWS, GCP, Azure):

#!/bin/bash
# =============================================================================
# edgeProxy POP - User Data / Cloud Init Script
# =============================================================================
# Works on: AWS EC2, GCP Compute Engine, Azure VM, any Ubuntu 22.04+
#
# Required variables:
# POP_REGION - Region code (eu, ap, us, sa)
# WG_PRIVATE_KEY - WireGuard private key for this POP
# WG_ADDRESS - WireGuard IP address (e.g., 10.50.5.1/24)
# =============================================================================

set -e
exec > >(tee /var/log/userdata.log) 2>&1
echo "=== edgeProxy POP Setup Started: $(date) ==="

# Configuration
POP_REGION="${POP_REGION:-ap}"
WG_PRIVATE_KEY="${WG_PRIVATE_KEY}"
WG_ADDRESS="${WG_ADDRESS:-10.50.5.1/24}"
WG_LISTEN_PORT="${WG_LISTEN_PORT:-51820}"

# All backend peers (full mesh)
declare -a WG_PEERS=(
# EC2 Ireland (central hub)
"bzM6rw/efq+75VGhBgkCRChDnKfFlXQY560ejhvKCQY=|54.171.48.207:51820|10.50.0.1/32|ec2-ireland"

# South America
"He2jX3+iEl7hUaaJG/i3YcSnStEFAcW/rs/lP0Pw+nc=||10.50.1.1/32|gru"

# North America
"rImgzxPu9MuhqLpcvXQ9xckSSA+AGbDOpBGvTUOwaHQ=||10.50.2.1/32|iad"
"SIh+oa2J6k4rYA+N1SzskwztVVR/1Hx3ef/yLyyh+VU=||10.50.2.2/32|ord"
"z7JmcJguquFBQiphSSmYBsttr6BoRs8MkCev9o5JkAU=||10.50.2.3/32|lax"

# Europe
"w+XApd9CmhlyweQr8Fp7YPMbjd6RAk/cmXA6OET9/H0=||10.50.3.1/32|lhr"
"g5IzaRpt1hkvFhGTfy5LC0HLwPxVTC5dQb3if5sds24=||10.50.3.2/32|fra"
"C1My7suqoLuYchPIaVLbsB5A/dX21h7wICqa7yL2oX4=||10.50.3.3/32|cdg"

# Asia Pacific
"9ZK9FzSzihxrRX9gktc99Oj0WFSJMa0mf33pP2LJ/lU=||10.50.4.1/32|nrt"
"gcwoqaT950PGW1ZaUEV75VEV7HOdyYT5rwdYOUBQzR0=||10.50.4.2/32|sin"
"9yHQmzbLKEyM+F1x7obbX0WNaR25XhAcUOdU9SLBeEo=||10.50.4.3/32|syd"
)

# Install packages
apt-get update
apt-get install -y wireguard curl jq

# Create WireGuard config
mkdir -p /etc/wireguard

cat > /etc/wireguard/wg0.conf << EOF
[Interface]
PrivateKey = ${WG_PRIVATE_KEY}
Address = ${WG_ADDRESS}
ListenPort = ${WG_LISTEN_PORT}

PostUp = sysctl -w net.ipv4.ip_forward=1
PostUp = iptables -A FORWARD -i wg0 -o wg0 -j ACCEPT
PostDown = iptables -D FORWARD -i wg0 -o wg0 -j ACCEPT
EOF

# Add all peers
for peer in "${WG_PEERS[@]}"; do
IFS='|' read -r pubkey endpoint allowed_ips name <<< "$peer"

cat >> /etc/wireguard/wg0.conf << EOF

# ${name}
[Peer]
PublicKey = ${pubkey}
AllowedIPs = ${allowed_ips}
PersistentKeepalive = 25
EOF

if [ -n "$endpoint" ]; then
sed -i "/PublicKey = ${pubkey}/a Endpoint = ${endpoint}" /etc/wireguard/wg0.conf
fi
done

chmod 600 /etc/wireguard/wg0.conf

# Start WireGuard
wg-quick up wg0
systemctl enable wg-quick@wg0

echo "=== WireGuard Status ==="
wg show

Operations

Starting WireGuard

# Start interface
sudo wg-quick up wg0

# Enable on boot
sudo systemctl enable wg-quick@wg0

# Check status
sudo wg show

Checking Connectivity

# Show all peers and their status
sudo wg show

# Ping specific backend
ping 10.50.4.1 # NRT
ping 10.50.4.2 # SIN
ping 10.50.4.3 # SYD

# Check handshake times
sudo wg show wg0 latest-handshakes

Adding a New Peer

# Generate keys for new peer
wg genkey > new-peer-private.key
cat new-peer-private.key | wg pubkey > new-peer-public.key

# Add peer dynamically (no restart needed)
sudo wg set wg0 peer $(cat new-peer-public.key) allowed-ips 10.50.6.1/32

# Save to config file
sudo wg-quick save wg0

Removing a Peer

# Remove peer dynamically
sudo wg set wg0 peer <public-key> remove

# Or edit config and restart
sudo vim /etc/wireguard/wg0.conf
sudo wg-quick down wg0 && sudo wg-quick up wg0

Troubleshooting

Peer Not Connecting

# Check interface exists
ip addr show wg0

# Check peer is configured
sudo wg show wg0 peers

# Check firewall
sudo iptables -L -n | grep 51820

# Check UDP port is open
nc -zvu <peer-ip> 51820

High Latency

# Measure latency to each peer
for ip in 10.50.4.1 10.50.4.2 10.50.4.3; do
echo "Ping to $ip:"
ping -c 3 $ip | tail -1
done

# If latency is high, check if traffic is going through hub
# Add direct peer endpoints for regional traffic

Handshake Not Happening

# Check last handshake time
sudo wg show wg0 latest-handshakes

# If handshake is old (>2 minutes), peer may be unreachable
# Try forcing a new handshake
ping -c 1 <peer-wg-ip>

Traffic Not Routing

# Check routing table
ip route | grep wg0

# Verify AllowedIPs includes destination
sudo wg show wg0 allowed-ips

# Check IP forwarding is enabled
sysctl net.ipv4.ip_forward

Security Best Practices

Key Management

  1. Never share private keys - Each node must have unique keys
  2. Rotate keys periodically - Regenerate keys every 6-12 months
  3. Store keys securely - Use secrets management (AWS Secrets Manager, Vault)

Firewall Rules

# Only allow WireGuard UDP
ufw allow 51820/udp

# Restrict SSH to known IPs
ufw allow from 1.2.3.4 to any port 22

Network Segmentation

  • Use separate subnets for each region
  • Limit AllowedIPs to minimum required
  • Don't use 0.0.0.0/0 unless absolutely necessary

Performance Optimization

MTU Tuning

[Interface]
MTU = 1420 # Optimal for most scenarios

Persistent Keepalive

[Peer]
PersistentKeepalive = 25 # Keep NAT mappings alive

Endpoint Selection

  • Use static endpoints for servers with public IPs
  • Omit endpoints for clients behind NAT (they'll connect to us)
  • Use DNS names for dynamic IPs