摘要 :Gateway(网关) 是 OpenClaw 的 常驻控制进程 。它在一个端口上同时处理多种协议:WebSocket 用于实时控制和远程调用(RPC),HTTP 提供 OpenAI 兼容的 API 接口,还有管理界面(UI)和画布(Canvas)功能。无论是即时通讯(IM)渠道、桌面客户端还是自动化脚本,都必须先连接到 Gateway,然后才能使用 Router(路由)、Brain(大脑)和 Hands(执行器)等功能。本文结合官方 Gateway Runbook(运行手册) 和 Network model(网络模型) 文档,讲解三个核心概念:单实例锁定 (通过独占端口实现)、默认身份验证 、健康检查与配置热重载 。同时,我们将基于源码(固定 commit)走读启动流程:从 openclaw gateway 命令行 到 runGatewayLoop(处理锁和信号) ,再到 startGatewayServer(组装运行时),为下一篇 Router 做好铺垫。
关键词 :OpenClaw;Gateway(网关);WebSocket;HTTP 多路复用;单实例;openclaw gateway;startGatewayServer;健康检查;源码走读
系列文章:
- OpenClaw 深度解析与源代码导读 · 第1篇:系列导读——术语、版本与读源码方法
- OpenClaw 深度解析与源代码导读 · 第2篇:Skills——能力扩展平面与源码中的「目录即技能」
源码版本说明 :本文引用路径基于 openclaw/openclaw 仓库;本地阅读使用的 commit 为 0dd4958bc8a78d26b3b526b1f2e63b15110c64a2 (2026-04-11)。GitHub 上可按该 SHA 查看对应版本的源码,避免 main 分支变动导致的差异。
在深入 Gateway 之前,先通过一张架构图理解 Gateway 在 OpenClaw 整体中的位置(延续第1篇的餐厅比喻):
1.1 各组件职责速查表
1.2 数据流向示例
场景:用户发送一条 WhatsApp 消息给 Agent
💡 理解要点 :Gateway 是 "一夫当关" 的入口,但它不处理业务逻辑 ------只负责 "接进来、送出去、保安全、管连接"。
在第1篇里,我们把 Gateway 比作餐厅的 前台 :它不亲自炒菜(Brain 负责),也不端盘子(Hands 负责),但 所有顾客(渠道消息)、外卖订单(HTTP API)、排号屏幕(控制 UI)都必须先经过它 。如果跳过 Gateway 直接研究 auto-reply 或某个具体渠道插件,很容易混淆几个关键问题:谁负责维持长连接?谁在做身份验证?谁在检查服务是否存活?
本文解答三个核心问题:
- 产品定位 :Gateway 进程 负责什么、不负责什么 (与多 Agent、workspace 隔离的关系在第1篇已有,本文补充 网络边界和进程边界)。
- 运维操作 :如何 启动 / 检查健康状态 / 排查故障 ,以及 为什么默认开启身份验证、为什么独占端口。
- 源码结构 :从
openclaw gateway命令 到startGatewayServer,建立后续 Router 篇需要的 "入口函数地图"。
💡 理解要点 :本文刻意 不展开每一条 WebSocket RPC 协议细节 (那是协议层内容,见 D1 bridge-protocol);本文聚焦 进程模型 + 端口模型 + 启动调用链。
官方 Runbook(D1:Gateway runbook)用几句话概括了运行时模型,核心要点如下:
- 一个常驻进程 负责消息路由、控制面和 渠道的长连接管理。
- 同一个端口 同时承载多种协议:
- WebSocket 用于实时控制和远程调用(RPC);
- HTTP 提供 OpenAI 兼容接口(如
/v1/models、/v1/chat/completions、/v1/responses、/v1/embeddings)、/tools/invoke等; - 管理 UI、Canvas 相关路由等。
- 默认绑定地址 :
loopback(回环地址,即 127.0.0.1);默认身份验证 :开启(通过共享密钥gateway.auth.token/password或环境变量OPENCLAW_GATEWAY_*);非回环地址场景可使用 trusted-proxy(可信代理) 等模式(见 D1 configuration、trusted-proxy-auth)。
🔍 实际例子 :默认地址是 ws://127.0.0.1:18789 (端口可修改)。本地命令行工具(CLI)、终端界面(TUI)、桌面客户端都通过 同一个 WebSocket 地址 进行远程调用;Open WebUI 这类客户端通常会先 GET /v1/models 获取模型列表,再 POST 聊天请求------这些请求都落在 同一个 Gateway 端口 上,由 HTTP 和 WebSocket 分别处理。
3.1 与网络模型文档的关系
docs/gateway/network-model.md 提示部分内容已并入站点 Network 总页,但核心结论值得深入理解:
为什么"建议每台主机运行一个 Gateway"?
核心原因是 WhatsApp Web 等渠道的技术限制 。这些 IM 渠道使用 QR 码扫码登录 机制,且一个手机号同一时间只能有一个活跃的 Web 会话。如果同一主机上运行多个 Gateway 进程,它们会互相竞争 WhatsApp Web 连接,导致:
- 频繁掉线:后启动的 Gateway 会踢掉先登录的会话
- 消息丢失:正在处理的对话可能中断
- 状态混乱:多个进程同时尝试维持心跳,触发平台的风控
其他渠道(Discord、Slack、Telegram 等 Bot Token 机制) 无此限制,但为统一管理,OpenClaw 仍建议 单主机单 Gateway 作为默认部署模式。
什么是"强隔离"?何时需要多 Gateway?
当以下场景出现时,需要在一台物理机上运行 多个完全独立的 Gateway 实例:
OPENCLAW_HOME 目录
测试 vs 生产 测试环境的故障不能影响生产服务 不同的
profile (如
--profile test)
多 WhatsApp 号 一个公司需要同时运营多个 WhatsApp 业务号 不同的
端口 + 不同的工作目录
不同网络环境 部分服务走 VPN,部分走公网 不同的绑定地址 + 路由规则
"多 profile、多端口、多 OPENCLAW_HOME" 详解
这三个是 正交维度,可以组合使用:
1. Profile(配置档案)
- 作用:隔离不同的配置集合(生产配置、测试配置、开发配置)
- 使用:
openclaw gateway --profile productionvs--profile staging - 存储位置:
~/.openclaw/profiles//
2. 端口(Port)
- 作用:网络层隔离,避免端口冲突
- 使用:
openclaw gateway --port 18789(默认)vs--port 18790 - 注意:每个端口对应一个独立的 Gateway 单实例锁(§4)
3. OPENCLAW_HOME(主目录)
- 作用:彻底隔离所有数据:配置、会话存储、日志、技能目录
- 使用:
export OPENCLAW_HOME=/opt/company-a/openclaw - 效果:两个 Gateway 实例即使运行在同一用户下,也看不到彼此的数据
典型部署模式示例
模式一:单用户单机(默认)
# 一个 Gateway,默认端口 18789
openclaw gateway
模式二:开发/测试分离
# 终端 1:生产环境
echo "PROD" OPENCLAW_HOME=/home/user/openclaw-prod openclaw gateway –port 18789 –profile default
终端 2:测试环境
echo "TEST" OPENCLAW_HOME=/home/user/openclaw-test openclaw gateway –port 18790 –profile test
模式三:多租户隔离(伪代码)
# 租户 A - 电商客服
sudo -u tenant-a OPENCLAW_HOME=/var/tenants/a openclaw gateway –port 18001
租户 B - 内部 IT 支持
sudo -u tenant-b OPENCLAW_HOME=/var/tenants/b openclaw gateway –port 18002
每个租户有:
- 独立的 Linux 用户(
tenant-avstenant-b) - 独立的
$OPENCLAW_HOME(/var/tenants/{a,b}) - 独立的端口(
18001vs18002) - 独立的 WhatsApp 登录会话
💡 理解要点 :"单主机单 Gateway" 是建议而非强制 。当业务需要隔离时,通过 profile × port × OPENCLAW_HOME 的组合,可以在同一台机器上构建出 逻辑上完全独立的多个 Gateway 实例 ,每个实例有自己的 进程边界、网络边界、存储边界。
详见 D1 Multiple gateways 完整文档。
D1 Gateway lock 文档解释得很清楚:
- 目的 :同一主机、同一 端口 上 只能运行一个 Gateway;第二个实例必须 立即失败 并给出清晰的错误提示。
- 机制 :启动时 立即 在 WebSocket 监听地址上建立 独占的 TCP 监听(exclusive TCP listen) ;如果端口已被占用(
EADDRINUSE错误),抛出GatewayLockError------不需要 额外的 lock 文件,进程崩溃或被强制终止(SIGKILL) 后,操作系统会自动回收端口。 - 运维 :如果端口被 非 OpenClaw 的程序占用,错误表现与"第二个 Gateway"相同;需要通过
openclaw gateway --port更换端口,或释放占用该端口的程序。
这与"传统守护进程写 /var/run/foo.pid 文件"的方式不同:锁就是监听套接字(socket)本身 ,排查故障时直接用 netstat 或端口诊断工具即可。
Runbook 的 5-minute local startup 可直接作为本文的"验收清单":
- 启动 Gateway :
openclaw gateway --port 18789(或使用openclaw gateway --force强制释放占用端口后再启动)。 - 检查状态 :
openclaw gateway status/openclaw status------ 确认看到Runtime: running和RPC probe: ok等基础信息。 - 检查渠道 :
openclaw channels status --probe------ 当 Gateway 可访问 时,对各渠道进行 在线探测 ;如果 Gateway 不可达,命令行工具会 降级为仅显示配置摘要(Runbook 已说明这种分叉行为)。
更深入的健康检查见 D1 health.md:openclaw health、openclaw status --deep 等命令会 向运行中的 Gateway 请求快照或实时探测 ------注意 openclaw health 默认不直接连接各渠道的套接字 ,而是通过 WebSocket 询问 Gateway,由 Gateway 侧协调探测。
配置热重载 :Runbook 的 Note 说明:Gateway 监听 活动配置文件路径 (OPENCLAW_CONFIG_PATH 或 profile 默认路径),gateway.reload.mode 默认值为 hybrid ------首次成功加载后,进程持有 内存中的配置快照 ,成功重载时 原子化切换 快照。这样 Gateway 可以在 不完全重启 的情况下应用部分配置变更(具体支持哪些配置项以 D1 文档为准)。
下面是一条 "可放入脑图"的主路径 ,供你在本地用 rg 或跳定义功能跟随走读。
5.1 命令行注册:gateway 子命令是什么?
src/cli/gateway-cli/register.ts 把子命令注册到 Commander 框架上,描述直接点题:WebSocket Gateway 的运行、巡检与发现功能:
// src/cli/gateway-cli/register.ts(节选)
export function registerGatewayCli(program: Command) { const gateway = addGatewayRunCommand(
program .command("gateway") .description("Run, inspect, and query the WebSocket Gateway") // ... 帮助示例:gateway run / status / discover ...
💡 理解要点 :openclaw gateway 不是"另一个 REST 小工具",而是 同一套运行时 的 运维入口 ------与 openclaw status 等命令共享 "如何找到正在运行的那个进程" 这一语境。
5.2 运行循环:runGatewayLoop —— 处理锁、信号、重启
src/cli/gateway-cli/run-loop.ts 在真正启动 startGatewayServer 之前调用 acquireGatewayLock ;持有锁期间创建 server,并处理 SIGINT/SIGTERM/SIGUSR1 等 优雅停机和重启 (包括 清空队列 、释放锁后再生成子进程 等细节,文件后半部分继续展开)。
// src/cli/gateway-cli/run-loop.ts(节选)
export async function runGatewayLoop(params: { start: (params?: { startupStartedAt?: number }) => Promise
>>; runtime: RuntimeEnv; lockPort?: number; }) { let lock = await acquireGatewayLock({ port: params.lockPort }); let server: Awaited
> | null = null; // … 注册信号;关机时 releaseLock;重启路径可能生成新进程 …
读这里的目的 :把 "GatewayLockError = 端口冲突" 与源码 入口 对齐------文档里的锁机制,对应代码里 acquireGatewayLock + start 失败路径,而不是散落在各渠道插件里。
5.3 服务器组装:startGatewayServer —— 配置、插件、渠道、WebSocket
src/gateway/server.ts 只是 薄转发层(thin re-export) ;实现位于 server.impl.ts 。startGatewayServer(port, opts) 一进来就 把端口写入环境变量 OPENCLAW_GATEWAY_PORT,随后流水线大致如下:
- 加载配置快照
loadGatewayStartupConfigSnapshot→prepareGatewayStartupConfig(包含 身份验证引导(auth bootstrap) 、可能 生成并持久化 token); - 诊断心跳 、SIGUSR1 重启策略 、控制 UI 的 allowedOrigins 种子 等横切关注点;
prepareGatewayPluginBootstrap:整理 插件 / 渠道 相关注册表和 gatewayMethods 列表;resolveGatewayRuntimeConfig、startGatewayEarlyRuntime、attachGatewayWsHandlers(WebSocket 运行时)、createChannelManager、startManagedGatewayConfigReloader……直到 HTTP/WebSocket 监听建立。
节选(只看"头部在做什么"):
// src/gateway/server.impl.ts --- startGatewayServer(节选)
export async function startGatewayServer(port = 18789, opts: GatewayServerOptions = {}): Promise
{ const minimalTestGateway =
process.env.VITEST === "1" && process.env.OPENCLAW_TEST_MINIMAL_GATEWAY === "1";
process.env.OPENCLAW_GATEWAY_PORT = String(port); const configSnapshot = await loadGatewayStartupConfigSnapshot({ minimalTestGateway, log }); const authBootstrap = await prepareGatewayStartupConfig({
configSnapshot, authOverride: opts.auth, tailscaleOverride: opts.tailscale, activateRuntimeSecrets,
}); const cfgAtStart = authBootstrap.cfg; // … 诊断 / 重启策略 / 控制 UI 种子 … const pluginBootstrap = await prepareGatewayPluginBootstrap({
cfgAtStart, startupRuntimeConfig: applyConfigOverrides(configSnapshot.config), minimalTestGateway, log,
}); // … resolveGatewayRuntimeConfig → attachGatewayWsHandlers / channels / reload …
🔍 实际例子 :如果启动日志出现 "生成了 runtime token 但未写入配置" 这类警告,对应 authBootstrap 分支里对 persistedGeneratedToken 的判断------这直接影响 "重启后 token 是否会变化" ,排查故障时应回到 D1 configuration + secrets 文档确定 持久化策略。
5.4 一张总图:把 §5.1~§5.3 串起来
Skills 子系统解决 "磁盘上的 SKILL.md 如何变成模型可见的
" (见第2篇);Gateway 解决 "谁长期在线、谁在哪个端口上同时接受 WebSocket/HTTP、谁去拉起渠道和健康探测" 。二者在运行时 交汇 (会话快照、配置重载、RPC),但 职责不混写 :读 Skills 不必深入 HTTP 路由;读 Gateway 也不必读完整个 SKILL.md 解析器。
Gateway 作为 所有流量的入口 和 常驻进程 ,其配置直接决定了系统的攻击面大小。以下是基于文档设置的关键安全风险及应对建议(更全面的安全分析将在 第14篇(安全与成本) 展开)。
7.1 网络暴露风险(与 bind 设置相关)
loopback(127.0.0.1) 仅本机可访问,风险最低 §2
改为 0.0.0.0 或公网 IP 任何人可尝试连接,若
身份验证配置不当则完全暴露 §2
trusted-proxy 模式 依赖上游代理做鉴权,若代理配置错误(如未过滤伪造头),攻击者可绕过 §2
实际风险场景 :如果将 Gateway 绑定到 0.0.0.0:18789 且使用弱 token 或关闭鉴权 ,攻击者可直接调用 /v1/chat/completions 消耗你的 API Key,或通过 WebSocket 接口操纵 Agent。
7.2 身份验证绕过(与 auth 设置相关)
文档提到的鉴权方式(§2):
gateway.auth.token/password(共享密钥)- 环境变量
OPENCLAW_GATEWAY_TOKEN/OPENCLAW_GATEWAY_PASSWORD trusted-proxy(可信代理,风险最高)
隐患 :若使用 password 且密码强度不足,或 token 泄露(如提交到 GitHub),攻击者可在任何能访问该端口的主机上伪装为合法客户端。
7.3 单实例锁的副作用(与端口占用相关)
文档§3说明:"锁就是监听套接字(socket)本身"。
安全隐患 :若 Gateway 崩溃后未正确释放端口(极少数内核异常),或恶意程序 故意占用 18789 端口并伪装成 Gateway,客户端可能连接到假 Gateway,导致中间人攻击(MITM)。
7.4 配置热重载的风险(与 reload.mode 相关)
§4提到 gateway.reload.mode 默认 hybrid ,支持不完全重启即可应用配置变更。
安全隐患 :如果攻击者通过某种方式(如配置文件注入、环境变量篡改)修改了 gateway.auth.token,Gateway 可能在不中断服务 的情况下应用新配置,导致合法用户被踢出 或非法用户获得访问权。
7.5 健康检查信息泄露(与 health 端点相关)
§4提到 openclaw health、openclaw status –deep 等命令会返回健康快照(health snapshot)。
隐患 :这些快照可能包含渠道连接状态、运行时配置片段、会话统计信息。如果 Gateway 的鉴权被绕过 ,攻击者可借此进行信息收集,为后续攻击做准备。
7.6 安全加固建议(基于文档设置)
loopback;如需远程访问,使用
Tailscale/SSH 隧道 而非直接暴露 §2, §2.1
认证层 使用强随机 token(
gateway.auth.token),定期轮换;避免
password 模式 §2
进程层 使用
–force 重启确保旧进程完全终止;监控
GatewayLockError 日志 §3, §4
配置层 限制配置文件权限(
~/.openclaw/ 目录 600);谨慎使用
hybrid reload §4
监控层 定期检查
openclaw gateway status 和日志,确认无异常连接 §4
💡 理解要点 :Gateway 的绑定地址(bind) 、身份验证模式(auth mode) 、端口占用策略 共同构成了 OpenClaw 的第一道防线。文档§2-§4 的所有设置项都应从安全视角重新审视——它们既是功能配置,也是安全策略。
8.1 OpenClaw 官方视角博客
- OpenClaw Gateway Explained(dench.com) —— 架构层面的 Gateway 解读,适合理解设计哲学。
- How to Set Up an OpenClaw AI Gateway in 2026(getclawhosting.com) —— 运维部署向,含端口配置、systemd 服务设置等实操内容。注意核对其端口/路径描述是否与你本机
openclaw.json一致。
8.2 AI Gateway 安全通用参考(跨项目借鉴)
以下资源虽非 OpenClaw 专属,但讨论了 AI Gateway 共性的安全挑战:
- LLM API Gateway Security Patterns(Cloudflare Blog) —— 讨论 API Key 轮换、速率限制、提示词过滤等通用模式,可借鉴到
gateway.auth配置思路。 - AI Infrastructure Security: Gateway & Proxy Patterns(MITRE/OWASP) —— 模型供应链攻击、提示词注入防御,可与第14篇安全内容对照阅读。
- Tailscale + AI Tools 安全实践(Tailscale Blog) —— 与本文§2.1提到的 Tailscale 替代直接暴露 思路一致,提供具体组网方案。
8.3 安全专项内容预告
更全面的安全分析将在 第14篇(安全与成本) 展开,包括:
- 多 Agent 攻击面与
OPENCLAW_HOME强隔离 - 沙箱逃逸风险与 Hands 权限边界
- 按 Agent 选择模型的成本与安全权衡
- 小结 :Gateway = 单进程控制面 ;单端口多协议 ;独占 bind(绑定) = 单实例锁 ;身份验证默认开启 ;健康与渠道探测由 Gateway 侧协调 ;启动主链
registerGatewayCli→runGatewayLoop→startGatewayServer。安全方面需重点关注 bind 地址、auth 模式、token 生命周期。 - 下一篇(第4篇) :Router(路由器) ——入站消息进入 Gateway 之后,如何 分发到 Brain / 快捷路径 / 渠道回包(与官方 Data flow 第 2 步对齐)。
- OpenClaw 主仓库:https://github.com/openclaw/openclaw
- Architecture Overview(D2):http://clawdocs.org/architecture/overview
- Gateway(D2):http://clawdocs.org/architecture/gateway
- Gateway Runbook(D1):https://github.com/openclaw/openclaw/blob/0dd4958bc8a78d26b3b526b1f2e63b15110c64a2/docs/gateway/index.md
- Network model(D1):https://github.com/openclaw/openclaw/blob/0dd4958bc8a78d26b3b526b1f2e63b15110c64a2/docs/gateway/network-model.md
- Gateway lock(D1):https://github.com/openclaw/openclaw/blob/0dd4958bc8a78d26b3b526b1f2e63b15110c64a2/docs/gateway/gateway-lock.md
- Health checks(D1):https://github.com/openclaw/openclaw/blob/0dd4958bc8a78d26b3b526b1f2e63b15110c64a2/docs/gateway/health.md
- Gateway configuration(D1):https://github.com/openclaw/openclaw/blob/0dd4958bc8a78d26b3b526b1f2e63b15110c64a2/docs/gateway/configuration.md
- Bridge protocol(D1,WS/RPC):https://github.com/openclaw/openclaw/blob/0dd4958bc8a78d26b3b526b1f2e63b15110c64a2/docs/gateway/bridge-protocol.md
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/266363.html