通过 bash 连接 CISCO Anyconnect ***

Posted

技术标签:

【中文标题】通过 bash 连接 CISCO Anyconnect ***【英文标题】:Connect CISCO Anyconnect *** via bash 【发布时间】:2014-08-04 06:52:48 【问题描述】:

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

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

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

【问题讨论】:

如果您正在尝试编写交互式程序脚本,您可能需要查看expect(1) 谢谢!让它使用期望工作。如果其他人有类似的问题,这里是我使用的教程(我什至不知道期望,所以它非常基本):thegeekstuff.com/2010/10/expect-examples 这也是您可以使用 OpenConnect 而不是使用官方 AnyConnect 客户端轻松完成的事情。 【参考方案1】:

我必须下载期望的软件包(yum install expect)。这是我用来自动化 *** 连接的代码

#!/usr/bin/expect

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

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

set timeout 60
expect "***>"

真的很简单! :D

【讨论】:

【参考方案2】:

虽然expect 可以更干净,但并非绝对必要。假设 /opt/cisco/anyconnect/bin/***agentd 自动运行:

连接

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

替换 USERNAMEPASSWORDHOST。最后的\ny 是接受登录横幅 - 这是特定于我的主机的,因此您可能不需要它。

我了解此方法存在明显的安全问题;仅供参考。

要获得状态

/opt/cisco/anyconnect/bin/*** state

断开连接

/opt/cisco/anyconnect/bin/*** disconnect

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

【讨论】:

参考:在我的 *** cli 手动选项中,“-s 从标准输入读取命令示例:***cli.exe -s 我很好奇管道“|”在这里工作。为什么“*** connect HOST”会从管道中读取密码?我尝试对 ssh 使用相同的方法。但它没有用。 "printf "password" | ssh user@HOST " 给出错误 "伪终端将不会被分配,因为 stdin 不是终端。" 后来我发现,对于SSH来说,这是因为它的安全特性可以防止它从不安全的来源读取密码,比如文件或println【参考方案3】:

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

例如,假设我想使用帐户 foo 和密码 bar 连接到 foo.bar.com

    foobar 对保存在钥匙串中(登录而不是 iCloud),名称为 fookey 运行以下 bash 脚本进行连接
/opt/cisco/anyconnect/bin/*** connect foo.bar.com -s << EOM
0    # foo.bar.com doesn't require two factor authorization
foo  # *** account
$(sudo security find-generic-password -ws fookey)  # *** password
EOM

使用这种方法,您无需每次都输入您的 *** 密码,也不会将密码写入未加密的文件中。

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


/opt/cisco/anyconnect/bin/*** connect -s 进入非交互模式。 &lt;&lt; EOM ... EOM 称为here-docs,它使用字符串替换文件。编写交互式 CLI 脚本非常有用,通过将每个响应编写为新行。 security 是从命令行访问钥匙串的好工具。

【讨论】:

【参考方案4】:

c# 解决方案...在这种情况下 profile 是组名。

//file = @"C:\Program Files (x86)\Cisco\Cisco AnyConnect Secure Mobility Client\***cli.exe"
var file = ***Info.ExecutablePath;
var host = ***Info.Host;
var profile = ***Info.ProfileName;
var user = ***Info.User;
var pass = ***Info.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>()  "***ui", "***cli" ;
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("1020304050"
    , 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 ***.");

    Thread.Sleep(waitTime);
    output = stdOut.ToString();
    count++;

stdOut.Append("*** connection established! ...");

【讨论】:

【参考方案5】:

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

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


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

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

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

【讨论】:

以上是关于通过 bash 连接 CISCO Anyconnect ***的主要内容,如果未能解决你的问题,请参考以下文章

通过 Python 连接 CISCO Anyconnect ***

通过 Cisco IPSec 连接时,应用程序无法解析内部 DNS 条目

通过Cisco ASA inspection拦截Teamviewer

linux 下连接 Cisco AnyConnect

以编程方式确定 Cisco *** 客户端是不是已连接

怎样通过SecureCRT连接到CISCO路由器CONSOLE口