Split Tunneling in WireGuard on Windows
Recently I stumbled upon a situation in which I needed to use split tunneling in WireGuard. I had an application that I wanted to route through WireGuard, but everything else I wanted to route through my regular default gateway.
By default, WireGuard will create a new default route setting it as high priority (low metric). This forces all of your traffic out the WireGuard tunnel. You can delete the default route, but then you’d have to add a route each time the tunnel is connected.
That seemed like a hassle, so after some digging, I found a better solution.
Here’s the how I accomplished split tunneling with WireGuard:
- Disable automatic default route creation
- Configure allowed IPs
- Enable the use of scripts
- Add post-up/pre-down commands
Disable automatic default route creation:
[Interface] section of your tunnel config, add
Table = off
This tells WireGuard not to create a default route automatically.
Configure allowed IPs:
You’ll probably want to set this to all IPs.
AllowedIPs tells WireGuard what IP addresses to route through the tunnel. So if your application connects to various IPs, or you aren’t sure, perform this step. (After this we will fix the default routes so packets don’t actually go out through the tunnel.)
[Peer] section of your tunnel config, set this
AllowedIPs = 0.0.0.0/0
Enable the use of scripts:
Scripts are not enabled in WireGuard on Windows by default. We need to enable scripts so we can properly set up the correct route. To do this, you’ll need to enable the
DangerousScriptExecution registry key.
Open the registry editor and navigate to
Create a new
DWORD value named
And set its value to
It should look like this
Add post-up/pre-down commands:
[Interface] section of your tunnel config, add these lines
PostUp = powershell -command "$wgInterface = Get-NetAdapter -Name %WIREGUARD_TUNNEL_NAME%; route add 0.0.0.0 mask 0.0.0.0 0.0.0.0 IF $wgInterface.ifIndex metric 9999; Set-NetIPInterface -InterfaceIndex $wgInterface.ifIndex -InterfaceMetric 9999; route add 10.124.0.0/23 0.0.0.0 IF $wgInterface.ifIndex;"PreDown = powershell -command "$wgInterface = Get-NetAdapter -Name %WIREGUARD_TUNNEL_NAME%; route delete 0.0.0.0 mask 0.0.0.0 0.0.0.0 if $wgInterface.ifIndex metric 9999; Set-NetIPInterface -InterfaceIndex $wgInterface.ifIndex -InterfaceMetric 9999;route delete 10.124.0.0/23 0.0.0.0 if $wgInterface.ifIndex;"
This will tell WireGuard to add a new default route after the tunnel is up (
PostUp) with a metric of
9999 (low priority), as well as setting the metric of the interface itself to
9999. (low priority). That means although Windows will technically route traffic through the tunnel, it will [probably] never happen because all other routes precede it in priority. As a comparison, most route metrics are less than 500 (lower is higher priority).
If you’d like to see your routes, open PowerShell and type
Once the tunnel disconnects, it will delete that route (
To confirm your metrics are working correctly, open PowerShell and type
netsh interface ip show address
Your VPN interface should show a Gateway Metric of 9999 and an Interface Metric of 9999.
If you want to confirm which traffic is passing over your VPN vs your regular connection, the easiest way I’ve found is to use NetworkTrafficView from NirSoft which shows each connection. (Note the “Process Filename” column)
DNS….it’s always DNS!
DNS is something to be concerned about when it comes to privacy.
9999 metric trick above works mainly because traffic will always traverse a non-VPN adapter first before traversing the VPN.
With DNS it’s different…
The way Windows handles DNS is complex and can result in a DNS leak. This is because even if your primary and secondary DNS servers on your physical adapter are working, your VPN’s DNS will still receive queries which will also be traversing the DNS servers itself.
This article from YogaDNS describes this perfectly. YogaDNS forces DNS traffic over a specific interface. I’ve never used YogaDNS, but I have used its sister-product Proxifier and I love it (see below).
If you run into connectivity issues with certain apps, remove this line from your WireGuard config.
If you’re concerned about privacy… use YogaDNS to force specific apps to use specific DNS servers on specific interfaces. They have a free version.
DNS = x.x.x.x
Forcing Traffic through a Specific Network Interface:
The only downside to split-tunneling through a traditional method, like the above, is that the program you want to use on that specific network interface must support the ability to let you choose which network interface to use.
I don’t work for Proxifier nor do I know them, but I can say if you want ultimate control over which app to use which connection, use Proxifier.
Proxifier is absolutely terrific. Not only can you specify specific applications to route through specific interfaces, but it also supports SOCKS5 and other proxies. You can even specify certain hostnames or ports to re-route traffic for.
…. plus you don’t even have to worry about split-tunneling!