Why WireGuard for a Site-to-Site VPN?
WireGuard has become one of the most practical VPN choices for modern Linux environments because it is fast, secure, and easy to troubleshoot. Unlike many older VPN stacks, WireGuard uses a small codebase and straightforward configuration files. In this tutorial, you will set up a site-to-site WireGuard VPN between two Linux servers (or gateways) so that two private networks can reach each other reliably, even after reboots.
Example scenario (adjust to your environment): Site A has LAN 10.10.0.0/24 and a Linux gateway with public IP A_PUBLIC. Site B has LAN 10.20.0.0/24 and a Linux gateway with public IP B_PUBLIC. WireGuard tunnel network will be 10.99.0.0/24, using 10.99.0.1 on Site A and 10.99.0.2 on Site B.
Prerequisites
You need root (or sudo) access on both gateways, outbound UDP allowed, and ideally a static public IP or stable DNS name for each side. This guide assumes Ubuntu/Debian, but the same concepts apply to other distributions. You should also confirm that each gateway can route traffic for its LAN (common when the gateway is also the LAN router, or when static routes exist on the LAN router pointing to the gateway).
Step 1: Install WireGuard
On both servers, install WireGuard tools:
Command:
sudo apt update && sudo apt install -y wireguard
Step 2: Generate Key Pairs
WireGuard uses public/private key pairs. Generate them on each gateway and store them with correct permissions:
On Site A:
umask 077
wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey
On Site B:
umask 077
wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey
Display each public key (you will paste it into the opposite side’s config):
Command:
cat /etc/wireguard/publickey
Step 3: Create the WireGuard Interface Config
WireGuard configurations live in /etc/wireguard/. Create wg0.conf on each site. Replace placeholders like A_PRIVATE_KEY, B_PUBLIC_KEY, and public IPs/DNS names.
Site A: /etc/wireguard/wg0.conf
[Interface]
Address = 10.99.0.1/24
ListenPort = 51820
PrivateKey = A_PRIVATE_KEY
[Peer]
PublicKey = B_PUBLIC_KEY
Endpoint = B_PUBLIC:51820
AllowedIPs = 10.99.0.2/32, 10.20.0.0/24
PersistentKeepalive = 25
Site B: /etc/wireguard/wg0.conf
[Interface]
Address = 10.99.0.2/24
ListenPort = 51820
PrivateKey = B_PRIVATE_KEY
[Peer]
PublicKey = A_PUBLIC_KEY
Endpoint = A_PUBLIC:51820
AllowedIPs = 10.99.0.1/32, 10.10.0.0/24
PersistentKeepalive = 25
The key detail for site-to-site routing is AllowedIPs. It tells WireGuard what networks to send through the tunnel. Here, each side includes the other site’s LAN (10.10.0.0/24 or 10.20.0.0/24) so packets are routed correctly.
Step 4: Enable IP Forwarding
If your gateways must pass traffic between LAN and VPN, Linux needs forwarding enabled. On both sites, run:
Command:
sudo sysctl -w net.ipv4.ip_forward=1
To make it persistent across reboots, edit /etc/sysctl.conf (or create a file under /etc/sysctl.d/) and ensure this line exists:
net.ipv4.ip_forward=1
Step 5: Adjust Firewall to Allow WireGuard UDP
WireGuard typically listens on UDP 51820. Allow it on both gateways. If you use UFW:
Command:
sudo ufw allow 51820/udp
If you rely on nftables/iptables, allow inbound UDP 51820 and ensure forwarding is permitted between your LAN interface and wg0. Firewall rules vary by environment, but the goal is consistent: UDP port open and forwarding allowed.
Step 6: Bring Up the Tunnel and Enable Autostart
Start the interface on both sides:
Command:
sudo wg-quick up wg0
Enable it at boot:
Command:
sudo systemctl enable wg-quick@wg0
Step 7: Test Connectivity and Routing
First, verify WireGuard handshake status:
Command:
sudo wg
You should see a recent “latest handshake” timestamp after traffic flows. Next, test the tunnel IPs:
From Site A:
ping -c 4 10.99.0.2
From Site B:
ping -c 4 10.99.0.1
Then test LAN-to-LAN reachability. For example, from a host on Site A LAN, ping a host on Site B LAN (or test from the gateway if it can reach the LAN):
Example:
ping -c 4 10.20.0.50
Common Problems (and Quick Fixes)
No handshake: confirm UDP 51820 is reachable from the internet, double-check Endpoint address/port, and ensure the correct public keys are pasted. A mismatched key is the fastest way to waste an hour.
Handshake works but LAN traffic fails: this is usually routing or firewall forwarding. Confirm IP forwarding is enabled and that your firewall allows forwarding between LAN and wg0. Also verify that each peer’s AllowedIPs includes the remote LAN subnet.
Remote LAN devices don’t know the return route: if your WireGuard box is not the default router for the LAN, you may need a static route on the LAN router (e.g., route 10.20.0.0/24 via the Site A WireGuard gateway IP, and vice versa).
Final Notes for a Stable Production Setup
For long-term reliability, keep configs simple and document your addressing plan. Consider using DNS names for Endpoints if IPs change, but make sure DNS is stable. Once everything works, capture the working configuration and back up /etc/wireguard/ securely, since private keys are sensitive. With the tunnel online, you can extend this design to multiple sites or add policy-based firewall rules to limit traffic between subnets.
Comments
Post a Comment