How do you dynamically change the proxy configuration on Windows laptop computers depending on network, all using PowerShell?

Determining if an IP address is within a range is quite cumbersome when you think about it in terms of programming…

Here was the problem we had to solve while migrating from a proxy solution:
Today, all managed computers (100’000+) that we have in our domain are using a proxy to gain access to the outside, there are 5 proxy servers split out by region (As an example: Europe, North America, Australia, Singapore, and China). These proxy servers are configured on the clients using our home grown computer management system which is backboned by PowerShell… we specify a configuration value on the computer and the agent that is installed on the computer assigns the proper proxy server to Internet Options. However, starting now, we are in the middle of rolling out default routes at all sites and that project will take about many months to complete….

The problem:

We can dynamically change the configuration value of all computers at a site in our system to “Disable Proxy” and Windows would just use the default route… easy, right?

Well, what happens when we assign that new value to 20 mobile laptops at one site and then those users travel to a different site that does not have the same solution in place? (a specified proxy is required) Well, the internet would not work for that computer… obviously 

So, our problem was, how do we dynamically change the proxy configuration on laptop computers depending on if that computer was located as a legacy proxy site or default route site, all using PowerShell?

Before implementing what we did…. we investigated a lot of options (like .pac files) but we needed something dynamic that could be changed on the fly.
The first solution we played with was we ended up getting the IP address on a computer and checking if it was in range of a list of networks on a distributed file share (UNC), this worked but it was very slow and the project did not want to list each network on a text file because there are dozens of networks at one location and that list would become massive over time. Remember, we are talking about 500+ sites in 60+ countries… we had to think big.

So, the solution we implemented and we are using today is kind of just combining a bunch of stuff we already knew. Here are the steps:

  1. Laptop computers grab a list of networks from a DFS – I will talk about what this looks like and how it is setup below
  2. PowerShell checks if their current IP address is within any network on that list – we do a lot of checking like (is the computer on VPN?, is the computer on a local network (home)?, etc. etc.) – this all happens client side
  3. Depending on the flow, the PowerShell script modifies the proxy settings and refreshes Internet Settings to instantly update computer – this is done in the user’s context since proxy settings are in HKCU.

The list of networks is maintained by a network administrator (from the rollout project) in a DFS, the text file looks something like this:
10.0.0.0/20#Site A LAN
10.60.20.0/23#Site B Wireless

Then the admin double clicks on a RunMe.cmd file that just calls a PowerShell script in the same directory to create the actual file that the computer grabs, which contains:
167772160..167776255#10.0.0.0/20#10.0.0.0-10.0.15.255#Site A LAN
171709440..171709951#10.60.20.0/23#10.60.20.0-10.60.21.255#Site B Wireless
(the PowerShell script that creates the script also copies the previous file into a backup folder in case of rollback purposes)

The first part of each line is the IP address’ span in decimal format, separated by “..” so that PowerShell treats that as an array. The rest of each line is just information, like the entered network, the actual span and the comment. We transport this information to the local client for logging purposes like “proxy disabled because it is in span XXX called XXX”

When the logon script runs, it fetches the file (if newer than the one it might already have) and does a check, as an example:
If ((Convert-IPAddressToDecimal $ipAddress) -in 171709440..171709951)
{
         #Do things
}

If you think of another solution, I would love to hear it…. Or if you want me to go into details or need the functions to convert IP Address’ let me know as well.

Tack!
/Matt