RTFM · Networking
Site-to-site VPN routing
Connect branch, office, home, and datacentre prefixes while keeping each site a distinct routed network.

Routes, not just handshakes
Each site needs a VPN peer, a route to the other site's IPv4 prefixes, a route to its IPv6 /64s, forwarding enabled, and firewall rules in both directions. If one side can send but not reply, inspect the return route before changing encryption settings.
Branch office Head office
192.168.20.0/24 192.168.10.0/24
2001:db8:20::/64 ← VPN → 2001:db8:10::/64
Allowed: monitoring and application API
Denied: guest LAN and unrelated managementComplete routed WireGuard example
This example connects a branch users LAN to a head-office servers LAN. The VPN itself has a tiny transport prefix; the important routes are the LAN prefixes in AllowedIPs. Every network listed for a peer must be unique across the design. Use your own keys and public endpoint names.
# Branch gateway: /etc/wireguard/wg0.conf
[Interface]
Address = 10.250.0.2/30, fd42:250::2/64
ListenPort = 51820
PrivateKey = <branch-private-key>
[Peer]
PublicKey = <head-office-public-key>
Endpoint = vpn.head.example.test:51820
AllowedIPs = 10.250.0.1/32, 192.168.10.0/24, 192.168.11.0/24, 2a02:8012:bc57:10::/64, 2a02:8012:bc57:11::/64
PersistentKeepalive = 25
# Head-office gateway: /etc/wireguard/wg0.conf
[Interface]
Address = 10.250.0.1/30, fd42:250::1/64
ListenPort = 51820
PrivateKey = <head-office-private-key>
[Peer]
PublicKey = <branch-public-key>
Endpoint = vpn.branch.example.test:51820
AllowedIPs = 10.250.0.2/32, 192.168.20.0/24, 192.168.21.0/24, 2a02:8012:bc57:20::/64, 2a02:8012:bc57:21::/64
PersistentKeepalive = 25The gateway needs IP forwarding for both families. The LAN's default gateway must be the Saphira router, or its existing router must have static routes pointing the remote prefixes at Saphira. Otherwise a server may receive a packet through the VPN but send its reply somewhere else.
# Enable now; make the equivalent sysctl settings persistent under /etc/sysctl.d.
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv6.conf.all.forwarding=1
# Prove the kernel selects the tunnel for a remote site prefix.
ip route get 192.168.10.25
ip -6 route get 2a02:8012:bc57:10::25
wg show wg0NAT versus routed VPN
NAT can make a private VPN pool appear as one address, which may help a simple remote-access design. A routed site-to-site VPN preserves source networks and makes policy and logging clearer. Do not NAT merely because routing feels unfamiliar; document the reason when translation is necessary.
# Conceptual nftables forwarding policy: adapt interfaces and prefixes.
table inet filter {
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
iifname "wg0" oifname "servergw0" ip daddr 192.168.10.0/24 accept
iifname "servergw0" oifname "wg0" ip saddr 192.168.10.0/24 accept
iifname "wg0" oifname "servergw0" ip6 daddr 2a02:8012:bc57:10::/64 accept
iifname "servergw0" oifname "wg0" ip6 saddr 2a02:8012:bc57:10::/64 accept
}
}A site-to-site VPN normally does not need NAT. If a return route exists at both sites, preserving source addresses makes logs, ACLs, and troubleshooting far clearer. Use NAT only for a documented interoperability reason.
DNS across sites
Decide whether each site keeps its own DNS or whether selected queries cross the VPN. Advertise or configure the correct DNS servers to VPN clients. A name resolving to a private address is useful only when the client also has a route and firewall permission to reach it.
# Verify both route families
ip route get 192.168.10.25
ip -6 route get 2001:db8:10::25
ping 192.168.10.25
ping6 2001:db8:10::25
ss -ntpOverlapping networks and MTU
Two sites using the same private range cannot be cleanly routed without renumbering, translation, or a carefully isolated proxy. Prefer renumbering before growth makes it expensive. If only small packets work through the VPN, investigate MTU/MSS and Path MTU discovery with tracepath and tcpdump.