Always On VPN is Microsoft's replacement for DirectAccess. Always On VPN device tunnels securely extend your domain to internet-connected clients.

Have you had someone try to log into a laptop at a conference and then receive the "no logon servers are available" error? Ever wish your remote devices could easily update policies, install deployed applications, or configure changes? If so, you will love Always On VPN device tunnels!

When Microsoft first released Always On VPN, it only allowed user connections and did not support device connections. Windows 10 1709 introduced device tunnels, Windows 10 1803 improved the implementation, and development toward Windows 10 1809 ironed out some remaining bugs. Before you dive into the steps below, make sure you have followed this core Always On VPN setup guide.

Requirements for Always On VPN device tunnels ^

Windows 10 currently supports device tunnels on two editions: Education and Enterprise. Unlike user tunnels, device tunnels require a domain-joined client. Although you can use Windows 10 1709, it is better to use clients that are either Windows 10 1803 (fully patched) or Windows 10 1809.

The next requirement is that all remote clients have a machine certificate issued by your public key infrastructure (PKI) for the purpose of client authentication. You can check this by running certlm.msc and opening the local computer's personal certificate store. View the details of the certificate and check that Enhanced Key Usage contains the Client Authentication value.

This client has the correct certification for Always On VPN device tunnels

If you do not see a certificate or do not have one for Client Authentication, you can issue the default machine certificate template and configure client auto-enrollment with these steps.

Finally, no other device VPN profile can exist on the computer. If you are not sure if another profile exists, open PowerShell as an administrator and run this command:

Get-VpnConnection ‑AllUserConnection

Configuring RRAS for Always On VPN device tunnels ^

Open the Routing and Remote Access service (RRAS) Microsoft Management Console (MMC) and connect to your VPN server. On the left side of the RRAS console, right-click on your server name and select Properties.

Under Properties, select Security and then select Authentication Methods. Check the Allow machine certificate authentication for IKEv2 box and click OK. Restart RRAS.

Enabling device tunnels over IKEv2

Enabling device tunnels over IKEv2

By default, any valid certificate from any trusted certificate authority (CA) can complete machine certificate authentication to your environment. Just guessing here, but you probably only want machines with a certificate from your CA to be able to authenticate. To restrict access to just your CA, run these PowerShell commands on your VPN server:

$VPNRootCertAuthority = "Common Name of trusted root certification authority"
$RootCACert = (Get-ChildItem -Path cert:LocalMachine\root | Where-Object {$_.Subject -Like "*$VPNRootCertAuthority*" })
Set-VpnAuthProtocol -UserAuthProtocolAccepted Certificate, EAP -RootCertificateNameToAccept $RootCACert -PassThru
#Source - https://docs.microsoft.com/en-us/windows-server/remote/remote-access/vpn/vpn-device-tunnel-config#device-tunnel-requirements-and-features

For reference, you can find the CA common name in the Issuer attribute of the machine certificate you checked earlier. Right-click on the certificate, select Details, and click on the Issuer attribute. The common name is on the first line and is to the right of CN =.

Creating the Always On device tunnel profile ^

Copy this text and save it as an XML file in a location accessible to domain computers:

<VPNProfile>
<NativeProfile>
<Servers>VPNServer.Domain.Com</Servers>
<NativeProtocolType>IKEv2</NativeProtocolType>
<Authentication>
<MachineMethod>Certificate</MachineMethod>
</Authentication>
<RoutingPolicyType>SplitTunnel</RoutingPolicyType>
<!-- disable the addition of a class-based route for the assigned IP address on the VPN interface -->
<DisableClassBasedDefaultRoute>true</DisableClassBasedDefaultRoute>
</NativeProfile>
<!-- use host routes(/32) to prevent routing conflicts -->
<Route>
<Address>10.0.0.2</Address>
<PrefixSize>32</PrefixSize>
</Route>
<Route>
<Address>10.0.0.3</Address>
<PrefixSize>32</PrefixSize>
</Route>
<Route>
<Address>10.0.0.4</Address>
<PrefixSize>32</PrefixSize>
</Route>
<Route>
<Address>10.0.0.5</Address>
<PrefixSize>32</PrefixSize>
</Route>
<!-- traffic filters for the routes specified above so that only this traffic can go over the device tunnel -->
<TrafficFilter>
<RemoteAddressRanges>10.0.0.2, 10.0.0.3, 10.0.0.4, 10.0.0.5</RemoteAddressRanges>
</TrafficFilter>
<!-- need to specify always on = true -->
<AlwaysOn>true</AlwaysOn>
<!-- new node to specify that this is a device tunnel -->
<DeviceTunnel>true</DeviceTunnel>
<!--new node to register client IP address in DNS to enable manage out -->
<RegisterDNS>true</RegisterDNS>
<!-- inside/outside detection -->
<TrustedNetworkDetection>Domain.Com</TrustedNetworkDetection>
</VPNProfile>

Edit the XML file and change the <Servers> line and the <TrustedNetworkDetection> line to the correct values in your environment.

Next, list any IP your remote clients will need to access in the <Route> and <RemoteAddressRanges> sections. The sample profile you copied lists four IPs as examples. Ideally, your profile will only contain the critical services a client needs. These might include domain controllers, WSUS/SCCM, or network policy servers. Even though you can include subnets by changing the PrefixSize line below an IP, I recommend scoping route lines down to a single IP.

In the same folder where you saved the XML file, create a new PowerShell script and paste in the following code:

$ProfileName = 'Always On VPN - Device'

$ProfileXML = 'PASTE DEVICE PROFILE XML BETWEEN SINGLE QUOTATION MARKS'

$ProfileNameEscaped = $ProfileName -replace ' ', '%20'

$ProfileXML = $ProfileXML -replace '<', '&lt;'
$ProfileXML = $ProfileXML -replace '>', '&gt;'
$ProfileXML = $ProfileXML -replace '"', '&quot;'

$nodeCSPURI = './Vendor/MSFT/VPNv2'
$namespaceName = "root\cimv2\mdm\dmmap"
$className = "MDM_VPNv2_01"

$session = New-CimSession

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)
    $Message = "Created $ProfileName profile."
    Write-Host "$Message"
}
catch [Exception] {
    $Message = "Unable to create $ProfileName profile: $_"
    Write-Host "$Message"
    exit
}
$Message = "Complete."
Write-Host "$Message"

Be sure to copy and paste your device profile XML in the $ProfileXML portion of the PowerShell script. You should now have two files in your folder. The first one is an XML file. The second one is a PowerShell script with the contents of your XML file pasted into it.

Deploying the Always On device tunnel profile ^

To deploy your profile, you just need to run the PowerShell script you created under the System account of a client. There are a few options for doing this.

For a single machine (or for testing), you can use the PSExec tool. Run it with the -S parameter and start PowerShell. Finally, run the PowerShell script you created previously.

The second option is to deploy the PowerShell script as a startup script in Group Policy. Startup and shutdown scripts process under the computer's account and run with the required permissions needed to create the VPN profile.

Always On VPN device profile deployment with Group Policy

Always On VPN device profile deployment with Group Policy

Finally, you can deploy it with SCCM. Create a package for your script and allow it to run with administrative rights whether or not a user is logged on.

Always On VPN device profile deployment with SCCM

Always On VPN device profile deployment with SCCM

After using any of these options, verify that the VPN profile is installed. You can verify that the connection is installed with the Get-VPNConnection -AllUserConnection command.

Subscribe to 4sysops newsletter!

You should then be able to connect to an external network and communicate with one the IPs listed in the Route section of your profile. If you included a domain controller in that list, restart the client, connect to a remote network, and log on with a new user. It is a beautiful sight to see that a logon server is indeed available!