Wireguard | Client inside the network problem

Hello,

A bit late to the party, but having finished setting up all the wireguard tunnels between all routers, I decided that maybe it is time to also move the client machines to wireguard.
For quite a while now, all client machines (90% Windows, rest iOS and Android, no linux) were using IPSEC/IKE2 with certificates and RADIUS.
Having only one VPN solution sounded great, so I began testing with one location.
Everything works, the “reconnection” is mighty fast when changing networks, the speed through the tunnel is great but…


The problem

Wireguard (official client) on Windows machines can only be installed and setup under an administrator account (without certain tweaks).
At 1st, I thought this can’t be right. The user has to have access to an ON/OFF VPN switch.
On second thought, users not having access to public and preshared keys is nice.
Also, getting less headache from users forgetting to toggle the darn VPN switch before calling support to complain they cannot access network resources is also a bonus.
So 1st thought is out the window, No access to wireguard GUI for user accounts seems fine.
But the problem, at least when it comes to high speed LAN connections like accessing large files from the local file-server for example, is that I cannot find a way to bypass the tunnel when the client is in the office/behind the wireguard server.
Client connects physically (WIFI or ethernet) to local network, can access all required resources, but the traffic to the local resources goes through the tunnel.
In most places, I have decently speedy routers, but even those cannot sustain 1 Gb/s or more of WG traffic for several users.
I found some users on reddit suggesting some batch files to detect when inside the “home” network, but that looks very sketchy and prone to errors.

I guess the question is: anyone found a way to bypass the wireguard tunnel when a Windows client connects physically to the local network without the user having the ability to disable/enable the tunnel?



Topology example:

WG-server: 172.17.10.1
WG-client1: 172.17.10.2
WG-client2: 172.17.10.3

Mikrotik router private IP: 192.168.150.1
A file-server behind Mikrotik: 192.168.150.2

Machine of WG-client1 connects to local WiFi. Gets a DHCP of 192.168.150.3
Machine of WG-client1 also has wireguard activated with IP 172.17.10.2
WG-Client1 Allowed IP: 172.17.10.1/32, 192.168.150.0/24

For WG-Client1 to access the file-server at 192.168.150.2 it has to pass through the wireguard tunnel, consuming a lot of CPU on the router with high speed transfers

tracert 192.168.150.2

Tracing route to file-server [192.168.150.2]
over a maximum of 30 hops:

1 4 ms 2 ms 1 ms wg-server.tun [172.17.10.1]
2 2 ms 2 ms 1 ms file-server [192.168.150.2]

Trace complete.

Example of a single WG client on 1 Gb/s ethernet link doing a local speed test through the tunnel of a RB1100AHx4
https://streamable.com/mxlir5

Hope I am just missing something obvious.

The ugly and dirty way, but very much functioning fix.

Solution presented below is based on the assumption that:
a: you need to bypass the Wireguard tunnel when behind the Wireguard server for better network performance and to give the poor router a break.
b: you have access to an administrator account.
c: you only have one subnet behind the Wireguard server. If multiple subnets, I guess modify the batch file and share here for others also.
d: valid only for Windows clients.

1: Save the following as a batch file as C:\Windows\Scripts\check-network.bat

@ECHO OFF
set privateSubnet="192.168.150."
for /f "tokens=3 delims=:" %%A in ('sc query state^= all^|findstr /c:"WireGuard Tunnel"') do set tunnel=%%A
set tunnel=%tunnel: =%
set behindWG=0
ipconfig|findstr %privateSubnet%|findstr "IPv4"
if %errorlevel%==0 set behindWG=1
set WGrunning=0
sc query WireGuardTunnel$%tunnel%|findstr "RUNNING"
if %errorlevel%==0 set WGrunning=1
if %behindWG%==1 if %WGrunning%==1 net stop WireGuardTunnel$%tunnel%
if %behindWG%==0 if %WGrunning%==0 net start WireGuardTunnel$%tunnel%

1.a: Edit the second line to match your private subnet. If the client gets an IP via DHCP of 192.168.150.10, omit the 10.

2: Save the following as disableWGservice.xml (the name of the file gives the name of the task)

<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <URI>\Check network for Wireguard</URI>
  </RegistrationInfo>
  <Triggers>
    <EventTrigger>
      <Enabled>true</Enabled>
      <Subscription>&lt;QueryList&gt;&lt;Query Id="0" Path="Microsoft-Windows-NetworkProfile/Operational"&gt;&lt;Select Path="Microsoft-Windows-NetworkProfile/Operational"&gt;*[System[Provider[@Name='Microsoft-Windows-NetworkProfile'] and EventID=10000]]&lt;/Select&gt;&lt;/Query&gt;&lt;/QueryList&gt;</Subscription>
    </EventTrigger>
  </Triggers>
  <Principals>
    <Principal id="Author">
      <LogonType>Password</LogonType>
      <RunLevel>HighestAvailable</RunLevel>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>StopExisting</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <StartWhenAvailable>false</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>true</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <StopOnIdleEnd>true</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>true</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession>
    <UseUnifiedSchedulingEngine>true</UseUnifiedSchedulingEngine>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>C:\Windows\Scripts\check-network.bat</Command>
    </Exec>
  </Actions>
</Task>

2.a: edit C:\Windows\Scripts\check-network.bat if you saved the batch file elsewhere.
2.b: Import the xml into Task Scheduler

2.b: Modify the imported task as in the image below
1.png
2.c: Save the imported task.

Done

With everything setup as described above, when a laptop for example connects to the network, the batch file will run via task scheduler and will check if any IPv4 contains my subnet.
If true, the Wireguard tunnel will be disabled.
If false, the Wireguard tunnel will be enabled.

Tested extensively and it works for my needs.
Of course, there are situations where this might lead to the tunnel not activating, if for example the user connects from a remote network that happens to use the same subnet.
Hope it helps someone until Wireguard devs. implement a solution inside the Windows Wireguard client itself.

If anyone has a better solution, please share.