termal.in

← 博客

OpenClaw SSH:用隧道打开面板,让代理无需密钥连上你的服务器

· Termalin Team mcpai-agentssshsecuritytutorial

“OpenClaw SSH”这个说法背后藏着两件不同的活儿,把它们混为一谈,正是人们卡住的地方。一件是够到 OpenClaw 本身:它的面板跑在 localhost 上,所以你通过一条 SSH 隧道打开它。另一件正相反——让 OpenClaw 代理在你自己的服务器上执行命令。本文两件都讲,而对于第二件,它给出一种做法:绝不把 SSH 密钥放到代理能读到的地方。

先做一点披露:我们开发 Termalin,也就是第二部分里那个无密钥的选项。OpenClaw 是一个你自托管的开源代理网关——它跑在一台机器上,提供一个 Web 面板,并从它的市场 ClawHub 安装“技能”。对其他方案,我们会像希望别人公平描述我们那样,公平地描述它们。

人们说“OpenClaw SSH”时的两种意思

  • **通过 SSH 够到 OpenClaw。**面板绑定在 localhost 上,所以你把它的端口转发到你自己的机器。这是第一部分。
  • **让 OpenClaw 够到你的服务器。**你想让代理在别的机器上执行命令。这是第二部分,也是值得谨慎对待的部分。

第一部分——用 SSH 隧道打开 OpenClaw 面板

OpenClaw 网关在它运行的主机上绑定到 127.0.0.1:18789,这是有意为之。面板是一个管理控制平面,不是一个公开网站。在你的笔记本上,通过你已有的 SSH 登录把那个端口转发过来:

ssh -N -o ServerAliveInterval=30 -L 18789:127.0.0.1:18789 user@vps

然后在浏览器里打开 http://127.0.0.1:18789。-N 的意思是“不要 shell,只要隧道”;ServerAliveInterval=30 让连接不至于因空闲而断开。流量走的是你本来就信任的那条 SSH 会话,所以没有任何新东西暴露到互联网上。

不要为了省掉隧道而把网关绑定到 0.0.0.0。那会把你代理的控制平面放到公网上,谁找到那个端口,谁就拿到了这个代理。OpenClaw 自己的文档也是这么说的:用 SSH 隧道,别暴露网关端口。把它留在 127.0.0.1 上,通过 SSH 够到它。

当隧道连不上时

“Connection refused”、“check failed”,或者一个空白页面,通常意味着下面之一:

  • **网关没在运行,或在另一个端口上。**在机器上用 ss -tlnp | grep 18789 检查。
  • **你本地的 18789 端口已被占用。**换一个本地端口:-L 28789:127.0.0.1:18789,然后打开 http://127.0.0.1:28789。
  • **你拿到的是一个 shell,而不是隧道。**你漏掉了 -N。

更多情形见 SSH 连接被拒绝或超时。

让面板隧道保持在线

一条普通的 ssh -L 隧道会在你的网络断掉时停下。要一条始终在线的隧道,用 autossh 或一个小小的 systemd 服务,或者一个会替你重连的隧道管理器。本地转发和远程转发的原理,在 SSH 端口转发与隧道(英文)里讲了。

第二部分——让 OpenClaw 在你的其他服务器上执行命令

这是大多数人想要的部分:OpenClaw 发现一个服务挂了,然后在真正的机器上把它修好。常见的做法是给代理一把 SSH 密钥——一把放在网关主机 ~/.ssh 里的密钥,或者一个来自 ClawHub 的 SSH 技能。这能用。但它也是风险最大的安排,所以在你伸手去拿它之前,值得先搞明白。

风险所在:网关上的一把密钥

一个技能市场,就是你没写过的代码,跑在你的密钥旁边。2026 年初,Koi Security 的“ClawHavoc”研究审查了 2,857 个 ClawHub 技能,把其中 341 个标记为恶意。有几个专门用来窃取 SSH 密钥和凭据;大多数通过伪造的“前置条件”安装 AMOS 窃密程序,还有一些把代理自己的 .env 文件偷传了出去。

再加上每个代理都有的那种失效方式——来自它读到的网页或邮件的提示注入——后果就一目了然。网关上的一把 SSH 密钥,等于在每一台信任它的主机上都开了一个完整的 shell,任何能操纵这个代理的东西都够得到。撤销它,意味着在所有那些主机上轮换这把密钥。

所以第二部分的目标是:让 OpenClaw 跑你想让它跑的命令,而不留下一把它——或一个流氓技能——能顺走的密钥。

无密钥路线:先装一个 Connector,再把 Termalin 当作远程 MCP 服务器

两块东西。

第一,在每一台你想让 OpenClaw 够到的服务器上装一个 Termalin Connector。它一行命令就能装好,而且仅出站:它从不监听端口,所以在 NAT 或 CGNAT 之后也能用,不需要在你的防火墙上开任何东西。注册时,服务器的 sshd 会被设置为信任 Termalin 的 SSH 证书颁发机构(CA),之后每次登录都用一张为你的账户签发的短期证书。机器上没有常驻的长期密钥,也绝不会有任何密钥交到代理手里。

第二,把 Termalin 作为一个远程 MCP 服务器加进 OpenClaw。MCP(英文)是 OpenClaw 与那些它自己不自带的工具对话的方式。Termalin 的托管端点,把你通过 Connector 注册的服务器暴露成工具:hosts_list、ssh_exec、ssh_exec_many、SFTP 的读与写、server_metrics、alerts_list,等等。

OpenClaw 从 ~/.openclaw/openclaw.json 读取一份 JSON5 配置,并自动重新加载。先说一个坑:**当你不写 transport 时,当前的 OpenClaw(2026.10.x)默认用 SSE。**Termalin 说的是 Streamable HTTP,所以你必须设 "transport": "streamable-http",否则连接会失败。

有两种认证方式。

**API 密钥——适合跑在 VPS 上的网关。**在 Termalin 网页控制台里创建一把密钥,把它的范围限定到这个代理该碰的服务器,再把值作为 TERMALIN_API_KEY 放进环境变量。然后用一条命令添加这个服务器:

openclaw mcp set termalin '{"url":"https://termal.in/api/v1/mcp","transport":"streamable-http","headers":{"Authorization":"Bearer ${TERMALIN_API_KEY}"}}'

或者把同样的内容写进 ~/.openclaw/openclaw.json:

{
  "mcp": {
    "servers": {
      "termalin": {
        "url": "https://termal.in/api/v1/mcp",
        "transport": "streamable-http",
        "headers": {
          "Authorization": "Bearer ${TERMALIN_API_KEY}"
        }
      }
    }
  }
}

用 ${TERMALIN_API_KEY} 这个引用,而不是把密钥明文写进去。openclaw mcp doctor 发现有 token 被直接写进 headers 时会发出警告,而且它的日志里会把 header 的值打码。

**OAuth——适合由人来登录的场景。**把服务器指向 https://termal.in/mcp,把 auth 设为 oauth,然后登录:

openclaw mcp set termalin '{"url":"https://termal.in/mcp","transport":"streamable-http","auth":"oauth"}'
openclaw mcp login termalin
openclaw mcp doctor termalin --probe

openclaw mcp login 会打印一个授权 URL,并在一个本地回环回调(http://127.0.0.1:<port>/callback)上等待。Termalin 的 OAuth 接受这些回环重定向 URI,所以你在浏览器里批准这次登录,token 就被保存下来——没有密钥需要粘贴。如果 OpenClaw 跑在一台无头 VPS 上、而你的浏览器在笔记本上,就用 openclaw mcp login termalin --code <code> 手动完成它。注意,一旦设了 auth: "oauth",OpenClaw 会忽略该服务器上任何静态的 Authorization header,所以只选一种方法。

无论哪种方式,openclaw mcp doctor termalin --probe 都会确认服务器可达并列出它的工具,之后 Termalin 的工具就会出现在代理面前。(你也可以从 Control UI 添加服务器:chat → + → Connectors → Add MCP server…,仅限管理员。)

先决定它能做什么,再把一切都记下来

一个常驻的代理应该从小处起步。在 Termalin 的 AI 应用卡片里,给这个连接设一个命令策略:只读、一份精确命令的允许列表,或完全访问。从只读开始——“我的服务器怎么样”、磁盘、失败的服务、一份日志的最后几行,都通过 server_metrics 和 alerts_list。然后放宽到一份窄窄的允许列表,再到写操作,一步一步来。收紧的按主机命令允许列表(英文)背后的道理,在这里直接适用。

代理跑的每一件事都在案。每条命令都会落进会话录制、实时监控网格,以及审计日志(英文),并被标记为代理的。因为那个机密是一份 Termalin 凭据,而不是一把散布在各台主机上的 SSH 密钥,所以关掉这个代理是一个开关,而不是在每一台服务器上轮换密钥。如果好几个人共用一个 OpenClaw,OpenClaw 可以给每个发起者一个单独的身份(oauth.identity: "per-requester"),这样审计轨迹就按人区分。

当 MCP 服务器连不上时

  • **它连上了却不显示工具,或者在握手时失败。**你没写 transport,OpenClaw 退回到了 SSE。设 "transport": "streamable-http"。
  • **401 Unauthorized。**API 密钥缺失或超出范围,或者你用的是 OAuth 的 URL(/mcp)却没跑过 openclaw mcp login。密钥端点是 /api/v1/mcp;OAuth 端点是 /mcp。
  • **${TERMALIN_API_KEY} 传过来是空的。**这个变量没在 OpenClaw 运行的环境里设置。在网关启动的地方把它导出。
  • **你期待的某台服务器没出现在 hosts_list 里。**它还没有 Connector,或者它在密钥的范围之外。

跑 openclaw mcp status --verbose 和 openclaw mcp doctor termalin --probe,看是哪一步失败了。

公平地看待其他选项

无密钥路线不是唯一的一条。另外两种视你的需要而定,也都合理。

**直接给代理一把密钥。**在网关主机的 ~/.ssh 里放一把 SSH 密钥,或者装一个 ClawHub 的 SSH 技能(ssh-executor、ssh-full、sshx 等等),让它去读一把密钥、一个密码,或一个保险库条目。这是最快搭好的方式,也不依赖任何托管服务。代价正是上面描述的那个风险:密钥对代理跑的任何东西都可读,它的触及范围是每一台信任它的主机,而撤销它意味着在所有这些主机上轮换密钥。如果你要这么做,用一把专用的低权限密钥,在 authorized_keys 里用 command= 把它狠狠限制住,而且绝不要复用你的个人密钥。

**跑一个自己持有密钥的独立 SSH-MCP 服务器。**一个带 ssh_exec 工具的小型自托管 MCP 服务器,把密钥留在它自己的配置里,放在模型的上下文之外。这是一个实实在在的改进——一份泄露的对话记录里不再包含凭据。但这类服务器大多出厂时没有命令策略、没有实时查看、也没有审计轨迹,所以任何一次工具调用都能在任何已配置的主机上跑任何东西,而你对发生过什么的记录,全凭代理自己汇报。我们按一次被攻破的代价,给这些以及其他每一种安排排了名,见按影响半径看给 AI 代理 SSH 访问(英文)。

常见问题

**OpenClaw 支持 MCP 吗?**支持。当前的 OpenClaw(2026.10.x)通过 HTTP 连接远程 MCP 服务器。用 openclaw mcp set 或 openclaw mcp add 添加一个,或者从 Control UI 添加(chat → + → Connectors → Add MCP server…,仅限管理员)。对 Termalin 这样的服务器要设 "transport": "streamable-http",因为默认否则是 SSE。

**OpenClaw 能 SSH 进我的服务器吗?**能,有两种方式。直接地:通过 exec 工具或一个 ClawHub SSH 技能给它一把密钥。或者无密钥地:把它接到一个替它持有访问权的 MCP 服务器上——就是上面那套 Connector 加 MCP 的设置,其中没有任何密钥会到达代理。

**把我的 SSH 密钥给 OpenClaw 安全吗?**把它当作高风险来对待。网关上的一把密钥,代理所遵循的任何技能或被注入的指令都能读到,而 ClawHub 上确实出现过专门用来窃取它的技能(Koi Security 在 2026 年初标记了 341 个恶意技能)。如果非给不可,用一把一次性的低权限密钥,配上 command= 限制——绝不要用你的个人密钥。

**我怎么解决“openclaw ssh connection refused”?**对于面板隧道,检查网关在运行、并绑定到 127.0.0.1:18789(在机器上跑 ss -tlnp | grep 18789),确认你本地的端口空着,并在 ssh -L 命令上保留 -N。更多情形见 SSH 连接被拒绝或超时。

**我需要开任何端口吗?**不需要。面板隧道用的是你已有的 SSH 连接,而 Termalin Connector 仅出站——它从不监听端口,所以在 NAT 和 CGNAT 之后也能用,防火墙上什么都不用开。


Termalin 是一款跨平台 SSH 客户端,带一个托管 MCP 服务器、一个密钥托管方(替你保管密钥、代为签名的中间层)和按主机的代理策略。托管端点和基于 Connector 的访问属于 Pro($10/月,或按年付费 $8/月)和 Team,带 14 天 Pro 试用、无需绑卡——见 MCP、Connector,或面向 AI 代理的 SSH。

先在一台主机上试试。

Termalin 是为你和你的智能体打造的高速 SSH 客户端。

免费版 · Pro 14 天试用 · 价格