WireGuard Split Tunneling with AllowedIPs
WireGuard's AllowedIPs parameter doubles as both an ACL filter and a routing table. NetRoute Pro generates a ready-to-paste AllowedIPs string from any website's domains. No extra ip route commands needed — just edit the peer config and reload.
Command Syntax
Syntax:
AllowedIPs = <CIDR1>, <CIDR2>, <CIDR3>
Example:
AllowedIPs = 1.1.1.0/24, 8.8.8.0/24, 162.159.0.0/16
Add to the [Peer] section of wg0.conf. Officially documented in the WireGuard quickstart.
Prerequisites
- Any WireGuard client:
wg-quickon Linux, the WireGuard GUI on Windows/macOS, the mobile apps on Android/iOS, or a router with WireGuard support - NetRoute Pro Chrome extension installed
- A working WireGuard peer you can edit
Step 1. Generate AllowedIPs in NetRoute Pro
- Open the target website in Chrome
- Click the NetRoute Pro icon in your extensions
- Select the WireGuard platform
- Click Analyze Website
- Copy the generated
AllowedIPsline — it looks like:
AllowedIPs = 104.21.32.0/24, 172.67.182.0/24, 162.159.135.0/24, ...
Step 2. Paste into your peer config
Linux (wg-quick)
Edit your tunnel config file (typically in /etc/wireguard/, for example /etc/wireguard/wg0.conf). Under the [Peer] section, replace the existing AllowedIPs = ... line with the string you copied:
[Peer]
PublicKey = <your-peer-public-key>
Endpoint = <your-endpoint>:51820
AllowedIPs = 104.21.32.0/24, 172.67.182.0/24, 162.159.135.0/24
PersistentKeepalive = 25
Windows / macOS (GUI)
- Open the WireGuard app
- Select your tunnel and click Edit
- In the config editor, modify the
AllowedIPsfield under[Peer] - Click Save
Android / iOS
- Open the WireGuard mobile app
- Tap your tunnel → Edit
- Replace the Allowed IPs field value
- Tap Save (top right)
Step 3. Restart the tunnel
Reload the peer so the new routing table takes effect.
- Linux:
sudo wg-quick down wg0 && sudo wg-quick up wg0(replacewg0with your tunnel name) - Windows/macOS GUI: toggle the tunnel off and then on again
- Mobile: disable and re-enable the tunnel switch
DNS leak — required reading
WireGuard’s AllowedIPs routes traffic by IP. It does not route DNS. Your browser still asks the system resolver (usually your ISP’s, learned via DHCP) for example.com first — only the resulting IP traffic flows through the tunnel. The ISP sees which sites you visit even though the data is encrypted.
Three options, by threat model:
- Hide DNS from ISP fully (split-DNS via wg-quick). Add a
DNS =line under[Interface]— wg-quick configures it at tunnel up:
The[Interface] PrivateKey = ... Address = 10.0.0.2/24 DNS = 10.0.0.1, ~example.com, ~another-site.com~domainentries make systemd-resolved use the VPN’s DNS only for those domains (split-DNS). Without them, all DNS goes through the VPN. - Reduce ISP visibility (public DoH/DoT). Use a public resolver for everything:
ISP no longer sees domain queries; Cloudflare does.DNS = 1.1.1.1, 1.0.0.1 - Accept the leak. Skip the
DNSline entirely — only the data path is encrypted, lookups stay on your default resolver. Fine for unblocking-only use cases.
Verify with dnsleaktest.com or browserleaks.com/dns — the resolver shown should belong to your VPN provider or chosen DoH, not your ISP.
Browser-level IP leaks (WebRTC)
Even with split tunneling correctly configured at the OS level, JavaScript on a webpage can use WebRTC to discover your real local and public IP addresses through STUN/ICE, bypassing the VPN. This is by design (P2P video/audio needs direct addresses), not a bug — but it’s a leak the VPN cannot prevent at the network layer.
- Chrome/Edge: open
chrome://flags/#enable-webrtc-hide-local-ips-with-mdnsand enable. Hides the local IP behind a per-session mDNS hostname. - Firefox:
about:config→ setmedia.peerconnection.enabledtofalseif you don’t use any WebRTC apps. More granular control via per-site policy. - uBlock Origin (any browser): Settings → Privacy → enable “Prevent WebRTC from leaking local IP addresses”.
- Test at browserleaks.com/webrtc — the public IP shown should match your VPN exit, not your ISP.
IPv6 dual-stack bypass
WireGuard’s AllowedIPs entries are address-family specific. If you listed only IPv4 prefixes, traffic to the same domain over IPv6 (which most modern sites prefer per RFC 6724) bypasses the tunnel and exits via your ISP’s default v6 route.
Two fixes:
- Route v6 too (if your VPN has an IPv6 endpoint). Add v6 prefixes alongside v4:
For full v6 traffic through the tunnel:AllowedIPs = 1.1.1.0/24, 8.8.8.0/24, 2606:4700::/32, 2001:4860::/32AllowedIPs = 0.0.0.0/0, ::/0. - Disable IPv6 system-wide if your VPN doesn’t support v6. On Linux:
sysctl net.ipv6.conf.all.disable_ipv6=1. On Windows: disable IPv6 on the active adapter. On routers: per-WAN IPv6 toggle. All traffic falls back to v4 and gets tunneled.
Fail-closed (kill switch)
When the WireGuard tunnel goes down (network change, manual stop, routing failure), the kernel removes routes bound to the wg interface — and traffic to the previously-tunneled CIDRs leaks via the default route. Use wg-quick’s PostUp/PostDown hooks to install fail-closed firewall rules tied to the tunnel lifecycle:
[Interface]
PrivateKey = ...
Address = 10.0.0.2/24
# Fail-closed: drop traffic to tunneled CIDRs unless it goes via %i (this tunnel)
PostUp = iptables -I OUTPUT ! -o %i -d 1.1.1.0/24 -j REJECT
PostUp = iptables -I OUTPUT ! -o %i -d 8.8.8.0/24 -j REJECT
PostDown = iptables -D OUTPUT ! -o %i -d 1.1.1.0/24 -j REJECT
PostDown = iptables -D OUTPUT ! -o %i -d 8.8.8.0/24 -j REJECT
%i is replaced by the actual interface name (e.g. wg0). When the tunnel is up, traffic flows through it; when it goes down via wg-quick down, the rules are removed. If the tunnel crashes without running PostDown, those CIDRs stay blocked — which is the safe failure mode (block, don’t leak).
Advanced: Table = off
By default, wg-quick installs a route for every CIDR in AllowedIPs into the main routing table. Setting Table = off under [Interface] tells wg-quick to skip route installation entirely — you manage routing yourself via PostUp/PostDown. Useful when you need policy routing (route based on source IP, mark, or process), a custom routing table, or integration with frr/bird/quagga.
[Interface]
PrivateKey = ...
Address = 10.0.0.2/24
Table = off # do not auto-install routes
# Manage your own routes — typical policy routing example:
PostUp = ip route add 1.1.1.0/24 dev %i table 100
PostUp = ip rule add from 192.168.1.100 lookup 100
PostDown = ip rule del from 192.168.1.100 lookup 100
PostDown = ip route flush table 100
Most users don’t need this — the default behaviour (auto-install routes from AllowedIPs) is what NetRoute Pro’s output expects.
Verify
Run sudo wg show — the peer should be listed with the new allowed ips values:
sudo wg show
You can also confirm routing with ip route (Linux/macOS) or route print (Windows) — the listed subnets should point through your WireGuard interface.
Common issues
Pages hang or only partially load (PMTU black hole)
Symptom: a page starts loading, the first few KB arrive, then it freezes; or some sites work fine while others stall. This is a classic path MTU black hole — large packets get fragmented along the path, ICMP “fragmentation needed” replies are dropped by an upstream firewall, and the sender keeps retransmitting blindly.
WireGuard’s default MTU is 1420 (or 1280 over IPv6). On PPPoE the underlying link is 1492; on 4G/LTE often 1400; some CGNAT paths are 1280. Lower the MTU under [Interface]:
[Interface]
MTU = 1380 # try 1380 first, drop to 1280 / 1200 if pages still hang
On routers that forward through the tunnel (e.g. WG client on a router serving a LAN), also clamp TCP MSS so downstream clients don’t blow past PMTU:
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
Losing all network access
If you removed 0.0.0.0/0 but your new AllowedIPs doesn't cover the default route you intended to use, only the listed subnets will go through the tunnel — that's the whole point of split tunneling. Make sure your list contains exactly the subnets you want and nothing else is unintentionally missing.
Android tunnel stuck on "connecting"
Re-save the config explicitly: enter edit mode, tap out of the AllowedIPs field, and tap Save again. Some Android versions need this to commit the change.
Error: AllowedIPs has invalid format
Check for trailing commas, stray whitespace, or newline characters inside the value. AllowedIPs must be a single comma-separated list on one logical line.
Example Configuration File
Ready-to-edit template with inline comments. Replace the example routes with output from NetRoute Pro for your target sites.
wireguard-split-tunnel.conf— WireGuard peer config withAllowedIPssplit tunneling
# Example WireGuard peer config with split tunneling.
# Generated by NetRoute Pro: https://alexander2k.github.io/netroute-site/
#
# AllowedIPs in [Peer] section doubles as both an ACL and routing table.
# Only the listed networks are sent through the tunnel — everything else
# uses the default route. Replace placeholders with your real keys/addresses.
[Interface]
PrivateKey = YOUR_CLIENT_PRIVATE_KEY
Address = 10.0.0.2/24
DNS = 1.1.1.1
[Peer]
PublicKey = YOUR_SERVER_PUBLIC_KEY
Endpoint = your.vpn.server:51820
PersistentKeepalive = 25
# Networks to route via VPN — add/remove based on NetRoute Pro output.
AllowedIPs = 1.1.1.0/24, 8.8.8.0/24, 162.159.0.0/16
# To route everything via VPN, use: AllowedIPs = 0.0.0.0/0, ::/0
# Apply with: sudo wg-quick down wg0 && sudo wg-quick up wg0
Tip: Need a config without these comment lines? In NetRoute Pro options, uncheck “Include comments in exported files” — the extension will export only the route commands. Useful for routers that don’t tolerate comment lines.
View all example configs on GitHub →
Official Documentation
- WireGuard Quick Start — official
- wg-quick(8) man page
- wg(8) man page — config syntax
- Pro Custodibus: AllowedIPs Calculator
Related Guides
- Keenetic — Routes from
.batfile upload - MikroTik — RouterOS
.rscscript import - Linux —
ip routevia shell script - OpenVPN — client config
routedirectives
Ready to try?
NetRoute Pro — a free Chrome extension to generate routes from any website.
Install Extension