Files
AskaEth 985860b2a2 docs: 将反检测作为核心设计原则,全面更新架构和文档
- architecture.md: 新增反检测为核心第一性原理,新增 §3 反检测设计(13 个指纹维度全覆盖)
- anti-detection.md: 新增反检测专项文档(14 节,详尽列举检测方式和应对策略)
- api.md: POST /pages 新增 profile 参数,新增 GET /profiles 端点
- cli.md: 新增 --profile 全局选项,新增 visionl profiles 命令
- contributing.md: 新增反检测开发规范、检测站点验证要求
- README.md: 更新项目定位和特性描述
2026-08-12 20:21:53 +08:00

20 KiB
Raw Permalink Blame History

VisionL 架构设计

面向 AI 智能体的开源可持久化浏览器 — 架构设计文档

1. 概述

要解决的根本问题

让 LLM 访问各类页面尽可能不被简单的人机验证所拦截。

这是 VisionL 存在的第一性原理,所有设计决策必须围绕这个目标展开。

市面上绝大多数自动化浏览器(Playwright/Puppeteer 裸跑)会在数十个维度上暴露自动化痕迹, 被 Cloudflare、Akamai、DataDome 等反爬服务轻松识别。VisionL 的核心竞争力在于: GUI 浏览器所有能被页面/页面后端检测到的特征,在 CLI 中均有值(可以是模拟的)

次要目标

  • 页面持久化:页面在客户端断连后依然存活,只有显式 kill 才能终止
  • 智能体优先:CLI 子命令为 LLM 工具调用而设计,输出结构化 JSON
  • 本地优先Daemon 仅监听 localhost,不对外开放
  • GUI 就绪HTTP/WS API 同时服务于 CLI 和未来的 GUI

2. 技术栈

层级 选择 理由
浏览器引擎 Playwright + Chromium AI 浏览器自动化的事实标准
反检测框架 playwright-extra + puppeteer-extra-plugin-stealth 自动处理 WebDriver 标记和基础指纹
指纹补充 自研 stealth 模块 stealth 插件只覆盖约 60% 的指纹,剩余需自行实现
语言 TypeScript + Node.js Playwright 原生语言
通信协议 HTTP REST + WebSocket (localhost) 职责分离,GUI 可复用
包管理 npm workspaces (monorepo) 共享类型
CLI 框架 commander + chalk 轻量
HTTP 服务 原生 http + ws 本地 daemon 无需重型框架

JSON 转义处理

所有返回给智能体的 JSON 必须通过 JSON.stringify 序列化整个响应对象, 禁止手动拼接 JSON 字符串。页面内容字段中的引号、反斜杠、控制字符均正确处理。


3. 反检测设计(核心)

3.1 指纹覆盖全景

目标:所有能通过 JS API 读取到的浏览器特征,都必须返回真实 GUI 浏览器的值, 不能留下任何自动化痕迹。

以下表格列出页面/后端可检测的维度、Playwright 默认值的问题、以及 VisionL 的应对策略。

3.1.1 Navigator 属性

属性 裸 Playwright 值 问题 VisionL 策略
navigator.webdriver true 最致命的暴露 stealth 插件 → false
navigator.userAgent 含 "HeadlessChrome" 直接暴露 模拟真实 Chrome UA,可配置
navigator.plugins 空数组 真实 Chrome 有 5 个插件 stealth 插件 → 注入 PDF Viewer 等
navigator.languages ["en-US"] 需匹配目标地区 可配置,默认 ["zh-CN", "en-US"]
navigator.platform 随 OS 无问题但需一致性 随系统,但确保与其他指纹一致
navigator.hardwareConcurrency 实际 CPU 核数 OK 保持真值
navigator.deviceMemory 实际值 OK 保持真值
navigator.maxTouchPoints 0 桌面无触摸 可配置,桌面默认 0
navigator.vendor "Google Inc." stealth 会修正 stealth 插件处理
navigator.productSub "20030107" 需一致 stealth 插件处理
navigator.connection undefined (headless) 真实 Chrome 有值 注入 NetworkInformation 对象
navigator.mediaDevices 存在 可能暴露空设备列表 模拟至少一个音频设备

3.1.2 Chrome 特有属性

属性 裸 Playwright 值 问题 VisionL 策略
window.chrome undefined (headless) 真实 Chrome 有此对象 注入完整 window.chrome 对象
chrome.runtime N/A 检测自动化时常用 注入 mock runtime
navigator.brave N/A Brave 检测用,非必须 不注入(伪装 Chrome 不是 Brave

3.1.3 屏幕与视口

属性 裸 Playwright 值 问题 VisionL 策略
screen.width/height 默认 1280x720 非标准分辨率 可配置,默认 1920x1080
screen.availWidth/Height 同 screen 任务栏高度需扣除 模拟,比 screen 小 40-80px
screen.colorDepth 24 OK 24
screen.pixelDepth 24 OK 24
window.outerWidth/Height 与视口相同 真实浏览器窗口含边框 比视口大(含窗口装饰)
window.innerWidth/Height 视口尺寸 需与 screen 逻辑一致 保证 inner < outer < screen
window.devicePixelRatio 1 现代设备多为 2 可配置,默认 1 或自动检测

3.1.4 Canvas 指纹

页面可以在 canvas 上渲染特定图形,获取像素哈希作为指纹。不同 GPU/驱动/OS 的渲染结果 有微小差异。VisionL 需要在 canvas 渲染中加入可控的随机噪声,使每次指纹不同但看起来 像正常设备,从而绕过基于 canvas 哈希的追踪。

措施 实现
Canvas 2D 噪声 toDataURL()getImageData() 返回时在像素末尾添加 ±1 随机扰动
WebGL 噪声 getParameter()readPixels() 添加类似扰动
一致性 同一页面会话内噪声种子固定,跨页面会话刷新

3.1.5 WebGL 指纹

属性 裸 Playwright 值 VisionL 策略
UNMASKED_VENDOR_WEBGL 真实 GPU 厂商 可保留真值(多样化),也可统一模拟
UNMASKED_RENDERER_WEBGL 真实 GPU 型号 同上
WebGL 渲染噪声 类似 Canvas,在 readPixels 加入微量噪声

3.1.6 AudioContext 指纹

页面通过 AudioContext 处理音频信号提取指纹。VisionL 策略:

  • createOscillator() 生成的波形在浮点精度末尾加入随机噪声
  • createAnalyser()getByteFrequencyData() 同样处理
  • 噪声量级极小(-100dB 级别),不改变音频语义

3.1.7 字体枚举

页面无法直接枚举系统字体列表,但可通过以下方式探测:

  • 测量指定字体的文本宽度
  • document.fonts API
  • Flash(已消亡)

VisionL 默认不做字体列表注入(多数反爬不会测字体),但保持基础常见字体的一致性。

3.1.8 HTTP 请求头

头部 裸 Playwright 值 VisionL 策略
User-Agent 含 HeadlessChrome 模拟真实 Chrome UA,可配置
Accept-Language en-US 匹配 navigator.languages
Sec-CH-UA 不完整 补全 "Chromium";v="xxx", "Google Chrome";v="xxx"
Sec-CH-UA-Platform 随 OS 确保一致性
Sec-CH-UA-Mobile ?0 ?0(桌面)
Accept OK 保持默认
Accept-Encoding OK 保持默认
Connection keep-alive 保持默认
Upgrade-Insecure-Requests 1 保持默认

3.1.9 权限状态

权限 裸 Playwright 值 VisionL 策略
notifications prompt 可配置:prompt/granted/denied
geolocation prompt 可配置,granted 时提供模拟坐标
camera prompt 可配置
microphone prompt 可配置
midi prompt 保持 prompt

3.1.10 行为模拟

鼠标移动v1 基础版,v2 增强):

  • 点击前鼠标从当前位置线性移动到目标中心(带随机抖动)
  • 移动速度加入随机变化(不恒定)
  • mousemove 事件在移动路径上均匀发射

键盘输入v1 基础版):

  • 每个字符间隔 50-150ms 随机
  • keydownkeypresskeyup 完整序列
  • 中文输入法暂不模拟

滚动

  • 非瞬间跳转,分段滚动
  • 每次滚动步长加入随机抖动

3.2 实现方案

daemon/
├── src/
│   ├── stealth/                    # 反检测模块
│   │   ├── index.ts               # 统一入口,页面创建时注入
│   │   ├── navigator.ts           # navigator 属性覆盖
│   │   ├── chrome-runtime.ts      # window.chrome 注入
│   │   ├── screen.ts              # 屏幕/视口尺寸管理
│   │   ├── canvas-noise.ts        # Canvas/WebGL/Audio 噪声
│   │   ├── headers.ts             # HTTP 头拦截修正
│   │   ├── permissions.ts         # 权限状态管理
│   │   ├── human-input.ts         # 鼠标/键盘/滚动行为模拟
│   │   ├── fingerprint-profile.ts # 指纹配置文件结构
│   │   └── profiles/              # 内置指纹模版
│   │       ├── desktop-chrome.ts  # 桌面 Chrome 通用模版
│   │       ├── desktop-windows.ts # Windows Chrome
│   │       └── desktop-mac.ts     # macOS Chrome

3.3 指纹配置(FingerprintProfile

// packages/core/src/types/fingerprint.ts
interface FingerprintProfile {
  // 浏览器基础
  userAgent: string;
  platform: string;
  languages: string[];
  acceptLanguage: string;

  // 屏幕
  screen: {
    width: number;
    height: number;
    colorDepth: number;
    pixelRatio: number;
  };
  viewport: {
    width: number;
    height: number;
  };

  // GPU
  webglVendor: string;
  webglRenderer: string;

  // 时区与位置
  timezone: string;
  geolocation?: { latitude: number; longitude: number; accuracy: number };

  // 权限
  permissions: {
    notifications: 'prompt' | 'granted' | 'denied';
    geolocation: 'prompt' | 'granted' | 'denied';
    camera: 'prompt' | 'granted' | 'denied';
    microphone: 'prompt' | 'granted' | 'denied';
  };

  // 行为
  behavior: {
    mouseMoveDelay: { min: number; max: number };   // ms
    keyPressDelay: { min: number; max: number };     // ms
    scrollStepDelay: { min: number; max: number };   // ms
  };

  // Canvas 噪声
  canvasNoise: {
    enabled: boolean;
    strength: number;  // 0-1, 噪声强度
  };
}

3.4 WebDriver 检测网站验证

v1 目标:通过以下检测站点的自动化识别:

检测站点 检测方式 目标
https://bot.sannysoft.com 综合(navigator + screen + chrome + canvas + webgl + fonts 必须全绿
https://fingerprint.com/demo 综合指纹(最全面) 降低置信度到非 bot 区间
https://abrahamjuliot.github.io/creepjs/ 浏览器指纹各维度逐一打分 所有维度分数控制在合理范围

4. 项目结构

VisionL/
├── docs/
│   ├── development/
│   │   ├── architecture.md      # 本文档
│   │   ├── anti-detection.md    # 反检测专项文档(检测维度详情、绕过原理)
│   │   ├── api.md               # REST + WS 接口文档
│   │   ├── cli.md               # CLI 命令参考
│   │   └── contributing.md      # 开发规范
│   └── usage/
│       ├── quickstart.md        # 快速开始
│       ├── llm-integration.md   # 智能体集成指南
│       └── examples.md          # 典型场景示例
├── packages/
│   ├── core/                    # 共享库:类型定义、HTTP 客户端
│   │   ├── src/
│   │   │   ├── types/
│   │   │   │   ├── page.ts
│   │   │   │   ├── api.ts
│   │   │   │   ├── ws.ts
│   │   │   │   └── fingerprint.ts   # 指纹配置类型
│   │   │   ├── client.ts
│   │   │   ├── escape.ts
│   │   │   └── index.ts
│   │   └── package.json
│   ├── daemon/                  # 后台进程
│   │   ├── src/
│   │   │   ├── server.ts
│   │   │   ├── routes/
│   │   │   │   ├── pages.ts
│   │   │   │   ├── actions.ts
│   │   │   │   ├── content.ts
│   │   │   │   └── health.ts
│   │   │   ├── browser-manager.ts
│   │   │   ├── page-registry.ts
│   │   │   ├── ws-relay.ts
│   │   │   ├── pidfile.ts
│   │   │   └── stealth/            # 反检测模块
│   │   │       ├── index.ts        # 统一注入入口
│   │   │       ├── navigator.ts
│   │   │       ├── chrome-runtime.ts
│   │   │       ├── screen.ts
│   │   │       ├── canvas-noise.ts
│   │   │       ├── headers.ts
│   │   │       ├── permissions.ts
│   │   │       ├── human-input.ts
│   │   │       ├── fingerprint-profile.ts
│   │   │       └── profiles/
│   │   │           ├── desktop-chrome.ts
│   │   │           ├── desktop-windows.ts
│   │   │           └── desktop-mac.ts
│   │   └── package.json
│   └── cli/
│       ├── src/
│       │   ├── index.ts
│       │   ├── commands/
│       │   │   ├── page.ts
│       │   │   ├── action.ts
│       │   │   ├── view.ts
│       │   │   └── daemon.ts
│       │   ├── format.ts
│       │   └── auto-daemon.ts
│       └── package.json
├── package.json
├── tsconfig.json
├── .gitignore
├── README.md
└── LICENSE

5. Daemon 设计

5.1 REST API

方法 路径 说明 请求体 响应
POST /pages 打开新页面 { url, alias?, profile? } { id, url, alias?, title, status, profileId }
GET /pages 列出所有页面 [{ id, url, alias?, title, status }]
GET /pages/:id 页面详情 同上
DELETE /pages/:id 杀死页面 { ok: true }
POST /pages/:id/navigate 跳转 URL { url } { url, title }
POST /pages/:id/click 点击元素 { selector } { success }
POST /pages/:id/type 输入文本 { selector, text } { success }
POST /pages/:id/scroll 滚动页面 { deltaY?, toBottom? } { success }
POST /pages/:id/eval 执行 JS { code } { result }
POST /pages/:id/wait 等待条件 { selector?, ms? } { success }
GET /pages/:id/screenshot 页面截图 { base64, mime }
GET /pages/:id/text 页面纯文本 { text }
GET /pages/:id/html 页面 HTML { html }
GET /profiles 列出可用的指纹配置 [{ id, name }]
GET /health 健康检查 { status: "ok" }

新增POST /pagesprofile 字段指定指纹配置(默认 desktop-chrome)。 GET /profiles 返回所有内置指纹模版。

5.2 WebSocket 事件

同前,另增:

事件 数据 触发时机
page:detection:warning { id, level, detail } 页面检测到潜在的自动化特征

5.3 页面创建流程(含反检测注入)

visionl page open https://example.com --alias demo --profile desktop-windows
  → POST /pages  { url, alias: "demo", profile: "desktop-windows" }
  → browser-manager.createPage(url, fingerprintProfile)
    → 1. 创建 BrowserContext(从 profile 读取 viewport、locale、timezone、geolocation
    → 2. 创建 Page
    → 3. 注入 stealth 插件(navigator.webdriver 等基础隐藏)
    → 4. 注入自研 stealth 模块:
         - 注入 navigator 覆盖脚本(evalOnNewDocument
         - 注入 window.chrome 对象
         - 注入 canvas/webgl/audio 噪声脚本
         - 注册请求拦截器修正 HTTP 头
         - 注入权限状态
    → 5. 导航到目标 URL
    → 6. 注册到 PageRegistry
  → 返回 { id: "p_abc123", ..., profileId: "desktop-windows" }

5.4 行为模拟流程

操作命令(click/type/scroll)不走 Playwright 的 API,而是走自研的 human-input 模块:

visionl click p_abc123 "#login"
  → POST /pages/p_abc123/click { selector: "#login" }
  → action-handler:
    → 1. 获取元素 bounds
    → 2. 计算鼠标路径(当前坐标 → 目标中心 + 抖动)
    → 3. 沿路径逐个发射 mousemove
    → 4. 到达后依次发射 mousedown → mouseup → click
    → 5. (Future) 考虑 ancestor visibility 和 z-index
visionl type p_abc123 "#username" "hello"
  → POST /pages/p_abc123/type { selector: "#username", text: "hello" }
  → action-handler:
    → 1. 聚焦元素(click or focus
    → 2. 逐字符:keydown → keypress → keyup
    → 3. 每字符间隔随机 50-150ms
    → 4. 完成后可选触发 change/blur 事件

6. CLI 设计(略,同前版本)

CLI 子命令不变。page open 新增 --profile <name> 指定指纹模版。


7. 类型定义(core 包核心类型)

// 新增
interface FingerprintProfile {
  id: string;                         // "desktop-chrome"
  name: string;                       // "桌面 Chrome (通用)"
  userAgent: string;
  platform: string;
  languages: string[];
  screen: { width: number; height: number; colorDepth: number; pixelRatio: number };
  viewport: { width: number; height: number };
  webgl: { vendor: string; renderer: string };
  timezone: string;
  geolocation?: { latitude: number; longitude: number; accuracy: number };
  permissions: FingerprintPermissions;
  behavior: FingerprintBehavior;
  canvasNoise: { enabled: boolean; strength: number };
}

interface FingerprintPermissions {
  notifications: PermissionState;
  geolocation: PermissionState;
  camera: PermissionState;
  microphone: PermissionState;
}

interface FingerprintBehavior {
  mouseMoveDelay: { min: number; max: number };
  keyPressDelay: { min: number; max: number };
  scrollStepDelay: { min: number; max: number };
}

8. 关键设计决策

反检测为首要质量指标

测、集成测试、手动检测结果共同构成反检测的"质量门"。任何新功能引入不能降低 反检测评分。

指纹模版化

不同网站对不同地区的浏览器有不同的预期。VisionL 提供多套预置指纹模版, 智能体可根据目标网站选择。v1 提供 3 套:

模版 ID 说明 UA 平台
desktop-chrome 桌面 Chrome 通用 Linux x86_64
desktop-windows Windows 10 Chrome Windows NT 10.0
desktop-mac macOS Chrome Macintosh Intel

Canvas 噪声策略

  • 同一页面会话(BrowserContext)使用相同的随机种子
  • 跨页面会话自动刷新种子
  • 噪声强度可配置(0-1),默认 0.3

HTTP 头注入时机

  • User-AgentAccept-Language:在创建 BrowserContext 时通过 Playwright API 设置
  • Sec-CH-UA-* 系列:通过请求拦截(page.route())修改

其他设计决策(同前)

  • v1 不包含会话恢复
  • 无身份认证(仅 localhost
  • Page ID + 别名双轨引用
  • 每个 daemon 一个 Browser 实例

9. 测试策略

层级 工具 范围
反检测验证 脚本 + 人工 对 bot.sannysoft.com、fingerprint.com 全绿验证
stealth/navigator vitest navigator 各属性值验证
stealth/chrome-runtime vitest window.chrome 对象完整性
stealth/canvas-noise vitest 噪声输出一致性、强度控制
stealth/headers vitest + msw HTTP 头正确性
stealth/human-input vitest 鼠标路径计算、键盘延迟分布
core 类型 ts 类型检查 编译期正确性
daemon/routes vitest + playwright-test 路由逻辑
cli/commands vitest + mock 命令解析
集成测试 vitest + 真实 daemon CLI → daemon → Playwright
JSON 转义 vitest 特殊字符安全

10. 未来规划(v1 范围外)

  • visionl-gui:桌面 GUI
  • 会话持久化
  • 更多指纹模版(移动端 Chrome、Safari、Edge 等)
  • 指纹随机化(每个页面随机微调指纹参数)
  • 行为模拟增强(贝塞尔曲线鼠标路径、人类式打字节奏)
  • 验证码自动识别(对接打码服务)
  • 多用户支持
  • 插件系统
  • 远程 daemon
  • 网络拦截和 Mock API
  • Cookie/存储管理 CLI
  • 页面录制与回放