Azure “Always On” VPN Point to Site Workaround

Hello, everyone! Recently, I talked about how to deconstruct the Azure VPN client (article in Portuguese) detailing a process to manually create the VPN connection between On-premises and Azure. Today I’m going to give a workaround to keep the connection alive all the time. As you may know, there’s no built-in functionality in Windows to automatically reconnect or start the connection after the boot process. The idea is to use the information we gathered from the first article to create a script to close the connection between the parties.

First of all, if you haven’t at this point, Configure a Point-to-Site VPN connection to a VNet. You need the Azure VPN client installed and working.

Second, we need to start the connection through PowerShell scripting. Here’s a modified version of Tom Wu‘s script (original here). Save this file as ConnectAzure.ps1. Make sure to change variables below according to your scenario otherwise the script will not work. Just read the comments carefully.


function Log-Message{
    param($Message)
    
    # Where to save log files?
    $dirLog = "c:\VPN\Logs"
        
    $dir = Get-Item -Path $dirLog
    if(-not $dir)
    {
        New-Item -ItemType directory -Path $dirLog
    }
    
    $today = Get-Date
    $logFile = $dirLog + "\" + $today.Day + ".log"

    $today.ToString() + " : " + $Message >> $logFile
}

while($true)
{
    # Wait 60 seconds before new check
    Start-Sleep 60

    # Make sure you have Azure VPN Client installed and working
    $vpnParentDir = $env:APPDATA + "\Microsoft\Network\Connections\Cm"
    $itemsInDir = Get-ChildItem -Path $vpnParentDir | ?{ $_.PSIsContainer } | Select-Object Name
    if(-not $itemsInDir)
    {
        Log-Message -Message "Can't find Azure Point to Site VPN installed on this computer, please double check."
        continue
    }

    if($itemsInDir -isnot [System.Array])
    {
        $vpnGateway = $itemsInDir.Name
    }
    else
    {
        Log-Message -Message "Multiple directory found under $vpnParentDir, we select the first one as vpn gateway."
        $vpnGateway = $itemsInDir[0].Name
    }

    # Check if a cloud server can be contacted
    # Replace with your Azure server private IP
    $azureServerIp = "10.0.0.36"    
    $result = gwmi -query "SELECT * FROM Win32_PingStatus WHERE Address = '$azureServerIp'" 
    if ($result.StatusCode -eq 0) { 
        Log-Message -Message "Server $azureServerIp is up."
    } 
    else
    { 
        Log-Message -Message "Server $azureServerIp is down."

        # Double checking if VPN is really down. Try to disconnect first.
        Log-Message -Message "Disconnecting..."
        rasdial $vpnGateway /DISCONNECT 
        
        # Connect using Azure VPN gateway 
        Log-Message -Message "Connecting..."
        rasdial $vpnGateway /PHONEBOOK:$vpnParentDir\$vpnGateway\$vpnGateway.pbk 

        # Check assined IP address
        # Replace with your Azure VNET Point to site IP segment
        $azureVnetP2SRange = "172.16.0"
        $azureIpAddress = ipconfig | findstr $azureVnetP2SRange
        
        $azureIpAddress = $azureIpAddress.Split(": ")
        $azureIpAddress = $azureIpAddress[$azureIpAddress.Length-1]
        $azureIpAddress = $azureIpAddress.Trim()

        # If Azure hasn't given us one yet, exit and let u know
        if (!$azureIpAddress){
            Log-Message -Message "You do not currently have an IP address in your Azure subnet."
            continue
        }

        # Delete any previous configured routes for these ip ranges
        $azureVnetRange = "10.0.0.0"
        $routeExists = route print | findstr $azureVnetRange
        if($routeExists) {
            Log-Message -Message "Deleting route to Azure: $azureVnetRange"
            route delete $azureVnetRange
        }

        # Add our new routes to Azure Virtual Network
        Log-Message -Message "Adding route to Azure: $azureVnetRange"
        Log-Message -Message "route add $azureVnetRange MASK 255.255.255.0 $azureIpAddress"
        route add $azureVnetRange MASK 255.255.255.0 $azureIpAddress
    }
}

Create a new task in Windows task scheduler to execute this script periodically. Here’s a quick way of doing it:

schtasks /create /tn "Connect Azure VPN" /tr "%windir%\system32\WindowsPowerShell\v1.0\powershell.exe C:\VPN\ConnectAzure.ps1" /sc onstart /ru "myuser" /rp "mypassword"

Make sure to change file path and user account/password.

…And that’s it. If everything goes right, VPN connection should start automatically and the connection will be verified every minute to guarantee it’s still alive.

The only downside is that you have no control over the IP that your client is going to get making the DNS Server a must have for this use case.

References

[1] Configurando VPN Point to Site para o Azure Manualmente

[2] Tom Wu’s Blog

[3] Configure a Point-to-Site VPN connection to a VNet

[4] Azure VPN Scripts

 

3 thoughts on “Azure “Always On” VPN Point to Site Workaround

  1. Hi Bruno!
    I use your script on two computers and they are connected to azure vpn, but when I have been trying ping from first to second (and vice versa) I recive message from my private ip gateway vpn address: “destination net unreachable”.
    I couldn’t connected with remote desktop from first to second.
    Have you any suggestion what do I doing wrong?

    1. Point to Site is not transitive, which means from your workstation you can access the Azure network, but you can’t access other computers connected through VPN. A -> Azure <- B, which means, A can reach Azure and B can reach Azure, but A never reaches B and vice-versa.

Leave a Reply

Your email address will not be published. Required fields are marked *