|
| 1 | +# Policy-Based Routing in WrapGuard |
| 2 | + |
| 3 | +WrapGuard supports policy-based routing, allowing you to route traffic through specific WireGuard peers based on destination IP addresses, protocols, and port ranges. |
| 4 | + |
| 5 | +## Configuration Syntax |
| 6 | + |
| 7 | +In addition to the standard WireGuard configuration, you can add `Route` directives to each peer: |
| 8 | + |
| 9 | +```ini |
| 10 | +[Peer] |
| 11 | +PublicKey = ... |
| 12 | +Endpoint = ... |
| 13 | +AllowedIPs = ... |
| 14 | +# Route directives for policy-based routing |
| 15 | +Route = <CIDR> |
| 16 | +Route = <CIDR>:<protocol>:<ports> |
| 17 | +``` |
| 18 | + |
| 19 | +### Route Format |
| 20 | + |
| 21 | +- `<CIDR>`: Destination network in CIDR notation (e.g., `192.168.1.0/24`, `0.0.0.0/0`) |
| 22 | +- `<protocol>`: `tcp`, `udp`, or `any` (optional, defaults to `any`) |
| 23 | +- `<ports>`: Port or port range (optional, defaults to all ports) |
| 24 | + - Single port: `80` |
| 25 | + - Port range: `8080-9000` |
| 26 | + - Multiple ports: `80,443` (comma-separated) |
| 27 | + |
| 28 | +## Examples |
| 29 | + |
| 30 | +### Basic Routing by Destination Network |
| 31 | + |
| 32 | +```ini |
| 33 | +[Peer] |
| 34 | +PublicKey = peer1_public_key |
| 35 | +Endpoint = vpn1.example.com:51820 |
| 36 | +AllowedIPs = 0.0.0.0/0 |
| 37 | +# Route all traffic through this peer by default |
| 38 | +Route = 0.0.0.0/0 |
| 39 | + |
| 40 | +[Peer] |
| 41 | +PublicKey = peer2_public_key |
| 42 | +Endpoint = vpn2.example.com:51820 |
| 43 | +AllowedIPs = 192.168.0.0/16 |
| 44 | +# Route specific subnet through this peer |
| 45 | +Route = 192.168.1.0/24 |
| 46 | +``` |
| 47 | + |
| 48 | +### Protocol and Port-Based Routing |
| 49 | + |
| 50 | +```ini |
| 51 | +[Peer] |
| 52 | +PublicKey = web_peer_public_key |
| 53 | +Endpoint = web-vpn.example.com:51820 |
| 54 | +AllowedIPs = 0.0.0.0/0 |
| 55 | +# Route web traffic through this peer |
| 56 | +Route = 0.0.0.0/0:tcp:80,443 |
| 57 | + |
| 58 | +[Peer] |
| 59 | +PublicKey = dev_peer_public_key |
| 60 | +Endpoint = dev-vpn.example.com:51820 |
| 61 | +AllowedIPs = 0.0.0.0/0 |
| 62 | +# Route development services through this peer |
| 63 | +Route = 0.0.0.0/0:tcp:3000-4000 |
| 64 | +Route = 0.0.0.0/0:tcp:8080-9000 |
| 65 | +``` |
| 66 | + |
| 67 | +### Complex Multi-Peer Setup |
| 68 | + |
| 69 | +```ini |
| 70 | +[Interface] |
| 71 | +PrivateKey = your_private_key |
| 72 | +Address = 10.150.0.2/24 |
| 73 | + |
| 74 | +# Peer 1: General purpose VPN |
| 75 | +[Peer] |
| 76 | +PublicKey = general_vpn_public_key |
| 77 | +Endpoint = general-vpn.example.com:51820 |
| 78 | +AllowedIPs = 0.0.0.0/0 |
| 79 | +Route = 0.0.0.0/0 # Default route for all traffic |
| 80 | + |
| 81 | +# Peer 2: Corporate network access |
| 82 | +[Peer] |
| 83 | +PublicKey = corp_vpn_public_key |
| 84 | +Endpoint = corp-vpn.example.com:51820 |
| 85 | +AllowedIPs = 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 |
| 86 | +# Route corporate networks |
| 87 | +Route = 10.0.0.0/8 |
| 88 | +Route = 172.16.0.0/12 |
| 89 | +Route = 192.168.0.0/16 |
| 90 | +# Route specific services |
| 91 | +Route = 0.0.0.0/0:tcp:22 # SSH through corporate VPN |
| 92 | +Route = 0.0.0.0/0:tcp:3389 # RDP through corporate VPN |
| 93 | + |
| 94 | +# Peer 3: Streaming and gaming |
| 95 | +[Peer] |
| 96 | +PublicKey = gaming_vpn_public_key |
| 97 | +Endpoint = gaming-vpn.example.com:51820 |
| 98 | +AllowedIPs = 0.0.0.0/0 |
| 99 | +# Route gaming and streaming ports |
| 100 | +Route = 0.0.0.0/0:udp:5000-6000 # Gaming ports |
| 101 | +Route = 0.0.0.0/0:tcp:1935 # RTMP streaming |
| 102 | +``` |
| 103 | + |
| 104 | +## Routing Priority |
| 105 | + |
| 106 | +1. **Most specific CIDR wins**: `/32` routes take precedence over `/24`, which take precedence over `/0` |
| 107 | +2. **Order matters**: For same CIDR specificity, routes listed first have higher priority |
| 108 | +3. **Protocol matching**: Protocol-specific routes only match their protocol |
| 109 | +4. **Port matching**: Port-specific routes only match connections to those ports |
| 110 | + |
| 111 | +## How It Works |
| 112 | + |
| 113 | +1. When a connection is initiated, WrapGuard checks the destination IP, protocol, and port |
| 114 | +2. It searches through all configured routing policies to find the best match |
| 115 | +3. Traffic is routed through the WireGuard peer with the matching policy |
| 116 | +4. If no policy matches, it falls back to checking AllowedIPs |
| 117 | +5. If still no match, the default peer (first one with `0.0.0.0/0`) is used |
| 118 | + |
| 119 | +## Testing Your Configuration |
| 120 | + |
| 121 | +To test your routing configuration: |
| 122 | + |
| 123 | +```bash |
| 124 | +# Check which peer would handle specific traffic |
| 125 | +wrapguard --config=policy-routing.conf -- curl https://example.com |
| 126 | +wrapguard --config=policy-routing.conf -- ssh user@192.168.1.100 |
| 127 | +wrapguard --config=policy-routing.conf -- nc -v 10.0.0.5 3000 |
| 128 | +``` |
| 129 | + |
| 130 | +Enable debug logging to see routing decisions: |
| 131 | + |
| 132 | +```bash |
| 133 | +wrapguard --config=policy-routing.conf --log-level=debug -- your_command |
| 134 | +``` |
| 135 | + |
| 136 | +## Limitations |
| 137 | + |
| 138 | +- Currently only supports IPv4 routing |
| 139 | +- Maximum of one route per line (no comma-separated CIDRs) |
| 140 | +- Port ranges in route specifications don't support comma-separated values |
0 commit comments