WEngineTunnel (webvpn2ssl) 是一款专为桂林电子科技大学 (GUET) 定制开发的 Android 端 VPN 与透明代理客户端。本系统核心适用于金智教务网 CAS 统一身份认证系统以及网瑞达 WEngine WebVPN 网关。它巧妙地结合了 Go 语言高性能并发代理引擎 与 Android 原生 VpnService,实现了内网资源极速、稳定、安全的免浏览器直接访问与应用分流。
- 免密直达 (Fast-Path):自动持久化存储会话 Cookie,启动时优先尝试使用旧凭证免密直达,避免频繁登录。
- 双阶段 2FA 短信验证:密码认证通过后自动判定是否需要二次验证(
NEED_MFA),在移动端支持一键触发短信码发送、弹窗录入以及校验。 - 可信设备与 7 天免密:在多因子验证成功后,自动申请并注入
_cas_device_等授信设备特征 Cookie,大幅延长免登周期。 - 设备指纹绑定:原生生成基于用户名 MD5 算法的唯一浏览器设备指纹(BFP),自动关联
/bfp/info以防止网关会话风控拦截。
- JA3 TLS 指纹模拟 (utls):基于
github.com/refraction-networking/utls技术,模拟真实桌面端 Chrome 的 TLS Client Hello 握手特征,完美绕过高校网关 WAF 或防爬虫系统的 JA3 指纹拦截。 - 自动密钥提取 (AES CFB):网关默认采用
wrdvpnisthebest!作为 URL 资源混淆密钥。本引擎可在用户成功登录后,自动拉取 Portal 首页并基于正则表达式解析非默认 AES 密钥,实现完全自适应域名加解密。
- 随机心跳探测:后台协程在代理运行期间每隔 5 至 8 分钟(随机抖动)对网关发起一次轻量级定时刷新,确保 Session 持续活跃不掉线。
- 静默重连自愈:一旦探测到或请求中遇到 302 强制重定向至登录页,引擎将在后台挂起请求并使用密码凭证发起静默自动重新认证。成功恢复会话后无缝重试原请求,使用户在网络瞬断或长期待机后完全无感知。
- CONNECT 隧道劫持:对于目标域名为 WebVPN 自身或 CAS 认证中心的 HTTPS
CONNECT请求,引擎会主动拒绝建立隧道,强制移动端浏览器退回到纯 HTTP 代理流,从而使重写逻辑得以实施,绕过 HSTS 证书强推限制。 - URL 协议降级与替换:对网关返回的文本内容(HTML/JS/JSON)进行实时流式内容改写,将
https://强降级为http://,防止手机浏览器自动升级协议导致代理闭环破裂或产生 SSL 证书错误。 - 二进制传输兼容:强行剔除客户端的
Accept-Encoding头,防止后端启用gzip或brotli压缩导致响应文本替换失效。最大支持 200MB 的请求 Body 内存级缓存,保证会话恢复重试时 POST/PUT 大文件上传链路不损坏。
- 原生 Android 10+ 代理注入:利用 Android 系统的
VpnService.Builder.setHttpProxy将本地所有流量无感路由至 Go 底座代理端口(默认9999)。 - 精细化分流模式:
- 全局代理 (ALL):拦截并路由整机所有流量。
- 应用分流 (BY_APP):支持在 UI 中勾选指定的应用程序(如特定浏览器或校内 App),仅对这些应用进行 VPN 劫持,不干扰微信、支付宝等日常软件。
- 实时网络速度显示:通知栏前台服务展示实时上行(Tx)/下行(Rx)网络流量速度。
webvpn2ssl/
├── webvpn-core/ # 核心 Go 代理引擎模块 (Go 1.26+)
│ ├── cas_login.go # CAS 统一身份认证接口、JA3 模拟及 2FA 核心实现
│ ├── crypto.go # AES CFB URL 加密/解密算法实现
│ ├── mobile.go # gomobile 导出给 Android Kotlin 的 API 桥接层
│ ├── mobile_test.go # 单元测试用例
│ └── gobuild.bat # 编译为 .aar 依赖包的批处理脚本
├── app/ # Android 壳应用工程 (Kotlin, Gradle)
│ ├── libs/ # 存放 webvpncore.aar 依赖
│ └── src/main/java/.../
│ ├── WebVpnService.kt # 继承自 VpnService 的前台通知与流量隧道管理器
│ ├── LoginManager.kt # 登录状态机与多因子认证逻辑
│ ├── VpnStateManager.kt # 双向协程流式 VPN 运行状态管理器
│ ├── MainActivity.kt # 现代化的 Material Design UI 控制器
│ └── ProxyConfig.kt # 代理配置定义 (包含分流、包名过滤等)
└── build.gradle.kts # Android 工程构建脚本
- Android SDK (API 29+) & Android Studio
- Go 环境 (Go 1.26.3 或更高版本)
- gomobile 工具链:
go install golang.org/x/mobile/cmd/gomobile@latest gomobile init
进入 webvpn-core 目录并运行批处理文件 gobuild.bat,该操作会自动编译生成 Android 兼容的 AAR 库并将其拷贝到 App 模块的 libs 目录中:
cd webvpn-core
./gobuild.bat
gobuild.bat内部主要执行:gomobile bind -target=android/arm64 -androidapi 31 -v -ldflags="-s -w" -trimpath -o webvpncore.aar .
- 使用 Android Studio 打开根目录
webvpn2ssl。 - 等待 Gradle 同步完成。
- 连接手机或启动模拟器(建议 Android 10 或更高版本)。
- 点击 Run 'app' 按钮,或者在终端中执行:
./gradlew installDebug
sequenceDiagram
participant App as Android App (Kotlin)
participant Go as Go Core (webvpn-core)
participant CAS as GUET CAS Server
App->>Go: CasLoginStart(username, password)
rect rgb(240, 248, 255)
Go->>Go: 关联/bfp/info指纹并请求CAS登录页
Go->>CAS: 提交加密密码与 execution 令牌 ( rememberMe 开启 )
end
alt 免密或直接登录成功 (SUCCESS)
CAS-->>Go: 返回 wengine_vpn_ticket Cookie
Go-->>App: 返回 SUCCESS, 写入持久化 Cookie
else 需要多因子验证 (NEED_MFA)
CAS-->>Go: 302跳转 reAuthLoginView.do 携带新 execution
Go-->>App: 返回 NEED_MFA + execution 流水号
App->>App: 弹窗提示输入短信码,并提供“获取验证码”按钮
App->>Go: CasSendSmsCode(username)
Go->>CAS: POST /dynamicCode/getDynamicCodeByReauth.do 触发验证码发送
App->>Go: CasLoginSubmitMfa(execution, smsCode, trustDevice=true)
Go->>CAS: POST /reAuthCheck/reAuthSubmit.do 验证短信码
CAS-->>Go: 返回正式会话 Cookie 凭证
Go-->>App: 返回成功,保存授信 Cookie 并拉取 Portal 激活会话
end
当 Android 系统的 VpnService 捕获到 HTTPS 流量时,会向 Go 本地代理服务器发起 CONNECT host:443 请求。
- 普通内网 HTTPS 资源:由
handleConnectTunnel方法进行 TCP 盲转发,完美兼容。 - VPN 网关 (
v.guet.edu.cn) / CAS 统一身份认证 (cas.guet.edu.cn): 由于现代浏览器启用 HSTS 会导致解密代理出现证书不可信错误,引擎会在检测到目标为网关或 CAS 域名时主动拒绝建立 CONNECT 隧道(返回502 Bad Gateway)。 这一操作将迫使浏览器回退到纯 HTTP 协议流,引擎即可对传输中的 HTML、JavaScript、JSON 进行域名降级与替换(将https://...替换为http://...),从而在手机浏览器中维持一条完全闭环且免证书报错的透明代理体验。
graph TD
A[应用发起请求] --> B[本地代理拦截并加密 Host]
B --> C[附加 WebVPN Cookie 转发至网关]
C --> D{网关返回状态?}
D -- 200 OK / 正常响应 --> E[提取Set-Cookie并回传给用户]
D -- 302 重定向到 /login --> F[检测为会话超时失效]
F --> G[启动后台静默自愈 reconnectSession]
G --> H{重连是否成功?}
H -- 成功 --> I[使用新 Cookie 自动重新投递请求]
I --> J[返回最新结果,用户完全无感知]
H -- 失败 --> K[向手机抛出登录失效,引导进入主界面]
本项目的设计与开发受到了以下开源项目的启发与帮助,特此致谢:
- Bistutu/GoCampusLogin — 提供了优秀的 CAS 统一身份认证与网络登录分析思路。
- Metaphorme/webVPN_mitm — 提供了关于 webVPN mitm与透明代理流量改写的灵感。
本项目基于 Apache License 2.0 协议开源。请勿将本软件用于任何违反内网相关规定、国家网络安全法以及侵犯他人隐私的活动,仅限学习交流使用。