Recently, we were in a situation where we needed to remove some left over Always-on VPN user tunnels from a lot of Windows 10 machines. (We had duplicate profiles, and this was a tidy up exercise)
The following scripts address this issue, it gets a list of all the VPN connections and then removes all the connections. The second script would be used if you wanted to remove all the connections then add the correct profile. We use these scripts with SCCM. This is wrapped into a package and the PowerShell is called from a batch file using psexec.exe.
These scripts are modified versions of scripts originally created by Richard Hicks – if you haven’t already come across his site, and you are working on Direct Access or Always-on VPN, I strongly recommend you head over to his site and take a look! www.richardhicks.com
<#
#
.SYNOPSIS
Deletes all Always On VPN user tunnel connections.
.DESCRIPTION
This script will delete all Always On VPN device tunnels on supported Windows 10 devices.
.LINK
https://docs.microsoft.com/en-us/windows-server/remote/remote-access/vpn/always-on-vpn/deploy/vpn-deploy-client-vpn-connections#bkmk_fullscript
.NOTES
Version: 1.01
Creation Date: April 04, 2020
Special Note: This script adapted from published guidance provided by Microsoft.
Original Author: Microsoft Corporation
Original Script: https://docs.microsoft.com/en-us/windows-server/remote/remote-access/vpn/always-on-vpn/deploy/vpn-deploy-client-vpn-connections#bkmk_fullscript
Author: Richard Hicks
Organization: Richard M. Hicks Consulting, Inc.
Contact: ri**@ri**********.com
Web Site: www.richardhicks.com
#>
# Lets log the output for troubleshooting..
New-Item -ItemType Directory -Force -Path "C:\programdata\AlwaysOnVPN"
Start-Transcript -Path "C:\programdata\AlwaysOnVPN\create_tunnel_transcript.txt"
# Get the ID and security principal of the current user account
# OMA URI information
$NodeCSPURI = './Vendor/MSFT/VPNv2'
$NamespaceName = 'root\cimv2\mdm\dmmap'
$ClassName = 'MDM_VPNv2_01'
try {
$Username = Get-WmiObject -Class Win32_ComputerSystem | Select-Object username
$User = New-Object System.Security.Principal.NTAccount($Username.Username)
$Sid = $User.Translate([System.Security.Principal.SecurityIdentifier])
$SidValue = $Sid.Value
Write-Verbose "User SID is $SidValue."
Write-Output "User SID is $SidValue." | Out-File C:\ProgramData\AlwaysONVPN\UserSID.txt
}
catch [Exception] {
Write-Output "Unable to get user SID. User may be logged on over Remote Desktop: $_"
Write-Output "Unable to get user SID. User may be logged on over Remote Desktop: $_ "| Out-File C:\ProgramData\AlwaysONVPN\SIDError.txt
#exit
}
$Session = New-CimSession
$Options = New-Object Microsoft.Management.Infrastructure.Options.CimOperationOptions
$Options.SetCustomOption('PolicyPlatformContext_PrincipalContext_Type', 'PolicyPlatform_UserContext', $false)
$Options.SetCustomOption('PolicyPlatformContext_PrincipalContext_Id', "$SidValue", $false)
# delete the profiles
$deleteInstances = $session.EnumerateInstances($namespaceName, $className, $options)
foreach ($deleteInstance in $deleteInstances)
{
$InstanceId = $deleteInstance.InstanceID
$session.DeleteInstance($namespaceName, $deleteInstance, $options)
$Message = "Removed $ProfileName profile $InstanceId"
Write-Host "$Message"
}
Write-Output 'Script complete.'
stop-transcript
The second script has a couple of lines you will want to change in lines 32 and 36.
This script removes all Always-on VPN user tunnels and replaces them with the one you specify
<#
#
.SYNOPSIS
Creates an Always On VPN user tunnel connection.
.PARAMETER xmlFilePath
Path to the ProfileXML configuration file.
.PARAMETER ProfileName
Name of the VPN profile to be created.
.EXAMPLE
New-AovpnConnection.ps1 -xmlFilePath "C:\Users\rdeckard\desktop\ProfileXML.xml" -ProfileName "Always On VPN User Tunnel"
.DESCRIPTION
This script will create an Always On VPN device tunnel on supported Windows 10 devices, and delete all other profiles.
.LINK
https://docs.microsoft.com/en-us/windows-server/remote/remote-access/vpn/always-on-vpn/deploy/vpn-deploy-client-vpn-connections#bkmk_fullscript
.NOTES
Version: 1.01
Creation Date: April 04, 2020
Special Note: This script adapted from published guidance provided by Microsoft.
Original Author: Microsoft Corporation
Original Script: https://docs.microsoft.com/en-us/windows-server/remote/remote-access/vpn/always-on-vpn/deploy/vpn-deploy-client-vpn-connections#bkmk_fullscript
Author: Richard Hicks
Organization: Richard M. Hicks Consulting, Inc.
Contact: ri**@ri**********.com
Web Site: www.richardhicks.com
#>
New-Item -ItemType Directory -Force -Path "C:\programdata\AlwaysOnVPN"
Start-Transcript -Path "C:\programdata\AlwaysOnVPN\create_tunnel_transcript.txt" -NoClobber
cls
###########################################################################
# change this line to point to your vpnrofile.xml that you wish to deploy #
###########################################################################
$xmlFilePath = "C:\ProgramData\AlwaysONVPN\VPNprofile.xml"
##########################################################################
# Name the connection - this is what users will see! #
##########################################################################
$ProfileName = "AlwaysON VPN Connection"
# Import ProfileXML
$ProfileXML = Get-Content $xmlFilePath
# Escape spaces in profile name
$ProfileNameEscaped = $ProfileName -replace ' ', '%20'
$ProfileXML = $ProfileXML -replace '<', '<'
$ProfileXML = $ProfileXML -replace '>', '>'
$ProfileXML = $ProfileXML -replace '"', '"'
# OMA URI information
$NodeCSPURI = './Vendor/MSFT/VPNv2'
$NamespaceName = 'root\cimv2\mdm\dmmap'
$ClassName = 'MDM_VPNv2_01'
try {
$Username = Get-WmiObject -Class Win32_ComputerSystem | Select-Object username
$User = New-Object System.Security.Principal.NTAccount($Username.Username)
$Sid = $User.Translate([System.Security.Principal.SecurityIdentifier])
$SidValue = $Sid.Value
Write-Verbose "User SID is $SidValue."
Write-Output "User SID is $SidValue." | Out-File C:\ProgramData\AlwaysONVPN\UserSID.txt
}
catch [Exception] {
Write-Output "Unable to get user SID. User may be logged on over Remote Desktop: $_"
Write-Output "Unable to get user SID. User may be logged on over Remote Desktop: $_ "| Out-File C:\ProgramData\AlwaysONVPN\SIDError.txt
#exit
}
$Session = New-CimSession
$Options = New-Object Microsoft.Management.Infrastructure.Options.CimOperationOptions
$Options.SetCustomOption('PolicyPlatformContext_PrincipalContext_Type', 'PolicyPlatform_UserContext', $false)
$Options.SetCustomOption('PolicyPlatformContext_PrincipalContext_Id', "$SidValue", $false)
# remove all the profiles
$deleteInstances = $session.EnumerateInstances($namespaceName, $className, $options)
foreach ($deleteInstance in $deleteInstances)
{
$InstanceId = $deleteInstance.InstanceID
$session.DeleteInstance($namespaceName, $deleteInstance, $options)
$Message = "Removed $ProfileName profile $InstanceId"
Write-Host "$Message"
}
try {
$NewInstance = New-Object Microsoft.Management.Infrastructure.CimInstance $className, $namespaceName
$Property = [Microsoft.Management.Infrastructure.CimProperty]::Create('ParentID', "$nodeCSPURI", 'String', 'Key')
$NewInstance.CimInstanceProperties.Add($Property)
$Property = [Microsoft.Management.Infrastructure.CimProperty]::Create('InstanceID', "$ProfileNameEscaped", 'String', 'Key')
$NewInstance.CimInstanceProperties.Add($Property)
$Property = [Microsoft.Management.Infrastructure.CimProperty]::Create('ProfileXML', "$ProfileXML", 'String', 'Property')
$NewInstance.CimInstanceProperties.Add($Property)
$Session.CreateInstance($namespaceName, $NewInstance, $Options)
Write-Output "Created $ProfileName profile."
Write-Output "Created $ProfileName profile." | Out-File C:\ProgramData\AlwaysONVPN\CreatedProfile.txt
}
catch [Exception] {
Write-Output "Unable to create $ProfileName profile: $_"
Write-Output "Unable to create $ProfileName profile: $_" | Out-File C:\ProgramData\AlwaysONVPN\ProfileCreationError.txt
exit
}
Write-Output 'Script complete.'
stop-transcript