Introduction
This is another post, I have wanted to do for some time now. Always On VPN is not something new, but many organizations are moving away from Direct Access, and Always On VPN seems to be the preferred and logical choice for many – including ours.
Also, I don’t think that the current outbreak of COVID-19 has missed anyone’s attention, which is why working from home and remote via VPN has become highly relevant these days.
This post will not go into details on the infrastructure required in order to setup Always On VPN (Remote Access Server, Network Policy Server, PKI etc.), but rather explain the configurations made on the client with Microsoft Intune and Configuration Manager. I will also elaborate on my experiences, again from the perspective of a production environment.
Finally, a big shout out to Michael Mardahl for always being a tremendous help. Go follow this dude. He’s amazing at what he does. π
Microsoft Intune
Configuring the Always On VPN client on Windows 10 can be done i numerous ways. Microsoft Intune came out as the obvious choice for us, as this is being done with a GUI (and we co-manage our devices with Resource access policies being managed in the cloud).
- Note: The alternatives are messing around with Powershell and deploying a script, which in return creates the VPN profile for you. This is the more difficult choice, but can be necessary, if you need a configuration which is not possible through Intune.
A quick peek at the overall settings of the Always On VPN configuration in Microsoft Intune down below. I will elaborate on each where it makes sense.
Base VPN
The Base VPN settings are configured like below:
- Connection name: Always On VPN
- This is just the display name of the connection.
- Servers: aovpn.imab.dk
- This is the entry point. This is the IP address or FQDN where the VPN client tries to establish a connection to.
- Connection type: Automatic
- This is the protocol being used and the VPN strategy of the connection
Attention: This particular part of the configuration is especially interesting, as the recommended protocol is IKEv2.
However, selecting Automatic will result in a VPN strategy, where the Windows 10 client is attempting to establish a VPN connection using SSTP first and then IKEv2.
- Note: You can verify and see the VPN strategy by browsing the Application event log as shown below:
What most are trying to accomplish here though, is to use IKEv2 first and then SSTP as the fallback option.
Note: Using IKEv2 is not without obstacles, and in my experience, you cannot solely rely on IKEv2 as the primary protocol. IKEv2 is not permitted everywhere, why you must have a fallback option like SSTP in place (which practically translates into HTTPS).
In order to achieve the desired VPN strategy, you will have to do some modifying of the rasphone.pbk file (AppData\Roaming\Microsoft\Network\Connections\Pbk).
Powershell
Over on my GitHub page at https://github.com/imabdk, as well as down below, you will find a script which is capable of modifying the local rasphone.pbk file and the VPN strategy.
The script accepts and requires the parameter: -strategyNumber, and the input is validated to only accept any of the numbers: 5 – 6 – 7 – 8 – 14
The numbers translates as following:
5 = Only SSTP is attempted
6 = SSTP is attempted first
7 = Only IKEv2 is attempted
8 = IKEv2 is attempted first
14 = IKEv2 is attempted followed by SSTP
<# .SYNOPSIS This script reads the current AlwaysOn VPN strategy and changes it to the set value if required. .DESCRIPTION This script reads the current AlwaysOn VPN strategy and changes it to the set value if required. This is to cater for situation where Windows 10 automatically changes the VPN strategy to something undesirable. Intune currently only supports setting the connection type to either IKEv2, L2TP, PPT or automatic. If you want a different strategy, you will need to use a script like this. .PARAMETER strategyNumber Specify the desired VPN strategy by number. The options are: 5 = Only SSTP is attempted 6 = SSTP is attempted first 7 = Only IKEv2 is attempted 8 = IKEv2 is attempted first 14 = IKEv2 is attempted followed by SSTP .NOTES Filename: Set-VPNStrategy.ps1 Version: 1.0 Author: Martin Bengtsson Blog: www.imab.dk Twitter: @mwbengtsson #> [cmdletbinding()] param( [Parameter(Mandatory=$true)] [ValidateSet("5","6","7","8","14")] [string]$strategyNumber ) function Get-VPNStrategy() { switch ($strategyNumber) { 5 {$strategyDesc = "Only SSTP is attempted"} 6 {$strategyDesc = "SSTP is attempted first"} 7 {$strategyDesc = "Only IKEv2 is attempted"} 8 {$strategyDesc = "IKEv2 is attempted first"} 14 {$strategyDesc = "IKEv2 is attempted followed by SSTP"} } $rasphonePath = "$env:APPDATA\Microsoft\Network\Connections\Pbk\rasphone.pbk" if (Test-Path $rasphonePath) { try { $currentStrategy = (Get-Content $rasphonePath) -like "VpnStrategy=*" } catch { } } else { Write-Verbose -Verbose -Message "The path for rasphone.pbk does not exist" } Write-Output $currentStrategy } function Set-VPNStrategy() { switch ($strategyNumber) { 5 {$strategyDesc = "Only SSTP is attempted"} 6 {$strategyDesc = "SSTP is attempted first"} 7 {$strategyDesc = "Only IKEv2 is attempted"} 8 {$strategyDesc = "IKEv2 is attempted first"} 14 {$strategyDesc = "IKEv2 is attempted followed by SSTP"} } $rasphonePath = "$env:APPDATA\Microsoft\Network\Connections\Pbk\rasphone.pbk" $currentStrategy = Get-VPNStrategy $newStrategy = "VpnStrategy=$strategyNumber" if ($currentStrategy) { if ($currentStrategy -ne $newStrategy) { try { (Get-Content $rasphonePath).Replace($currentStrategy,$newStrategy) | Set-Content $rasphonePath Write-Verbose -Verbose -Message "VPN strategy is now configured to: $newStrategy" Write-Verbose -Verbose -Message "The VPN strategy description is: $strategyDesc" } catch { Write-Verbose -Verbose -Message "Failed to apply new VPN strategy" } } elseif ($currentStrategy -eq $newStrategy) { Write-Verbose -Verbose -Message "VPN strategy is already properly configured to: $currentStrategy" Write-Verbose -Verbose -Message "The VPN strategy description is: $strategyDesc" } } } try { Write-Verbose -Verbose -Message "Script is running" Set-VPNStrategy } catch { Write-Verbose -Verbose -Message "Something went wrong during running of the script" } finally { Write-Verbose -Verbose -Message "Script is done running" }
Configuration Manager
Above Powershell script is something you can run on a schedule, and therefore always make sure the VPN strategy on your devices is a given value.
- powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile -WindowStyle Hidden -File .\Set-VPNStrategy.ps1 -strategyNumber 14
- powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile -WindowStyle Hidden -File .\Set-VPNStrategy.ps1 -strategyNumber 8
- powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile -WindowStyle Hidden -File .\Set-VPNStrategy.ps1 -strategyNumber 7
- powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile -WindowStyle Hidden -File .\Set-VPNStrategy.ps1 -strategyNumber 6
- powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile -WindowStyle Hidden -File .\Set-VPNStrategy.ps1 -strategyNumber 5
Below is a snippet of the package in my environment, which has a program for each of the available VPN strategies:
Below another example from the Software Center in my environment, illustrating that this is something you are able to deploy to whatever device that needs it.
A real world scenario might be, that some devices might need a configuration of Always On VPN, that currently isn’t supported by the GUI in Microsoft Intune.
Intune Continued
Base VPN
The authentication lies within PEAP (Protected Extensible Authentication Protocol), and the configuration needed here is based on some exported XML.
This piece of XML basically comes from the VPN connection, which initially was made manually and tested as working.
Below the example of my VPN connection. This is the one created automatically by Intune once the configuration profile has been assigned, but the profile created manually will obviously be similar.
Note: Create the piece of XML needed for the configuration profile with below 2 lines of Powershell
$Vpn = Get-VpnConnection -Name 'Always On VPN' $Xml = $Vpn.EapConfigXmlStream.InnerXml | Out-File .\eap.xml -Encoding ASCII
DNS Settings
DNS! Boy this one initially caused me some headaches.
My domain imab.dk exists both externally and internally, and while aovpn.imab.dk only resolves externally, that can cause some connection issues if aovpn.imab.dk isn’t excluded from the NRPT rules.
So if you include your entire domain like I do, and tell the VPN client to resolve DNS lookups internally, make sure you exclude the FQDN for the Always On connection by not configuring any DNS servers. This will make sure that aovpn.imab.dk is always resolved externally. This should make sure that you don’t face the issue I did, where aovpn.imab.dk was being looked up internally, which of course caused the connection to fail.
Split Tunneling
This part is pretty straight forward. You configure the various destination prefixes which you want to have routed through your VPN server. That’s usually all of your internal LAN, or at least the networks you want your VPN clients to be able to reach from the Always On VPN connection.
I’m mentioning this part regardless, as in a split tunneling scenario, there might be some very specific websites which has access granted through IP validation. In other words, these type of websites, you will want to browse as coming from inside of your corporate network. The only way I could get this to work properly, was to simply fetch the said websites IP and configure it with a prefix of 32.
Note: I know IP addresses are subject to change, but some providers are actually able to provide you with an IP address which is considered static.
Note: Further to above configuration, depending on the setup on your VPN server, you might need additional configuration in terms of adding permanent routes using ADD ROUTE, sending the traffic onwards to a gateway which has Internet access. I’m going to spare you on the technical details on this part for now. π
Other gotchas?
For now I’ve only stumbled across one other oddity, which again is related to how DNS does it magic.
This is not directly related to each device or the configuration hereof, but rather the ISP or the equipment providing the Internet connection. I don’t have comprehensive details here, but on a small percentage of our devices, once the device was connected through VPN, the device had difficulties doing any local naming resolution lookups.
Turned out that Smart Multi-Homed Name ResolutionΒ is evil and we had to turn it off on those experiencing the issue:
ENJOY π
I have seen the issues on multiple builds on Windows as well with DNS.
It looks like the issue is most with a specific modem device from the ISP which has Ipv6 as DNS server on LAN connection. Often on wifi it works without an issue.
The issue is especially when you have a DNS record in place both internal and publically availabe as for Outlook for example is often the case.
In some cases at build 1803 (not sure if this is still an issue) i had to force the VPN profile to get a lower metric than local network card before the issue was resolved.
Thanks for sharing that, and I concur with your observation. I’ve only seen it when devices are connected via specific equipment π
Hi! We had the same issue with DNS. Some sites deliver internal another content then external. Split brain DNS. If I was connected via WLAN I got internal DNS resolution than connected via LAN to VPN. The resolution is to set the metric if the VPN adapter to something lower the the WLAN / LAN adapter. During creation of the VPN profile (yes we do not use Intune, I deploy the profile with ConfigMgr).
I set IpInterfaceMetric and Ipv6InterfaceMetric to 10 with the pbk file.
(Get-Content -Path “C:\Users\$Benutzer\AppData\Roaming\Microsoft\Network\Connections\Pbk\rasphone.pbk”) | `
ForEach-Object {$_ -replace ‘VPNStrategy=.*’, ‘VPNStrategy=14’} | `
ForEach-Object {$_ -replace ‘NumCustomPolicy=.*’, “NumCustomPolicy=1 `r`nCustomIPSecPolicies=020000000200000003000000030000000200000003000000”} | `
ForEach-Object {$_ -replace ‘IpInterfaceMetric=.*’, ‘IpInterfaceMetric=10’} | `
ForEach-Object {$_ -replace ‘Ipv6InterfaceMetric=.*’, ‘Ipv6InterfaceMetric=10’} | `
Set-Content -Path “C:\Users\$Benutzer\AppData\Roaming\Microsoft\Network\Connections\Pbk\rasphone.pbk” -Force
Now everything works like expected.
a-ha! thanks for the extra details Dietmar. π
Hi Martin, I have successfully deployed an always-on VPN across 100+ of our users using SCEP and machine certificates, however one of them is located in a location where VPN connections are blocked to Azure over IKEv2. As I already had a working solution my plan was to follow this guide and add a second configuration purely for this and any other similarly affected users in future and simply change to the Automatic method, adopting SSTP. Unfortunately no matter what settings I use in the EAP security I am told that no certificates exist that can be used with EAP, despite it working fine on IKEv2 with the same certificates but no EAP specific config.
Do you have any ideas as to what I may have done wrong or if I’m simply missing something?
Thanks, Lee
Splendid article Martin. I have one follow-up question. During your deployment, did you encounter any problems with the remediation of the VPN-Profile when it was deployed from Intune?
I have seen it take some time for the assignment status to settle in. Initially, it often comes back with error, though the clients have received it just fine. I’ve learned to ignore that, as the assignment status always seem to settle in the following days after initial assignment or when doing changes to the existing profile.
Cool. I actually managed to remediate the issue. Apparently I had the wrong formatting for the EAP-XML. The VPN-connection worked but every time I Intune-synced the device Intune got “remediation failed” for the VPN-profile and as a result it disconnected-reconnected. Very odd error, but exporting the EAP-XML again and verifying the exact formatting solved the issue. Thanks for the reply.
Hey Martin π
Any thoughts on sizing “always on” vpn server? (RRAS)
Thanks in advance
Hi,
Are you aware of any issues with Win 10 2004 with AlwayOnVPN not auto connecting?
We are having this on our 2004 test machines. You boot up and login as normal but the AlwaysOnVPN has not connected. You have to manually connet and enter your password which then works.
Have you seen this?
Thanks
Hey Matt, I’m not aware of any issues like that. I’m running 2004 myself with Always On VPN, and my VPN auto connects without any prompts for anything π
Hi Matt,
There’s a known issue for this now – https://admin.microsoft.com/AdminPortal/Home#MessageCenter?id=MC218133. IT’s a random issue though and the workaround is to not apply to 2004 builds and use ‘an alternative solution’.
Great article thanks. Do you know if there any way to tie the VPN status into Toast notifications? One of my main concerns about AoVPN is the fact there is no notification when the tunnel goes down and there is no obvious way for users to be made aware of this.
On our AAD joined devices, we experienced that vpn is still connected when device was using LAN. Do you have any suggestions on how to resolve this?
Hi.
Mr Hicks told me of another option if you want to just have VPN Strategy 14 (Ike first then sstp), you can set a registry key so Windows doesnt change vpn strategy. Then you can set Vpn strategy 14 in rasphone and it will stay that way.
Only works with 1903 and newer.
HKLM\SYSTEM\CurrentControlSet\Services\RasMan\Parameters\VPNStrategyUsageDisabled DWORD 1
Have a nice weekend.
/Simon
Wow nice. Thanks for letting me know π
Thankyou for all your effort on this. We have a dual VPN setup, Device tunnel is IKEv2 and User is Auto. Currently users have reverted to VpnStrategy 6, Device tunnel is solid as uses only IKEv2 and it doesn’t change. The script when run by the user can update the value to be correct. But SCCM doesn’t have a User based deployment and Task Scheduler when running the script using an account like SYSTEM will return the same account using $env:username, not the user whom is logged in. cant use $env:appdata in the PS script as it uses the account running the script, in this case SYSTEM.
Trying to find a way to update all out users to VpnStrategy 14 and in the process also install the RegKey “VPNStrategyUsageDisabled” so it doesnt flop back again.