Multi-Exit WireGuard VPN with Policy Routing
Multi-Exit WireGuard VPN with Policy Routing
This guide explains how to build a WireGuard setup where a central VPN server can route traffic through different exit gateways depending on which client profile connects.
The idea is simple:
- Clients connect to one WireGuard server
- The server decides where traffic exits
- Different clients can exit through different gateways
This allows profile-based switching without requiring complex routing logic on the client.
Architecture
The topology looks like this:
Client Device
↓
WireGuard Server (public IP)
↓ policy routing
Gateway Node (remote network)
↓ NAT
Local Internet
Example addressing used in this guide:
WireGuard network 10.44.0.0/24
Server 10.44.0.1
Gateway node 10.44.0.9
Special client 10.44.0.21
Step 1 - Install the WireGuard Server
On a Linux server with a public IP:
apt update
apt install wireguard
Enable packet forwarding:
sysctl -w net.ipv4.ip_forward=1
Persist the setting:
Create:
/etc/sysctl.d/99-wireguard.conf
Contents:
net.ipv4.ip_forward=1
Apply:
sysctl --system
Step 2 - Create the Server Configuration
Example server configuration:
/etc/wireguard/wg0.conf
[Interface]
Address = 10.44.0.1/24
ListenPort = 51820
PrivateKey = <server_private_key>
Enable the interface:
systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0
Step 3 - Add a Gateway Node
A remote machine connects to the server and acts as an exit gateway.
Add this peer on the server:
[Peer]
PublicKey = <gateway_public_key>
AllowedIPs = 10.44.0.9/32, 0.0.0.0/1, 128.0.0.0/1
The split prefixes allow the server to route internet traffic through the gateway without affecting the server’s own routes.
Step 4 - Configure the Gateway Node
On the gateway machine:
Install WireGuard:
apt install wireguard
Create:
/etc/wireguard/wg0.conf
[Interface]
Address = 10.44.0.9/24
PrivateKey = <gateway_private_key>
[Peer]
PublicKey = <server_public_key>
Endpoint = <server_ip>:51820
AllowedIPs = 10.44.0.0/24
PersistentKeepalive = 25
Start the tunnel:
systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0
Step 5 - Enable Gateway Forwarding
Enable forwarding:
sysctl -w net.ipv4.ip_forward=1
Add NAT rules (assuming the internet interface is eth0):
iptables -t nat -A POSTROUTING -s 10.44.0.0/24 -o eth0 -j MASQUERADE
iptables -A FORWARD -i wg0 -o eth0 -j ACCEPT
iptables -A FORWARD -i eth0 -o wg0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
Step 6 - Create a Client Profile
Example client configuration:
[Interface]
Address = 10.44.0.21/24
PrivateKey = <client_private_key>
DNS = 1.1.1.1
[Peer]
PublicKey = <server_public_key>
Endpoint = <server_ip>:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
Add the peer to the server:
[Peer]
PublicKey = <client_public_key>
AllowedIPs = 10.44.0.21/32
Step 7 - Configure Policy Routing on the Server
Create a routing table.
Edit:
/etc/iproute2/rt_tables
Add:
100 exitgw
Add the route:
ip route add default via 10.44.0.9 dev wg0 table exitgw
Add the rule:
ip rule add from 10.44.0.21 lookup exitgw
Now all traffic from that client is routed through the gateway.
Step 8 - Test the Setup
From the client:
curl -4 ifconfig.me
The returned IP should match the gateway’s internet connection.
Traceroute should show the path through the server and gateway:
1 10.44.0.1
2 10.44.0.9
3 gateway router
Step 9 - Make Routing Persistent
Create a routing script on the server:
/usr/local/sbin/wg-exit-routing.sh
#!/bin/sh
ip route replace default via 10.44.0.9 dev wg0 table exitgw
ip rule add from 10.44.0.21 lookup exitgw 2>/dev/null || true
Make it executable:
chmod +x /usr/local/sbin/wg-exit-routing.sh
Attach it to the WireGuard interface:
PostUp = /usr/local/sbin/wg-exit-routing.sh
PostDown = ip rule del from 10.44.0.21 lookup exitgw
Step 10 - Persist Firewall Rules
Install persistent firewall support:
apt install iptables-persistent
Save rules:
iptables-save > /etc/iptables/rules.v4
Extending the Design
Multiple gateways can be added easily:
Gateway A → exit location A
Gateway B → exit location B
Gateway C → exit location C
Each gateway receives its own routing table and client profile.
Advantages
This architecture provides:
- centralized routing control
- multiple exit locations
- simple client configuration
- efficient WireGuard tunnels
- minimal client-side complexity
Clients connect only to the server; the server decides where traffic exits.
Final Notes
WireGuard’s cryptokey routing model combined with Linux policy routing makes it possible to build flexible multi-exit VPN systems with minimal overhead.
A small Linux machine can serve as a reliable gateway node, allowing the architecture to scale easily as additional exit locations are added.