功能开关
Agent 如何决定自身暴露哪些功能 —— 完全在 Agent 主机上配置。
ServerBee 通过 Agent 能力(Capabilities)落实最小权限原则。能力由 Agent 主机拥有:每个 Agent 从自己的配置文件(以及可选的 CLI 参数)计算出自身的能力集合并上报给 Server。Server 可以读取并展示这些能力,但无法修改它们 —— 服务端没有任何开关。
这是一个有意为之的信任边界设计。运行 Agent 的那台机器,是唯一决定该 Agent 行为的地方。一个被攻陷或配置错误的 Server,无法在你的主机上悄悄打开远程终端、文件访问或命令执行。
功能列表
ServerBee 定义了 11 个功能位,分为两个风险等级,有效掩码为 2047(bits 0..=10)。
高风险(默认关闭)
| 功能 | 键名 | 位值 | 说明 |
|---|---|---|---|
| Web 终端 | terminal | CAP_TERMINAL (1) | 允许通过浏览器打开远程终端 |
| 远程执行 | exec | CAP_EXEC (2) | 允许远程执行命令 |
| 文件管理 | file | CAP_FILE (64) | 允许远程浏览、编辑、上传/下载文件 |
| Docker 管理 | docker | CAP_DOCKER (128) | 允许 Docker 容器监控、日志流和容器操作 |
这些能力允许在目标服务器上执行任意代码或访问文件系统,因此默认关闭。只在受信任的主机上、通过编辑该主机的 Agent 配置来开启它们。
低风险(默认开启)
| 功能 | 键名 | 位值 | 说明 |
|---|---|---|---|
| 自动升级 | upgrade | CAP_UPGRADE (4) | 允许远程二进制升级 |
| ICMP Ping | ping_icmp | CAP_PING_ICMP (8) | 允许 ICMP 探测任务 |
| TCP 探测 | ping_tcp | CAP_PING_TCP (16) | 允许 TCP 端口探测任务 |
| HTTP 探测 | ping_http | CAP_PING_HTTP (32) | 允许 HTTP 探测任务 |
| 安全事件 | security_events | CAP_SECURITY_EVENTS (256) | 允许 Agent 上报 SSH 登录 / 暴力破解 / 端口扫描事件(见 安全事件) |
| 防火墙封禁 | firewall_block | CAP_FIREWALL_BLOCK (512) | 允许 Agent 应用 Server 下发的 nftables 封禁列表。需要 root 或 CAP_NET_ADMIN 及主机上的 nft 命令。见 防火墙封禁 |
| IP 质量 | ip_quality | CAP_IP_QUALITY (1024) | 允许 Agent 运行服务解锁探测并上报结果;可选的元数据与风险评分由 Server 完成 |
没有任何 [capabilities] 覆盖的 Agent 默认值为 1852(自动升级 + 三种 ping 探测 + 安全事件 + 防火墙封禁 + IP 质量),即高风险的终端、执行、文件和 Docker 能力保持关闭。
配置能力(在 Agent 主机上)
Agent 按如下方式计算自身的能力位图:
- 从内置默认集合开始(
CAP_DEFAULT = 1852)。 - 应用配置文件
[capabilities]段 ——allow增加位,deny移除位。在这一层中deny优先于allow。 - 在其上应用 CLI
--allow-cap/--deny-cap参数,用于临时覆盖。CLI 层优先于配置层。 - 与子系统可用性对账:
file仅在[file].enabled = true且至少配置一个root_path时保留;firewall_block在启动时的nft探测失败(缺少二进制、内核支持或权限)时被剔除。上报的能力始终意味着 Agent 真正能提供该功能。
未知的能力键名在启动时会直接报错,因此拼写错误会快速失败,而不是悄悄丢掉某个能力。
配置文件
安装脚本管理的部署请在 Agent 主机上编辑 /opt/serverbee/etc/agent.toml。手工部署也可能使用 /etc/serverbee/agent.toml 或工作目录下的 agent.toml:
[capabilities]
# 开启该主机应暴露的高风险能力。
allow = ["terminal", "file"]
# 移除该主机不应暴露的默认能力。
deny = ["ip_quality"]重启 Agent 使更改生效:
sudo serverbee restart agent环境变量
同样的配置也可以通过环境变量提供(Figment,SERVERBEE_ 前缀,__ 表示嵌套):
SERVERBEE_CAPABILITIES__ALLOW=["terminal","file"]
SERVERBEE_CAPABILITIES__DENY=["ip_quality"]CLI 参数
如需一次性覆盖,可在启动 Agent 时传入可重复的参数:
serverbee-agent --allow-cap terminal --allow-cap file --deny-cap ip_quality安装时
安装脚本支持 --caps,在注册时为 Agent 的能力配置预置初值:
curl -fsSL https://raw.githubusercontent.com/ZingerLittleBee/ServerBee/main/deploy/install.sh | sudo sh -s -- agent \
--server-url https://monitor.example.com \
--enrollment-code YOUR_ONE_TIME_CODE \
--caps terminal,file交互式运行安装脚本时也会提示选择能力,默认项已预先勾选。
临时授予
编辑配置并重启 Agent 是永久开启某个能力的正确方式。而对于短时、临时性的需求 —— 比如「给这台机器 30 分钟的终端」—— Agent 自带一个主机本地 CLI,可以临时开启某个默认关闭的能力,并在时间窗结束时自动关回去。
临时授予是一种主机本地机制,与「能力由 Agent 拥有」的信任模型完全一致:只有在 Agent 主机上拥有 shell 的人才能发起。Server 以及 Web/iOS UI 始终只读,无法授予能力。Server 只是镜像 Agent 上报的内容、据此拦截控制面请求、审计变更,并可触发告警。
CLI
在 Agent 主机上运行这些子命令(通常需要 sudo,因为它们写入 state_dir,而守护进程一般以 agent 用户/root 运行)。它们共用守护进程的配置(安装脚本部署为 /opt/serverbee/etc/agent.toml),因此 grants 文件位置和最大时长都来自同一个 [capabilities] 段。
# 临时开启某个默认关闭的能力,限定一个时间窗。
serverbee-agent grant terminal --for 30m --reason "debugging a stuck deploy"
serverbee-agent grant file --for 2h
serverbee-agent grant docker --for 1d
# 提前撤销一个生效中的授予。
serverbee-agent revoke terminal
# 列出当前生效的授予(能力、剩余秒数、授予者、原因)。
serverbee-agent grants- 传给
--for的时长格式为<数字><单位>,单位为s(秒)、m(分钟)、h(小时)、d(天)之一 —— 例如90s、30m、2h、1d。--reason为可选的自由文本,会随授予一同记录。 grant只能开启当前关闭的能力。对在agent.toml中已启用的能力执行授予会被拒绝('terminal' is already enabled in agent.toml; nothing to grant)。- 超过
temporary_max_duration(默认24h,见 配置)的时长会被拒绝。 - CLI 是一次性的:写完 grants 文件即退出。运行中的守护进程会在数秒内拾取该变更 —— 无需重启 Agent。
重启与过期语义
授予会持久化到 <state_dir>/capability_grants.json(默认 /var/lib/serverbee/capability_grants.json,以 0600 权限写入),其 expires_at 是绝对时间戳(Unix epoch),而非相对倒计时。这让行为足够健壮:
- 跨重启存活 —— 若 Agent 在时间窗中重启,授予会被重新加载,并在原始时间窗内保持生效。
- 在原始截止时刻过期 —— 重启不会延长授予。
30m的授予在发起后 30 分钟过期,无论期间 Agent 重启多少次。 - 失败时安全归零(OFF) —— 若 grants 文件缺失、为空、损坏,或由未知 schema 版本写入,Agent 会将其视作「无授予」,对应能力保持关闭。临时授予永远不会增强永久能力集,它只能在自己的时间窗内把一个原本关闭的位翻为开启。
- 过期约束的是运行中的工作,而不只是新请求 ——
terminal授予过期或被撤销时,在该授予下打开的终端会话会被立即关闭(浏览器端会看到会话结束);security_events授予生效的那一刻就会启动 Agent 的安全事件管道,时间窗结束时将其停止 —— 包括在 Agent 已运行期间发起的授予。
Server 看到什么
当某个授予生效(或过期 / 被撤销)时,Agent 会重新上报其有效能力集,因此 Server 会实时打开或关闭对应的门控:
- 变更会镜像到
servers.capabilities并广播给浏览器,UI 实时更新。 - 该转换会写入 审计日志,动作为
capability_temporarily_granted、capability_grant_expired或capability_grant_revoked。 - 对高危能力(
terminal、exec、file、docker)的临时授予还会评估事件驱动的capability_grant_detected告警规则。过期、撤销以及低风险授予会被审计,但不触发告警。 - Agent 为该服务器执行的全部工作会按新的能力集重新同步:ping 任务重新过滤、网络探测目标与 IP 质量服务重新下发、防火墙黑名单先重置(仅当
firewall_block仍生效时才会重新推送)。撤销 ping 能力会立即停止对应探测;撤销firewall_block会立刻移除 ServerBee 在主机上的 nftables 规则,无需等待重连。
在 Agent 与 Server 断连期间发起的授予,会在本地生效并在重连后展示出来,但不会产生 granted 审计记录或告警。Server 只能看到重连后的能力状态,看不到转换发生的瞬间,因此无法区分「刚刚授予」与「本就生效」的能力。若你把该告警当作触发器(tripwire)使用,请考虑这一点。
Web UI 中的展示
在临时授予生效期间,受影响的能力会带一个琥珀色的 Temporary 徽章和一个到期实时倒计时,服务器详情 → 能力 弹窗与 设置 → 能力开关 全机群矩阵中均会显示。授予过期或被撤销后,徽章会自动消失。
强制执行模型
Agent 主机是唯一的权威来源,但为了纵深防御,强制执行发生在两个边界上。
服务端拦截(基于上报的能力)
Server 记录每个 Agent 上报的能力,并拒绝 Agent 未启用能力对应的控制面请求:
- 终端:WebSocket 升级被 403 拒绝
- 执行:
POST /api/tasks与定时任务运行会过滤掉 Agent 缺少exec的服务器,并写入合成结果(exit_code = -2) - 自动升级:未上报
upgrade时,POST /api/servers/{id}/upgrade返回 403 - Ping 与 Traceroute:探测任务按能力过滤;traceroute 需要
ping_icmp - 文件管理:未上报
file时,文件接口在下发前即拒绝请求 - Docker:Docker 读取/操作接口及 Docker 日志 WebSocket 路由需要
docker以及 Agent 运行时支持 Docker
由于能力由 Agent 拥有,拒绝原因始终是 agent_capability_disabled。
Agent 侧强制执行
即使某个服务端请求被绕过,Agent 仍会在本地复核能力:
- 对未授权命令返回
CapabilityDenied消息 - Server 收到
CapabilityDenied后写入合成结果(exit_code = -1) - 拒绝事件记录到审计日志
上报与展示
Agent 连接(或重连)时会发送携带 agent_local_capabilities 的 SystemInfo。Server 会:
- 将该值持久化到
servers.capabilities列作为展示镜像(这样即使 Agent 离线,仪表盘也能展示能力)。 - 向所有已连接的浏览器广播
CapabilitiesChanged,使 UI 实时反映当前集合。
如果重连之间 ping 相关位发生变化,Server 会自动为该 Agent 重新同步 ping 任务。
前端行为
Web 和 iOS 客户端以只读方式展示能力:
- 服务器详情 → 能力:只读展示该 Agent 已启用的能力,并提示它们在 Agent 配置文件中设置
- 设置 → 能力开关:只读的全机群矩阵,按服务器展示启用/关闭状态
- 远程命令页:Agent 缺少
exec的服务器置灰 - 终端按钮:对 Agent 缺少
terminal的服务器隐藏 - 文件按钮:对 Agent 缺少
file的服务器隐藏 - Docker 入口:对 Agent 缺少
docker的服务器隐藏
运行时能力字段
Server 响应暴露三个能力字段,在能力由 Agent 拥有的模型下它们都相等:
capabilities:Agent 上次上报值的持久化镜像agent_local_capabilities:已连接 Agent 上报的实时值effective_capabilities:实际强制执行的值(与 agent-local 值一致)
这些字段在 API 中保持区分,以便向前兼容,并使离线服务器仍能从镜像展示最后已知的能力。