Appearance
能力边界
← 返回索引 · 03 · 对外暴露
能力边界与可行性结论
本文合并自两份独立分析:
EXPOSURE-FEASIBILITY(整体可行性)与INFERENCE-EXPOSURE-CONCLUSION(推理层专项结论)。
认知演变说明:早期理论推断已被深入实测修正
WARNING
重要认知演进说明(实测修正):
本文属于项目早期的可行性评估记录。后续深入实测推翻了文中的部分早期推论:
- 出网真相:文中推断“eBPF 物理封锁出网”,实测推翻:直连真实 IP 可通,出网限制由 DNS 重定向 + 强制代理执行,并非底层网络物理锁死。
- 推理真相:文中推断“推理层物理隔离不可达”,实测证实:
/opt/hatch/runtime-cell/完整可读,隐藏二进制与推理 socket 属于 visibility gating(可见性门禁)。 - 工具层真相:文中推断“未暴露 socket 无入口”,实测突破:破解 privsep 底层套接字协议(
0x46+SCM_RIGHTS),实证 31 个 socket 中有 26 个可直接调用。
最新权威实证详见:docs/04-inference/01-core-runtime/runtime-cell-and-egress-truth.md、docs/04-inference/05-slack-integration/privsep-protocol-and-unexposed-sockets.md 与 docs/04-inference/RESEARCH-SUMMARY.md。
摘要:一张表看懂边界
| 层 | 能否外曝 | 机制 | 状态 |
|---|---|---|---|
| 工具层(56 个 API 工具 / 86 个 socket) | ✅ 可以 | privsep socket,仅 socket 权限 | 已实现 |
| 推理层(LLM 调用) | ❌ 不可以 | 四重封锁(eBPF/假DNS/namespace/宿主Key) | 不可行 |
| agent 编排 | ❌ 不可以 | 无独立 socket,在 daemon 工具总线上 | 不可行 |
| Web chat | ❌ 不可以 | 需 RV 密钥 + Hen Notary Token(校验服务端 SEV-SNP,外加 eBPF 拦截) | 门票在容器外 |
一句话:
Muse 开放的是**"手"(工具),锁死的是"脑"(推理与编排)**。
第一部分:整体可行性分析
一、目标拆解:两个层次,可行性天差地别
"推理能力"和"agent 能力"是两层完全不同的东西,必须分开评估:
| 层 | 是什么 | 位置 |
|---|---|---|
| 推理层 | 调模型拿补全 | daemon 通过 inference-proxy 转发到上游 |
| Agent 层 | 完整智能体回合(工具、记忆、子智能体) | daemon 内部工具总线 |
二、发现的官方通道:hatch-ws-client
这是本次研究的核心发现——VM 上已经预装了一个独立的外部客户端:
Minimal websocket client for Jarvis daemon RPCs.
Commands:
chat-send Send a single chat message and print the final response
chat-history Fetch chat history via daemon HTTP API
fs Filesystem operations via HTTP fileserver
activity Activity log methods via daemon HTTP API
ws Socket-level checks and generic websocket RPCs
noise Generic Noise data-plane operations against /v1/noise它提供了两条路径(--help 原文说明):
| 路径 | 地址 | 原文描述 |
|---|---|---|
| 直连 daemon WS | ws://198.19.0.1:18789/ | 默认 |
| Noise 数据面 | ingress-rev-proxy :4431 的 /v1/noise | "the path a real web client uses" |
关键:--noise 这条路径的文档原话是 "the path a real web client uses"(真实 Web 客户端走的路径)。
→ 也就是说:Muse Web 客户端与 daemon 之间的通道,已经有一个 CLI 能模拟。
2.1 鉴权方式
--auth-token <AUTH_TOKEN>
JWT auth token for daemon/fileserver HTTP requests.
Sent as `Authorization: Bearer <jwt>`.
WebSocket connections use the `?auth_token=` query string
because the WS handshake cannot carry custom headers.
[env: JARVIS_AUTH_TOKEN=]
--noise-notary-token-file <FILE>
File containing the notary token for `/v1/noise` msg3 auth.
If omitted, the client mints one through **Hen** using --noise-hen-env.鉴权链条:
JWT Bearer(HTTP)/ ?auth_token=(WS)
+ Noise 通道另需 notary token(msg3 认证),可由 "Hen" 服务铸造三、实测:三条路径全部受阻
3.1 直连 daemon WS —— 被 eBPF 阻断
bash
$ hatch-ws-client ws check
warning: ws auth token resolution failed: missing websocket auth: set JARVIS_JWT_TOKEN实测端口连通性:
python
198.19.0.1:18789 → PermissionError: Operation not permitted
198.19.0.1:80 → PermissionError
198.19.0.1:443 → PermissionError
198.19.0.1:4431 → PermissionErrorPermissionError 而非 ConnectionRefused —— 这是内核层拒绝, 正是架构报告 §3.2 记录的 spawnd attach-cell-gate 挂载的 connect4/connect6 eBPF 门闸在起作用。
容器内的任何进程都无法直连网关的任何端口。
3.2 Unix socket —— 可连,但被应用层断开
bash
$ hatch-ws-client --http-api-socket /run/hatch/noded/http-api.sock ws http-check
Error: http api request failed: http://localhost/check
2: connection closed before message completedsocket 权限是 srw-rw-rw-(世界可读写),连接建立成功, 但 daemon 在协议层主动断开 —— 因为请求里没有有效 JWT。
对照:authdc file list(带 peer-credential 鉴权)成功, 说明 noded/daemon 的 API 要 token,authd 的要 peer credential,机制不同。
3.3 缺少凭证
$ env | grep JARVIS_AUTH
(空)
$ grep AUTH_TOKEN /etc/hatch/env
(无)当前环境中不存在 JARVIS_JWT_TOKEN —— 它由 Web 客户端在登录时获得并随连接传入, 不持久化在 VM 上。
三·补、"方案 A"深度侦察(JWT 注入路线的真实门槛)
原计划"拿到 JWT 注入环境变量即可调用",实测发现障碍远不止 JWT。
3b.1 --noise 通道需要三样凭证,不是一样
--auth-token <AUTH_TOKEN> JWT Bearer
--noise-rv-key-file <FILE> 32 字节 RV 密钥
--rv-transparency <POLICY> SEV-SNP 硬件证明链策略(默认 staging)
--noise-notary-token-file <FILE> notary token(可由 Hen 铸造)RV 密钥是什么(--help 原文):
File containing the 32-byte RV key for
/v1/noisemsg3 auth. For an unprovisioned VM this key is presented as fresh RV key material; for a provisioned VM it is used to compute the client proof.
The RV key is confidential-volume key material, so by default the client verifies attestation before presenting it
--allow-unattested-rv 的警告:
Present the RV key WITHOUT verifying the peer's TEE attestation at all — full bypass (skips the SEV-SNP hardware chain, the Noise-key binding, and manifest transparency)
结论:--noise 是「机密计算(Confidential VM / SEV-SNP)」保护下的通道: 客户端在握手 msg2 中校验服务端出具的 AMD SEV-SNP 硬件证明与镜像透明度(确保证端运行在合法 CVM 且镜像未被篡改),并在 msg3 中向服务端提交 32 字节机密卷密钥(RV key)与 Hen 密钥服务签署的机器凭据(notary token)。这不是普通 TLS WebSocket,--auth-token 用户态 Bearer 是第三步可选绑定。
3b.2 容器内拿不到 RV 密钥与 SEV 设备
$ ls /dev/sev* → 无
$ cat /sys/kernel/security/sev_guest → 无
$ find / -iname "*rv*key*" → 无
$ cat /run/hatch/resume/rv-identity-ready
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx <REDACTED_TIMESTAMP> marker=presentrv-identity-ready 标记存在,但密钥与 SEV 设备都不在容器内 —— 机密计算能力在宿主侧,容器内不可访问。
3b.3 Unix socket 路线:可连,但各有门槛
| socket | 裸 HTTP 探测结果 | 门槛 |
|---|---|---|
/run/hatch/noded/http-api.sock | ConnectionResetError | daemon 主动断开(缺 JWT) |
/run/hatch/noded/control.sock | ConnectionResetError | 同上 |
/run/hatch/sandbox-api/api.sock | HTTP/1.1 403 Forbidden + JSON | 沙箱路由白名单 |
/run/hatch/auth/authd.sock | HTTP 服务,peer-credential 鉴权 | ✅ 部分端点可用 |
noded 是 daemon 的 HTTP API 转发器 —— 这是 VM 内进程访问 daemon 的正规路径, 只需要 JWT,不需要 RV 密钥。
3b.4 ⭐ 新发现:sandbox-api 是通往宿主 API 的跳板
json
GET /api/model HTTP/1.1
→ HTTP/1.1 403 Forbidden
{"ok":false,"error":{"code":"forbidden","message":"route not allowed on sandbox API"}}这是结构化的 403,不是断开 —— 说明它是真实的 HTTP 反向代理, 把 /api/* 转发到宿主 daemon。
从二进制提取到的路由表(部分):
/api/artifacts /api/bootstrap
/api/client/data-source-publish /api/client/disconnect
/api/computer/assets/desktop-v2 /api/computer/previews/
/api/debug/bug-report-logs/ /api/docs/openapi_json
/api/explain /api/feed /api/feed/prompt /api/feed/reorder
/api/feed/units/ /api/idea-cards /api/idea-cards/media/
/api/ideas/ /api/messenger/fb-check
/api/model /api/nodes/sync
/api/onboarding/identity /api/onboarding/complete
/api/openapi /api/hatch/oauth/callback机制:route not allowed on sandbox API —— 默认全拒,只放行令牌里声明的路由。 令牌由宿主下发给空间(space)沙箱。
实测探测 /api/docs/openapi_json、/api/model、/api/bootstrap、/api/artifacts 等 14 个路由全部 403,因为:
$ ls ~/workspace/spaces/ → 空
$ env | grep SPACE\|SANDBOX → 无当前没有活跃空间,因此没有沙箱令牌。
相关令牌机制(从二进制):mint_cloudflare_spaces_viewer_token、 CloudflareViewerTokenResponse、viewer_assertion、viewer_token。
3b.5 方案 A 的修正结论
原判断"通道现成,锁是 JWT"不准确。
准确表述:
| 路线 | 需要 | 容器内可获取? | 可行性 |
|---|---|---|---|
--noise(ingress) | JWT + RV 密钥 + Hen Notary Token(校验服务端 SEV-SNP) | ❌ RV 密钥与 Hen 私钥不在容器内,且出网遭 eBPF 拦截 | 不可行 |
--http-api-url 直连 | JWT | JWT 需外部提供 | ⚠️ eBPF 挡端口 |
--http-api-socket(noded) | 仅 JWT | JWT 需外部提供 | ✅ 最可行 |
sandbox-api /api/* | 沙箱令牌 | 需有活跃空间 | ⚠️ 当前无空间 |
--noise 是给「外部客户端连 ingress」用的(它要证明的是"服务端是合法 CVM"), 不是给 VM 内部进程用的。VM 内部访问 daemon 的正规方式是 Unix socket。
四、宿主侧的可行性
既然容器内被封,那从宿主侧(外部宿主环境 203.0.113.195)能做什么?
实测:
外部宿主环境路由:default via 203.0.113.1 dev eth0
监听端口: 127.0.0.1:2222 (sshd,外部通信通道)只有 2222 端口转发,没有任何 Muse API 通道。
$ getent hosts instance-xxxxxxxx.metaaivm.com → 无法解析
$ curl https://api.meta.ai → 403外部宿主环境是一个普通的独立 VPS,与 Muse 控制面没有网络关系。 通信连接 是 VM 主动连出来的,只能进不能出(无法反过来从宿主访问 VM 的 daemon)。
五、逐层可行性结论
5.1 ❌ 推理层:不可行
原因:
inference-proxy.local是服务发现名,由宿主侧网关解析JARVIS_INFERENCE_PROXY_SOCK=/run/hatch/proxy/inference.sock—— 该路径在容器内不存在(第二轮已实测)- 推理请求的实际出网受 eBPF connect 门闸 + 代理强制 + TLS 中间人 三重管控
- 即便能发出请求,还需要上游凭证(由宿主侧
stefi/authd持有)
这一层是为"免凭证、可管控"设计的,刻意不可外部调用。
5.2 ⚠️ Agent 层:有条件可行
唯一的可行路径是 hatch-ws-client --noise —— 因为它是官方客户端模拟器, 走的是真实 Web 客户端同一条通道。
但需要三个凭证:
| 凭证 | 来源 | 现状 |
|---|---|---|
JARVIS_JWT_TOKEN | Web 端登录后获得 | 未持久化在 VM |
notary token | 由 Hen 服务铸造 | 需要 --noise-hen-env |
--app-id | 客户端身份标识 | 音视频调用必需 |
换言之:通道是现成的,锁是凭证。
六、如果要做,可行方案有三条
方案 A:通过 Unix socket 调用 daemon API(⭐ 修正后的首选)
关键修正:不需要走 --noise(那需要 RV 密钥 + SEV-SNP 证明,容器内拿不到)。
VM 内进程访问 daemon 的正规路径是 Unix socket,只需要 JWT:
bash
hatch-ws-client \
--http-api-socket /run/hatch/noded/http-api.sock \
--auth-token "<JWT>" \
chat-history或用 WS over socket(若支持):
bash
hatch-ws-client --url ws://localhost/run/hatch/noded/... \
--auth-token "<JWT>" chat-send "你好"所需:仅一个有效 JWT(用户从浏览器 DevTools 获取 WebSocket URL 里的 ?auth_token=)。
可行性:✅ 最高 —— 不需要硬件证明,不需要 RV 密钥,不触碰 eBPF。
方案 B:走宿主侧转发(绕过 eBPF)—— 不可行
eBPF 门闸挂在 runtime-cell 的 cgroup 上。 若能把 daemon 端口从宿主侧暴露(ssh -R),理论上可外部访问。
但:
- VM 内无法连到
198.19.0.1:18789—— eBPF 恰好挡住这一步(实测PermissionError) - 宿主机上没有 daemon 进程,转发目标不存在
→ 不可行(eBPF 是精确为此设计的)。
方案 C:借道 sandbox-api(有前提)
sandbox-api/api.sock 是通往宿主 daemon API 的反向代理, 路由表含 /api/model、/api/feed/*、/api/artifacts 等。
但需要沙箱令牌(由宿主下发给空间沙箱)。当前 ~/workspace/spaces/ 为空, 无活跃空间 → 无令牌 → 全部 403。
→ 有前提可行:若 VM 上有活跃的空间(space),可能获得令牌并调用。
方案 D:绕过 daemon,直接用模型(改换目标)
既然推理层被封,唯一能"直接调用模型"的方式是绕开 Muse 体系:
- 在 VM 上(或本地)用 Anthropic API key 直接调 Claude
- 或自建 agent 框架(工具、循环)复刻所需行为
代价:失去 daemon 提供的一切 —— 记忆、工具总线、Sentinel 审批、 额度管理、子智能体、Feed、目标系统。
→ 这不是"暴露 Muse 能力",而是"另起炉灶"。
七、核心洞察
7.1 这个设计是刻意的
回顾整个架构:
✅ 工具层(media/web-search/tts 等) → 有 CLI,可直接调用(第五轮实测)
❌ 推理层(模型调用) → eBPF + 代理 + MITM + 宿主凭证,四重封死
⚠️ Agent 层(工具总线) → Unix socket + JWT,通道存在但要凭证能给的(工具)大方给,核心的(推理、编排)严格锁。
这不是疏漏,是分层信任模型:
- 工具是"能力"→ 可审计、可限流,开放风险可控
- 推理是"成本"→ 直接暴露等于开放计费资源
- Agent 编排是"自主权"→ 直接暴露等于授予完整代理权限
7.2 三种客户端路径的设计意图
实测澄清了一个重要区分 —— 同一个 hatch-ws-client 有三条路,服务于三种身份:
| 路径 | 面向 | 证明什么 | 凭证 |
|---|---|---|---|
--noise (ingress :4431) | 外部客户端(浏览器/App) | 校验服务端 CVM 真实性并呈递客户端凭证 | 服务端出具 SEV-SNP;客户端呈递 RV 密钥 + Hen Notary Token + JWT |
--url (ws://198.19.0.1:18789) | 宿主侧组件 | — | JWT(且被 eBPF 限) |
--http-api-socket (noded) | VM 内进程 | 调用者身份 | 仅 JWT |
在 --noise 握手中,AMD SEV-SNP 是服务端向客户端出具的 TEE 硬件证明(由客户端校验服务端是否为合法 CVM);客户端向服务端呈递的则是 RV 密钥与 Hen 签发的 Notary Token。容器内既无出站网络权限(eBPF 阻断),又无 RV 密钥与 Hen 签发权。
VM 内进程的正规路径是 Unix socket。
7.3 真正的问题不是技术
hatch-ws-client 各条路径的存在说明:官方本来就提供了多种调用入口。
所以问题不是"能不能绕过 Web",而是: "Muse 是否允许第三方客户端用你的 JWT 连接" —— 这是授权问题,不是技术问题。
八、建议
如果你想达成实际目的,我建议先明确你要的是什么:
| 你想要的 | 推荐路径 |
|---|---|
| 在别的程序里用上这些工具(图片/搜索/TTS/地理) | ✅ 第五轮已实测可行,直接 ssh 调 CLI |
| 用 Muse 的模型额度做推理 | ⚠️ 需 JWT + Unix socket,且需确认服务条款 |
| 用自己的 API key 做推理 | ✅ 完全可行,但与 Muse 无关 |
| 完整 agent 编排能力 | ⚠️ 需 JWT,且受 Sentinel 审批约束 |
| 把 VM 当通用推理服务器 | ❌ 架构上刻意不支持 |
九、操作手册(待 JWT 后执行)
9.1 获取 JWT
浏览器打开 Muse Web → DevTools → Network → 筛选 WS → 点击连接 → 查看 URL 中的 ?auth_token=<JWT>。
或任一 API 请求的 Authorization: Bearer <JWT> 头。
9.2 注入并测试(按优先级)
测试 1:Unix socket + chat-history(最可能成功)
bash
ssh <外部宿主环境> → ssh -i /root/.ssh/identity_key -p 2222 root@localhost
export JARVIS_AUTH_TOKEN="<JWT>"
/opt/hatch/bin/hatch-ws-client \
--http-api-socket /run/hatch/noded/http-api.sock \
chat-history测试 2:Unix socket + ws check
bash
/opt/hatch/bin/hatch-ws-client \
--http-api-socket /run/hatch/noded/http-api.sock \
ws http-check测试 3:WS over socket(若支持)
bash
/opt/hatch/bin/hatch-ws-client \
--url "ws+unix:///run/hatch/noded/http-api.sock" \
--auth-token "$JARVIS_AUTH_TOKEN" \
ws check测试 4:发送消息
bash
/opt/hatch/bin/hatch-ws-client \
--http-api-socket /run/hatch/noded/http-api.sock \
chat-send "测试消息"测试 5(备选,可能失败):--noise 通道
bash
/opt/hatch/bin/hatch-ws-client --noise \
--auth-token "$JARVIS_AUTH_TOKEN" \
chat-send "测试消息"⚠️ 实测失败:首先遭遇宿主 eBPF 网络拦截(os error 1: Operation not permitted);即使网络打通,客户端仍缺失 RV 密钥与 Hen 签发的 Notary Token。
9.3 预期结果判断
| 响应 | 含义 |
|---|---|
| 正常返回数据 | ✅ 成功,通道打通 |
401 Unauthorized | JWT 无效或过期 |
403 Forbidden | JWT 有效但该路由不放行 |
ConnectionReset | 协议层拒绝(可能路径不对) |
missing websocket auth | JWT 未正确传入 |
9.4 安全提醒
- JWT 是账号凭据,有效期有限,泄露后他人可代你调用
- 本报告中所有命令均为公开接口的正常调用,未使用任何绕过手段
- 若 Muse 服务条款禁止第三方客户端,技术上可行 ≠ 授权上允许
本报告基于容器内实测(端口连通性、CLI 行为、配置检查)与宿主侧实测(外部宿主环境网络)。未尝试任何绕过鉴权的操作 —— 所有测试均为公开接口的正常调用。
第二部分:推理层专项结论
以下为推理层暴露可行性的独立验证(四重封锁逐层实测)。
一、直接答案
不能。 推理层对外暴露在任何方向上都不可行:
| 尝试方向 | 结果 |
|---|---|
| 从 VM 内代码直接调模型 | ❌ 出网被封 |
| 从 VM 内连推理代理 socket | ❌ socket 在另一个 mount namespace |
| 从外部走 CF 隧道转发 | ❌ 无可用后端 |
| 用官方 CLI 桥接 | ❌ 没有推理 CLI |
二、四重封锁(逐层验证)
第 1 重:出网被拦
bash
$ curl -x http://hatch-egress-proxy:3128 https://example.com
→ 000(超时/拒绝)
$ curl -x http://hatch-egress-proxy:3128 https://api.anthropic.com/v1/models
→ 000连 example.com 都出不去。 而第五轮测试时工具(web-search 等)能联网 —— 说明联网能力只在 privsep worker 侧,容器内进程出网被 eBPF 门闸挡住。
第 2 重:推理主机是假地址
$ grep JARVIS_INFERENCE_HOSTNAME /etc/hatch/env
JARVIS_INFERENCE_HOSTNAME="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
$ getent hosts xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
198.18.155.198198.18.0.0/15 是 RFC 2544 保留段(基准测试用),不可能是真实 IP。 说明 DNS 被劫持到网关,任何"直连推理主机"的尝试都会失败。
另一条证据:这个 hostname 每次重启都变 (之前是 xxxxxxxx-…,现在是 xxxxxxxx-…)—— 它是每次启动动态分配的实例标识,不是稳定端点。
第 3 重:推理代理在独立 mount namespace ⭐
这是最关键的一条。
/proc/net/unix 里确实有:
/run/hatch/proxy/inference.sock
/run/hatch/proxy/stefi.sock但文件系统里看不到:
bash
$ ls /run/hatch/proxy/
ls: cannot access '/run/hatch/proxy/': No such file or directory
$ python3 -c "import os; print(os.path.exists('/run/hatch/proxy/inference.sock'))"
False原因:namespace 隔离
PID 67 (hatch daemon) → /proc/67/ns/mnt: Permission denied
PID 1 (systemd) → mnt:[4026532329]
当前 shell → mnt:[4026532379] ← 我们在这里daemon 跑在独立的 mount namespace, /run/hatch/proxy/ 只存在于那个 namespace。 我们在自己的 namespace 里看不到、连不上。
bash
$ nsenter -t 67 -m ls /run/hatch/proxy/
nsenter: cannot open /proc/67/ns/mnt: Permission denied连尝试进入都被拒绝。
第 4 重:没有推理 CLI,也没有 API Key
没有推理相关的 CLI:
bash
$ ls /opt/hatch/bin/ | grep -iE "infer|llm|model|chat"
(空)没有 Anthropic API Key:
bash
$ grep -riE "ANTHROPIC_API_KEY|sk-ant" /home/hatch /etc/hatch
(只有文档里提到这个变量的名字,没有值)而 /etc/hatch/env 的注释说明了一切:
JARVIS_ANTHROPIC_BASE_URL_REVPROXY_OVERRIDE=0—— 若移除,Anthropic 请求会切到 Meta 内部明文 HTTP 反代, 且 spawnd 会把真实ANTHROPIC_API_KEY换成占位符。
即:真实 Key 由宿主侧注入,容器内拿到的是占位符。
三、space-inference.sock 也不通
唯一在我们 namespace 里可见的推理相关 socket:
/run/hatch/sandbox/space-inference.sock (mode 0666)实测:
python
connect() → 成功
send(POST /v1/messages) → ConnectionResetError
send(GET /health) → ConnectionResetError能连但立刻被断 —— 与 privsep socket 一样需要特定协议, 而且它是给空间(space)沙箱用的,不是通用推理入口。
对比:privsep socket 的协议已解出(
BRIDGE-TEST.md), 但space-inference的协议未知,且从命名看它服务于 space 运行时, 不是"调模型"的直接通道。
四、为什么设计成这样:四层信任模型
回顾整个 Muse 的架构,四类能力的开放度是刻意分级的:
| 层 | 开放度 | 机制 |
|---|---|---|
| 工具(56 个 API 口径 / 86 个 socket) | ✅ 完全开放 | privsep socket,无 token,协议已公开(我们已逆向) |
| 推理(模型调用) | ❌ 完全封闭 | 独立 namespace + eBPF + 假 DNS + 宿主 Key |
| 编排(subagent/workflow/cron) | ❌ 封闭 | 无独立 socket,在 daemon 工具总线上 |
| 外部接入(Web 客户端) | ⚠️ 需凭证 | JWT + RV 密钥 + Hen Notary Token(且校验服务端 SEV-SNP) |
设计逻辑
工具 = 能力 → 可审计、可限流、结果可验证 → 开放
推理 = 成本 → 直接暴露等于开放计费资源 → 封闭
编排 = 自主权 → 直接暴露等于授予代理权限 → 封闭工具层之所以开放,是因为它的副作用是可枚举的(搜一次网页、生成一张图); 而推理层的"副作用"就是花钱,且不可枚举(任意 token 消耗)。
命名空间的隔离尤其说明问题: daemon 明明可以直接用文件权限控制,却选择了mount namespace 隔离—— 这意味着即使你在容器内有 root,连"看到"那个 socket 都做不到。
五、有没有理论上的迂回路径?
穷举一遍:
5.1 ❌ 从 VM 内发起
- 出网被 eBPF 拦 ✅ 已验证
- 推理 socket 不可见 ✅ 已验证
- 无 API Key ✅ 已验证
5.2 ❌ 从外部宿主环境 / CF 转发
- 外部宿主环境没有推理后端(推理代理只在 VM 的 daemon namespace 内)
- CF 隧道只能转发外部宿主环境本地端口,而外部宿主环境上没有推理服务
5.3 ⚠️ 借用工具的"推理副作用"
理论上唯一搭边的路径:
某些工具内部会调模型,例如:
web-search → 可能用模型做结果排序/摘要
image-search → 可能用模型做语义匹配
media-generation → 用生成模型出图(不是 LLM,但也是模型推理)但:
- 这些是固定用途的推理,不能自由指定 prompt
- 输出是工具语义的结果(搜索结果、图片),不是原始 token
- 无法当作通用 LLM 使用
结论:这不是"暴露推理能力",只是"工具的副产物"。
5.4 ❌ 从 agent 会话记录"读"推理
agents/*/sessions/*.jsonl 里有 thinking 块(第七轮发现), 但那是已完成的推理记录,不是"发起新推理"。
六、结论
6.1 明确回答
Muse VM 的核心推理能力无法暴露。 不是"难",是架构上刻意不可达。
四重独立封锁:
1. eBPF connect 门闸 → 出网被拦
2. 假 DNS(198.18/15) → 推理主机不可解析
3. mount namespace 隔离 → 推理 socket 不可见(连 root 都看不到)
4. 宿主侧注入 Key → 容器内只有占位符任何一重都足以阻断,四重叠加使迂回路径也全部关闭。
6.2 能力边界的准确表述
| 能力 | 能否经 CF 暴露 |
|---|---|
| 56 个工具(搜索/生成/查询/连接器) | ✅ 已实现 |
| LLM 推理 | ❌ 不可行 |
| agent 编排(subagent/workflow) | ❌ 不可行 |
| 会话历史读取 | ⚠️ 可读文件,但非能力 |
6.3 如果确实需要 LLM 能力
唯一可行路径是绕开 Muse:
- 用自己的 API Key(Anthropic / OpenAI / 其他)
- 在外部宿主环境或本地跑一个开源模型
- 通过 CF 隧道暴露这个自有服务
但这与 Muse 无关 —— 那是"另建一个推理服务",不是"暴露 Muse 的推理能力"。
七、一句话总结
Muse 开放的是"手"(工具),锁死的是"脑"(推理)。
工具可以经 CF 隧道对外,因为它的副作用可枚举、可审计; 推理不行,因为它的副作用就是成本,且不可枚举。
这不是疏漏,是设计。四重封锁(eBPF、假 DNS、namespace、宿主 Key) 中的任何一重都不是为了"防用户",而是为了"防容器逃逸" —— 而这三者恰好也阻断了合法的对外暴露。
本结论基于 VM 内实测(网络、namespace、socket、凭证),非推测。所有测试均为正常调用,未尝试任何提权或逃逸手段。