如何在 Linux 和 macOS 上编写 AnyConnect 登录脚本
vpn 二进制按提示顺序从标准输入读取答案。把顺序构建好,只引用一次,别让它出现在进程列表中,并先测试一个资源。
脚本以零退出,隧道出现,而下次运行还没等它索要密码就被拒绝。或者同一条命令在终端里能用,从计划任务运行却失败,报一个「找不到事件」的错误,什么有用的信息都没说。两者都是 AnyConnect 客户端的标准输入对话出了偏差,而不是网络故障。把登录当成一段写好的问答,失败就变得可预测,而且很小。
为什么同一条命令在脚本里会失败
客户端按网关提问的顺序,从标准输入逐行读取答案。任何改变提示数量的东西,比如新的横幅、组选择器或第二因素挑战,都会让之后每个答案错位一行。于是客户端在本该填密码的位置读到了用户名,报出的失败两个都不指向。
密码里带一个感叹号,会带来一个更安静的第二种失败。在双引号里,shell 早在客户端看到任何内容之前就把它展开了。
用单引号包住载荷,字符就能原样传递。这就是全部的修复,它也解释了整整一类报告:同一份凭据手输能用,存档却失败。检查网关之前先检查 shell 做了什么:用能显示确切字节的包装器打印载荷,并数一数行数。大多数这类排查到这里就结束了。
按客户端提问的顺序写答案
先交互式地运行一次客户端,把每个提示按顺序记下来。只有当网关发布了多个配置文件时才会出现组选择器,只有当配置了横幅时才会出现横幅提示。答案文件必须匹配你实际指向的网关,而不是文档里的那个。
然后用这个确切的顺序构建文件,一行一个答案。组索引是客户端列出的编号,而不是配置文件在文档中的位置。只有当你的网关会发送横幅时才接受它,并为该网关已知会提出的每个额外问题补一行。用非交互标志启动客户端,让它读取文件,而不是等待终端。
connect vpn.lab.example
0
username
password
y
exit/opt/cisco/anyconnect/bin/vpn -s < anyconnect.txt如果你不想在磁盘上保留文件,同一串内容也可以通过管道传进去。引用规则仍然决定它能不能存活。
把凭据留在进程列表之外
命令行参数在进程整个生命周期内对每个本地用户都可读,所以密码属于文件或管道,永远不该出现在参数列表里。让那个文件只对运行脚本的账户可读,任务结束就删掉。macOS 上二进制通常和 Linux 在同一路径,但要去确认安装位置,而不是假设。一个同时探测两条路径的包装器,比一份事故报告要短。
printf 'username\npassword\ny\n' | /opt/cisco/anyconnect/bin/vpn -s connect vpn.lab.example也别让脚本无休止地重试。横幅变了,或者密码夜里过期了,固定的答案文件就会变成重试循环,而正是这个循环把账户锁死。
失败一次,打印客户端自己的错误文本,然后退出。计划任务需要和任何无人值守任务一样,做身份与凭据可用性的复核,因为悄悄过期的凭据,和凌晨三点的故障没法区分。
在相信退出码之前先确认会话
已连接状态只证明隧道存在,别的什么也证明不了。在脚本开始真正的工作之前,先测试一个必须能通过它访问的资源,并把那里的失败当成与登录失败不同的故障。否则你会去重试一个完全正常、只是到不了目的地的连接。
断开前后都向客户端询问状态,因为过期的会话可能拒绝下一次连接,而你的脚本却在报告成功。
/opt/cisco/anyconnect/bin/vpn state
/opt/cisco/anyconnect/bin/vpn disconnect把状态输出记在退出码旁边,因为单看一个码无法区分登录被拒和会话从未关闭。当网关要求第二因素或交互式批准时,别再把这步写进脚本,改用客户端支持的机制。固定答案文件是给你能控制的凭据图个方便,不是绕过你控制不了的认证步骤的办法。把范围守得这么窄,它就仍然是一段短脚本。
固定答案文件何时是错的工具
第二因素或批准提示会彻底击败这个模式,那是设计边界,不是脚本难题。改用客户端为该步骤支持的任何机制,而不要预先猜答案。固定文件只适用于在多次运行之间保持不变的凭据。
还有两种更老的凭据形式常被误认为 AnyConnect。vpnc 配置文件说的是另一种协议,它要先把组名当作 IPSec 标识符,然后是共享组密钥,再然后是你自己的账户信息。
由于协议不同,vpnc 无法到达只发布 AnyConnect 配置文件的网关,而该服务通常的开源替代是选用 anyconnect 协议的 openconnect。pcf 文件属于旧的 Cisco 客户端,虽然它的主机、组名和组密码可以重新输入到仍然支持 Cisco IPsec 的客户端,文件本身并不能跨客户端迁移。不常见的端口或非标准的隧道模式通常会在这次迁移中丢失。选工具之前,先确定网关提供的是哪种协议。