monitor

开始

设计哲学

安全

装 agent 不扩大被监控机器的攻击面

  • 不监听端口。连接由 agent 主动向 hub 发起,被监控的机器不用开端口,也不用改防火墙
  • 不写文件。只读 /proc、/sys/class/net、/etc/os-release 和 statvfs,没有配置文件、数据库或缓存。累加流量、识别重启这类有状态的工作都在 hub 侧
  • 不执行 hub 下发的东西。hub 下发的只有 TCP 探测任务(host:port 和间隔),没有任何指令能让 agent 运行命令或写文件
  • 不自动更新。自更新意味着 agent 能以 root 下载并执行任意二进制。升级由你在机器上执行 --upgrade

最小权限运行

一键脚本写出的 systemd 单元带着这些限制:

agenthub
身份专用系统用户 monitor-agent专用系统用户 monitor
文件系统ProtectSystem=strict + ProtectHome,全盘只读同上,另加 ReadWritePaths 只开 data/
提权NoNewPrivileges、RestrictSUIDSGIDNoNewPrivileges、RestrictSUIDSGID
隔离PrivateTmp、PrivateDevicesPrivateTmp、PrivateDevices
网络RestrictAddressFamilies=AF_INET AF_INET6 AF_NETLINKAF_INET AF_INET6
内存MemoryMax=64MMemoryMax=256M

hub 因此改不了自己的二进制,可写的只有数据库和主题所在的那一个目录。

没开 nesting 的 LXC 容器建不了挂载命名空间,systemd 会跳过「文件系统」和「隔离」两行,服务照常启动,其余几行不受影响。agent 不用 DynamicUser 正是因为这一点:带着它的单元在这种容器里无法启动,报 226/NAMESPACE。

节点 token 写在 /opt/monitor/agent.env,权限 0600,不写进服务定义,因为服务定义会出现在 systemctl cat 和日志里。

OpenRC 上 agent 同样以专用用户 monitor-agent 运行。上表其余几行是 systemd 的单元选项,OpenRC 没有对应的开关,两边一致的只有运行身份、自动重启和 token 的存放方式。

凭证的边界

  • 节点 token 是 256 位随机值,走 Authorization: Bearer 头而不是 URL query,因为 query 会进反代的 access log。它只能上报自己那一个节点,读不到别的节点,也改不了任何设置
  • 换发 token 立即生效,已经建立的连接也会被断开
  • 会话是 256 位随机 token,数据库里只存 sha256,14 天过期。cookie 带 HttpOnly 与 SameSite=Lax,HTTPS 下加 Secure
  • 面板的每个 handler 都在参数里带一个 Admin 提取器,框架在进入函数体之前校验会话,不会漏掉某个接口
  • 浏览器发来的写请求带着 Sec-Fetch-Site 且不是同源,一律回 403,在进路由之前统一拦下:同一注册域名下兄弟子域上的脚本也借不到会话 cookie。不发这个头的客户端(curl、脚本)照常放行;明文 HTTP 的非回环地址上浏览器不发它,这层保护不生效
  • 应急密码用 argon2id 存储。同一地址 15 分钟内失败 5 次即锁定;另有一道并发闸门,同一时刻只做一次密码校验

面板默认不对公网开放

一键脚本写死 --listen 127.0.0.1,装完后从公网打不开面板,要先配反向代理。

原因是明文 HTTP 上,会话 cookie 和节点 token 都在链路上明文传输,中间人还能替换安装命令下载的脚本和二进制,而那个脚本以 root 执行。所以 agent 和 install.sh 拒绝用明文连远程 hub,从 IP 或明文地址进面板时也不给出安装命令。

配法见反向代理。

极简

零配置文件

hub 只有四个运行参数:--listen、--db、--themes、--site,外加一个执行完就退出的 --reset-password。其余设置都存在 SQLite 里,在面板上改。

没有配置文件,也就没有「文件在哪、权限对不对、和数据库是否一致」这类问题。

不做的功能

不做原因
负载告警阈值、持续时长、节点范围是一整套规则引擎。通知只做掉线、流量、到期、登录这几件判定明确的事
远程 SSH / web terminal只读的观察者被攻破,和能执行命令的工具被攻破,代价差一个数量级
插件系统等于把第三方代码请进 hub 的进程
ICMP / HTTP 探测TCP 一种够用,三种要三套超时语义、三套图例
agent 自动更新自更新意味着 agent 能以 root 下载并执行任意二进制
跨平台 agent加 Windows / macOS 等于推翻整个采集实现

这些不在计划里。探针只报告机器的状态,不代管机器;不写的代码既不占内存,也不会出漏洞。

高效

同一台机器、同一套负载的实测数字,完整数据在性能:

可执行文件6.8 MiB
冷启动到能响应请求6.5 ms
空转内存7.0 MiB
200 个节点在线,每 2 秒上报10.8 MiB,一颗核的 2%
1000 个节点在线,每秒上报29.5 MiB,一颗核的 9%

Rust 没有 GC,也没有语言运行时,内存只随在线节点数缓慢增长,每台约 23 KiB。换语言只带来体积和内存上的优势,响应速度靠的是几处具体的调优,记在同一页。

在 GitHub 上修改这一页最后更新 2026-10-11