IronClaw 已经在本地迷你主机上运行一段时间了,之前主要是把 IronClaw 接入到本地或者云端免费的 LLM,通过处理日常琐碎事务来感受各种 LLM 的能力——所有对话都是通过 IronClaw 自带的管理面板完成的。出于安全考虑,我一直没有接入像飞书、Telegram 这样的 IM 即时通讯软件,因为这得将本地服务通过 tunnel 暴露在公网上。
如果你不了解
IronClaw,可以参考我之前写的文章 钢铁版 OpenClaw - IronClaw 安全机制解析。简单地说IronClaw就是安全版的OpenClaw,或者说是安全版的 AI 小助手。
目前 IronClaw 支持两种方式接入 IM:轮询方式和 tunnel 方式。
前者不需要将本地服务暴露在公网上:由 IronClaw 周期性地向 IM 服务器发起请求,一次性拉取所有 DM 私信然后本地处理。这样做实时性很差,因为你通过 IM 发出的消息,不能立即到达 IronClaw,而是需要等待 IronClaw 下一次轮询。如果为了提高实时性,把周期设置的很短,又可能触发服务限速,并且大部分时间你不会跟这个 AI 小助手聊天,因此大部分的轮询都是没必要的。
最理想的接入方式是后者,即通过 tunnel 的方式。
这段时间,我想让自己的 AI 小助手变得方便些,比如人不在电脑前面的时候,让 IronClaw 帮忙查信息,这就不得不考虑接入 IM 了。
以下是将飞书接入 IronClaw 的过程。
1. 创建飞书应用
访问 飞书开放平台,登录后点击“开发者后台” -> “创建企业自建应用”
填写应用名称、描述,选择图标,点击“创建”

创建应用后在左侧菜单点击“添加应用能力” -> 找到“机器人” -> 点击“添加”

在“权限管理”页面,点击“批量导入/导出权限”,粘贴以下 JSON 配置:
{
"scopes": {
"tenant": [
"contact:user.base:readonly",
"im:message",
"im:message.group_at_msg:readonly",
"im:message.p2p_msg:readonly",
"im:message:send_as_bot",
"im:resource"
]
}
}

- 在左侧“凭证与基础信息”中可以找到
App ID和App Secret
- 在左侧“事件与回调” -> “加密策略” 中可以找到
Verification Token
此时,创建的应用尚未发布,飞书聊天界面中也看不到,等后面配置“事件与回调”再发布即可。
2. IronClaw 配置
飞书应用创建后,执行 ironclaw onboard --channels-only 为 IronClaw 配置 channel:
$ ironclaw onboard --channels-only
ℹ Tunnel Configuration (for webhook endpoints):
ℹ A tunnel exposes your local agent to the internet, enabling:
ℹ - Instant Telegram message delivery (instead of polling)
ℹ - Slack, Discord, GitHub webhooks
## 1. 是否为 ironclaw 配置自启动 tunnel,
## 这里输入 `N` 即可,
## 即不需要通过 ironclaw 启动 tunnel,
## 原因会在下面设置 tunnel 时说明。
Configure a tunnel? [y/N] N
Which channels do you want to enable?
(Use arrow keys to navigate, space to toggle, enter to confirm)
▸ [✓] CLI/TUI (always enabled)
[·] HTTP webhook
[·] Signal
[·] Discord (will install)
[✓] Feishu (installed)
[·] Slack (will install)
[·] Telegram (will install)
[·] Whatsapp (will install)
## 2. 通过方向键上下移动选项,选中 Feishu 后
## 按`空格`选中,按`回车`确认
## 3. 接下来按提示输入:
## `feishu_app_id`,
## `feishu_app_secret`,
## `feishu_verification_token`
我配置的 OpenClaw 版本是 0.24.0,需要在 commit 732c23e06b 基础上打上下面的补丁,才能正常接入飞书:
diff --git a/src/extensions/manager.rs b/src/extensions/manager.rs
index be97971d..6b28ed0f 100644
--- a/src/extensions/manager.rs
+++ b/src/extensions/manager.rs
@@ -4523,11 +4523,16 @@ impl ExtensionManager {
config_updates.extend(self.load_channel_runtime_config_overrides(name).await);
let mut should_rerun_on_start = false;
- // Refresh webhook secret
- if let Ok(secret) = self
- .secrets
- .get_decrypted(user_id, &webhook_secret_name)
- .await
+ // Refresh webhook secret (only if managed by host)
+ let managed_by_host = capabilities_file
+ .as_ref()
+ .map(|f| f.webhook_secret_managed_by_host())
+ .unwrap_or(true);
+ if managed_by_host
+ && let Ok(secret) = self
+ .secrets
+ .get_decrypted(user_id, &webhook_secret_name)
+ .await
{
router
.update_secret(name, secret.expose().to_string())
该补丁与
verification token有关,详细信息可以参考个人 github 仓库分支 fix/feishu-with-0.24.0 分支。如果不这么改,后续为飞书应用配置“事件与回调”时,ironclaw 会对飞书发来的首次验证请求返回401 Unauthorized,导致配置无法完成。
配置完成后,重新启动 IronClaw,让配置生效。
3. tunnel 设置
IronClaw 支持下面几种自启动 tunnel:
- ngrok
- cloudflared
- Tailscale Funnel
- 本地自定义 tunnel
自启动 tunnel 就是由 IronClaw 来启动/停止的 tunnel。IronClaw 以子进程的方式启动这类 tunnel,因此本地还需要安装相应的 tunnel 命令。
需要注意的是,IronClaw 将 Gateway 和 Webhook Server 作为单独的服务启动,分别绑定在不同端口。先前踩的一个坑是通过命令 ironclaw onboard --channels-only 配置自启动 tunnel,tunnel 启动后没有绑定在接入 IM 对应的 Webhook Server 服务上,而是绑定在 Gateway 服务。这是因为由 IronClaw 启动 tunnel 时,优先绑定 Webhook Server,但是根据配置情况,可能会回退到 Gateway。其中的细微关键,在 IronClaw 文档中没有说明,需要查看项目代码。
为了简化配置,我没有配置自启动 tunnel(输入 N 跳过了),而是在 IronClaw 之外单独启动一个 tunnel,直接绑定在 Webhook Server 上。
ngrok 和 cloudflared 是两种常见的 tunnel。相比自建 tunnel,这两种方式不需要云服务器,相对简便。其中 ngrok 最为直接,cloudflared 额外需要一个域名。出于篇幅考虑,下面先介绍 ngrok 配置方式。
3.1 ngrok tunnel
ngrok 一个轻量级的隧道工具,能在你的本地服务和公网之间建立加密通道。它的核心优势是无需公网 IP、无需配置防火墙、自动处理 HTTPS 证书。ngrok 有免费和付费套餐,对于将 AI Agent 接入 IM 这种场景,免费套餐够用了。

- 安装 ngrok - 注册登录后,ngrok 官网会显示各种环境下的安装方法

安装完成后,需要执行 ngrok config add-authtoken ${AUTH_TOKEN} 将 AUTH_TOKEN 添加到用户默认的配置文件 ngrok.yml 中。
AUTH_TOKEN属于个人重要安全信息,务必妥善保护!
- 为 ngrok
添加
AUTH_TOKEN后,ngrok 就可以直接启动了:
# 将本地 8080 端口暴露到公网
$ ngrok http 8080
启动后,终端会显示相关信息,包括本地服务暴露在公网的临时地址 https://${temporary_subdomain}.ngrok-free.app 以及临时地址所在区域等信息。
暴露在公网的服务地址也需要保密,其他人拿到这个地址之后便可以对本地服务发起请求,对于没有妥善防护的本地服务,这是极其危险的!
也可以将 ngrok 配置为系统服务:
## 在命令中指定配置文件路径
sudo ngrok service install --config=/opt/ngrok/ngrok.yml
启动 ngrok 服务之前,将指定的配置文件准备好:
## /opt/ngrok/ngrok.yml
version: "3"
endpoints:
- name: ironclaw ## 用户指定的名字
url: https://xxxxxxxxxxxxxx.ngrok-free.dev ## 免费用户不能自定义域名,需使用 dev domain
upstream:
url: http://127.0.0.1:8080 ## 待暴露的本地服务,ironclaw webhook 服务默认绑定 8080 端口
agent:
authtoken: xxxxxxxxxxxxxxxxxx ## ngrok 提供的 AUTH_TOKEN,妥善保管,泄漏后应立即重置

ngrok 会提供一个免费的固定地址
dev domain,可以在Domains查看,同样需要妥善保护!
- 测试 ngrok tunnel
启动 ironclaw(已配置 feishu)和 ngrok,通过 curl 命令验证 tunnel 是否正常运行:
curl -X POST 'https://${subdomain}.ngrok-free.dev/webhook/feishu' \
-H "Content-Type: application/json" \
-d '{"event": "user.created", "id": 12345, "name": "张三"}'
## 收到这样的响应说明 tunnel 配置成功
{"error":"Webhook authentication failed"}%
如果收到 {"error":"Webhook authentication failed"} 这样的响应说明 tunnel 正常,因为通过 curl 命令发出的请求并不是合法的飞书 DM 事件。
4. 配置飞书事件订阅
完成前面一系列的设置后,需要为飞书应用配置“事件和回调”:

- 在“请求地址”这里填入暴露在公网的 Webhook Server 地址:
https://${ngrok_free_dev_subdomain}/webhook/feishu
点击“保存”,飞书会向这个地址发送首次验证请求,验证成功后才允许添加事件:

在“事件配置”页面点击“添加事件”,搜索
im.message.receive_v1(接收消息),勾选后确认添加:
然后发布飞书应用:
点击页面上方“创建版本”,填入“应用版本号”和“更新说明”,并确认,发布应用。应用发布成功后,飞书聊天界面会收到提示:
点击“打开应用”,可以进入到和飞书机器人的聊天页面。在和飞书机器人聊天之前,需要在 IronClaw 批准配对请求,否则 IronClaw 仅接收机器人的信息,不会进行处理。
## 列出待处理的配对请求
$ ironclaw pairing list feishu
## 批准飞书配对,配置请求开始的部分就是配对码,类似 ABC12345 这样
$ ironclaw pairing approve feishu ${paring_code}
IronClaw 批准配对后,即可通过飞书机器人与 AI 小助手正常聊天。

IronClaw 0.24.0 版本中飞书 channel 的实现依旧简陋,处理飞书机器人首次聊天时,不会主动提醒用户完成配对,只是返回一个 body 为空的响应。相比之下,IronClaw 中 Telegram 的实现会在第一次收到信息时,主动提示用户执行配对命令。这是在接入过程中踩的另一个坑。
但是 IronClaw 项目官方似乎不理睬外部贡献者创建的 issue 或者 PR:我在 0.18.0 版本创建的一个 issue,直到 0.21.0 版本,发现问题解决主动关闭这个 issue 时都没有官方人员的评论回复;类似的还有一个修复性质的 PR,也一直悬而未决,PR 下面没有拒绝,没有评论,也不会批准。
这是很“退烧”的体验,如果不是因为 IronClaw 已经在本地运行一段时间,我可能会尝试 OpenClaw + NemoClaw 的组合。
5. 安全风险
用隧道工具把本地服务暴露到公网确实方便,但“能访问”和“安全”是两回事。ngrok 的情况比较特殊,它不只是开发工具,它们也是黑客工具箱里的常客。由于 ngrok 常被恶意软件用来建立 C2 通信通道,很多杀毒软件已经将 ngrok 的二进制文件标记为“潜在不需要的程序”。
即使把服务托管在 ngrok 后面,也不能假设边缘网络会挡住所有攻击。当你在内网机器上运行 ngrok 时,相当于在外网和内网之间开了一个不受控的入口。tunnel 工具暴露的不仅是那个端口,而是运行 tunnel 的整台机器的网络可达性。一旦隧道入口的服务存在漏洞,整个内网都可能被波及。这是最容易被忽略的架构级风险。
一个额外的主观因素:ngrok 提供的免费域名通常是亚马逊位于日本的节点。飞书的 DM 事件先绕到日本,才能送到本地 IronClaw,所以将飞书接入 IronClaw 后,现在我已经弃用 ngrok。
ngrok 最大的优势是配置简单,便于个人开发临时调试,建议用完即关。相比之下,cloudflared 可以提供更多的安全防护,但是对于 IM 接入来说,它和 ngrok 没有本质上的区别。如果追求更好的安全性,可以考虑自建 tunnel,或者干脆弃用 tunnel 方案,转向其他集成方式。
写在最后
先是分享如何通过 ngrok tunnel 将 IM 接入到本地 IronClaw,然后又说 ngrok 不安全,前后显得自相矛盾了。写下这篇文章主要还是为了分享折腾 IronClaw 过程中踩过的坑;关于 ngrok 的风险也必须说明,算是叠个甲,避免非计算机专业的读者按步照搬后,将本地暴露在不必要的安全风险中。
cloudflared tunnel 的配置方式后面有时间会单独介绍,最近还在考虑非 tunnel 的接入方案,实现后也会公布出来,敬请期待。