One of the problems I've faced working from home for the last one year is the rigidity of the VPN software used at my work. If we were using something like OpenVPN, then I could modify the client config to setup any overrides I wanted to the network routing table or DNS, but we use FortiClient SSL VPN, which does not have such a functionality. Also, I've been using Windows 10 on my work setup for some time now because WSL works very well for me.
But first, why did I even need to modify the routing table or DNS at all?
- I use a slightly non-standard network setup for my home, and one of my home subnets actually clashes with one of the routed work subnets (which I don't need). So, the easy solution for me is to change this routing table entry to what works for me.
- I use diversion on my home router to do central ad-blocking, and wanted to leverage that even when connected to the work VPN.
Here is the PowerShell script that does the changes I want:
Explanation of what it does:
- Uses Start-Transcript and Stop-Transcript to log the output to a file.
- Checks if the system is connected to SSID "Home Wifi".
- If so, checks if the adapter with description with the pattern "Fortinet SSL*" is up
- If so, changes the DNS server address
- In the routing table, it increases the route metric of
0- sets it to
500. This route is added by FortiClient, which I wanted to de-prioritize.
From the Set-NetRoute docs:
The computer selects the route with the lowest combined value.
Now, we just need to setup some automation to run this whenever the VPN is connected. For this, I used Windows Task Scheduler. Whenever windows activates any network profile, a
Microsoft-Windows-NetworkProfile/Operational log is generated with Event Id
10000. Windows Task Scheduler has the capability to schedule a task to be run whenever any event is triggered.
Here are some screenshots of the task configuration:
Here's the exported XML of the task:
<?xml version="1.0" encoding="UTF-16"?> <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"> <RegistrationInfo> <Date>2021-01-19T23:24:57.7398228</Date> <Author>srijan</Author> <Description>Currently: 1. Set local DNS 2. Route 192.168.2.0/24 locally</Description> <URI>\Network post connect automation</URI> </RegistrationInfo> <Triggers> <EventTrigger> <Enabled>true</Enabled> <Subscription><QueryList><Query Id="0" Path="Microsoft-Windows-NetworkProfile/Operational"><Select Path="Microsoft-Windows-NetworkProfile/Operational">*[System[Provider[@Name='Microsoft-Windows-NetworkProfile'] and EventID=10000]]</Select></Query></QueryList></Subscription> <Delay>PT10S</Delay> </EventTrigger> </Triggers> <Settings> <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy> <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries> <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries> <AllowHardTerminate>true</AllowHardTerminate> <StartWhenAvailable>false</StartWhenAvailable> <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable> <IdleSettings> <StopOnIdleEnd>true</StopOnIdleEnd> <RestartOnIdle>false</RestartOnIdle> </IdleSettings> <AllowStartOnDemand>true</AllowStartOnDemand> <Enabled>true</Enabled> <Hidden>false</Hidden> <RunOnlyIfIdle>false</RunOnlyIfIdle> <WakeToRun>false</WakeToRun> <ExecutionTimeLimit>PT1H</ExecutionTimeLimit> <Priority>7</Priority> </Settings> <Actions Context="Author"> <Exec> <Command>powershell</Command> <Arguments>-File C:\Users\srijan\Apps\network-post-connect.ps1 -WindowStyle Hidden</Arguments> </Exec> </Actions> </Task>
I have gotten used to the ease of setting up things like this for Linux, but was pleasantly surprised that it's easy enough for Windows as well. Windows Task Scheduler actually supports a lot of different conditionals for tasks as well. For example, only starting the task if the computer has been idle for some time, or only starting if connected to AC power, etc..
Let me know in the comments if you think there is an easier way, or if you have any improvement suggestions for the above.