04-gateway:云端网关与外部连接

← 返回主报告:Kimi Agent(云端沙箱)技术报告GitHub 原文

合规与风险声明:本报告为安全研究与互操作学习目的的逆向分析,全程只读采集,未对目标系统做任何修改;文中所有密钥、token、账号级标识(chat_id / project_id / tenant_id 等)均已脱敏;沙箱内发现的默认弱口令(VNC/SSH)属平台侧配置,仅作安全发现披露,请勿用于访问任何不属于自己的系统。docx/pdf/xlsx/kimi-slides 等引擎二进制为 Moonshot 专有许可(禁再分发/逆向),本文仅作行为级描述。报告基于单次分析窗口(约 50 分钟生命周期),软件版本与技能库存随镜像更新可能变化。

采集时间:2026-08-18(CST)。沙箱:Kimi 原生 agent(kimiagent)Debian 12 容器。 访问方式:ssh -p 12222 kimi@127.0.0.1(frp 隧道)+ 兜底 HTTP 文件服务 http://127.0.0.1:18080/。 本节覆盖:agent-gw.json、portal 网关参数、envd、socat 服务、所有指向 msh.team / moonshot / 内网 IP 的配置、npm/pip/apt 镜像,以及沙箱↔Moonshot 云端的全部通信通道与认证方式。 注:采集尾声(17:26 CST)远端 frpc 断线,少量待验证项在文末标注。

1. /root/.kimi/agent-gw.json —— agent 上行网关凭证

路径 /root/.kimi/agent-gw.json(root 所有,kimi 用户不可读,经 18080 文件服务读取)。/root/.kimi/ 下只有这一个文件。内容(api_key 已脱敏):

{
  "api_key": "sk-kimi-8OQEd910...[REDACTED,原始长度 64 字符后缀]",
  "base_url": "https://agent-gw.kimi.com/coding",
  "kimi_chat_id": "1a014098-****-****-****-********15cb"
}
  • 结构:三个字段——api_keysk-kimi- 前缀的长期 API key)、base_url(agent 网关 HTTPS 端点,路径 /coding 表明这是 Kimi Code/编码 agent 的上行通道)、kimi_chat_id(当前会话/项目 ID,与 drive9 挂载路径中的项目 UUID 1a01406e-*---*****d0ce 属同一 UUID 家族但不相同)。
  • 认证方式:API key,推测以 Authorization: Bearer 或自定义头随 HTTPS 请求发往 agent-gw.kimi.com
  • 该文件是”agent 回云端”的主凭证;沙箱内未发现名为 kimi 的 CLI 二进制(/usr/local/bin 清单中无),实际消费方可能是宿主侧/控制面组件,或任务运行时才注入的 agent 进程(采集时沙箱处于空闲态,ps 中无 agent 进程)。

2. portal —— 存储/能力网关客户端(drive9 覆盖层)

服务脚本 /etc/s6-overlay/s6-rc.d/portal/run(全文可读),进程 PID 65: /usr/local/bin/portal -http-bind -allow-other -env prod ... /mnt/portal-overlay

2.1 网关地址

脚本注释与默认值明确写出两套网关:

# dev=https://kimi.kimi.team/apiv2
# prod=https://kimi-api-sandbox.msh.team/apiv2

运行期由环境变量注入(/run/s6/container_environment/ 实测值):

KIMI_PROJECT_PORTAL_CAPABILITY_ENABLED=true
KIMI_PROJECT_PORTAL_CAPABILITY_ENV=prod
KIMI_PROJECT_PORTAL_CAPABILITY_MOUNT=/mnt/portal-overlay
KIMI_PROJECT_PORTAL_CAPABILITY_PROD_ADDR=https://kimi-api-sandbox.msh.team/apiv2

即当前沙箱 portal 连的是 https://kimi-api-sandbox.msh.team/apiv2。portal 二进制 strings 中另发现 dev 侧 agent 网关:https://agent-gw-dev.dev.kimi.team/coding

2.2 认证与绑定流程(bind-token STS 合同)

脚本注释完整描述了三方握手:

  1. portal 以空挂载清单启动,-http-bind 监听 :8080
  2. 宿主侧 kimiwarden 在 claim(任务认领)时向 portal POST /api/v1/bind_token 下发 warden 签名的 HS256 JWT
  3. portal 拿 JWT 向 kimiapi 的 PortalService 换取限定范围的 STS 临时凭证
  4. kimiwarden 再 POST /api/v1/bind 下发覆盖层清单(skills/plugins/auth/vault),portal 挂载到 /mnt/portal-overlay

关键设计:*静态 K_OSS_ 对象存储凭证已被废弃**(注释:the new portal fails closed on them),改由 claim 时 bind-token→STS 动态换证。这是最短生命周期的最小权限授权。

2.3 portal 二进制揭示的 RPC 面

strings /usr/local/bin/portal 显示它是 Connect-RPC 客户端(portalv1connect.PortalServiceClient),proto 包路径暴露内部 GitLab:dev.msh.team/protos/kimi-go/...kimi.portal.v1 PortalService 方法包括:

  • ValidateBindToken —— 校验 warden JWT
  • GetS3Credentials —— 换取 S3 STS 凭证(覆盖层存储后端是 S3 兼容对象存储)
  • GetAPIKey
  • SetupAppListChatFilesGetEvoSessionFileListEvoSessionFiles

另有 dev.msh.team/protos/kimi-go 下的 kimi/im/v1kimi/chat/v1kimi/claw/v1kimi/skill/v1kimi/file/v1 等包(可能仅为链接进来的共享 proto 库)。

3. envd —— E2B 兼容命令执行守护

  • 二进制 /usr/local/bin/envd(Go,18MB,未 strip),启动脚本 /etc/s6-overlay/s6-rc.d/envd/runenvd -isnotfc 运行,监听默认端口 49983ss 实测 :::49983 LISTEN)。
  • 来源确认:strings 中大量 github.com/e2b-dev/infra/packages/envd/... 符号——这是 E2B infra 的开源 envd(Connect-RPC 协议),提供 process(Start/Connect/SendInput/SendSignal/List/Update)与 filesystem(ListDir/MakeDir/Stat/Move/Remove/WatchDir…)两大类 RPC。
  • -isnotfc 的作用:run 脚本注释写明——AGS 不是 firecracker 环境,没有 MMDS(169.254.169.254 不可达);envd 默认会在 /init 校验和后台轮询访问 MMDS,每次挂起约 10s client timeout,是 create 耗时(实测 ~7s)的主要构成。-isnotfc 让 envd 跳过一切 MMDS 行为,/init 立即可达。这是 Moonshot 对上游 envd 的定制补丁。
  • 其他 flag-cgroup-root(默认 /sys/fs/cgroup)、-cmd(daemon 启动时跑一条命令)、-commit/-version-port(默认 49983)。
  • 用途:供云端控制面(注释称 “Tencent E2B command execution”)远程在沙箱内执行命令/读写文件——即 E2B 协议兼容的沙箱控制通道,走 Connect-RPC over HTTP,认证应由外层网关/网络层承担(沙箱内未见 envd 侧凭证文件)。

4. “socat” 服务 —— 实为 CDP 反向代理

/etc/s6-overlay/s6-rc.d/socat/run(与 user/user2 同目录)并不跑 socat,而是:

/usr/local/bin/python3 /opt/moonbox-project-template/bin/project-cdp-proxy.py

该脚本(全文可读)是一个 asyncio TCP 代理:

  • 监听 0.0.0.0:9223CDP_PROXY_LISTEN_PORTss 实测在听),转发到上游 127.0.0.1:9222(Chromium CDP,Chromium 自己只绑 loopback)。
  • /json/json/list/json/version 等 discovery 响应做改写:把 webSocketDebuggerUrl 里的 ws://127.0.0.1:9222 重写为客户端 Host 头对应的 ws(s)://<公网入口>,同时把入站请求的 Host 头重写为 127.0.0.1:9222 再转给 Chromium。
  • 作用:把只监听 loopback 的 Chromium DevTools 协议安全地暴露给外部(经外层网关 wss),供远程浏览器自动化(browser use)使用。容器环境变量 USE_CDP=true 与之呼应。

5. 指向 msh.team / moonshot / kimi 域名与内网 IP 的完整清单

5.1 域名端点

域名用途出处
agent-gw.kimi.comagent 上行网关(/coding),API key 认证/root/.kimi/agent-gw.json
kimi-api-sandbox.msh.teamportal PortalService 生产网关(/apiv2,Connect-RPC)portal run 脚本 + 容器环境变量
kimi.kimi.teamportal dev 网关(/apiv2)portal run 脚本注释
agent-gw-dev.dev.kimi.teamdev 环境 agent 网关(/coding)portal 二进制 strings
dev.msh.team内部 GitLab(proto 仓库、npm 私有包 registry /api/v4/projects/1993/packages/npm/portal 二进制、skills 模板 package.json
npm.mirrors.msh.teamnpm 镜像 registrysshd_config SetEnv + npm config get registry 实测
pypi.mirrors.msh.teampip 主索引容器环境变量 PIP_INDEX_URL
pypi.msh.teampip 额外索引容器环境变量 PIP_EXTRA_INDEX_URL
msh-sandbox.tencentcloudcr.com基础镜像仓库(kimiclaw/moonbox-okc:project-20260811-2容器环境变量 MOONBOX_BASE_IMAGE
mirrors.volces.comapt Debian 镜像(火山引擎)/etc/apt/sources.list.d/debian.sources

5.2 内网 IP

  • 10.213.5.144 —— drive9 存储服务器。/run/service/drive9-fuse/run 中:drive9 mount --foreground --mode=fuse ... --server http://10.213.5.144 --profile kimi-project --durability close-sync ':/projects/1a01406e-*---*****d0ce' /mnt/agents。即工作区 /mnt/agents 是内网 drive9 存储网关上项目目录的 FUSE 挂载。配套 watchdog(/run/service/drive9-fuse-watchdog/run):每 15s 探活 .drive9-health 目录,连续 3 次失败 pkill -9 drive9 交给 s6 重启。
  • DNS:/etc/resolv.conf 指向 183.60.83.19 / 183.60.82.98(腾讯云 DNSPod 系 nameserver,NetworkManager 生成)。
  • 容器身份环境变量:SCF_POD_ID=2d9b504a104a439f9374a6374a236fa7(与 hostname 前缀一致)、CUBE_CONTAINER_ID_SANDBOX=2d9b504a...CUBE_CONTAINER_ID_MONITOR_SIDECAR=ac4e908b...(存在一个同 Pod 的监控 sidecar 容器)。

5.3 /etc 与 /app 的 grep 结果说明

  • /etc 内 msh.team 命中只有两处:/etc/ssh/sshd_config:124SetEnv NPM_CONFIG_REGISTRY=https://npm.mirrors.msh.team/ ...(同时给 SSH 会话注入了 skills 模板 node_modules/.bin 的 PATH),以及 portal run 脚本注释。
  • /app/.agents/skills/*-swarm 的模板 package-lock.json 全部锁到 npm.mirrors.msh.teamplugin-inspect-react-code/package.json 指向 GitLab 私有 npm registry dev.msh.team/api/v4/projects/1993/packages/npm/
  • 未发现任何硬编码 moonshot.cn / moonshot.ai 域名(云端面统一走 msh.team 与 kimi.com/kimi.team)。

6. 包管理镜像配置汇总

  • npm:registry = https://npm.mirrors.msh.team/(经 sshd SetEnv 注入 NPM_CONFIG_REGISTRYnpm config get registry 实测生效)。/home/kimi/.npmrc 只设 prefix=/home/kimi/.npm-globalcache=/home/kimi/.npm-cache
  • pipPIP_INDEX_URL=https://pypi.mirrors.msh.team/simplePIP_EXTRA_INDEX_URL=https://pypi.msh.team/simplePIP_TRUSTED_HOST=mirrors.cloud.aliyuncs.com(容器级环境变量注入,无 pip.conf 文件)。
  • apt:Debian bookworm 主/安全源走火山引擎 mirrors.volces.com(snapshot 2025-09-29);另有 packages.microsoft.com(debian/12 prod)与 deb.nodesource.com node_20.x 两个外部源。

7. 沙箱↔云端通信通道全景

通道方向端点认证本地载体
agent 上行沙箱→云https://agent-gw.kimi.com/codingsk-kimi- API key/root/.kimi/agent-gw.json
portal 存储/能力沙箱→云https://kimi-api-sandbox.msh.team/apiv2(Connect-RPC PortalService)warden HS256 JWT → 换 STS(GetS3Credentials/ValidateBindTokenportal :8080 + /mnt/portal-overlay
工作区存储沙箱→内网http://10.213.5.144(drive9,明文 HTTP 内网)profile kimi-project + 项目 UUID/mnt/agents FUSE
命令执行云→沙箱envd :49983(E2B Connect-RPC)外层网关承担/usr/local/bin/envd -isnotfc
浏览器自动化云→沙箱CDP :9223 → 127.0.0.1:9222外层网关(wss Host 改写)project-cdp-proxy.py
Jupyter云→沙箱kernel-server :8888未在本节核实/app/kernel_server.py
VNC/桌面云→沙箱:6080(kasmvnc web)、Xvnc :99VNC_PASSWORD=vncpassword(弱口令,容器环境变量)kasmvnc
SSH运维→沙箱sshd :22(经 frp 隧道暴露)密钥 + SSH_PASSWORD=sshpassword(弱口令)sshd_config
取证/兜底运维→沙箱python http.server :18080(root 权限目录列表/读取)无(仅靠隧道隔离)PID 17

宿主侧角色(从脚本注释与二进制证据推断):kimiwarden 负责任务 claim 时下发 bind token 与挂载清单;reception preset 设置 legacy KIMI_PROJECT_PORTAL_OVERLAY=1 信号与 init_script;云端还有一个 monitor sidecar 容器(CUBE_CONTAINER_ID_MONITOR_SIDECAR)与本沙箱同 Pod。

8. 密钥/凭证登记(均已脱敏)

凭证位置格式/用途
agent API key/root/.kimi/agent-gw.jsonsk-kimi-8OQEd910...,调 agent-gw.kimi.com
bind JWT运行时由 kimiwarden POST 注入,不落盘可见文件HS256 JWT,portal 换 STS
SSH 密码容器环境变量 SSH_PASSWORD=sshpassword弱固定口令,sshd
VNC 密码容器环境变量 VNC_PASSWORD=vncpassword弱固定口令,kasmvnc

9. 未完成验证项(隧道 17:26 CST 断开所致)

  • 出站 established 连接快照(ss -tn state established)未取到——采集期间沙箱空闲,且末尾连接中断。
  • 端口 32001、18082 的属主未最终确认(初步:8080=portal、49983=envd、9223=cdp-proxy、8888=kernel、6080=kasmvnc 已确认;32001 疑似 kasmvnc 相关或宿主映射,18082 疑似内部辅助服务)。
  • agent-gw.json 的实际消费进程未抓到(采集时沙箱内无 agent 进程运行,推测由控制面任务启动时拉起)。