Files
Nexus/docs/design/specs/2026-06-11-server-browser-chromium-design.md
2026-07-08 22:31:31 +08:00

7.2 KiB
Raw Permalink Blame History

服务端远程浏览器(Playwright Chromium)— 设计说明

取代 iframe 渲染方案(2026-06-11-embedded-browser-design.md 中的页面加载方式)。
UI 状态(标签、收藏 nav_links、窗口位置)仍走 /api/browser/state,不变。

背景与目标

运维需要在 Nexus 浮动面板内完整浏览任意公网站点,不受 X-Frame-Options / CSP frame-ancestors 限制,且使用服务端独立浏览器内核,而非用户本机标签页内的 iframe。

用户确认(2026-06-11

决策项 选择
可访问范围 任意公网 http / https
内核 ChromiumPlaywright),不要求 Firefox
交互 在 Nexus 面板内看画面 + 键鼠操作(非「新标签打开」为主)

与 iframe 方案对比

iframe(现状) 服务端 Chromium(目标)
渲染位置 用户浏览器 Nexus 服务器
站点嵌入限制 常被拒绝 无(顶层窗口)
SSRF 风险 有,必须缓解
资源 几乎无 每会话 ~200500MB RAM
Cookie / 登录 用户本机 服务器浏览器 Profile

方案概述

类比 RDPguacd → WebSocket → 前端画布),但 Nexus 拥有浏览器进程与协议:

管理员浏览器 (Vue SPA)
    │  JWT WebSocket + REST
    ▼
Nexus API (FastAPI) — 桥接,不跑 Chromium
    │  Worker Key + 内网 HTTPS
    ▼
Browser Worker VPS — Playwright Chromiumheadless + CDP screencast
    ▼
公网目标站点
组件 职责
Playwright Chromium 运行在 Browser WorkerNexus 桥接会话
URL 安全网关 导航前 DNS 解析 + IP 段校验,阻断私网/元数据 SSRF
/ws/browser/{session_id} 推送 JPEG 帧;接收 navigate / 键鼠 / 滚动
POST/DELETE /api/browser/sessions 创建、销毁会话
GlobalBrowserPanel <canvas> 替代 <iframe>;保留地址栏、标签、收藏、最小化
/api/browser/state 不变 — tabs、visits、nav_links、rect

刻意不做(首版)

  • 不做 HTTP 反向代理(HTML 改写 / Cookie 注入)
  • 不做浏览内容审计或页面录制落库
  • 不做多管理员并发压测级扩展(单人运维,全局并发 ≤2)
  • 不做本机 Cookie 与服务器 Profile 双向同步

WebSocket 协议(草案)

鉴权:与终端/RDP 一致,query ?token= = 常规 access JWTsub = admin_id),且 session 归属该校验通过的管理员。

服务端 → 客户端

type 字段 说明
BROWSER_INIT session_id, viewport_w, viewport_h 连接就绪
SCREENCAST_FRAME data_b64, metadata CDP screencast JPEG
PAGE_INFO url, title 导航完成或标题变化
ERROR message, code URL 拒绝、超时、Playwright 错误
PONG 心跳

客户端 → 服务端

type 字段 说明
NAVIGATE url 经 SSRF 校验后 page.goto
RELOAD / GO_BACK / GO_FORWARD 历史导航
MOUSE event, x, y, button move / down / up / wheel
KEY event, key, code, text down / up / type
VIEWPORT width, height 面板尺寸变化
PING 心跳

坐标:x/y 为相对 viewport 的 CSS 像素,与 screencast 帧尺寸一致。

SSRF 防护(任意公网)

导航与每次 redirect 后 重新校验 最终 URL

  1. http: / https:;拒绝凭据、javascript:data:file:
  2. 解析 hostname → getaddrinfo所有解析 IP 必须不在阻断段:
    • 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
    • 169.254.0.0/16, 0.0.0.0/8, 100.64.0.0/10
    • IPv6: ::1, fc00::/7, fe80::/10
  3. 阻断常见 metadata 主机名(如 169.254.169.254*metadata* 字面)
  4. 导航超时 30s;单页资源不限制由 Chromium 自身处理
  5. 失败时 WS 返回 ERROR静默降级

单人运维下 residual riskDNS rebinding 需 TTL 短重查或 redirect 链逐跳校验;首版采用 redirect 监听 + 每跳校验

会话与资源

策略
每管理员活跃会话 1
全局活跃会话 ≤2
空闲超时 30 min 无 WS 活动 → 关闭 browser context
视口默认 1280×720(可随面板 resize
Screencast CDP Page.startScreencast, JPEG quality ~80

进程模型:单例 Playwright Browser 进程 + 每会话独立 BrowserContext(隔离 Cookie)。

部署(选定:独立 Worker 服务器)

购机与装机计划2026-06-11-browser-worker-server-procurement.md

Playwright Chromium 不装入 Nexus 主站镜像,而在**单独 VPSBrowser Worker**运行;Nexus 主站仅桥接 WebSocket。

管理员浏览器 → Nexus APIJWT)→ Browser WorkerWorker Key)→ 公网
组件 部署位置
browser-worker/ 服务 + Chromium Worker VPS2C4G 起)
/api/browser/sessions/ws/browser/* 桥接 Nexus 主站
MySQL UI 状态 Nexus 主站(不变)

Nexus 主站 .env

NEXUS_BROWSER_ENABLED=1
NEXUS_BROWSER_WORKER_URL=https://<worker-internal-or-vpn>:8443
NEXUS_BROWSER_WORKER_SECRET=<shared-secret>
NEXUS_BROWSER_MAX_SESSIONS=2
NEXUS_BROWSER_IDLE_TIMEOUT_SEC=1800

Worker 防火墙8443 Nexus 主站 IP;不对公网开放 Worker API。

降级NEXUS_BROWSER_ENABLED=0 或 Worker 不可达 → POST /api/browser/sessions 503;前端提示「服务端浏览器未启用」。

Dockerfile.prod 增加 ChromiumWorker 模式不修改主站镜像体积

前端变更

  • GlobalBrowserPanel.vue<iframe><canvas> + useRemoteBrowserSession.ts
  • 保留:浮动/最小化/不可关闭/重启、标签、历史、收藏(nav_links 待做 UI
  • 移除或隐藏:「新标签打开」可保留作 导出 URL 辅助,非主路径
  • useGlobalBrowser.tsnavigate 改为 WS NAVIGATEframeKey 不再需要

安全与隐私

  • 页面内容经 JPEG 帧过 Nexus不持久化截图
  • 服务器 Chromium 内 Cookie 存于容器 ephemeral context(重启会话丢失)
  • get_current_admin 可创建/连接会话
  • CUD:创建/销毁会话可选写 audit(首版 不做,与 RDP 无连接审计一致)

验收标准

  • 打开 https://example.com 等公网站,面板 canvas 有画面且可点击链接
  • 曾 iframe 白屏的站点(如带 X-Frame-Options: DENY 的站)可正常显示
  • 访问 http://127.0.0.1 / http://10.x / metadata → 明确 ERROR,不发起请求
  • 刷新页面后会话内 Cookie 保留;重启浏览器会话 Cookie 清空
  • 标签、收藏、窗口位置仍持久化到 /api/browser/state
  • NEXUS_BROWSER_ENABLED=0 时有可读降级提示
  • Worker VPS 部署完成,防火墙仅 Nexus 主站可连

回滚

  • NEXUS_BROWSER_ENABLED=0 → 503,前端可回退 iframe 分支(保留 feature flag 一段过渡期)
  • 卸载 Playwright 依赖仅当确认不再使用