通过 bash 连接 Cisco Anyconnect VPN

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24209953/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 10:40:37  来源:igfitidea点击:

Connect CISCO Anyconnect VPN via bash

bashvpncisco

提问by Brayden Hancock

As title says, trying to connect vpn via bash. The following script seemed closest to the answer I'm looking for:

正如标题所说,尝试通过 bash 连接 vpn。以下脚本似乎最接近我正在寻找的答案:

#!/bin/bash
/opt/cisco/anyconnect/bin/vpn -s << EOF
connect https://your.cisco.vpn.hostname/vpn_name
here_goes_your_username
here_goes_your_passwordy
EOF

When I run this the vpn starts but then exits without an error and without connecting. This seems to be caused by the -s. If I remove this parameter the VPN will start but none of the commands (ie connect vpn, username, password) will be entered. From what I read the -s option will allow the username/password to be passed. Help!

当我运行它时,vpn 启动但随后退出而没有错误且没有连接。这似乎是由 -s 引起的。如果我删除此参数,VPN 将启动,但不会输入任何命令(即连接 vpn、用户名、密码)。从我读到的 -s 选项将允许传递用户名/密码。帮助!

回答by Brayden Hancock

I had to download the expect packages (yum install expect). Here is the code I used to automate vpn connection

我不得不下载expect包(yum install expect)。这是我用来自动化 vpn 连接的代码

#!/usr/bin/expect

eval spawn /opt/cisco/anyconnect/bin/vpn connect vpn.domain.com

expect "Username: " { send "username\r" }
expect "Password: " { send "password\r" }

set timeout 60
expect "VPN>"

Real easy! :D

真容易!:D

回答by Acumenus

Although expectcan be cleaner, it is not strictly necessary. Assuming /opt/cisco/anyconnect/bin/vpnagentdis running as it automatically should be:

虽然expect可以更干净,但不是绝对必要的。假设/opt/cisco/anyconnect/bin/vpnagentd正在运行,因为它应该自动运行:

To connect:

连接

printf "USERNAME\nPASSWORD\ny" | /opt/cisco/anyconnect/bin/vpn -s connect HOST

Replace USERNAME, PASSWORD, and HOST. The \nyat the end is to accept the login banner - this is specific to my host, and so you may not need it.

替换USERNAMEPASSWORDHOST。将\ny在年底是接受登录旗帜-这是针对我的主人,所以你可能不需要它。

I understand that there are obvious security concerns with this method; it's for illustration purposes only.

我知道这种方法存在明显的安全问题;它仅用于说明目的。

To get state:

获取状态

/opt/cisco/anyconnect/bin/vpn state

To disconnect:

断开连接

/opt/cisco/anyconnect/bin/vpn disconnect

This was tested with AnyConnect v3.1.05160.

这是使用 AnyConnect v3.1.05160 测试的。

回答by Brip22

c# solution ... in this case profile is the group name.

c# 解决方案 ... 在这种情况下,配置文件是组名。

//file = @"C:\Program Files (x86)\Cisco\Cisco AnyConnect Secure Mobility Client\vpncli.exe"
var file = vpnInfo.ExecutablePath;
var host = vpnInfo.Host;
var profile = vpnInfo.ProfileName;
var user = vpnInfo.User;
var pass = vpnInfo.Password;
var confirm = "y";

var proc = new Process
{
    StartInfo = new ProcessStartInfo
    {
        FileName = file,
        Arguments = string.Format("-s"),
        UseShellExecute = false,
        RedirectStandardInput = true,
        RedirectStandardOutput = true,
        RedirectStandardError = true,
    }
};

proc.OutputDataReceived += (s, a) => stdOut.AppendLine(a.Data);
proc.ErrorDataReceived += (s, a) => stdOut.AppendLine(a.Data);

//make sure it is not running, otherwise connection will fail
var procFilter = new HashSet<string>() { "vpnui", "vpncli" };
var existingProcs = Process.GetProcesses().Where(p => procFilter.Contains(p.ProcessName));
if (existingProcs.Any())
{
    foreach (var p in existingProcs)
    {
        p.Kill();
    }
}

proc.Start();
proc.BeginOutputReadLine();

//simulate profile file
var simProfile = string.Format("{1}{0}{2}{0}{3}{0}{4}{0}{5}{0}"
    , Environment.NewLine
    , string.Format("connect {0}", host)
    , profile
    , user
    , pass
    , confirm
    );

proc.StandardInput.Write(simProfile);
proc.StandardInput.Flush();

//todo: these should be configurable values
var waitTime = 500; //in ms
var maxWait = 10;

var count = 0;
var output = stdOut.ToString();
while (!output.Contains("state: Connected"))
{
    if (count > maxWait)
        throw new Exception("Unable to connect to VPN.");

    Thread.Sleep(waitTime);
    output = stdOut.ToString();
    count++;
}
stdOut.Append("VPN connection established! ...");

回答by MasterCarl

Building on Brayden Hancock's answer, I built a solution that reads the password from the macOS Keychain. As a first step, I added a new password item with the accountfield set to mycompany-vpnvia the Keychain Access app. The first part of the script reads that item back from the keychain and extracts the password using the ruby snippet, the expectscript section does the rest.

基于 Brayden Hancock 的回答,我构建了一个从 macOS 钥匙串读取密码的解决方案。作为第一步,我通过钥匙串访问应用程序添加了一个新密码项,该account字段设置为mycompany-vpn。脚本的第一部分从钥匙串读回该项目并使用 ruby​​ 片段提取密码,expect脚本部分完成其余的工作。

#!/usr/bin/env bash
get_pw () {
    security 2>&1 >/dev/null find-generic-password -ga mycompany-vpn \
    |ruby -e 'print  if STDIN.gets =~ /^password: "(.*)"$/'
}

USER=username
ADDR=vpn.company.com
PASSWORD=$(get_pw)

/usr/bin/expect -f - <<EOD
set timeout 10

spawn /opt/cisco/anyconnect/bin/vpn connect $ADDR
expect "\r\nUsername:*" {send -- "$USER\r"}
expect "Password: " {send -- "$PASSWORD\r"}
expect "Connected"
EOD

回答by Jay Wong

If you are using macOS, I recommend to save your vpn password in Keychain, then request it from your Anyconnect script.

如果您使用的是 macOS,我建议将您的 vpn 密码保存在钥匙串中,然后从您的 Anyconnect 脚本中请求它。

For example, say I want to connect to foo.bar.comwith account fooand password bar.

例如,假设我想foo.bar.com使用 accountfoo和 password连接bar

  1. Save fooand barpair in Keychain (login not iCloud) with name fookey
  2. Run the following bash script to connect
  1. 使用名称保存foobar配对钥匙串(登录而不是 iCloud)fookey
  2. 运行以下 bash 脚本进行连接
/opt/cisco/anyconnect/bin/vpn connect foo.bar.com -s << EOM
0    # foo.bar.com doesn't require two factor authorization
foo  # vpn account
$(sudo security find-generic-password -ws fookey)  # vpn password
EOM

Using this approach, you don't need to type in your vpn password every time, and you won't write your password to files without encryption.

使用这种方法,您不需要每次都输入您的 vpn 密码,并且您不会将密码写入未加密的文件。

If you are not familiar with bash script, read below for explanation:

如果您不熟悉 bash 脚本,请阅读以下说明:



  • /opt/cisco/anyconnect/bin/vpn connect -senters non-interactivel mode.
  • << EOM ... EOMis called here-docs, which uses a string to replace a file. It is very useful to script interactive CLI, by writing each respond as a new line.
  • securityis a nice tool to access your Keychain from the command line.
  • /opt/cisco/anyconnect/bin/vpn connect -s进入非交互模式。
  • << EOM ... EOM称为here-docs,它使用字符串替换文件。通过将每个响应编写为一个新行来编写交互式 CLI 脚本非常有用。
  • security是一个很好的工具,可以从命令行访问您的钥匙串。