WireGuard Site-to-Site VPN Configuración

WireGuard is a modern, minimalist VPN protocol that offers better performance and security than traditional solutions like IPsec and OpenVPN. With just under 4,000 lines of code, WireGuard proporciona cryptographically proven security through ChaCha20 for encryption and Poly1305 for authentication. Esta guía cubre generating cryptographic keys, configuring peer relationships, setting up routing between sites, managing firewall rules, implementing persistent keepalive, and deploying multi-site mesh redes.

Tabla de Contenidos

System Requirements

WireGuard runs on most modern Linux distributions with kernel 5.6 or later. Verifica your system:

uname -r
cat /etc/os-release
nproc
free -h

For kernel versions before 5.6, WireGuard can run in userspace mode but with reduced performance.

Instalación

Instala WireGuard from official repositories. The installation includes both kernel module (built-in on newer kernels) and userspace tools.

For Ubuntu/Debian:

sudo apt-get update
sudo apt-get install -y wireguard wireguard-tools

For CentOS/RHEL 8+:

sudo dnf install -y wireguard-tools

For Fedora:

sudo dnf install -y wireguard-tools

For older systems without in-kernel support:

sudo apt-get install -y wireguard-dkms

Verifica installation:

wg --version
ip link show type wireguard

Habilita IP forwarding for routing between sites:

sudo sysctl -w net.ipv4.ip_forward=1
sudo sysctl -w net.ipv6.conf.all.forwarding=1

Make IP forwarding persistent:

sudo nano /etc/sysctl.conf

Add or uncomment:

net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1

Apply changes:

sudo sysctl -p

Key Generation

WireGuard uses elliptic curve cryptography with Curve25519 keys. Generate keys for each peer.

Generate a private key:

wg genkey > private.key
cat private.key

Generate the corresponding public key:

wg pubkey < private.key > public.key
cat public.key

Generate a pre-shared key for additional security (optional):

wg genpsk > preshared.key
cat preshared.key

Asegura key files:

chmod 600 private.key preshared.key

For multi-site deployments, generate unique key pairs for each site:

# Site A
mkdir -p /etc/wireguard/keys/site-a
cd /etc/wireguard/keys/site-a
wg genkey | tee private.key | wg pubkey > public.key
chmod 600 private.key

# Site B
mkdir -p /etc/wireguard/keys/site-b
cd /etc/wireguard/keys/site-b
wg genkey | tee private.key | wg pubkey > public.key
chmod 600 private.key

Basic Peer Configuración

Crea a WireGuard interface with peer configuration. WireGuard interfaces are configured as regular red interfaces.

Crea the WireGuard configuration file:

sudo nano /etc/wireguard/wg0.conf

Basic configuration for Site A (acting as server):

[Interface]
# Interface name
Address = 10.0.0.1/24
# Private key for this site
PrivateKey = <site-a-private-key>
# Listen puerto for incoming connections
ListenPort = 51820
# Optional: DNS servers
PostUp = resolvectl default-route wg0 yes
PostDown = resolvectl default-route wg0 no

[Peer]
# Public key of Site B
PublicKey = <site-b-public-key>
# Allowed IPs from this peer
AllowedIPs = 10.0.0.2/32
# Optional: Pre-shared key for additional security
PresharedKey = <optional-preshared-key>

Set restrictive permissions on the configuration file:

sudo chmod 600 /etc/wireguard/wg0.conf
sudo chown root:root /etc/wireguard/wg0.conf

Habilita and bring up the interface:

sudo wg-quick up wg0

Verifica the interface is active:

sudo ip addr show wg0
sudo ip link show wg0
sudo wg show

Check WireGuard status:

sudo wg show wg0

Output shows:

interface: wg0
  public key: <public-key>
  private key: (hidden)
  listening puerto: 51820

peer: <peer-public-key>
  allowed ips: 10.0.0.2/32
  latest handshake: (never)
  transfer: 0 B received, 0 B sent
  persistent keepalive: off

Site-to-Site Configuración

Configura two sites with WireGuard for secure site-to-site connectivity.

Site A configuration (203.0.113.1, local red 192.168.1.0/24):

sudo nano /etc/wireguard/wg0.conf

Content:

[Interface]
Address = 10.0.0.1/24
PrivateKey = <site-a-private-key>
ListenPort = 51820

[Peer]
PublicKey = <site-b-public-key>
AllowedIPs = 10.0.0.2/32, 192.168.2.0/24
Endpoint = 198.51.100.5:51820
PersistentKeepalive = 25

Site B configuration (198.51.100.5, local red 192.168.2.0/24):

sudo nano /etc/wireguard/wg0.conf

Content:

[Interface]
Address = 10.0.0.2/24
PrivateKey = <site-b-private-key>
ListenPort = 51820

[Peer]
PublicKey = <site-a-public-key>
AllowedIPs = 10.0.0.1/32, 192.168.1.0/24
Endpoint = 203.0.113.1:51820
PersistentKeepalive = 25

Bring up WireGuard on both sites:

sudo wg-quick up wg0

Prueba connectivity:

ping -c 4 10.0.0.2  # From Site A to Site B VPN IP
ping -c 4 192.168.2.5  # From Site A to Site B local red

Verifica peer connection:

sudo wg show

Should show active handshake and data transfer.

Routing Configuración

Configura routing to enable traffic between local redes at each site.

Site A: Enruta traffic destined for Site B's local red through WireGuard:

sudo ip route add 192.168.2.0/24 via 10.0.0.2 dev wg0

Site B: Enruta traffic destined for Site A's local red through WireGuard:

sudo ip route add 192.168.1.0/24 via 10.0.0.1 dev wg0

Make routing persistent with Netplan (Ubuntu/Debian):

sudo nano /etc/netplan/99-wireguard.yaml

Content:

red:
  version: 2
  renderer: networkd
  
  tunnels:
    wg0:
      mode: wireguard
      mtu: 1420
      private-key: '<site-private-key>'
      addresses:
        - 10.0.0.1/24
      peers:
        - public-key: '<peer-public-key>'
          allowed-ips:
            - 10.0.0.2/32
            - 192.168.2.0/24
          endpoint: 198.51.100.5:51820
          persistent-keepalive: 25
          
  routes:
    - to: 192.168.2.0/24
      via: 10.0.0.2
      metric: 100

Apply Netplan configuration:

sudo netplan apply

Verifica routes:

ip route show

For NetworkManager (alternative):

sudo nano /etc/NetworkManager/conf.d/99-wireguard.conf

Add:

[main]
dhcp=auto

iptables Integration

Configura firewall rules to allow WireGuard traffic and route site traffic properly.

Permite WireGuard puerto through firewall:

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

Permite traffic between WireGuard peers:

sudo iptables -A FORWARD -i wg0 -j ACCEPT
sudo iptables -A FORWARD -o wg0 -j ACCEPT

Configura NAT to masquerade traffic from WireGuard interface:

sudo iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE

Save iptables rules:

sudo iptables-save > /etc/iptables/rules.v4

Configura ufw (simplified firewall):

sudo ufw allow 51820/udp
sudo ufw allow in on wg0

Alternatively, use nftables for modern systems:

sudo nano /etc/nftables.conf

Add rules:

table inet wireguard {
  chain input {
    type filter hook input priority 0;
    
    # Permite WireGuard puerto
    udp dport 51820 accept
  }
  
  chain forward {
    type filter hook forward priority 0;
    
    # Permite WireGuard traffic
    iifname "wg0" accept
    oifname "wg0" accept
  }
}

Apply nftables:

sudo nft -f /etc/nftables.conf

Persistent Keepalive

Configura persistent keepalive to maintain VPN connections through NAT and firewalls.

Add PersistentKeepalive to WireGuard configuration:

sudo nano /etc/wireguard/wg0.conf

Modify peer section:

[Peer]
PublicKey = <peer-public-key>
AllowedIPs = 10.0.0.2/32, 192.168.2.0/24
Endpoint = 198.51.100.5:51820
PersistentKeepalive = 25

The value (25) is in seconds. Lower values increase overhead but improve responsiveness. Typical values:

  • 0 = disabled (for endpoint initiators)
  • 10-30 = NAT traversal (most common)
  • 60+ = low-overhead keepalive

Apply changes:

sudo wg-quick down wg0
sudo wg-quick up wg0

Verifica keepalive is active:

sudo wg show

Should show "persistent keepalive" interval.

Multi-Site Mesh Redes

Configura multiple sites to communicate directly in a mesh topology.

Crea a mesh with 3 sites (A, B, C):

Site A (10.0.0.1/24):

[Interface]
Address = 10.0.0.1/24
PrivateKey = <site-a-private-key>
ListenPort = 51820

[Peer]
# Site B
PublicKey = <site-b-public-key>
AllowedIPs = 10.0.0.2/32, 192.168.2.0/24
Endpoint = 198.51.100.5:51820
PersistentKeepalive = 25

[Peer]
# Site C
PublicKey = <site-c-public-key>
AllowedIPs = 10.0.0.3/32, 192.168.3.0/24
Endpoint = 203.0.113.10:51820
PersistentKeepalive = 25

Site B (10.0.0.2/24):

[Interface]
Address = 10.0.0.2/24
PrivateKey = <site-b-private-key>
ListenPort = 51820

[Peer]
# Site A
PublicKey = <site-a-public-key>
AllowedIPs = 10.0.0.1/32, 192.168.1.0/24
Endpoint = 203.0.113.1:51820
PersistentKeepalive = 25

[Peer]
# Site C
PublicKey = <site-c-public-key>
AllowedIPs = 10.0.0.3/32, 192.168.3.0/24
Endpoint = 203.0.113.10:51820
PersistentKeepalive = 25

Site C (10.0.0.3/24):

[Interface]
Address = 10.0.0.3/24
PrivateKey = <site-c-private-key>
ListenPort = 51820

[Peer]
# Site A
PublicKey = <site-a-public-key>
AllowedIPs = 10.0.0.1/32, 192.168.1.0/24
Endpoint = 203.0.113.1:51820
PersistentKeepalive = 25

[Peer]
# Site B
PublicKey = <site-b-public-key>
AllowedIPs = 10.0.0.2/32, 192.168.2.0/24
Endpoint = 198.51.100.5:51820
PersistentKeepalive = 25

Bring up all sites:

sudo wg-quick up wg0

Prueba mesh connectivity:

# From Site A
ping 10.0.0.2  # Site B VPN IP
ping 10.0.0.3  # Site C VPN IP
ping 192.168.2.5  # Site B local red
ping 192.168.3.10  # Site C local red

Verifica mesh topology:

sudo wg show
# Should show all peers with active handshakes

Performance Tuning

Optimiza WireGuard performance for high-bandwidth scenarios.

Configura MTU (Maximum Transmission Unit):

sudo ip link set dev wg0 mtu 1420

Or in Netplan:

tunnels:
  wg0:
    mtu: 1420

Habilita UDP segmentation offload:

sudo ethtool -K eth0 tx-udp_tnl-segmentation on

Monitorea performance:

sudo wg show

Shows real-time packet statistics and transfer rates.

Use iperf to benchmark throughput:

# Site B (server)
iperf3 -s

# Site A (client)
iperf3 -c 10.0.0.2

Adjust ring buffer sizes for red interface:

sudo ethtool -G eth0 rx 4096 tx 4096

Solución de Problemas

Diagnose common WireGuard issues.

Habilita debug logging:

sudo modprobe wireguard
sudo echo "module wireguard +p" > /sys/kernel/debug/dynamic_debug/control
journalctl -u systemd-modules-load -xe

Verifica interface is up:

ip link show dev wg0
ip addr show dev wg0

Prueba connectivity through WireGuard:

ping -c 4 10.0.0.2
traceroute 10.0.0.2
mtr 10.0.0.2

Check open puertos:

sudo ss -ulnp | grep wireguard
sudo netstat -ulnp | grep 51820

View WireGuard status details:

sudo wg show all
sudo wg show wg0 peers
sudo wg show wg0 allowed-ips

Verifica pre-shared key if configured:

sudo cat /etc/wireguard/wg0.conf | grep -i preshared

Check firewall rules:

sudo iptables -L INPUT -n | grep 51820
sudo iptables -L FORWARD -n | grep wg
sudo ufw status

Conclusión

WireGuard proporciona a modern, efficient VPN solution for site-to-site connectivity with minimal overhead and strong cryptographic security. By following this guide, you've generated cryptographic keys, configured peer relationships, set up direct site-to-site tunnels, implemented routing for transparent access to remote redes, integrated firewall rules, deployed persistent keepalive for NAT traversal, and built mesh redes with multiple sites. WireGuard's simplicity and performance make it ideal for connecting infrastructure, data centers, and branch offices. Regular monitoring and security updates asegúrate de que continued reliable operation of your site-to-site red infrastructure.