mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-31 16:33:34 +08:00
226 lines
8.3 KiB
Markdown
226 lines
8.3 KiB
Markdown
# 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 或隧道固定转发一个上游端口。
|
||
|
||
端口必须是 `1024–65535` 之间且浏览器允许访问的整数。修改后要重启应用才会生效。
|
||
|
||
### 断连保活
|
||
|
||
手机锁屏、切后台或短暂换网时:
|
||
|
||
- 正在执行的任务不会因为 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、用户名或路径。
|