68

I am trying to use Cisco anyconnect 3.1 from Linux command line to connect to a server. I can connect, but I have to submit one parameter at a time. I would like to connect from a script that will run in another server. Can I do that? Something like

vpn connect server_add group_name user_name passwd
phuclv
  • 30,396
  • 15
  • 136
  • 260
Kelly Goedert
  • 781
  • 1
  • 6
  • 4

10 Answers10

72

This is assuming /opt/cisco/secureclient/bin/vpnagentd is running as it automatically should be. It has been mentioned that the directory path changed in v5.1 from /opt/cisco/anyconnect/ to /opt/cisco/secureclient, and some may still have the old path.

To connect:

printf 'USERNAME\nPASSWORD\ny' | /opt/cisco/secureclient/bin/vpn -s connect HOST

Replace USERNAME, PASSWORD, and HOST. The \ny at the end is to accept the login banner - this is specific to my host.

Note the single quotes ' instead of double quotes " - this is because double quotes tell Bash to interpret certain characters within strings, such as exclamation marks, as Bash history commands. Double quotes will make this command fail with an "event not found" error if the password contains an exclamation mark. Single-quoted strings pass exclamation marks along without interpreting them.

To disconnect:

/opt/cisco/secureclient/bin/vpn disconnect

This was tested with AnyConnect v3.1.05160.

Asclepius
  • 1,162
17

I ran into the same difficulty try to use Cisco AnyConnect from Mac OS X Terminal. To get the Cisco vpn command to take its input from standard input, you have to specify the -s option, which puts the Cisco vpn command into interactive mode. Then you can provide the responses that you give in interactive mode.

The responses that you need to give depend upon how the VPN server administrator has configured the server. For me, the vpn interactive prompts are

Group: 
Username: 
Password: 

Blah, blah, blah, ...
accept? :

So the command that I run is

$ /opt/cisco/anyconnect/bin/vpn -s connect vpn.example.com <<"EOF"
0
username
password
y
exit
EOF

(The quotes around EOF are to prevent command/parameter expansion/substitution in the following input.)

The exit at the end is to exit the Cisco vpn interactive mode.

9

You can put your connection info in a separate file, e.g.

anyconnect.txt:

connect [HOST]
[GROUP or 0 or 1]
[USER]
[PASSWORD]
y
exit

And then do:

/opt/cisco/anyconnect/bin/vpn -s < anyconnect.txt
d0g
  • 2,380
  • 5
  • 36
  • 43
5

I like to simplify the command line, so I use the above approach in a shell script named gotowork. As above, I need to provide the group, my user name, and a passkey composed of a private PIN plus a RSA SecurID passcode. I don't have to answer the above "accept?" question. Everything but the RSA passcode is in the script, so the command line is

$ gotowork <RSA passcode>

I have to run it as root. Assume the PIN is 1234. The script essentials:

# put the interactive answers into a text file
echo -e "0\nusername\n1234$1\n" > /tmp/answers.txt
# find the path to the anyconnect executables
ciscopath="$(dirname $(find /opt/cisco -depth -name vpnagentd))"
# make sure the anyconnect daemon is running
[ $(pidof vpnagentd) ] || $ciscopath/vpnagentd
# connect
$ciscopath/vpn -s < /tmp/answers.txt connect remote.mycompany.com

Using anyconnect 3.1.05170. Tested on Debian 6, LinuxMint 17

4

This is what worked for me on OSX El Capitan. Placeholders are surrounded by [square braces].

To Enable

/opt/cisco/anyconnect/bin/vpn -s connect [HOST_ADDRESS] <<"EOF"
[VPN_USERNAME]
[VPN_PASSWORD] 
y
EOF

To Disable

/opt/cisco/anyconnect/bin/vpn disconnect

*I know this is similar to Peter S.'s answer above.

adampasz
  • 141
2

To avoid hard-coding your password in a plain-text config file or putting it on the command line, you can also integrate with a CLI password manager like pass.

#!/bin/bash

Easily connect to Cisco AnyConnect VPN

Get first parameter

COMMAND="$1"

case $COMMAND in connect | CONNECT | c | C) printf "2\n${username}\n$(pass show my_password_entry)\n" |
/opt/cisco/anyconnect/bin/vpn -s connect remote_host_url ;;

disconnect | DISCONNECT | d | D)
    /opt/cisco/anyconnect/bin/vpn disconnect
    ;;

*)
    cat &lt;&lt;EOF

Usage: vpnctl COMMAND connect | CONNECT | c | C Connect to the VPN disconnect | DISCONNECT | d | D Disconnect from the VPN EOF ;; esac

The initial 2 in the printf string just selects from a menu which my organization has configured to show up before you can put in your username and password. The exact printf statement may vary for you.

Tested using Cisco AnyConnect 4.10.02086 on Manjaro 21.2.6, with kernel 5.17.9.

2

I had to enter a two-step code, so I had to use the following template.

connect host
username
pass
twostep
y
exit

/opt/cisco/anyconnect/bin/vpn -s < anyconnect.txt


On Mac (Ventura 13.2.1) I wanted to integrate keychain and two-step together so I made the following script. It retrieves the key used for two-step, uses python OTP library to get the two-step code, and also uses keychain to get the password. Then connects to Cisco Connect.

Note that first you need to create the keychain entries as described in the blog referred below. Maybe for testing you can initially hardcode key and password.

Make sure to edit [Username] and [Host]. I had them hardcoded rather than keychain on Mac.

import time
import pyotp
import subprocess

key = subprocess.check_output("security find-generic-password -w -a $LOGNAME -s key", shell=True)[:-1].decode("utf-8")

uri = pyotp.totp.TOTP(key).provisioning_uri() totp = pyotp.TOTP(key)

key = totp.now()

print(key)

password = subprocess.check_output("security find-generic-password -w -a $LOGNAME -s key_password", shell=True)[:-1].decode("utf-8")

output = subprocess.check_output(f"/opt/cisco/anyconnect/bin/vpn -s connect [Host] <<'EOF'\n[UserName]\n{password}\n{key}\ny\nEOF", shell=True)

print(output)

Ref: https://blog.koehntopp.info/2017/01/26/command-line-access-to-the-mac-keychain.html


Steps to create keychain items :

  1. Add otp_key to keychain :
  • security add-generic-password -T "" -a $LOGNAME -s [hostname_otp] -w [otp_key]
  1. Add password of host :
  • security add-generic-password -T "" -a $LOGNAME -s [hostname_username] -w [host_password]

Steps to retrieve saved key and password :

  1. Retrieve host's otp_key
  • security find-generic-password -w -a $LOGNAME -s [hostname_otp]
  1. Retreive password of hostname_username
  • security find-generic-password -w -a $LOGNAME -s [hostname_username]

This will make sure that there is an extra step to connecting to host, i.e. retrieving secret info from keychain after providing the password, rather than hardcoding in a file.

Peregrino69
  • 5,004
0

For this use case, I used expect script. Pasting my solution below:

`#!/usr/bin/expect
spawn sudo /opt/cisco/anyconnect/bin/vpnagentd
expect ": "
send "Sudo Password goes here \r"
expect "$ "
spawn /opt/cisco/anyconnect/bin/vpn -s connect HOST
expect "*]*"
send -- "Username goes here\r"
expect "Password: "
send -- "Password goes here\r"
expect "Answer: "
send -- "If MFA is not enabled, then this step can be skipped\r"
0

Inspired from others answers, I've written a shell script for less key strokes:

#!/usr/bin/env bash

__quickvpn(){ local username="your_username_here" local password="your_pwd_here" local url="your_host_here" local vpn_tool="/opt/cisco/anyconnect/bin/vpn" if [[ -z $1 && -e /opt/cisco/anyconnect/bin/vpn ]];then echo "usage: on | off | state \n - on: connect\n - off: disconnect\n - state: connect status\n" elif [[ $1 == "on" ]];then print "${username}\n${password}\ny" | $vpn_tool -s connect $url > /dev/null 2>&1 elif [[ $1 == "off" ]]; then print "${username}\n${password}\ny" | $vpn_tool -s disconnect $url > /dev/null 2>&1 elif [[ $1 == "state" ]]; then $vpn_tool -s state | sed 's/>>//' | sed -n 's/(state:.)./\1/p;/state/q' else echo "cisco vpn not found" fi }

__quickvpn $1

Save above as a shell script file named as myvpn under /usr/local/bin and chmod 744 /usr/local/bin/myvpn then you could use it like:

myvpn on # connect
myvpn off # disconnect
myvpn state # connection status
TizeeU0U
  • 101
0

This is what worked on MacOS Monterey:

#connect to vpn 
cvpn() {
    printf 'y\n[your username]\n[password]\ny' | /opt/cisco/anyconnect/bin/vpn -s connect  <vpn dns/url>
}

#disconnect to vpn dvpn() { /opt/cisco/anyconnect/bin/vpn disconnect }