8

What I am trying to do is have a separate interface for some applications to use a VPN through WireGuard while ALL other applications use my regular interfaces (Split Tunneling by app). I have already solved how to get specific applications to use my WireGuard interface.

My problem now is ALL of my machines traffic is directed through my VPN when my WireGuard Tunnel is open.

I have tried removing allowedIPs = 0.0.0.0/0, ::/0 from under [Peer] and this resulted in my tunnel allowing no traffic from my applications to the internet.

I have also tried adding Table = off to under [Interface] to disable WireGuard from adding my tunnel to my systems routing table. What happens for this is WireGuard refuses to save or import the config and responds with "Invalid key for [Interface] section: "table".

I am using WireGuard for Windows v0.3.14.

Is there any other way to accomplish this?

2 Answers 2

11

One of my friends helped me solve this issue with the help of zx2c4 (Jason Donenfeld) from WireGuard. I am sharing our solution here for the next person with this same problem.

WireGuard for Windows added support for Table = off in v0.3.15. This makes it so WireGuard does not update the routing table when the tunnel is opened.

At this point we have a tunnel but windows will not route traffic through it even if it is the only adapter for the application. To solve this issue we need to add a default route to the adapter with a lower priority than our regular default route.

To do this we need to first enable DangerousScriptExecution in WireGuard. To do this we need to set the Registry Key HKEY_LOCAL_MACHINE\Software\WireGuard\DangerousScriptExecution to DWORD(1) using regedit. The key does not exist by default and needs to be created using regedit. Then WireGuard needs to be restarted.

Once this is done we need to run some PowerShell commands when we start and stop the tunnel to create our default route for the tunnel. This route needs to have a higher metric/cost (lower priority) than our normal default route. For this solution we used a metric value of 95 (10 higher than the highest automatic metric).

WireGuard has the ability to automatically execute windows commands specified in the PreUp, PostUp, PreDown, and PostDown options in the tunnel config. We use this to set up our routes automatically.

WireGuard sets the environment variable WIREGUARD_TUNNEL_NAME to the name of this exact tunnel when it is running commands. We can convert it to a PowerShell object by calling $wgInterface = Get-NetAdapter -Name %WIREGUARD_TUNNEL_NAME%.

Once we have the tunnel as a PowerShell object we can set up or take down our route in windows.

To create our route we call route add 0.0.0.0 mask 0.0.0.0 0.0.0.0 IF $wgInterface.ifIndex metric 95

To remove our route we call route delete 0.0.0.0 mask 0.0.0.0 0.0.0.0 if $wgInterface.ifIndex metric 95

When we combine all of this together we end up with the following under [Interface] in the tunnel config. PostUp, PreDown, and Table = off are what this solution gives.

[Interface]
PrivateKey = <...>
Address = <...>
DNS = <...>
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 95"
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 95"
Table = off

[Peer]
PublicKey = <...>
AllowedIPs = 0.0.0.0/0,::0/0
Endpoint = <...>

We are now done for IPv4. If you want to do this with IPv6 as well (optional) continue to the next section.

IPv6 Specific

If IPv6 is available on the host system and is supported by the WireGuard tunnel then we can also apply this to IPv6.

WARNING: IPv6 routing over WireGuard should NOT be configured if the host system is not on the IPv6 internet unless it is acceptable to send some of your non-tunneled traffic over the tunnel. Ignoring this will result in you mixing your non-tunneled and tunneled traffic (Example: some personal traffic being routed over a work network). If the host is on the the IPv6 internet this will not be a issue because any non-tunneled IPv6 traffic will be routed over the hosts default IPv6 interface.

To do this for IPv6 we need to run some PowerShell commands when we start and stop the tunnel to create our default IPv6 route for the tunnel. This route also needs to have a higher metric (lower priority) than our normal default route. For this solution we used a metric value of 205 (155 higher than the highest automatic IPv6 metric of 50). We also need to make sure this route is not persistent so it will be automatically removed on next boot if for any reason it is not removed by the script.

To create our IPv6 route we call netsh interface ipv6 add route prefix= ::0/0 interface= $wgInterface.name metric= 205 store= active

To remove our IPv6 route we call netsh interface ipv6 delete route prefix= ::0/0 interface= $wgInterface.name

These PowerShell commands need to be added to the end of the PostUp and PreDown of the tunnel config. When this change is made we should end up with the following PostUp and PreDown lines in the tunnel config.

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 95; netsh interface ipv6 add route prefix= ::0/0 interface= $wgInterface.name metric= 205 store= active"
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 95; netsh interface ipv6 delete route prefix= ::0/0 interface= $wgInterface.name"
0

I would have loved to reply directly to Ryan, but I couldn't ¯\_(ツ)_/¯

Based on his answer, I did a little powershell helper script.

It can setup the registry key, restart the WireGuard Manager Service, and of course, setup the default route (and one more!)

You'll find it here (with a configuration exemple) : https://gist.github.com/webtroter/36477c014e4cc5f169468891fa7652f2

2
  • 1
    Posting here is preferred instead of links
    – ZygD
    Commented Sep 24, 2021 at 0:24
  • Well, it's a very complete script, with more than a hundred lines. I thought about it. But I think it's better to write a verbose script than aiming for shortness Commented Sep 25, 2021 at 1:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .