https://github.com/ma-wenqian/vpn-playbook

概述

一般情况下,能用 Cisco AnyConnect(现称 Cisco Secure Client)的场景,基本都可以用 OpenConnect 替代。从便捷到进阶,本仓库提供了对应的脚本,辅助自动登录学校(或类似配置的)VPN。

目前 Cisco 基本都启用了双重认证:先输入 VPN 地址,然后输入账号、密码,接着输入二次验证码——也就是常见存储在 Google Authenticator、iCloud 钥匙串、Microsoft Authenticator 中的那个 6 位验证码。这个验证码本质上是基于一个固定的 Base32 密钥和当前时间戳计算得到的(TOTP),并没有什么"黑盒"逻辑。因此,只要在绑定 2FA 时提取到这个固定密钥,就可以自己算出验证码,从而实现全程自动登录:

  • Unix 平台:使用 oathtool 工具,OTP=$(oathtool --totp -b "$SECRET")
  • Windows 平台:使用 totp-go 命令行工具,totp-go "$SECRET"

⚠️ 请像保管密码一样保管这个密钥! 任何拿到这个密钥的人都可以无限期地为你的账号生成有效的二次验证码——它不像单次验证码那样会失效。切勿把填入了真实用户名/密码/密钥的配置文件提交到(哪怕是私有的)代码仓库。本仓库中的 config.bat / config.sh 都只是占位模板,请在本地填入真实信息后不要把这部分改动提交到 git。

仓库结构

.
├── Cisco/
│   ├── unix/
│   │   ├── cisco-vpn.sh          # 基于 oathtool + `vpn -s`(脚本化 stdin)实现 connect/disconnect
│   │   ├── config.sh             # 你的 VPN 地址/账号/密码/TOTP 密钥(模板)
│   │   └── install.sh            # 一键安装脚本(curl | bash)
│   └── win/
│       ├── cisco-vpn.bat        # 双击运行的入口脚本,用 totp-go 生成验证码并直接写入 vpncli.exe 的脚本化输入
│       ├── config.bat           # 你的 VPN 地址/账号/密码/TOTP 密钥(模板,变量名与 unix 端一致)
│       ├── icon/                # 桌面快捷方式用到的 connect.ico / disconnect.ico
│       └── install.ps1          # 一键安装脚本,顺带安装 totp-go,还能自动创建桌面快捷方式(irm | iex)
└── Openconnect/
    ├── openconnect-setup.sh       # OpenConnect + microsocks 的 Docker 部署(更轻量)
    └── openconnect-gost-setup.sh  # OpenConnect + gost 的 Docker 部署(功能更全)

移动端

  • iOS:无法做到完全自动化,顶多是借助自动填充功能填入验证码。
  • Android:本仓库暂未研究。

Cisco(桌面端,仅命令行)

不要启动 GUI 界面,全部使用命令行实现自动化操作。

Unix(macOS / Linux)

常规桌面版安装后,CLI 路径是:

/opt/cisco/secureclient/bin/vpn

(macOS 也可以选择安装 iOS 端的 AnyConnect App,这样还能做到 split tunnel,但功能和稳定性因版本而异。)

前置依赖

# Debian/Ubuntu
sudo apt install oathtool

# macOS
brew install oath-toolkit

同时需要已经安装好 Cisco AnyConnect/Secure Client(确保 /opt/cisco/secureclient/bin/vpn 存在)。

一键安装

curl -fsSL https://sh.mawenqian.com/cisco-unix-install.sh | bash

会把 cisco-vpn.sh 和一份 config.sh 模板放到 /opt/cisco-vpn(可用 INSTALL_DIR=... 覆盖;创建该目录需要 sudo,和下面 OpenConnect 的安装脚本一致),赋予 cisco-vpn.sh 执行权限,并软链接到 ~/.local/bin/ciscovpn。如果 ~/.local/bin 还不在你的 PATH 里,脚本会自动往 .bashrc/.zshrc/.profile(根据 $SHELL 判断用哪个)追加一行 export PATH=...,这样重启终端后 ciscovpn 才真的能直接调用,而不是软链接到一个够不着的地方——追加前会先检查这行是否已存在,所以重复运行安装脚本不会重复添加。以后重新运行这条命令即可更新 cisco-vpn.sh,不会覆盖你的 config.sh

也可以手动安装:

  1. Cisco/unix/cisco-vpn.shCisco/unix/config.sh 拷贝到任意目录。
  2. 编辑 config.sh,填入真实的 VPN_HOSTVPN_USERVPN_PASSWORDVPN_SECRET
  3. 赋予执行权限:chmod +x cisco-vpn.sh

使用

ciscovpn connect      # 先断开已有连接,再登录
ciscovpn disconnect   # 断开连接

# 若手动安装且没有创建软链接:
./cisco-vpn.sh connect
./cisco-vpn.sh disconnect

脚本内部会用 oathtool 现算一个 TOTP 验证码,然后把一段脚本化的命令序列,通过管道传给 CLI 的 -s(stdin 脚本化)模式——这和 Windows 那边用 vpncli.exe -s 是同一套机制,因为不管在哪个平台,这个 CLI 都不接受把 connect <host> 直接当命令行参数传入,它只认在自己那个交互式的 VPN> 提示符下输入的命令序列:

printf 'connect %s\n%s\n%s\n%s\n' "$VPN_HOST" "$VPN_USER" "$VPN_PASSWORD" "$OTP" \
    | /opt/cisco/secureclient/bin/vpn -s

全程不落盘——账号密码只存在于这个脚本和 CLI 进程之间的管道里,读取完就没了。

Windows

最新的安装目录是:

C:\Program Files (x86)\Cisco\Cisco Secure Client\vpncli.exe

因为 Windows 上没有现成的 oathtool 等价物,所以这里改用 totp-go 生成验证码——一个独立的小型命令行工具,不需要 Python。

前置依赖:PATH 中要有 totp-go(下面的一键安装脚本会在检测不到时自动帮你安装;手动安装的话执行 irm https://sh.mawenqian.com/totp-go-install.ps1 | iex)。

一键安装

irm https://sh.mawenqian.com/cisco-win-install.ps1 | iex

会把 cisco-vpn.bat 和一份 config.bat 模板放到 %USERPROFILE%\.local\opt\cisco-vpn(可用 -InstallDir ... 覆盖),在 totp-go 不在 PATH 中时自动安装它,然后询问是否要在桌面创建 “Connect VPN” / “Disconnect VPN” 快捷方式——选择创建之后就再也不用碰终端了。以后重新运行安装脚本只会刷新 cisco-vpn.bat,不会动你的 config.bat

快捷方式图标:默认使用仓库自带的 Cisco/win/icon/connect.icoCisco/win/icon/disconnect.ico(两个快捷方式各用各的)。想用自己的图标,传入 -ConnectIconUrl <url> / -DisconnectIconUrl <url> 指向一个 .ico 文件即可——快捷方式的图标必须是本地的 .ico/.exe/.dll 文件(Windows 本身不支持直接用远程 URL 做图标),所以提供的 URL 会先下载到安装目录,再指向本地文件。

也可以手动安装:

  1. Cisco/win/cisco-vpn.batCisco/win/config.bat 放到同一个目录。
  2. 安装 totp-goirm https://sh.mawenqian.com/totp-go-install.ps1 | iex
  3. 编辑 config.bat,填入真实的 VPN_HOSTVPN_USERVPN_PASSWORDVPN_SECRET——变量名和 unix 端的 config.sh 完全一致。
  4. 可选:把 cisco-vpn.bat 的快捷方式放到桌面,以后双击即可自动连接。

使用

双击运行 cisco-vpn.bat(或在终端里直接执行),它会依次:

  1. 打印当前 VPN 状态;
  2. 强制断开已有连接;
  3. 加载 config.bat,用 totp-go "%VPN_SECRET%" 现算一个 TOTP 验证码,直接在批处理脚本内把脚本化的登录输入写入 %TEMP%\cisco_input.txt(不再经过任何辅助进程);
  4. 把这个文件通过管道传给 vpncli.exe -s(脚本模式)完成登录,然后删除临时文件。

一键断开:上面的一键安装已经自动创建了这个快捷方式;也可以自己创建一个,目标设置为:

C:\Windows\System32\cmd.exe /c "C:\Program Files (x86)\Cisco\Cisco Secure Client\vpncli.exe" disconnect & timeout /nobreak /t 3

以后想换图标:右键快捷方式 → 属性 → 更改图标。

OpenConnect(Docker 化,SOCKS5 代理)

因为默认的 Cisco 客户端不支持 split tunnel 模式,且与其他 VPN/代理协作不友好,所以可以用兼容 AnyConnect 协议的 OpenConnect 替代。直接裸机运行的方案可以参考 Mark4551124015/HKU-VPN

这里提供的是一个 Docker 化的部署方式,并映射出一个 1080 端口的 SOCKS5 代理,可以直接使用,或作为其他 VPN 做代理链的一环,比如访问 ChatGPT / Claude 等服务。

提供了两种方案,二选一即可:

脚本代理后端说明
openconnect-setup.shmicrosocks更轻量,只做 SOCKS5
openconnect-gost-setup.shgost更重一些,支持更多协议/代理链能力

脚本引用的镜像构建自 ma-wenqian/dockerfiles/openconnect

一键安装(Linux/macOS):

# 更轻量:OpenConnect + microsocks
curl -fsSL https://sh.mawenqian.com/openconnect-setup.sh | bash

# OpenConnect + gost
curl -fsSL https://sh.mawenqian.com/openconnect-gost-setup.sh | bash

每个脚本都会:

  1. 创建安装目录(默认 /opt/openconnect-head/opt/openconnect-gost,可通过 INSTALL_DIR 环境变量覆盖);
  2. 生成一个 .env 模板(VPN 地址/账号/密码/TOTP 密钥 + 可选的本地网段路由),并设置权限为 chmod 600
  3. 写入对应的 Dockerfiledocker-compose.yaml,用于构建代理 + OpenConnect 镜像。

然后:

cd /opt/openconnect-head   # 或 /opt/openconnect-gost
$EDITOR .env               # 填入真实的 VPN 信息
docker compose up -d --build

容器内置了断线自动重连逻辑(--force-dpd=30 + 重启循环),并配置了健康检查(通过隧道 ping 1.1.1.1)。

如果希望局域网内的其他设备也能访问这个代理(而不仅仅是运行 Docker 的这台机器),需要在 .env 中设置 LOCAL_NETWORK / LOCAL_GATEWAY;如果只在本机使用,保持默认即可忽略这两项。