cc-haha/docs/desktop/06-h5-access.md
2026-07-23 20:46:33 +08:00

226 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# H5 访问
H5 是桌面服务的可选浏览器入口。启用后,手机可以通过局域网或你自己的反向代理访问同一套会话、消息、附件和权限流程。
它不是公开 SaaS也不是多租户账号系统。任何拿到有效 H5 Token 的设备都可以访问桌面服务暴露的核心能力只应在可信网络、VPN 或自己维护的 HTTPS 代理中使用。
## 推荐结构:一个地址、一个端口
当前服务端可以同时提供:
- H5 静态页面
- REST API
- Provider 代理
- WebSocket / SDK 连接
因此推荐让浏览器只访问一个来源:
```text
http://192.168.1.20:3456/
```
同源路径不需要再维护独立的前端地址,也能减少 Token 和 WebSocket 代理配置错误。源码运行时默认服务端口是 `3456`;发布版应以设置页显示的“当前端口”为准。
安全策略不会因为前后端同源就自动信任一个远程浏览器。该来源仍需出现在 H5 允许来源中;桌面端正常开启流程会沿用已保存的 H5 配置,源码或手工部署应按下文显式填写 `allowedOrigins`
## 桌面端开启步骤
1. 打开「设置 → H5 访问」。
2. 打开「启用 H5 访问」,阅读风险提示后确认。
3. 查看自动生成的 H5 链接和“当前端口”。
4. 如果保存的局域网 IP 已失效,使用设置页建议的新 IP或手动填写电脑当前的局域网 IP。
5. 需要稳定书签或反向代理时,在“固定端口”填写 `3456` 或其他浏览器允许的端口并保存。
6. 修改固定端口后重启桌面端,确认“当前端口”已经变成新值。
7. 用手机扫描二维码,或复制“扫码链接”到可信设备。
二维码链接会携带 Server URL 和 H5 Token。浏览器连接成功后会在本机保存连接信息后续打开可继续使用。
### 访问主机 / IP
普通局域网访问只填写电脑真实的私有 IP例如
```text
192.168.1.20
```
设置页会结合当前服务端口生成完整地址。如果电脑切换 Wi-Fi、网线或 VPN原 IP 可能不再属于当前网卡;桌面端会提示切换到可用地址。
使用反向代理时可以直接填写完整 URL
```text
https://cc.example.com
```
桌面端无法替你验证外部域名、隧道或证书是否持续可用。
### 固定端口
不设置固定端口时,桌面端会使用当前运行端口,并尽量复用已有端口。下列场景建议固定:
- 手机书签需要长期不变。
- 防火墙只允许指定端口。
- Nginx、Caddy 或隧道固定转发一个上游端口。
端口必须是 `102465535` 之间且浏览器允许访问的整数。修改后要重启应用才会生效。
### 断连保活
手机锁屏、切后台或短暂换网时:
- 正在执行的任务不会因为 H5 断连被直接停止。
- 任务可以在后台完成,重连后查看结果。
- 只有任务已经空闲且无人连接时,才会在保活时间到期后停止对应 CLI。
默认空闲保活时间为 30 秒,可配置范围是 5 秒到 24 小时。调大数值会让无人观察的空闲进程保留更久,不应把它当作云端永久任务。
## Token 生命周期
- Token 会保存在本机设置中,重启桌面端后仍可查看和生成二维码。
- **关闭 H5** 会立即拒绝远程访问,但会保留 Token方便以后重新启用已配对设备。
- **重新生成 Token** 会轮换凭证,旧二维码和旧 Token 立即失效。
- 不要把带 Token 的扫码链接贴到群聊、公开 Issue、日志截图或公共网页。
怀疑链接泄露时,应重新生成 Token而不只是关闭再打开 H5。
## 手机端可用范围
H5 优先保证对话主流程:
- 会话列表与项目切换。
- 消息发送、停止和流式回复。
- 图片和文件附件。
- 权限按钮与 AI 提问。
- 消息复制、分叉等操作。
- `@` 文件引用与适合触屏的输入布局。
- 手机安全区、软键盘和横竖屏下的基础布局。
桌面工作区、底部终端、原生文件“打开方式”、Computer Use 系统授权和桌面宠物不属于 H5 的完整等价体验。
## 从源码运行同源 H5
先构建 Web UI再让服务端在 `3456` 同时提供页面与 API
```bash
# 项目根目录
bun install
cd desktop
bun install
bun run build
cd ..
SERVER_HOST=0.0.0.0 \
SERVER_PORT=3456 \
CLAUDE_H5_AUTO_PUBLIC_URL=1 \
bun run src/server/index.ts
```
如果不是从项目根目录启动,设置:
```bash
CLAUDE_H5_DIST_DIR=/absolute/path/to/claude-code-haha/desktop/dist
```
没有 `desktop/dist` 时,控制 API 可以启动,但浏览器根路径会返回 404。
### 在服务器本机启用
H5 控制接口只接受本机可信请求。另开一个服务器终端:
```bash
curl -sS -X POST http://127.0.0.1:3456/api/h5-access/enable
```
响应中的 `token` 是完整 Token。为局域网地址设置同源入口和固定端口
```bash
curl -sS -X PUT http://127.0.0.1:3456/api/h5-access \
-H 'Content-Type: application/json' \
--data '{
"allowedOrigins": ["http://192.168.1.20:3456"],
"publicBaseUrl": "http://192.168.1.20:3456",
"fixedPort": 3456,
"disconnectGraceSeconds": 30
}'
```
把示例 IP 替换成服务器真实的局域网 IP。不要填写另一台机器或已经失效的网卡地址。
随后打开:
```text
http://192.168.1.20:3456/
```
更安全的个人方案是保持 `SERVER_HOST=127.0.0.1`,通过 SSH、VPN 或受控隧道访问;单纯 SSH 转发到本机时不需要启用 H5。
## 反向代理
推荐用一个 HTTPS 域名把静态页面和所有后端路径转到同一个上游:
```text
https://cc.example.com -> http://127.0.0.1:3456
```
至少确保下列路径进入同一个桌面服务:
- `/`
- `/api/*`
- `/proxy/*`
- `/ws/*`
WebSocket 路径必须支持协议升级。
### Nginx 必要请求头
反向代理连接本机服务时,后端看到的来源地址通常是 `127.0.0.1`。必须保留公开 Host或传递标准代理头防止远程请求被误判为本地直连
```nginx
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
```
Caddy 默认会保留原始 Host 并补充 `X-Forwarded-*`。如果自定义 `header_up`,不要同时把 Host 改成 `127.0.0.1` 并删除全部代理头。
反向代理域名也要加入 H5 允许来源。可从服务器本机调用控制接口:
```bash
curl -sS -X PUT http://127.0.0.1:3456/api/h5-access \
-H 'Content-Type: application/json' \
--data '{
"allowedOrigins": ["https://cc.example.com"],
"publicBaseUrl": "https://cc.example.com"
}'
```
如果必须把页面与 API 放在不同来源,需要把页面来源加入 `allowedOrigins`,并另外维护 Server URL。不要使用通配来源。除非现有基础设施强制要求否则优先使用同源方案。
## 安全检查
- H5 默认关闭。
- 远程 REST、Provider 代理与 WebSocket 都需要有效 Token。
- 本机回环豁免不会扩展到真实局域网或带代理痕迹的请求。
- 远程预览与桌面可信 session 分离,不会自动获得摄像头、麦克风或通知权限。
- 不使用时关闭 H5。
- 泄露时重新生成 Token。
- 公网使用 HTTPS、VPN、访问控制与防火墙不要只依赖一个长期 Token。
- 不要把桌面服务直接暴露给不受信任的团队或互联网扫描。
## 排查
| 现象 | 检查 |
|------|------|
| 二维码打不开 | 核对访问主机是否属于当前网卡、手机与电脑是否同网 |
| 地址端口不一致 | 以“当前端口”为准;固定端口修改后重启 |
| 页面 404 | 构建 `desktop/dist`,或检查 `CLAUDE_H5_DIST_DIR` |
| Token 无效 | 确认 H5 已启用;重新生成后更新旧书签 |
| 浏览器提示 CORS | 把浏览器地址栏中的来源精确加入 `allowedOrigins`,不要使用 `*` |
| REST 可用但消息不流式 | 检查 `/ws/*` 的 WebSocket upgrade |
| 反代后被当成本机或被拒绝 | 保留公开 Host 和标准代理头 |
| 切换网络后旧 IP 失效 | 在设置页应用建议 IP 或更新反向代理地址 |
| 手机切后台后连接消失 | 重新打开页面;运行中任务应继续,空闲任务受保活时间限制 |
仍无法定位时,到「设置 → 诊断」复制错误摘要与事件 ID。分享诊断材料前检查其中是否含私有域名、IP、用户名或路径。