Monitoring with PowerShell: Monitoring client VPN settings

So with all that’s going on a lot of people are having trouble keeping up with setting up VPNs correctly. I’ve also struggled with clients that do not have a cloud only solution but are still on a hybrid method of working.

In the past I’ve talked about Always On VPN which we tend to deploy at clients. This, and even just SSTP connections are our most used VPN method. I tend to like Microsoft solutions for everything. 😉 In any case – We’ve been having trouble with this too. Some people suggest using CMAK to assist in deploying VPN. Of course like using my RMM system instead. 😉

As with most of the blogs I’ve created two scripts; one for monitoring and one for remediation.

The monitoring script

In our RMM we can give each monitoring script a set of input variables. Using these input variables we check if the VPN is set the way we want it. If you can’t setup input variables on your RMM, just change them in the script.

$Settings = @{
    name                  = "Client based VPN"
    alluserconnection     = $true
    ServerAddress         = "remote.clientname.com"
    TunnelType            = "SSTP" #Can be: Automatic, Ikev2m L2TP, PPTP,SSTP.
    SplitTunneling        = $True 
    UseWinLogonCredential = $true
    #There's a lot more options to set/monitor. Investigate for your own settings.
}
$VPN = Get-VPNconnection -name $($Settings.name) -AllUserConnection -ErrorAction SilentlyContinue
if (!$VPN) {
    $VPNHealth = "Unhealthy - Could not find VPN Connection."    
} 
else {
    $ExpectedVPNSettings = New-Object PSCustomObject -property $Settings
    $Selection = $propsToCompare = $ExpectedVPNSettings.psobject.properties.name
    $CurrentVPNSettings = $VPN | Select-object $Selection
    $CompareVPNSettings = compare-object $CurrentVPNSettings  $ExpectedVPNSettings -Property $Selection
    if (!$CompareVPNSettings) { $VPNHealth = "Healthy" } else { $VPNHealth = "Unhealthy - Settings do not match." }
}

So now that you are monitoring the VPN connection and if the settings are correct, we’re moving on to the remediation or setup side of the house.

Remediation script

the remediation works by looking up the current VPN connections based on the name property, if the VPN does not yet exists we will add one. If it does exists, we will reset the settings to the way we would like them to be.

$Settings = @{
    name                  = "Client based VPN"
    alluserconnection     = $true
    ServerAddress         = "remote.clientname.com"
    TunnelType            = "SSTP" #Can be: Automatic, Ikev2m L2TP, PPTP,SSTP.
    SplitTunneling        = $True 
    UseWinLogonCredential = $true
    #There's a lot more options to set/monitor. Investigate for your own settings.
}
$VPN = Get-VPNconnection -name $($Settings.name) -AllUserConnection -ErrorAction SilentlyContinue
if (!$VPN) {
    Add-VPNconnection @Settings -verbose
}
else {
    Set-VpnConnection @settings -Verbose
}

What’s cool is that these scripts work for any VPN that uses the Windows VPN client. This makes it super simple to deploy and monitor your clients VPN connections, and always have the same settings across your entire customer base.

And that’s it! as always, Happy PowerShelling.

15 Comments

  1. Eric Chapman April 2, 2020 at 5:16 pm

    Kelvin,
    Superb post!
    As a MSP we also utilize SSTP (CHAPv2) as well as the Always On VPN configuration. I do find that you need to keep an eye on these settings as they change from time to time or do not “auto-reconnect” as expected.

    Do you use any similar remediation and monitoring scripts for your “Always On VPN” configurations? (Device Tunnel or User Tunnel).

    Eric

    1. Kelvin Tegelaar April 2, 2020 at 9:29 pm

      Hi Eric,

      Yes, we actually compare the XML to the configured VPN connection at that moment. There’s some caveats in it and I might blog about this next week. 🙂

      1. Eric Chapman April 3, 2020 at 7:13 pm

        Kelvin,
        That would be awesome. I would be quite interested to see your methods. I do find that most “Always On” documentation and posts are in a very corporate environment where it’s succeeded Direct Access. As an MSP – we typically are dealing with the SMB market where things quickly go out of the scope of a big corp. (i.e. – We are sending out a laptop to a user that has never even been to the LAN in the office, so no GPO’s, etc for certificates and such).

        I’ve noticed as of late, we have a number of user vpn profiles which seem to oddly change themselves / corrupt. The idea of auditing / re mediating is for sure the route we hope to expand.

        Looking forward to your post, and very much enjoying your previous posts. Glad I discovered your site. Thanks

  2. Pingback: ICYMI: PowerShell Week of 03-April-2020 | PowerShell.org

  3. Tony April 8, 2020 at 6:12 pm

    Hey Kelvin,

    Really interesting post, thanks.

    I just wanted to ask how would these scripts deploy/work in production – assuming they are a real-time job rather than something that runs ongoing and saves the output somewhere for admins to view? At this stage we only have the option to deploy scripts via GPO but assume I could run this script against a list of machines from AD assuming WSMAN access to the machines is open?

    Thanks

    1. Kelvin Tegelaar April 10, 2020 at 12:21 am

      Hi Tony,

      So most of my scripts are made to be run by an RMM system, which is what MSPs use to monitor and deploy environments for their clients.

      Other solutions could be running it as a startup logon script, or running it remotely yeah. 🙂

  4. Nedim April 17, 2020 at 4:11 pm

    Hi Kelvin,
    How can I add Pre-Shared key into this script? I tried Adding below, but looks like the script is hanging… please advise.

    L2tpPsk = $ENV:PreSharedKey

    also i was adding Variable Value PreSharedKey. thank you

    1. Kelvin Tegelaar April 17, 2020 at 4:36 pm

      Good question. I normally don’t use L2TP, and the method you are describing is correct for when you use DattoRMM. I’ll test it myself and come back to you later on this 🙂

      1. nedim April 19, 2020 at 12:34 am

        Thanks Kelvin,
        what do you use if I may ask? And thanks for checking this for me!

        1. Kelvin Tegelaar April 19, 2020 at 12:15 pm

          I’m going to be releasing an update soon, that’ll allow you to enter the PSK in DattoRMM. 🙂 I’m more of a SSTP type of guy.

      2. JC April 19, 2020 at 3:47 am

        This is something I’d like to see as well. Can it be a hashed value for the PSK?

  5. Dan Gilligan May 7, 2020 at 11:22 pm

    We also have clients setup with L2TP and use Datto RMM. Is there a way we can select unencrypted for password? I’m referring to the settings in the Security tab under “Allow these protocols. by default MS-CHAP is selected. We would like to have Unencrypted password selected (PAP) only.

    Thanks!

    1. Kelvin Tegelaar May 8, 2020 at 9:09 am

      I’m sorry but I can’t help you with that. There might be options for it but I would not feel comfortable creating insecure solutions.

  6. Robert April 28, 2021 at 4:38 am

    Hi Kelvin,

    Your script is great! I have a one-liner that can add it but this is much better. Have you had any luck with an updated version for support with a pre-shared key?

    I tested it out and looks like it defaulting the certificate option but I need the pre-shared key.

    Thanks,

    Robert H

Leave a comment

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.