OpenClaw Gateway 发现机制与传输方式详解:Bonjour、Tailscale 与 SSH 的多路径连接方案
2026/9/15 12:40:44 网站建设 项目流程

OpenClaw Gateway 发现机制与传输方式详解:Bonjour、Tailscale 与 SSH 的多路径连接方案

【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 🦞项目地址: https://gitcode.com/GitHub_Trending/cl/openclaw

OpenClaw 将"发现"拆解为两个既相关又彼此独立的问题:操作者远程控制(macOS 菜单栏 App 控制运行在其他主机上的 Gateway)与节点配对(iOS/Android 节点发现 Gateway 并安全配对)。本指南围绕 docs/gateway/discovery.md 展开,系统讲解 Gateway 的 Direct WS 与 SSH 两类传输方式、Bonjour/DNS-SD 广播信标(beacon)的 TXT 记录细节、Tailnet 跨网发现策略,以及客户端如何按策略选择传输路径。读完本文,你将掌握discovery.mdns.modeOPENCLAW_DISABLE_BONJOUROPENCLAW_SSH_PORT等配置项的完整语义,并能在真实部署中判断何时该用 LAN 直连、何时回退 SSH。

两个发现问题的本质区别

OpenClaw 的发现体系服务于两种完全不同的场景:

  1. 操作者远程控制:macOS 菜单栏 App 需要连接运行在其他主机上的 Gateway(例如家庭台式机或 VPS 上的常驻实例)。
  2. 节点配对:iOS/Android(以及未来的节点形态)需要发现某个 Gateway 并与之安全配对,把节点能力挂接到 Gateway 拥有的会话上。

这两类问题共享同一套底层设施,但关注点不同:操作者关心的是"如何到达我的 Gateway",节点关心的是"如何发现并信任一个 Gateway"。所有网络发现/广播能力都集中在 Gatewayopenclaw gateway)一侧实现,macOS App 与 iOS/Android 节点只是消费者,自身不广播任何服务。

核心术语

术语含义
Gateway单个长期运行进程,拥有会话(sessions)、配对(pairing)、节点注册表(node registry)等状态,并运行各渠道(channels)。多数部署一台主机一个 Gateway;也支持隔离的多 Gateway 配置
Gateway WS(控制面)WebSocket 端点,默认监听127.0.0.1:18789;可通过gateway.bind绑定到局域网/tailnet
Direct WS transport面向 LAN/tailnet 的 Gateway WS 端点(不经 SSH 转发)
SSH transport(fallback)通过 SSH 转发127.0.0.1:18789实现远程控制,作为兜底方案

协议层面的细节见 Gateway protocol。

为什么 Direct WS 与 SSH 同时存在

两种传输不是互相替代的关系,而是覆盖不同网络条件的互补方案:

  • Direct WS 是同一网络与 tailnet 内的最佳体验:同 LAN 下通过 Bonjour 自动发现,配对 token 与 ACL 由 Gateway 全权掌控,无需任何 shell 访问权限。
  • SSH 是普适兜底:只要你有 SSH 访问权限就能工作,即使跨无关网络也能连通;它能绕过组播 mDNS 无法跨网、部分 Wi-Fi 禁用组播等常见问题,且除 SSH 端口外不需要开放任何新的入站端口。

从部署实践看,SSH 通道的典型用法是 docs/gateway/remote.md 中的一行命令:

ssh -N -L 18789:127.0.0.1:18789 user@gateway-host

隧道建立后,openclaw healthopenclaw status --deep以及openclaw gateway status/health/probe/call(配合--url)都能经由ws://127.0.0.1:18789触达远端 Gateway。

发现输入之一:Bonjour / DNS-SD

Bonjour(mDNS/DNS-SD)是 OpenClaw 在同一局域网内发现 Gateway 的主要手段。需要注意它的边界:组播 Bonjour 是尽力而为(best-effort)的,且不能跨网络。为此 OpenClaw 同时支持通过配置的广域 DNS-SD 域(unicast DNS-SD,即 Wide-Area Bonjour)浏览同一个 Gateway 信标,使发现范围同时覆盖同 LAN 的local.与可跨网的配置域。详细的排障与信标说明见 Bonjour discovery。

启用后,Gateway 通过随附的bonjour插件广播其 WS 端点;客户端浏览并展示"选择一个 Gateway"列表,随后应用各自的连接信任策略。在 macOS 上,选择一个候选只会打开连接编辑器,不会直接保存该广播端点——最终连接仍需用户确认。

服务信标细节

  • 服务类型:_openclaw-gw._tcp(Gateway 传输信标)。
  • TXT 键(均为非机密提示):
Key说明
role=gateway始终存在
transport=gateway始终存在
displayName=<name>操作者配置的显示名
lanHost=<hostname>.local仅 LAN mDNS 广播者写入;广域 DNS-SD 不写此键
gatewayPort=18789Gateway WS + HTTP 端口
gatewayTls=1仅当 TLS 启用时存在
gatewayTlsSha256=<sha256>仅当 TLS 启用且存在指纹时存在
tailnetDns=<magicdns>可选提示;检测到 Tailscale 时自动生成
sshPort=<port>仅当discovery.mdns.mode="full"时存在;默认"minimal"模式下省略(SSH 默认22),LAN 广播者与广域 DNS-SD 均如此
cliPath=<path>sshPort相同的discovery.mdns.mode="full"门槛;作为 CLI 路径的远程安装提示

在源码层面,这些 TXT 键由 extensions/bonjour/src/advertiser.ts 构建:txtBase始终写入rolegatewayPortlanHostdisplayName,仅在gatewayTlsEnabled时追加gatewayTls/gatewayTlsSha256,仅在非 minimal 模式(!opts.minimal)下追加tailnetDnscliPath,而transport=gatewaysshPort属于 gateway 服务自身的 TXT。对应地,advertiser.test.ts 中有一条专门用例断言minimal 模式下sshPortcliPathtailnetDns均为undefined

安全要点

  • Bonjour/mDNS 的 TXT 记录未经认证。客户端必须只把 TXT 值当作 UX 提示,绝不能当作权威路由信息。
  • 路由(host/port)应优先使用解析后的服务端点(SRV + A/AAAA),而不是 TXT 提供的lanHosttailnetDnsgatewayPort
  • TLS 固定(pinning)绝不允许让广播的gatewayTlsSha256覆盖先前已存储的固定值。
  • iOS/Android 节点在所选路由为安全/TLS 路径时,存储首次固定值前应要求用户明确"信任此指纹"确认(带外验证)。

启用、禁用与覆盖

  • openclaw plugins enable bonjour启用 LAN 组播广播。
  • openclaw.json中的discovery.mdns.mode控制 mDNS 广播:"minimal"(默认,只发核心 TXT 键)、"full"(向 LAN 信标与广域 DNS-SD 区域追加cliPath/sshPort)、"off"(禁用 mDNS)。
  • OPENCLAW_DISABLE_BONJOUR=1强制禁用广播;discovery.mdns.mode="off"可独立禁用。OPENCLAW_DISABLE_BONJOUR=0是显式 opt-in,可覆盖插件在检测到容器(Docker、containerd、Kubernetes、LXC)内的自动禁用;但它不能覆盖discovery.mdns.mode="off"。随附bonjour插件在 macOS 主机上自动启动(enabledByDefaultOnPlatforms: ["darwin"],见 openclaw.plugin.json),并在检测到容器时自动禁用;Linux、Windows 及其他容器化部署需显式plugins enable bonjour
  • ~/.openclaw/openclaw.json中的gateway.bind控制 Gateway 绑定模式。
  • OPENCLAW_SSH_PORT覆盖广播的 SSH 端口(仅在discovery.mdns.mode="full"时生效)。
  • OPENCLAW_TAILNET_DNS发布tailnetDns提示(MagicDNS)。
  • OPENCLAW_CLI_PATH覆盖广播的 CLI 路径。

从源码看,OPENCLAW_DISABLE_BONJOUR的解析逻辑位于 advertiser.ts:未设置返回null(交由后续判定),真值(true/1/yes/on等经isTruthyEnvValue)返回true0/false/no/off返回false。容器的自动禁用判定(isContainerEnvironment)综合三类信号:Fly.io 机器环境变量(FLY_MACHINE_ID+FLY_APP_NAME)、常见容器哨兵文件(/.dockerenv/run/.containerenv/var/run/.containerenv)以及/proc/1/cgroup中的 docker/containerd/kubepods/lxc 特征串(advertiser.ts)。测试 advertiser.test.ts 分别验证了容器自动禁用、Fly 机器自动禁用与OPENCLAW_DISABLE_BONJOUR=0显式 opt-in 三种路径。

另外,插件入口 index.ts 通过api.registerGatewayDiscoveryService注册广播服务,并把 Gateway 侧提供的gatewayPortgatewayTlsEnabledgatewayTlsFingerprintSha256gatewayDirectReachablesshPorttailnetDnscliPathminimal等上下文透传给 advertiser。

发现输入之二:Tailnet(跨网络)

对于位于不同物理网络的 Gateway,Bonjour 无能为力。推荐的直接目标是一个 **Tailscale MagicDNS 名称(优先)**或稳定的 tailnet IP。

  • 当 Gateway 检测到自己运行在 Tailscale 下时,会发布tailnetDns作为客户端的可选提示(广域信标同样携带)。
  • 对已配置的 macOS 连接,优先信任 MagicDNS 名称而非裸 tailnet IP,这样名称总能解析到当前地址。发现不会替换已保存的地址

移动节点配对有一条硬性安全规则:发现提示绝不放松 tailnet/公网路由上的传输安全

  • iOS/Android 首次 tailnet/公网连接仍必须走安全路径(wss://或 Tailscale Serve/Funnel)。
  • 发现到的裸 tailnet IP 只是路由提示,不是允许在远端使用明文ws://的授权。
  • 私有 LAN 直连ws://仍然支持。
  • 移动节点最简单的 Tailscale 路径:使用 Tailscale Serve,让发现与设置都解析到同一个安全的 MagicDNS 端点。

发现输入之三:手动 / SSH 目标

当没有直接路由(或直接模式被禁用)时,客户端总可以通过 SSH 转发回环 Gateway 端口来连接,详见 Remote access。这种方式不依赖任何自动发现设施,是最可靠的兜底。

传输选择(客户端策略)

macOS App 使用其已配置的 direct 或 SSH 传输;发现不会替换这条路由,也不会替客户端选择回退方案。新建连接时,用户在连接编辑器中提供受信地址、SSH 目标或设置码并保存。基于发现的客户端选择遵循如下策略:

  1. 已配置且可达的直连端点 → 使用它。
  2. 否则,若发现机制在local.或配置的广域域中找到 Gateway → 为该候选提供设置流程。保存直连端点前应用客户端的信任策略;发现本身不是授权
  3. 否则,若配置了 tailnet DNS/IP → 尝试直连。对 tailnet/公网路由上的移动节点,"直连"指安全端点,而非明文远端ws://
  4. 否则 → 回退到 SSH。

配对与认证(Direct transport)

在直连传输下,Gateway 是节点/客户端准入的唯一事实来源

  • 配对请求在 Gateway 中创建/批准/拒绝(见 Gateway pairing)。
  • Gateway 强制认证(token/密钥对)、作用域/ACL(它不是到每个方法的裸代理),并实施速率限制。

这意味着发现层只负责"找到并展示候选",真正决定"谁能连"的权力始终收敛在 Gateway 一侧,与前述"TXT 记录未认证、发现不等于授权"的安全模型一脉相承。

各组件职责

组件职责
Gateway广播发现信标、拥有配对决策、托管 WS 端点
macOS App编辑受信 Gateway 连接、展示配对提示、使用已配置的 direct 或 SSH 传输
iOS/Android 节点将 Bonjour 浏览作为便利手段,连接到已配对的 Gateway WS

深入源码:Bonjour 广播的健壮性设计

结合 extensions/bonjour 插件的实现,可以看到发现广播在工程上的若干细节:

  • 服务名与主机名规范:系统主机名若含空格、下划线等非法 DNS label 字符,会回退为openclaw.local;主机名超过 63 字节 DNS label 上限时按 UTF-8 边界安全截断(advertiser.ts)。测试 advertiser.test.ts 覆盖了非法主机名回退与多字节 CJK 主机名截断场景。也可通过OPENCLAW_MDNS_HOSTNAME显式指定。
  • 冲突自动解决:同一主机广播多个 Gateway 时,Bonjour 会追加(2)(3)等后缀保持实例名唯一;advertiser 监听name-change/hostname-change事件并记录警告日志(advertiser.ts)。
  • 日志降噪:ciao 自探测重试消息与短命 Docker 桥被移除导致的ENODEV套接字警告被过滤,避免刷爆 Gateway 日志(advertiser.ts)。
  • 单一生命周期:OpenClaw 对每个 Bonjour 服务只启动一次,探测、重试、命名冲突解决与接口变更重发布全部交给 mDNS responder,避免在网络抖动时出现重叠发布(对应测试断言广告失败后不会启动竞争性的重试循环,advertiser.test.ts)。

Gateway 的滚动日志(启动时打印gateway log file: ...)中可检索bonjour:前缀行,例如bonjour: advertise failed ...bonjour: suppressing ciao netmask assertion ...bonjour: ... name conflict resolved

实战决策速查

  • 同一 LAN:启用bonjour插件(macOS 自动;Linux/Windows/容器内显式openclaw plugins enable bonjour),客户端浏览_openclaw-gw._tcp local.即可发现。
  • 跨物理网络:优先 Tailscale MagicDNS + Tailscale Serve;或配置广域 DNS-SD(discovery.wideArea.domain,配合openclaw dns setup --apply一次性搭建,见 Bonjour discovery);再不济就用 SSH 隧道。
  • 容器/Docker 部署:Bonjour 默认自动禁用,OPENCLAW_DISABLE_BONJOUR=0仅在 host 网络、macvlan 等 mDNS 组播可用的网络下才应设置;否则保持禁用,走直接 URL、Tailnet 或 SSH。
  • 希望广播更多提示sshPort/cliPath/tailnetDns):将discovery.mdns.mode设为"full",并配合OPENCLAW_SSH_PORTOPENCLAW_CLI_PATHOPENCLAW_TAILNET_DNS覆盖具体值;模式变更可热生效,无需重启 Gateway 或断开客户端。

相关文档

  • Remote access — SSH 隧道、CLI 远程默认值与 macOS 持久隧道
  • Tailscale — tailnet 直连配置
  • Bonjour discovery — mDNS 模式、Docker 注意事项与排障
  • Gateway pairing — 节点配对与审批
  • Gateway protocol — Gateway WS 协议细节

【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 🦞项目地址: https://gitcode.com/GitHub_Trending/cl/openclaw

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询