WireGuard Site-to-Site VPN: wg0.conf Configuration Example - 夜莺博客

WireGuard Site-to-Site VPN: wg0.conf Configuration Example

WireGuard has become the default answer for site-to-site VPNs between Linux gateways because a complete tunnel configuration fits in a few lines and the crypto is modern (Curve25519, ChaCha20-Poly1305). This tutorial walks through a real site-to-site WireGuard VPN between two networks, covering key generation, the wg0.conf format, AllowedIPs routing semantics, and the operational details (MTU, keepalives, NAT) that decide whether the tunnel actually survives in production.

How Site-to-Site WireGuard Works

Each site has a gateway with a public IP. The gateways form a UDP tunnel (default port 51820), and each LAN routes to the other LAN's subnet through the tunnel interface. Unlike IPsec, there are no phases, no SA lifetimes and no policy databases - every peer simply lists which IP ranges it is allowed to claim (AllowedIPs), which doubles as the routing table entry for the tunnel.

Step 1: Generate Keys on Each Gateway

Keys are generated on the gateway itself and the private key never leaves that machine:

sudo apt install wireguard
wg genkey | sudo tee /etc/wireguard/wgA.key
sudo cat /etc/wireguard/wgA.key | wg pubkey | sudo tee /etc/wireguard/wgA.pub
sudo chmod 600 /etc/wireguard/wgA.key

Only the .pub file is exchanged with the remote site. If a private key is ever copied across the network or appears in shell history, treat it as compromised and regenerate.

Step 2: Write wg0.conf on Both Gateways

Site A (10.10.10.0/24) and Site B (10.10.11.0/24) share the /31 tunnel network 10.10.9.0/31. On gateway A:

[Interface]
Address = 10.10.9.0/31
ListenPort = 51000
PostUp = wg set %i private-key /etc/wireguard/%i.key
MTU = 1420

[Peer]          # beta site
PublicKey = <contents of /etc/wireguard/wgB.pub>
AllowedIPs = 10.10.11.0/24, 10.10.9.0/31
Endpoint = <beta-gw-public-ip>:51000
PersistentKeepalive = 25

On gateway B the roles are reversed (Address = 10.10.9.1/31, peer AllowedIPs = 10.10.10.0/24, 10.10.9.0/31, Endpoint = alpha's public IP). Two details matter for site-to-site links:

  • MTU 1420: WireGuard adds roughly 60 bytes of overhead (IPv4 + UDP + WireGuard headers). On a 1500-byte path, 1420 keeps large packets from fragmenting or being silently dropped. On PPPoE links (1492 outer MTU) use 1432.
  • PersistentKeepalive 25: sends a keepalive every 25 s so NAT/firewall mappings on the path stay open. Required when either endpoint is behind NAT; harmless otherwise.

Step 3: Enable Routing and Start the Tunnel

sudo sysctl -w net.ipv4.ip_forward=1        # persist in /etc/sysctl.conf
sudo systemctl enable --now wg-quick@wg0
sudo wg show                                 # handshake + transfer counters

If LAN clients must reach the remote LAN through the gateway, add forwarding plus NAT rules on each gateway (PostUp iptables lines are shown in the related example configurations). Verify with wg show (look for a recent latest handshake) and a ping from a LAN client to the far LAN gateway IP.

Verification and Troubleshooting

  • sudo wg show - peer endpoint, allowed IPs, latest handshake, RX/TX bytes. No recent handshake means the tunnel never established; check UDP 51820 reachability and firewall rules.
  • sudo wg show wg0 fwmark - the routing mark used by wg-quick.
  • AllowedIPs mismatch is the #1 routing bug: the remote LAN prefix must appear in the local peer's AllowedIPs list, otherwise wg-quick never installs the route and packets go out the default gateway.
  • If traffic passes but large transfers stall, re-check MTU on both ends (ping with DF bit and 1400/1420-byte payloads to find the ceiling).

WireGuard is not the only tunnel option for connecting sites - compare it with route-based IPsec on the Juniper SRX for firewall-centric designs or GRE tunnels on Cisco IOS when you need multicast or a simpler L3 overlay, and see our SSH tunneling guide for quick single-service tunnels that need zero new software.

原文链接:https://ubuntu.com/server/docs/how-to/wireguard-vpn/site-to-site/