Skip to content

Instantly share code, notes, and snippets.

@jhorsman
Created January 6, 2015 10:11
Show Gist options
  • Select an option

  • Save jhorsman/88321511ce4f416c0605 to your computer and use it in GitHub Desktop.

Select an option

Save jhorsman/88321511ce4f416c0605 to your computer and use it in GitHub Desktop.
PowerShell to automate VPN connection with Cisco AnyConnect Secure Mobility Client
# Usage: & '.\Cisco_Anyconnect.ps1' [-Server <server name or ip>] [-Group <group>] [-User <user>] [-Password <password>]
#Source www.cze.cz
#This script is tested with "Cisco AnyConnect Secure Mobility Client version 3.1.00495"
# Usage: & '.\Cisco_Anyconnect.ps1' [-Server <server name or ip>] [-Group <group>] [-User <user>] [-Password <password>]
#Please change following variables
#IP address or host name of cisco vpn, Username, Group and Password as parameters
param (
[string]$Server = $( Read-Host "Input server, please" ),
[string]$Group = $( Read-Host "Input group, please" ),
[string]$User = $( Read-Host "Input username, please" ),
[string]$Password = $( Read-Host -assecurestring "Input password, please" )
)
#Please check if file exists on following paths
[string]$vpncliAbsolutePath = 'C:\Program Files (x86)\Cisco\Cisco AnyConnect Secure Mobility Client\vpncli.exe'
[string]$vpnuiAbsolutePath = 'C:\Program Files (x86)\Cisco\Cisco AnyConnect Secure Mobility Client\vpnui.exe'
#****************************************************************************
#**** Please do not modify code below unless you know what you are doing ****
#****************************************************************************
Add-Type -AssemblyName System.Windows.Forms -ErrorAction Stop
#Set foreground window function
#This function is called in VPNConnect
Add-Type @'
using System;
using System.Runtime.InteropServices;
public class Win {
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
}
'@ -ErrorAction Stop
#quickly start VPN
#This function is called later in the code
Function VPNConnect()
{
Start-Process -WindowStyle Minimized -FilePath $vpncliAbsolutePath -ArgumentList "connect $Server"
$counter = 0; $h = 0;
while($counter++ -lt 1000 -and $h -eq 0)
{
sleep -m 10
$h = (Get-Process vpncli).MainWindowHandle
}
#if it takes more than 10 seconds then display message
if($h -eq 0){echo "Could not start VPNUI it takes too long."}
else{[void] [Win]::SetForegroundWindow($h)}
}
#Terminate all vpnui processes.
Get-Process | ForEach-Object {if($_.ProcessName.ToLower() -eq "vpnui")
{$Id = $_.Id; Stop-Process $Id; echo "Process vpnui with id: $Id was stopped"}}
#Terminate all vpncli processes.
Get-Process | ForEach-Object {if($_.ProcessName.ToLower() -eq "vpncli")
{$Id = $_.Id; Stop-Process $Id; echo "Process vpncli with id: $Id was stopped"}}
#Disconnect from VPN
echo "Trying to terminate remaining vpn connections"
Start-Process -WindowStyle Minimized -FilePath $vpncliAbsolutePath -ArgumentList 'disconnect' -wait
#Connect to VPN
echo "Connecting to VPN address '$Server' as user '$User'."
VPNConnect
#Write login and password
[System.Windows.Forms.SendKeys]::SendWait("$Group{Enter}")
[System.Windows.Forms.SendKeys]::SendWait("$User{Enter}")
[System.Windows.Forms.SendKeys]::SendWait("$Password{Enter}")
#Start vpnui
Start-Process -WindowStyle Minimized -FilePath $vpnuiAbsolutePath
#Wait for keydown
#echo "Press any key to continue ..."
#try{$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")}catch{}
@janostl

janostl commented Jan 5, 2018

Copy link
Copy Markdown

Great script. Works fine as long as I have one (1) Cisco Anyconnect profile stored.
But when you have many profiles at same client (and want to use them via shortcuts using this script) it gets stuck.

Then it only work if the FIRST entry in the list is passed as parameters, not for the 2nd or higher entry.

So how to modify the script when there are multiple connection entries at the same client ????

2018-01-05 15-55-15

@hubertsvk

Copy link
Copy Markdown

hi,
i have problem with this script ... i have three profiles and when i can connect to specific profile

PS C:\Users\XXX\Documents> .\Cisco_Anyconnect.ps1 'a.b.com' '' 'a.b'
Process vpnui with id: 18412 was stopped
Process vpncli with id: 7840 was stopped
Trying to terminate remaining vpn connections
Connecting to VPN address 'a.b.com' as user 'a.b'.

and script stopt and then shows me anyconnect dialog with button connect ....

...and the second "problem" is how store username and password in secure way .... i try with this, but without success
$Path = "$home\Desktop\multipass.xml"
[PSCustomObject]@{
User3 = Get-Credential -Message domain\a.b
} | Export-Clixml -Path $Path

$multipass = Import-Clixml -Path $Path

can you help me?

@RamanaReddyV

Copy link
Copy Markdown

Hi

check the below link may be useful. if any problems while setup please let me know.
https://www.codeproject.com/Tips/1250398/Login-VPN-through-Cisco-AnyConnect-Secure-Mobility

@jakawell

Copy link
Copy Markdown

Love this script. Just sharing something that I did to automate import of a one-time password (a la, Google Authenticator, etc.). First, I installed this great open-source Python TOTP/HOTP CLI: https://github.com/JeNeSuisPasDave/authenticator
Once you setup your OTP account in that, you can get the latest OTP in your Powershell script like this:

$AuthResult = "foo" | authenticator generate --refresh "once" | Out-String
$AuthResult -match '([0-9]{6})'
$AuthCode = $matches[0]

Just update the authenticator password (foo, above) and update the regex to match the number of digits in your OTP (I used a typical 6 digit code above).

@UsamaWaheed

Copy link
Copy Markdown
$AuthResult = "foo" | authenticator generate --refresh "once" | Out-String
$AuthResult -match '([0-9]{6})'
$AuthCode = $matches[0]

I tried that but I get an error saying, authenticator command is unknown. If I open CLI and type authenticator generate it works perfectly fine.

authenticator : The term 'authenticator' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the 
spelling of the name, or if a path was included, verify that the path is correct and try again.
At C:\Users\testuser\Desktop\Mode Selector.ps1:218 char:25
+ $AuthResult = "abcde" | authenticator generate --refresh "once" | Out ...
+                         ~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (authenticator:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
 
False

The code that I added is exactly what u did

$AuthResult = "abcde" | authenticator generate --refresh "once" | Out-String
$AuthResult -match '([0-9]{6})'
$AuthCode = $matches[0]

@Shikha1912

Copy link
Copy Markdown

Is there anyway, if we can hide the command line window rather than minimize?

@dlwiii

dlwiii commented Mar 27, 2021

Copy link
Copy Markdown

This works great from the command line. But I added this as a windows scheduled task which runs "powershell" and it does not seem to work. Any idea why this would not work as a scheduled task?

@FPl47h

FPl47h commented Jul 20, 2021

Copy link
Copy Markdown

I had the same problem. I was able to fix it by starting the task as admin.
In the new Jabber version 4.10.01075 I suddenly had problems entering the password. Adjusted line 71 without the wait-operator [System.Windows.Forms.SendKeys] :: Send("$ User {Enter}")

@vensondiana

Copy link
Copy Markdown

Hi,

This was nice and working. Also, we have a banner to accept on dual authentication. Is there a way on how to auto-accept also the banner?

@uluvdj

uluvdj commented Sep 21, 2021

Copy link
Copy Markdown

Hi,

This was nice and working. Also, we have a banner to accept on dual authentication. Is there a way on how to auto-accept also the banner?

Hi, You may have figured this out by now but, what i did to get this to work was after the section that sends the keys to application, i added:

Sleep 20
[System.Windows.Forms.SendKeys]::SendWait(‘y~’)

@ommcodes

Copy link
Copy Markdown

Love this script. Just sharing something that I did to automate import of a one-time password (a la, Google Authenticator, etc.). First, I installed this great open-source Python TOTP/HOTP CLI: https://github.com/JeNeSuisPasDave/authenticator Once you setup your OTP account in that, you can get the latest OTP in your Powershell script like this:

$AuthResult = "foo" | authenticator generate --refresh "once" | Out-String
$AuthResult -match '([0-9]{6})'
$AuthCode = $matches[0]

Just update the authenticator password (foo, above) and update the regex to match the number of digits in your OTP (I used a typical 6 digit code above).

Hi, Did you achieved getting TOPT from Microsoft Authenticator based on the script in the link you provided ?

@mattcargile

Copy link
Copy Markdown

Ever try to automate a M365 login prompt with MFA? We recently switched to it and I really miss my script. I've considered some robo-hack but haven't gotten to it yet. It would be cool if one could hook in with a powershell module like MSAL.PS.

@brianhauge

Copy link
Copy Markdown

@mattcargile

Ever try to automate a M365 login prompt with MFA? We recently switched to it and I really miss my script. I've considered some robo-hack but haven't gotten to it yet. It would be cool if one could hook in with a powershell module like MSAL.PS.

I've added and extra parameters to by able to wait for a 2FA. Add the following after inputs of username and password:

if($Sms -eq 'yes') {
		do { 
            sleep -s 2
        } while (
            -not ( $Host.UI.RawUI.KeyAvailable -and ($Host.UI.RawUI.ReadKey("IncludeKeyUp,NoEcho").VirtualKeyCode -eq 13 ) ) 
       )
}

@brianhauge

brianhauge commented Oct 3, 2023

Copy link
Copy Markdown

I have a problem. After the latest Windows 11 Update, It's not possible to send @ as part of the parameters any longer, when using [System.Windows.Forms.SendKeys]::SendWait. Anyone knows a way around this?

Found out it is because I'm using a danish keyboard. Switching to en-US:

Set-WinUserLanguageList -Force 'en-US'
[System.Windows.Forms.SendKeys]::SendWait("$user{Enter}")
Set-WinUserLanguageList -Force 'da-DK'

@mattcargile

Copy link
Copy Markdown

Thanks @brianhauge . I might look into that. It still seems like I need AutoIT or AutohotKey to really maximize it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment