Always On Azure VPN with PowerShell, Task Scheduler, and Intune

The Beginning...

I would first, like to give thanks to Ben R. of Powers Hell who led me down this path of enlightenment.

Set your Azure VPN connections to “Connect Automatically” with PowerShell | Powers Hell (powers-hell.com)

tabs-not-spaces (Ben R.) (github.com)

I figured since we could use the rasman registry entries to keep the Azure VPN alive while connected to the internal network, why not use rasdial to initiate the connection based on the state of your network?

In our case, we wanted an Always On VPN solution that would auto connect and disconnect based on conditions of your network connection. For instance, if you were connected to an external network (like from home working remotely), the Azure VPN would automatically connect. If you brought your laptop to work, and connected to the corporate network, the Azure VPN client would automatically disconnect and vice versa.

Granted there are various posts on how to accomplish this using Microsoft’s solution as described here or on various other posts.

Configure an Always-On VPN user tunnel – Azure VPN Gateway | Microsoft Learn

However, I created another much simpler solution based on the rasdial command without all the overhead. Therefore, with a little help from my buddy Ben R, a PowerShell script, Scheduled Task, and Intune deployment was devised. Here is the script:

				
					Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
# Define the VPN Connection name
$vpnConnectionName = "Name Azure VPN"
#Check for network connectivity and VPN connection status in a loop

while ($true) {
# Get the VPN connection status
$vpnStatus = Get-VpnConnection -Name $vpnConnectionName -ErrorAction SilentlyContinue

# Get the default gateway IP
$defaultGatewayIp = (Get-NetRoute | Where-Object { $_.DestinationPrefix -eq '0.0.0.0/0' }).NextHop

# Check if the default gateway IP corresponds to an internal network
$internalNetworks = @("IpAddress1", "IpAddress2", "IpAddress3", "IpAddress4", "IpAddress5", "IpAddress6", "IpAddress7")

# Get the connection profile name
$connectionProfileName = (Get-NetConnectionProfile).Name

# Log the network status and connection profile
Add-Content -Path "C:\temp\Log\Network_Status.log" -Value "Default Gateway IP: $defaultGatewayIp, Connection Profile: $connectionProfileName"

# Check conditions based on network statuses to connect or stay connected to the VPN
if ($internalNetworks -contains $defaultGatewayIp -and $connectionProfileName -eq 'DomainName') {
    # If connected to an internal network and the VPN is connected, disconnect the VPN
    Write-Host "Connected to an internal network. Disconnecting VPN..."
    rasdial.exe $vpnConnectionName /disconnect
} elseif ($defaultGatewayIp -eq 'IpAddress1' -or $defaultGatewayIp -eq 'IpAddress2' -or $defaultGatewayIp -eq 'IpAddress3' -or $defaultGatewayIp -eq 'IpAddress4' -or $defaultGatewayIp -eq 'IpAddress5' -or $defaultGatewayIp -eq 'IpAddress6' -or $defaultGatewayIp -eq 'IpAddress7') {
    # If default gateway is equal to any of the internal network addresses, disconnect the VPN
    Write-Host "Connected to an internal network. Disconnecting VPN..."
    rasdial.exe $vpnConnectionName /disconnect
} elseif ($vpnStatus -eq $null -or $vpnStatus.ConnectionStatus -ne 'Connected') {
    # If the VPN is disconnected, connect the VPN
    Write-Host "VPN is disconnected. Connecting..."
    rasdial.exe $vpnConnectionName
}

# Adjust the sleep interval as needed
Start-Sleep -Seconds 10
				
			

Let’s break it down a bit for clarity.

  • $vpnConnectionName = “Name Azure VPN”
    Whatever the name of your Azure VPN connection, you will put that here.
  • $defaultGatewayIp = (Get-NetRoute | Where-Object { $_.DestinationPrefix -eq ‘0.0.0.0/0’ }).NextHop
    This variable/command, gets the Gateway of your network connection.
  • $internalNetworks = @(“IpAddress1”, “IpAddress2”, “IpAddress3”, “IpAddress4”, “IpAddress5”, “IpAddress6”, “IpAddress7”)
    Here you would replace “IpAddress1” and so forth, with the IP addresses of the Gateways within your internal network. i.e. “10.0.0.1” for example.
  • $connectionProfileName = (Get-NetConnectionProfile).Name
    This pulls in the Name of your network connection profile. If you are behind contoso.local as your internal network name, that is what you will get using this variable/command. The commands in 1 through 17 above are how you create the distinction between when you are connected to your internal network, or an external network.
  • Add-Content -Path “C:\temp\Log\Network_Status.log” -Value “Default Gateway IP: $defaultGatewayIp, Connection Profile: $connectionProfileName”
    This command parses the information to a log file on the local machine where the script will run. The log file is helpful in diagnosing any issues you might encounter with the script. More on this to follow.
    Once we have all the conditions established from the variables/commands above, we move to the next phase of looping through those conditions to connect and reconnect as needed.
  • # Check conditions based on network statuses to connect or stay connected to the VPN
    if ($internalNetworks -contains $defaultGatewayIp -and $connectionProfileName -eq ‘DomainName’) {
    # If connected to an internal network and the VPN is connected, disconnect the VPN
    Write-Host “Connected to an internal network. Disconnecting VPN…”
    rasdial.exe $vpnConnectionName /disconnect }
    elseif ($defaultGatewayIp -eq ‘IpAddress1’ -or $defaultGatewayIp -eq ‘IpAddress2’ -or $defaultGatewayIp -eq ‘IpAddress3’ -or $defaultGatewayIp -eq ‘IpAddress4’ -or $defaultGatewayIp -eq ‘IpAddress5’ -or $defaultGatewayIp -eq ‘IpAddress6’ -or $defaultGatewayIp -eq ‘IpAddress7’) {
    # If default gateway is equal to any of the internal network addresses, disconnect the VPN
    Write-Host “Connected to an internal network. Disconnecting VPN…”
    rasdial.exe $vpnConnectionName /disconnect }
    elseif ($vpnStatus -eq $null -or $vpnStatus.ConnectionStatus -ne ‘Connected’) {
    # If the VPN is disconnected, connect the VPN
    Write-Host “VPN is disconnected. Connecting…”
    rasdial.exe $vpnConnectionName }
    # Adjust the sleep interval as needed
    Start-Sleep -Seconds 10

    The PowerShell script was vigorously tested to connect/disconnect the Azure VPN automatically by connecting to an external network, then connecting to an internal network, both wired and wirelessly, and the Azure VPN connected and disconnected as intended. The next step is to create a scheduled task for the PowerShell script to run when the user logs on, or at startup. To create the scheduled task:

The Scheduled Task

  1. Create a batch file to call up the PowerShell script from within Task Scheduler.
    The contents of the batch file should include the following:
				
					@echo off
cd C:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -command "& {Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass -Force}"
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -WindowStyle Hidden -File "C:\temp\scripts\nameOfpowerShellScript.ps1" 1>C:\temp\log\vpn.log 2>&1
				
			

We tested running the PowerShell script directly from within Task Scheduler but got errors or it didn’t run as intended. Therefore, calling the PowerShell script from within a batch file worked flawlessly. The execution policy is necessary for task scheduler to run the PowerShell script from within the batch file using the Built-In Users group. It is also necessary to use absolute paths as opposed to relative paths in the batch file as well or you will get an error. See the logs for any errors.

  1. Add the batch file (NameYourBatch.bat), and PowerShell script (NameYourPowerShellScript.ps1) in the same folder. I used C:\temp\scripts
    Configure Task Scheduler as follows:
    a. General – Selected Built-In Users Group, Run with highest privileges
    b. Triggers – At log on, Any User, Enabled & At System Startup, Enabled
    c.  Actions – Start a program, Program/Script >cmd.exe, Add arguments >/C C:\temp\scripts\NameOfYourBatch.bat
    d. Conditions – leave blank
    e. Settings – Allow task to be run on demand, Run task as soon as possible after a scheduled start is missed, If the task fails, restart every 1 minute, If the running task does not end when requested, force it to stop, and finally, Stop the existing instance from the dropdown.
     

Once the scheduled task has been created, and you copied the batch file and PowerShell script to the C:\temp\scripts (or any folder of your choice), the scheduled task is ready to run. You can now test the state of your connections by connecting to your internal or external network to confirm the Azure VPN client connects, disconnects, and remains connected/disconnected as needed. The next step was to deploy the scripts (copy files to local machine) and create the scheduled task via Intune.

To deploy the scheduled task and files via Intune:

The Intune Deployment

  1. Export the scheduled task. This will export the XML file needed for Intune.
  2. Create an install.ps1 script to copy the files to the local machine (including the xml file) and register the scheduled task. See below…
    # Copy the XML file, batch file, and PowerShell script to the C:\temp\scripts folder, and created log directory
				
					$tempdir = "C:\temp\scripts"
$logdir = "C:\temp\log"
New-Item $tempdir -ItemType Directory -Force
New-Item $logdir -ItemType Directory -Force
Copy-Item ".\NameofYourXML.xml" "C:\temp\scripts" -Force
Copy-Item ".\NameofYourbatch.bat" "C:\temp\scripts" -Force
Copy-Item ".\NameofYourScript.ps1" "C:\temp\scripts" -Force

				
			

Register a new scheduled task using the exported XML.

				
					Register-ScheduledTask -xml (Get-Content C:\temp\scripts\NameofYourXML.xml | Out-String) -TaskName "Name of your task" -TaskPath "/"
				
			
  1. Create uninstall.ps1 to remove the scheduled task, log and scripts directory and contents.
				
					Unregister-ScheduledTask -TaskName "Auto Connect Azure VPN" -Confirm:$false
Remove-Item C:\temp\log -Recurse
Remove-Item C:\temp\scripts -Recurse

				
			
  1. Create detection.ps1 script to tell Intune if deployment was a success or failure.
				
					$taskExists = Get-ScheduledTask | Where-Object {$_.TaskName -like "NameOfScheduledTask"}
if($taskExists) {
Write-Host "Success"
Exit 0
} else {
Exit 1}

				
			
  1. Place all files in a folder of your choice.
  2. Create intunewin file from install.ps1 PowerShell script.
  3. Create Win32App in Intune

Use the following for install/uninstall commands:

Install Command:

				
					Powershell.exe -ExecutionPolicy ByPass -File .\install.ps1
				
			

Uninstall Command:

				
					Powershell.exe -ExecutionPolicy ByPass -File .\uninstall.ps1
				
			

        4. Configure the Win32App to run under the system context.
        5. Use a custom detection script (see below)

				
					$taskExists = Get-ScheduledTask | Where-Object {$_.TaskName -like "Your VPN Name"}
if($taskExists) {
Write-Host "Success"
Exit 0
}else {
Exit 1

				
			

         6. Assign to specified group(s) as Required.

NOTE: For Task Scheduler to run the batch file successfully on the local machine, it is necessary to use absolute paths, and the following had to be used to set the proper execution policy for the batch file to execute the PowerShell script using the Task Scheduler. >C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command “& {Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass -Force}”

ANOTHER NOTE: This solution will conflict with users working remotely, where their home network is set to use any of the gateways within your internal network. In this case, the Azure VPN will remain disconnected until their home network subnet is changed to anything other than any of your internal network IP Addresses.

 That’s it. Now you have a working “Always On” (like) Azure VPN connection when working remotely that disconnects automatically when working at the office and vice versa, that can be deployed via Intune. I hope you found this article helpful or at least down the path of enlightenment as myself. Please click the like button below, and feel free to share. Happy scripting!

Get in Touch

Ready for Worry-Free IT? We can help.

Copyright 2024 © All rights Reserved. The IT Geeks.

Share this:

Like this:

Like Loading...

Need Help?

We're Here To Assist You

Schedule Your Appointment.

Feel free to schedule your appointment, and we will be more than happy to assist you with all of your IT needs.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Need Help?

We're Here To Assist You

Something isn’t Clear?

Feel free to contact us, and we will be more than happy to answer all of your questions.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.