docs(design): browser UA research and BR-4 decisions
Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
1 parent
3051575989
commit
79202efdb5
2 files changed
+38
No files matched your search
@@ -0,0 +1,37 @@
|
|||||||
|
# BR-4 浏览器 UA / 指纹调研(只读)
|
||||||
|
|
||||||
|
## 1. camofox 1.17.0 / Camoufox 现状
|
||||||
|
- 内核 Camoufox 152.0.4-beta.28,camoufox-js 0.11.5。指纹在**浏览器进程启动时**生成(server.js `launchBrowserInstance` → `launchOptions({os: hostOS='linux', humanize, locale})`),BrowserForge 随机出 screen/WebGL/字体/硬件等,写进 `CAMOU_CONFIG_n` 环境变量;**同一进程内所有 context(每站点账号一个 profile)共用一套指纹**。
|
||||||
|
- 浏览器空闲 5 分钟关闭、容器重启都会重新 launch → 除 UA 外的指纹每次重随机(日志已见 6 次 launch)。UA 由 BrowserForge 生成后把版本号替换为 152,OS 固定 Linux,推测为 `Mozilla/5.0 (X11; Linux x86_64; rv:152.0) Gecko/20100101 Firefox/152.0`(当前浏览器未运行,未能读实值)。
|
||||||
|
- HTTP API 不能按会话指定 UA/os/screen/fingerprint;只有 env `CAMOFOX_LOCALE/TIMEZONE`(当前为空)。但有两个插件钩子可用:`browser:launching`(可改 launch options:传固定 `fingerprint`/`config`/`screen`/`window`)与 `session:creating`(可改 contextOptions,如 `userAgent`)。按 context 覆盖 UA 会与进程级的字体/WebGL/navigator 不一致(上游 issue 已记录),不建议。
|
||||||
|
- 上游 camoufox-js 支持传入固定 `fingerprint` 或 `config` 字典 → **可在 umt 插件里持久化一套指纹 JSON,每次 launch 复用**。
|
||||||
|
|
||||||
|
## 2. 我们两端的 UA / Cookie 流向
|
||||||
|
- HTTP 端:只有**登录(loginNexusPhp)与用户数据刷新**带 `acc.user_agent ?? settings.sites.userAgent`(Chrome 140/Windows)。**站点适配器(列表/搜索/详情/下载/healthCheck)`runtime.siteAdapter` 没传 `userAgent`,RSS fetcher 也没传** → 实际发的是 Deno 默认 UA(`Deno/2.9.7`)。同一账号 HTTP 端已经是两个 UA。
|
||||||
|
- 浏览器端:打开会话时 `prepareCookies` 把账号 Cookie(或先 HTTP 账密登录得到的会话 Cookie)经 umt-cookies 注入 profile;关闭/释放/周期时 `syncCookies` 把站点域名下**全部 Cookie 原样回写**账号(`writeBrowserCookie`),HTTP 随即使用。
|
||||||
|
- cf_clearance / __cf_bm 无任何特殊处理,会双向流动。当前 5 个 profile 未见 cf_ 类 Cookie;库里只有 1 个账号(hhanclub,Cookie 型,无 UA 覆盖,不走代理)。
|
||||||
|
- IP:HTTP 端仅站点开“代理”才走 proxyUrl;浏览器容器有 `HTTP_PROXY=172.17.0.1:7891` 环境变量,Firefox 是否实际走它待核实 → 两端出口 IP 可能不同。
|
||||||
|
|
||||||
|
## 3. 站点绑定情况(公开资料)
|
||||||
|
- Cloudflare 官方:clearance“securely tied to the specific visitor and device … preventing reuse across machines”,不公开输入;社区普遍实测绑定 **UA + IP(+TLS 指纹)**。Deno/rustls 的 TLS 指纹与 Firefox 必然不同 → 即使 UA 一致,浏览器拿到的 cf_clearance 在 HTTP 端也不保证可用。
|
||||||
|
- NexusPHP:c_secure_pass 等为 HttpOnly;经典实现仅在勾选“限制 IP”(securelogin)时把会话绑 IP,核心代码未见 UA 绑定。风险主要来自站点前置的 CF/WAF 和管理员的“多 UA/多 IP”风控。
|
||||||
|
- 馒头:抓取走 API Key(x-api-key),与网页登录态无关(我们已不注入);网页 token 的设备/UA 绑定无权威公开资料,未证实。
|
||||||
|
- 憨憨:NexusPHP 系,未找到 UA 绑定公开资料。
|
||||||
|
|
||||||
|
## 4. MoviePilot 做法
|
||||||
|
- `site.ua or 全局 UA` 贯穿 HTTP 请求(全局 NORMAL_USER_AGENT 为 Mac Chrome 138)。
|
||||||
|
- 仿真用 CloakBrowser(Chromium)或 FlareSolverr,新建 context 时传 `user_agent=site.ua`;FlareSolverr 返回的 userAgent 只在当次用。
|
||||||
|
- 账密“更新 Cookie”在浏览器里登录后读 `navigator.userAgent`,**把 cookie 与 ua 一起写回站点**(cookie.py:397,site.py:1036)——即“UA 跟随取得 Cookie 的浏览器”。Chromium 内核 + Chrome UA,两端天然一致。
|
||||||
|
|
||||||
|
## 5. 结论与方案
|
||||||
|
**推荐**:每账号一套“浏览器身份”(identity:UA + Camoufox 指纹 JSON),以浏览器为准,HTTP 全链路复用其 UA;不轮换。
|
||||||
|
1. OS:建议统一 **Windows**(用户面最大、UA 最常见);但字体/WebGL 需 Camoufox 伪装,headed Linux 下渲染差异有暴露风险——或选 Linux 最真实。需用户决定。
|
||||||
|
2. 因指纹是进程级,每账号不同指纹做不到;方案 A(推荐)全实例一套固定指纹,所有账号共用,插件在 `browser:launching` 读/首次生成并落盘;方案 B 每账号独立浏览器进程(资源翻倍,不推荐)。
|
||||||
|
3. UA 版本跟随 Camoufox 大版本;升级镜像时插件保留指纹其余字段、只改版本号,并同步写回设置里的默认 UA。
|
||||||
|
4. HTTP 端:siteAdapter、RSS、下载、登录统一带账号 UA;cf_clearance/__cf_bm 回写时剔除或标记“仅浏览器”。
|
||||||
|
|
||||||
|
**需改文件**:`docker/browser-desktop/root/opt/camofox/plugins/umt-cookies/index.js`(加 launching 钩子 + GET /umt/identity);`apps/server/src/modules/sources-identity/runtime.ts`(siteAdapter/RSS 传 UA,签名含 UA);`.../service/account.ts`、`credentials.ts`(回写时同步 UA、过滤 CF Cookie);`apps/server/src/modules/browser/service.ts`(会话开时读 identity);`packages/contracts/src/settings.ts`(默认 UA 改为 Firefox);迁移:`site_account` 增 `ua_source/identity_version`。
|
||||||
|
|
||||||
|
**风险与平滑迁移**:改 UA 通常不会让 NexusPHP Cookie 失效,但 CF 站点会立即要求重新过挑战。做法:不改已有账号的生效 UA,记录“待切换”;在下次重新登录 / 浏览器回写 Cookie 时原子地切换 Cookie+UA。Deno UA→浏览器 UA 的切换可立即做(风险低)。
|
||||||
|
|
||||||
|
**需用户决定**:OS 选 Windows 还是 Linux;全实例一套指纹是否可接受;是否允许浏览器 cf_clearance 给 HTTP 用(TLS 不同,大概率无效);是否统一浏览器与 HTTP 出口 IP。
|
||||||
@@ -196,3 +196,4 @@ NFO / 图片投影、身份巡检与挂载根因聚合、HTTP 失败自动切浏
|
|||||||
- 状态(分支 fix7):根因与改法——① 汇报兜底:`components/agent/report-humanize.ts` 展示时把 UUID(按本会话工具结果与子会话配名字,认不出缩成"…")、能力 ID(换能力标题)、原因码(`reasons.ts` 补了能力错误、下载盘判定、站点登录、待处理类型,`cache:` 这类前缀按后半段查)换成人话,原文进「正文原文」折叠区,历史不改;② 概况条把跳过算进分子,步骤清单只数完成——统一为 `stepProgress`:「步骤 4/6 · 完成 4 · 跳过 2」;③ "派出了 5 个子会话"是进度行把 3 次被预算拒绝的 `agent.spawn` 也算进去(产品计数错):失败的调用不计入动作计数,实际结果行加「派出 N 个子会话」(会话树),汇报格式加"数量以工具返回为准";④ 巡检执行时占位符已正确替换(补单测),界面显示的是模板本身:改成名称标签,会话标题里的 ISO 时间转「9月28日 18:53」,`download_failed` 等码转人话;⑤ 该会话运行时 qB 尚未添加(会话 12:06,qB 12:09 建),但根因是智能体根本没有查下载器的能力(`site.list` 不含下载器),新增只读能力 `downloader.list`(下载器与媒体服务器、连通状态、管理的任务数);⑥ 种子详情按识别状态说人话、解析结果 JSON 跟随技术信息默认收起;"主文件"只认视频(整理把字幕登记成独立资产时其位置 is_primary 为真,文件列表接口按扩展名收紧);悬浮操作只在鼠标悬浮时出现,选中行不再常驻遮挡;作品页空收录版本写「没设收录要求」,版本行写「库里有 N 个版本」。追加:文件管理目录树改成与主面板同款圆角卡片(头部「目录」+ 折叠钮与工具栏第一行对齐,拖宽与折叠记忆保留)。截图 `apps/web/test/screenshots/fix7/`。
|
- 状态(分支 fix7):根因与改法——① 汇报兜底:`components/agent/report-humanize.ts` 展示时把 UUID(按本会话工具结果与子会话配名字,认不出缩成"…")、能力 ID(换能力标题)、原因码(`reasons.ts` 补了能力错误、下载盘判定、站点登录、待处理类型,`cache:` 这类前缀按后半段查)换成人话,原文进「正文原文」折叠区,历史不改;② 概况条把跳过算进分子,步骤清单只数完成——统一为 `stepProgress`:「步骤 4/6 · 完成 4 · 跳过 2」;③ "派出了 5 个子会话"是进度行把 3 次被预算拒绝的 `agent.spawn` 也算进去(产品计数错):失败的调用不计入动作计数,实际结果行加「派出 N 个子会话」(会话树),汇报格式加"数量以工具返回为准";④ 巡检执行时占位符已正确替换(补单测),界面显示的是模板本身:改成名称标签,会话标题里的 ISO 时间转「9月28日 18:53」,`download_failed` 等码转人话;⑤ 该会话运行时 qB 尚未添加(会话 12:06,qB 12:09 建),但根因是智能体根本没有查下载器的能力(`site.list` 不含下载器),新增只读能力 `downloader.list`(下载器与媒体服务器、连通状态、管理的任务数);⑥ 种子详情按识别状态说人话、解析结果 JSON 跟随技术信息默认收起;"主文件"只认视频(整理把字幕登记成独立资产时其位置 is_primary 为真,文件列表接口按扩展名收紧);悬浮操作只在鼠标悬浮时出现,选中行不再常驻遮挡;作品页空收录版本写「没设收录要求」,版本行写「库里有 N 个版本」。追加:文件管理目录树改成与主面板同款圆角卡片(头部「目录」+ 折叠钮与工具栏第一行对齐,拖宽与折叠记忆保留)。截图 `apps/web/test/screenshots/fix7/`。
|
||||||
- **导航与站点类型(IA-2,用户 2026-09-29)**:「任务」归入系统组;站点、订阅、规则合为一组(组名「获取」,用户原话"都算做规则",组名可再改);独立的 RSS 页取消——RSS 属于站点,在站点详情里管理;"站点"增加类型,PT 站之外的下载来源(公开 BT、自定义 RSS 源,以后 Torznab/Jackett/Prowlarr 等)都作为一种站点类型,各类型声明自己支持的获取方式(搜索 / RSS / 详情 / 登录)。
|
- **导航与站点类型(IA-2,用户 2026-09-29)**:「任务」归入系统组;站点、订阅、规则合为一组(组名「获取」,用户原话"都算做规则",组名可再改);独立的 RSS 页取消——RSS 属于站点,在站点详情里管理;"站点"增加类型,PT 站之外的下载来源(公开 BT、自定义 RSS 源,以后 Torznab/Jackett/Prowlarr 等)都作为一种站点类型,各类型声明自己支持的获取方式(搜索 / RSS / 详情 / 登录)。
|
||||||
- **浏览器 UA 与指纹(BR-4,用户 2026-09-30:不着急,先研究明白)**:现状 HTTP 默认 Windows Chrome 140 UA、浏览器是 camofox(Firefox 内核)自生成 UA,同一站点账号 Cookie 两边互注 → UA 不一致。方向:每个站点账号一套固定 UA(跟随 camofox 的 Firefox)+ 固定指纹,浏览器与 HTTP 共用,不轮换,浏览器升级时同步。先做只读调研(camofox 能否按会话指定/持久化指纹、各站会话与 UA 绑定情况、MP 做法),出报告再定实现。
|
- **浏览器 UA 与指纹(BR-4,用户 2026-09-30:不着急,先研究明白)**:现状 HTTP 默认 Windows Chrome 140 UA、浏览器是 camofox(Firefox 内核)自生成 UA,同一站点账号 Cookie 两边互注 → UA 不一致。方向:每个站点账号一套固定 UA(跟随 camofox 的 Firefox)+ 固定指纹,浏览器与 HTTP 共用,不轮换,浏览器升级时同步。先做只读调研(camofox 能否按会话指定/持久化指纹、各站会话与 UA 绑定情况、MP 做法),出报告再定实现。
|
||||||
|
- 调研见 `docs/design/browser-ua-research.md`。用户决定(2026-09-30):对外伪装 **Windows**;全实例**一套固定指纹**(插件 `browser:launching` 首次生成落盘、之后复用);浏览器与 HTTP **按站点统一出口 IP**;站点适配器 / RSS 目前发 `Deno/2.9.7` UA 的问题**和 BR-4 一起做**(不单独先修)。cf_clearance 等 CF Cookie 回写时标"仅浏览器"。平滑迁移:下次重新登录 / 浏览器回写 Cookie 时原子切换 Cookie+UA。
|
||||||
Reference in new issue
Block a user