方案:Cloudflare Tunnel + Zero Trust(推荐,适合中国大陆)

为什么不用 Tailscale

  • Tailscale 登录依赖 Google/GitHub,在中国大陆访问不稳定
  • Tailscale Serve 的 MagicDNS (.ts.net) 可能被代理工具(Surge/Clash)劫持,导致浏览器无法解析
  • curl 能通但浏览器打不开的问题很难排查

为什么用 Cloudflare Tunnel

  • cloudflared 从本机主动建立出站连接到 Cloudflare 边缘节点
  • 不依赖特殊 DNS,浏览器访问的是普通 HTTPS 网站
  • Cloudflare 在全球有节点,中国大陆可达
  • 免费

前置条件

  1. Cloudflare 账号
  2. 一个托管在 Cloudflare 上的域名(DNS 已转到 CF nameserver)
  3. 本机已安装 cloudflaredbrew install cloudflared
  4. OpenClaw Gateway 正在运行(openclaw gateway status 确认)
  5. 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

1
cloudflared tunnel login

会打开浏览器让你登录并选择域名授权。完成后凭证保存在 ~/.cloudflared/cert.pem

第二步:创建 Tunnel

1
cloudflared tunnel create openclaw-gw

记下输出的 tunnel ID(类似 adc55e8a-df69-4fff-b13f-79878e48fa60)。

凭证文件自动保存在 ~/.cloudflared/<tunnel-id>.json

第三步:配置 DNS

1
cloudflared tunnel route dns openclaw-gw gw.example.com

这会自动在 Cloudflare DNS 上创建一条 CNAME 记录,指向你的 tunnel。

第四步:创建 cloudflared 配置文件

创建 ~/.cloudflared/config.yml

1
2
3
4
5
6
7
tunnel: <你的tunnel-id>
credentials-file: /Users/<你的用户名>/.cloudflared/<你的tunnel-id>.json

ingress:
  - hostname: gw.example.com
    service: http://127.0.0.1:18789
  - service: http_status:404

第五步:设置 Gateway 允许的来源(关键!)

1
openclaw config set gateway.controlUi.allowedOrigins '["https://gw.example.com"]'

这一步必须做。 Gateway 默认只接受来自 localhost 的 WebSocket 连接。不设置 allowedOrigins,CF Tunnel 代理过来的请求会被 Gateway 拒绝——Dashboard 页面能加载但 WebSocket 连不上。

第六步:配置开机自启

brew services start cloudflared 默认不带 tunnel run 参数,需要自己写 LaunchAgent:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
cat > ~/Library/LaunchAgents/com.cloudflare.openclaw-tunnel.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>com.cloudflare.openclaw-tunnel</string>
  <key>ProgramArguments</key>
  <array>
    <string>/opt/homebrew/bin/cloudflared</string>
    <string>tunnel</string>
    <string>run</string>
    <string>openclaw-gw</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
  <key>KeepAlive</key>
  <true/>
  <key>StandardOutPath</key>
  <string>/opt/homebrew/var/log/cloudflared-openclaw.log</string>
  <key>StandardErrorPath</key>
  <string>/opt/homebrew/var/log/cloudflared-openclaw.log</string>
</dict>
</plist>
EOF

launchctl load ~/Library/LaunchAgents/com.cloudflare.openclaw-tunnel.plist

⚠️ 注意:不要同时用 brew services start cloudflared,否则会起两个进程冲突。


第二部分:配置 Cloudflare Zero Trust Access(推荐)

在 CF Tunnel 前面加一层身份认证,只有你的邮箱能访问,安全性不依赖 OpenClaw 自身的 token 机制。

架构对比

1
2
不配 Zero Trust:  远程浏览器 → CF Tunnel → Gateway
配了 Zero Trust:  远程浏览器 → Cloudflare Access(邮箱验证)→ CF Tunnel → Gateway

配置步骤

⚠️ 必须先创建策略,再创建应用程序(应用程序需要选择已有的策略)。

1. 创建 Access 策略

  1. 打开 Cloudflare Zero Trust Dashboard
  2. 左侧菜单 → AccessPoliciesAdd a reusable policy
  3. 填写:
    • 策略名称:Email Whitelist
    • 操作:Allow
    • 添加规则 → 选择器:Emails → 值:填你的邮箱地址
  4. 保存

2. 创建 Access 应用程序

  1. 左侧菜单 → AccessApplicationsAdd an application
  2. 选择 Self-hosted(自托管)→ 添加公共主机名
  3. 填写应用域名(你的 tunnel 域名,如 gw.example.com
  4. 选择刚创建的策略 Email Whitelist
  5. 认证方式默认 One-time PIN(Cloudflare 发验证码到邮箱,不依赖 Google/GitHub)
  6. 保存

效果

  • 任何人访问你的域名,都会先弹 Cloudflare 登录页,要求输入邮箱
  • 只有白名单邮箱能收到验证码并通过
  • 不在白名单的邮箱直接被拦截,连 Gateway 页面都加载不了
  • 免费(50 用户以内)

远程访问:Dashboard(浏览器)

获取带 Token 的 URL

1
openclaw dashboard --no-open

输出类似:

1
Dashboard URL: http://127.0.0.1:18789/#token=你的gateway-token

远程访问

把域名替换进去:

1
https://gw.example.com/#token=你的gateway-token

Token 通过 URL hash(#token=xxx)传递给 Dashboard 前端,前端在 WebSocket 握手时通过 connect.params.auth.token 发送给 Gateway 认证。


远程访问:CLI(命令行)

在另一台机器上安装 OpenClaw 后,可以通过 CLI 远程连接 Gateway。

方式一:设为默认远程连接

1
2
3
openclaw config set gateway.mode "remote"
openclaw config set gateway.remote.url "wss://gw.example.com"
openclaw config set gateway.remote.token "你的gateway-token"

之后所有 CLI 命令默认走远程:

1
2
3
4
5
6
openclaw status          # 远程 Gateway 状态
openclaw health          # 远程健康检查
openclaw devices list    # 远程设备管理
openclaw config get ...  # 远程查看配置
openclaw cron list       # 远程定时任务
openclaw logs            # 远程日志

如果需要临时查本地 Gateway:

1
openclaw status --url ws://127.0.0.1:18789

方式二:保持默认本地,按需连远程

不改配置,每次手动指定:

1
openclaw status --url wss://gw.example.com --token 你的gateway-token

适合偶尔连一下的场景。哪边用得多,就把哪边设成默认。


设备配对(Pairing)

Dashboard 使用双重认证机制:

  1. Gateway Token:WebSocket 握手时验证身份(第一道门)
  2. 设备配对(Device Pairing):每个新设备/浏览器首次连接需要批准(第二道门)

即使 token 正确,新设备首次连接仍会显示 “pairing required”。只有 localhost(127.0.0.1)的连接会自动批准,远程连接必须显式批准。

通过 CLI 批准(推荐)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 查看所有设备和待批准请求
openclaw devices list

# 批准最新的 pending 请求
openclaw devices approve

# 批准指定请求
openclaw devices approve <requestId>

# 拒绝请求
openclaw devices reject <requestId>

通过本地 Dashboard 批准

  1. 在本机浏览器打开 http://127.0.0.1:18789/(本地连接自动批准,无需配对)
  2. 远程设备请求配对后,本地 Dashboard 会收到通知
  3. 点击"批准"即可

设备管理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 列出所有已配对设备
openclaw devices list

# 移除某个设备
openclaw devices remove <deviceId>

# 清除所有已配对设备
openclaw devices clear --yes

# 轮换设备 token
openclaw devices rotate --device <deviceId> --role operator

# 吊销设备 token
openclaw devices revoke --device <deviceId> --role operator

每个浏览器 profile 会生成唯一的 device ID。清除浏览器数据会触发重新配对。


⚠️ 安全风险提示

三层安全防护

配置完成后,你的 Gateway 有三层保护:

层级机制作用
第一层Cloudflare Zero Trust Access邮箱白名单,非白名单用户连页面都看不到
第二层Gateway TokenWebSocket 握手认证
第三层设备配对(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 限制。

安全建议

  1. Token 绝不能泄露 — 不要发在群聊、截图、公开文档中
  2. 保持更新openclaw status 查看是否有安全更新
  3. 定期审计 — 运行 openclaw security audit --deep
  4. 定期检查设备列表openclaw devices list,移除不认识的设备
  5. 轮换 token — 如果怀疑泄露,立即更换:
    1
    
    openclaw config set gateway.auth.token "$(openssl rand -hex 24)"
    
  6. URL 中的 token 注意保护#token=xxx 虽然不会发送到服务器(hash 不走网络),但会存在浏览器历史记录中

注意事项

  1. cloudflared 进程必须保持运行 — 断了远程就访问不了。
  2. Gateway 不需要重启allowedOrigins 等配置通过 openclaw config set 写入后会自动热加载。
  3. Tailscale 可以共存 — CF Tunnel 和 Tailscale Serve 不冲突,可以同时开着。

排错

现象原因解决
页面白屏 / ERR_CONNECTION_REFUSEDcloudflared 没运行检查 LaunchAgent 或手动 cloudflared tunnel run openclaw-gw
“unauthorized: gateway token missing”URL 里没带 tokenhttps://域名/#token=xxx 访问
页面加载但 WebSocket 连不上allowedOrigins 没配openclaw config set gateway.controlUi.allowedOrigins '["https://你的域名"]'
“pairing required”新设备首次连接openclaw devices approve
cloudflared 返回 404ingress hostname 不匹配检查 ~/.cloudflared/config.yml 的 hostname
CLI 远程连接超时URL 或 token 不对检查 gateway.remote.urlgateway.remote.token
Gateway 拒绝启动config 校验失败openclaw doctor 查看具体错误