方案:Cloudflare Tunnel + Zero Trust(推荐,适合中国大陆)
为什么不用 Tailscale
- Tailscale 登录依赖 Google/GitHub,在中国大陆访问不稳定
- Tailscale Serve 的 MagicDNS (
.ts.net) 可能被代理工具(Surge/Clash)劫持,导致浏览器无法解析 - curl 能通但浏览器打不开的问题很难排查
为什么用 Cloudflare Tunnel
cloudflared从本机主动建立出站连接到 Cloudflare 边缘节点- 不依赖特殊 DNS,浏览器访问的是普通 HTTPS 网站
- Cloudflare 在全球有节点,中国大陆可达
- 免费
前置条件
- Cloudflare 账号
- 一个托管在 Cloudflare 上的域名(DNS 已转到 CF nameserver)
- 本机已安装
cloudflared(brew install cloudflared) - OpenClaw Gateway 正在运行(
openclaw gateway status确认) - Gateway 已配置 auth token(远程访问必须有认证):
1 2 3 4# 查看当前 token openclaw config get gateway.auth.token # 如果没有,设置一个 openclaw config set gateway.auth.token "$(openssl rand -hex 24)"
第一部分:创建 Tunnel
第一步:登录 Cloudflare
| |
会打开浏览器让你登录并选择域名授权。完成后凭证保存在 ~/.cloudflared/cert.pem。
第二步:创建 Tunnel
| |
记下输出的 tunnel ID(类似 adc55e8a-df69-4fff-b13f-79878e48fa60)。
凭证文件自动保存在 ~/.cloudflared/<tunnel-id>.json。
第三步:配置 DNS
| |
这会自动在 Cloudflare DNS 上创建一条 CNAME 记录,指向你的 tunnel。
第四步:创建 cloudflared 配置文件
创建 ~/.cloudflared/config.yml:
| |
第五步:设置 Gateway 允许的来源(关键!)
| |
这一步必须做。 Gateway 默认只接受来自 localhost 的 WebSocket 连接。不设置 allowedOrigins,CF Tunnel 代理过来的请求会被 Gateway 拒绝——Dashboard 页面能加载但 WebSocket 连不上。
第六步:配置开机自启
brew services start cloudflared 默认不带 tunnel run 参数,需要自己写 LaunchAgent:
| |
⚠️ 注意:不要同时用 brew services start cloudflared,否则会起两个进程冲突。
第二部分:配置 Cloudflare Zero Trust Access(推荐)
在 CF Tunnel 前面加一层身份认证,只有你的邮箱能访问,安全性不依赖 OpenClaw 自身的 token 机制。
架构对比
| |
配置步骤
⚠️ 必须先创建策略,再创建应用程序(应用程序需要选择已有的策略)。
1. 创建 Access 策略
- 打开 Cloudflare Zero Trust Dashboard
- 左侧菜单 → Access → Policies → Add a reusable policy
- 填写:
- 策略名称:
Email Whitelist - 操作:
Allow - 添加规则 → 选择器:
Emails→ 值:填你的邮箱地址
- 策略名称:
- 保存
2. 创建 Access 应用程序
- 左侧菜单 → Access → Applications → Add an application
- 选择 Self-hosted(自托管)→ 添加公共主机名
- 填写应用域名(你的 tunnel 域名,如
gw.example.com) - 选择刚创建的策略
Email Whitelist - 认证方式默认 One-time PIN(Cloudflare 发验证码到邮箱,不依赖 Google/GitHub)
- 保存
效果
- 任何人访问你的域名,都会先弹 Cloudflare 登录页,要求输入邮箱
- 只有白名单邮箱能收到验证码并通过
- 不在白名单的邮箱直接被拦截,连 Gateway 页面都加载不了
- 免费(50 用户以内)
远程访问:Dashboard(浏览器)
获取带 Token 的 URL
| |
输出类似:
| |
远程访问
把域名替换进去:
| |
Token 通过 URL hash(#token=xxx)传递给 Dashboard 前端,前端在 WebSocket 握手时通过 connect.params.auth.token 发送给 Gateway 认证。
远程访问:CLI(命令行)
在另一台机器上安装 OpenClaw 后,可以通过 CLI 远程连接 Gateway。
方式一:设为默认远程连接
| |
之后所有 CLI 命令默认走远程:
| |
如果需要临时查本地 Gateway:
| |
方式二:保持默认本地,按需连远程
不改配置,每次手动指定:
| |
适合偶尔连一下的场景。哪边用得多,就把哪边设成默认。
设备配对(Pairing)
Dashboard 使用双重认证机制:
- Gateway Token:WebSocket 握手时验证身份(第一道门)
- 设备配对(Device Pairing):每个新设备/浏览器首次连接需要批准(第二道门)
即使 token 正确,新设备首次连接仍会显示 “pairing required”。只有 localhost(127.0.0.1)的连接会自动批准,远程连接必须显式批准。
通过 CLI 批准(推荐)
| |
通过本地 Dashboard 批准
- 在本机浏览器打开
http://127.0.0.1:18789/(本地连接自动批准,无需配对) - 远程设备请求配对后,本地 Dashboard 会收到通知
- 点击"批准"即可
设备管理
| |
每个浏览器 profile 会生成唯一的 device ID。清除浏览器数据会触发重新配对。
⚠️ 安全风险提示
三层安全防护
配置完成后,你的 Gateway 有三层保护:
| 层级 | 机制 | 作用 |
|---|---|---|
| 第一层 | Cloudflare Zero Trust Access | 邮箱白名单,非白名单用户连页面都看不到 |
| 第二层 | Gateway Token | WebSocket 握手认证 |
| 第三层 | 设备配对(Device Pairing) | 每个新设备需要显式批准 |
Gateway Token 的权限范围
Gateway Token = operator 级别的完全控制权限。拥有 token 的人(在通过设备配对后)可以:
| 操作 | 说明 |
|---|---|
| 执行任意命令 | 通过 sessions_spawn、/tools/invoke 在你的机器上 RCE |
| 修改配置 | 关闭 sandbox、修改 tool policy、开放更多权限 |
| 读取所有会话 | 查看全部历史对话、session 内容 |
| 注入消息 | 向任何 session 发送消息,操控 Agent 行为 |
| 控制 Agent | 创建新 session、修改 Agent 设置 |
已知历史漏洞
- CVE-2026-25253(已修复):攻击者构造恶意链接,诱骗用户点击后窃取 token,实现 1-click RCE。即使 Gateway 只绑定 loopback 也可被利用(通过受害者浏览器作为桥梁)。
- GHSA-943q-mwmv-hhvh(已修复):拿到 token 后可通过 HTTP
/tools/invoke端点升级权限,绕过 tool policy 限制。
安全建议
- Token 绝不能泄露 — 不要发在群聊、截图、公开文档中
- 保持更新 —
openclaw status查看是否有安全更新 - 定期审计 — 运行
openclaw security audit --deep - 定期检查设备列表 —
openclaw devices list,移除不认识的设备 - 轮换 token — 如果怀疑泄露,立即更换:
1openclaw config set gateway.auth.token "$(openssl rand -hex 24)" - URL 中的 token 注意保护 —
#token=xxx虽然不会发送到服务器(hash 不走网络),但会存在浏览器历史记录中
注意事项
- cloudflared 进程必须保持运行 — 断了远程就访问不了。
- Gateway 不需要重启 —
allowedOrigins等配置通过openclaw config set写入后会自动热加载。 - Tailscale 可以共存 — CF Tunnel 和 Tailscale Serve 不冲突,可以同时开着。
排错
| 现象 | 原因 | 解决 |
|---|---|---|
| 页面白屏 / ERR_CONNECTION_REFUSED | cloudflared 没运行 | 检查 LaunchAgent 或手动 cloudflared tunnel run openclaw-gw |
| “unauthorized: gateway token missing” | URL 里没带 token | 用 https://域名/#token=xxx 访问 |
| 页面加载但 WebSocket 连不上 | allowedOrigins 没配 | openclaw config set gateway.controlUi.allowedOrigins '["https://你的域名"]' |
| “pairing required” | 新设备首次连接 | openclaw devices approve |
| cloudflared 返回 404 | ingress hostname 不匹配 | 检查 ~/.cloudflared/config.yml 的 hostname |
| CLI 远程连接超时 | URL 或 token 不对 | 检查 gateway.remote.url 和 gateway.remote.token |
| Gateway 拒绝启动 | config 校验失败 | openclaw doctor 查看具体错误 |