跳转至

系统浏览器代理与多平台代理共存验收

后续通用漫游、Info 防伪属性恢复与后台重启验收已记录在校园服务验收。本文保留早期检查现场。

开发分支:web。本轮保留当前 Mac dev 窗口及既有账号,仅更新共享后台。网络设置变更由用户的系统代理接入请求授权。未提交作业、预约或修改学校业务记录。

修复原因与实现

  1. 信息门户能显示页面框架,但栏目为空:页面读取的防伪 Cookie 未投影给浏览器。适配器现在为 Info 和 Learn 分别按精确域名、路径和明确的非 HttpOnly 属性投影 XSRF-TOKEN,学校认证 Cookie 继续留在共享账号运行时。
  2. 独立校园浏览器点击课程后新标签页停住:新目标处于暂停状态时,初始化顺序等待了需要恢复运行才能完成的 Page.enable。调整为先建立代理认证,再恢复目标,最后等待页面事件准备。用真实可见链接点击验证,不再以直接访问提取的 URL 代替。
  3. 常用浏览器系统接入:新增 macOS 同用户 TCP 连接鉴权监听。操作系统 PAC 将校园来源导入这个监听,无需逐个浏览器输入代理密码。每条请求仍校验来源、Host、SNI 和账号 epoch。
  4. 与其他代理共存:按每个网络服务保留 HTTP、HTTPS、SOCKS 和绕过规则,生成独立 PAC。未知 PAC、WPAD、认证代理及无法表达的规则在变更前拒绝。外部软件后续修改设置会报告冲突,不反复覆盖。
  5. 统一认证浏览器入口:原配置把 id / oauth 导入代理后又拒绝账号接口,导致用户无法访问。现将两者从浏览器 PAC 接管名单和 CA 来源名单移除,按原代理或直连规则访问;共享代理的自定义名单也不能绕过这一边界。临时恢复原代理后,已在用户普通 Chrome 验证账号设置及其既有登录态正常。
  6. 全新浏览器的 Learn 空白:进一步复验发现 WebVPN Cookie 镜像中的防伪值 A 与当前课程 HTML 已公开的值 B 不同。相同只读学期接口使用 A 返回 403,使用 B 返回 200 JSON。现在只从已知 Learn 课程文档的有界前缀识别同源业务 URL 中唯一的公开 nonce,并按账号 epoch 暂存供浏览器使用;静态资源响应不会再把旧 A 写回浏览器。认证 Cookie、密码和请求内容保持原处理,不用重放业务请求掩盖失败。

当前 Mac 实测证据

项目 结果
系统 CA 当前安装专属 CA 已通过系统信任检查。测试未使用忽略 TLS 错误或 CA 公钥例外。
系统分流 Ethernet、Wi-Fi、USB 10/100 LAN、Thunderbolt Bridge 均生成各自 PAC。前两者保留原 127.0.0.1:7897 代理作为非校园出口,后两者保留直连。
干净 Chrome 不配置浏览器代理、代理密码、校园 Cookie 或证书例外,正常读取 11 张课程卡片;系统监听记录 101 个请求,无 JavaScript 错误。
外部 HTTPS 同一浏览器读取 Google favicon 返回 200,证书签发者不是 OneTHU。
用户普通 Chrome 现有浏览器打开 Learn 正常,点击课程链接新标签页能显示课程通知与课件。现有 NextTHULearn 插件也能读取页面。
Info 页面内容 独立浏览器读取用户截图的准确 URL:正文由约 303 字符增至 3066 字符,54 个列表项、69 个详情链接;21 个只读 XHR 返回 200,主栏目结果为 success 且数据非空。普通 Chrome 的同一入口已复验得到相同内容数量。用户主动进入三个明确只读首页的跨站导航增加精确例外;查询参数、业务接口、表单及子资源均不获此例外。
学校日历 可见的两个提示均为“日历服务漫游失败”。课程内容可加载;日历业务未通过。
其他业务 二级课表曾读取到 7 行;最终选课返回认证所需错误,研讨间返回 401 / code 300,校园卡部分页面可读但身份接口返回 HTML,三者均未计为业务通过。
Safari 原生自动化两次未能取得可操作窗口;尚未完成实机验收。
恢复流程 已确认四个网络服务恢复原代理、绕过规则及 PAC 关闭状态。Ethernet 保留已停用的旧 PAC URL,不参与路由;其余服务 URL 为空。恢复返回 restored:true,无冲突或失败。

最终后台 0d61a4a2a070… 已加载到同一账号,原 Mac dev 进程保持不变。修复公开 nonce 后,全新无历史 Cookie 的 Chrome 经系统代理读取 Learn 返回 200,页面出现 26 个不同查询组合的课程链接,系统监听记录 87 个请求,无密码框或 JavaScript 错误。Google favicon 和 ID 首页均返回 200,其 TLS 签发者均不是 OneTHU。普通 Chrome 中原有的 ID 账号设置登录态也仍可用。当前系统校园分流已重新启用,状态无待恢复项,非校园流量继续沿原 Clash 设置。

恢复流程中发现的问题

networksetup 无法把 PAC URL 设置为空。首个修补尝试逐服务使用 SystemConfiguration / JXA 清除地址,导致用户连续收到系统授权提示。这是本轮引入的问题;已停止相关进程并完整移除该实现。

最终实现只关闭原本未启用的 PAC,保留无效力的地址字段,恢复原手动代理。返回值通过 retainedInactivePacUrls 说明这个差异。不会为了清理停用字段另行请求管理员授权。恢复途中遇到 OS 权限拒绝会停止后续变更,保留 restorePending 供显式恢复;状态界面不会再把部分恢复显示为正常运行。

平台设计与边界

macOS 的已有手动代理组合在本轮实现。已有任意 PAC 不直接拼接执行,避免改变其逻辑和认证语义;TUN 的路由、DNS 和进程排除仍需与对应代理软件实测。系统代理监测到其他软件重写配置后,交由用户选择恢复或重新接入。

Windows 已有 CurrentUser 证书与系统 PAC 适配器,尚未完成同用户免代理密码入口及现有手动代理组合。WinINet、WinHTTP 和自行设置代理的客户端必须分别验收。微软文档说明 WinHTTP 客户端需正确配置或解析代理,不能以修改浏览器配置代替所有客户端覆盖:WinHTTP AutoProxy Support。

Android 保持 App 内共享会话。本轮没有实现系统 VPN 接入。后续方案需要处理 VPN 授权、常驻通知、前台服务、protect() 避免代理套回自身,以及与现有 VPN 的冲突。Android 同一用户或工作资料仅能有一个活跃 VPN;不能承诺与另一个 VpnService 同时独立运行:Android VPN。

用户安装 CA 并不使所有 Android App 接受它。现代 App 的信任配置、证书固定和网络栈会影响兼容性,微信小程序需单独验证:Network Security Configuration。

本轮不包含 LAN 扩散、WebSocket、HTTP/2/3 和任意应用流量接管。PAC 下载失败、后台崩溃、休眠恢复的完整自动恢复仍需单独实现和验收;已加载 PAC 对校园入口没有 DIRECT 后备,不等于整个操作系统具备网络隔离保证。

自动检查

最终完整检查:gateway 120/120(含平台 27 项)、SDK 249/249;UI fixture 32/32、桌面与 SDK TypeScript 检查通过、中英字典各 7751 键且 errors 0。公开 nonce 测试包含字节流保留、账号 epoch、非课程页面、外部 URL、多个不同 nonce 和超过前缀界限等情况。测试只证明其覆盖的分支,具体系统和真实账号结果以上表为准。