先说清楚我这边的网络有多少台设备。
我在几个不同地点各有一张局域网,互相连不通,每一张都要自己维护。设备加起来 86 台(这是 MiBee Steward 扫出来的数字,文里的截图都是它自己的界面),其中 13 台当时处于离线状态。
然后我打开自己的 Excel 表格准备核对——那张表是我半年前手打的。
半年前我按记忆记了一版,之后就没再更新。里面有三个 IP 早就换了设备,有两台机器我拆了搬走,还有一台 NAS 现在接在完全不同的网段上。也就是说这张表里至少 6 条记录是错的,而且我完全不知道是哪 6 条。
这不是懒的问题。是「靠人脑维护一份会过期的清单」这件事本身不成立——设备会变,而你不会在每次变化之后记得去改表。
哪怕你只有十几台设备,这件事也一样成立。手机换个 MAC、NAS 换个网段、路由器重启后 DHCP 重新分配,每一次变化都在让清单过期。
所以我写了 MiBee Steward:扫网络、认出设备、把状态持续跟踪下去。它今天刚发了 v0.7.0,这篇文章把它讲清楚。
扫到什么
设备列表。左上角四个数字:总数 86、在线 73、离线 13、未知 0——标题里那个 86 就是这里来的。每行带类型徽章,能按状态、类型、网络筛选,也能导出 CSV。
识别效果直接看名字:viomi-waterheater-e13 认成小米的热水器,Z4S-2PSE 认成极空间的 NAS,orangepi-zero3 认成香橙派的板子。这些名字都是设备自己在 DHCP 主机名、SSDP 里报出来的,Steward 从里面把品牌和型号抠出来。
仪表盘。顶部横幅「需要关注:13 台离线」,右上环形图是心跳成功率 85%——有设备掉线它直接摆在脸上,而不是等你哪天想起来去 ping 一下。
对一张网络资产表来说,第一件事不是「好看」,是「数字对不对」。我第一次扫完跟那张 Excel 对,差出来十几条。
拓扑视图是我做出来之后自己用得最多的。中心橙色节点是网关(我这里是 GL.iNet),一圈节点按网关/核心/接入层/终端四类着色,也能按这四类筛选。哪台交换机下挂了哪台机器、哪条链路通到哪个网段,看一眼就知道——比翻列表快得多。
它认设备靠的是指纹,不是你填表
自动发现这件事本身不新鲜,nmap 早就能扫出 IP 了。真正难的是「这台 IP 后面是什么设备」——网段里哪个是摄像头、哪个是交换机、哪个是 NAS。
MiBee Steward 的做法是插件化的扫描管线,五层:探测 → 分类 → 处理 → 持久化 → 编排。探测层拿到设备吐出来的 banner、HTTP 响应、RTSP/ONVIF 握手内容、SNMP 的 sysDescr;分类层拿这些证据去比对 YAML 写的指纹规则库,匹配上就推出类型、品牌、型号。
指纹库是能贡献的。你发现某个设备没被认出来,把它的 banner 抓下来写一条规则提 PR,识别能力就长一分。v0.7 里这个库刷新了两轮(recog 部分从 Rapid7 Recog 重新导入,2534 → 2548 条),OUI 厂商表也补上了小米生态的 13 个前缀——之前表里一个小米的 MAC 段都没有。
有两处设计我认为是这个项目真正区别于普通扫描器的地方:
一是被动发现优先。设备不一定要能被主动探测到才认出来。DHCP 租约里的主机名、旁听到的 mDNS/SSDP 公告、conntrack 里正在建立的连接、hostapd 的 STA 列表——这些信息设备自己是交出来的,不需要你发一个包过去。我在 R68S 路由器上实测过,主动 mDNS 查询 100% 无应答,但被动旁听能拿到很丰富的信息。这就是「能认出不回应的设备」和「只能认出肯回应的设备」的区别。
二是识别准确度需要积累。做两台设备的时候指纹库可能几百条就够,但真实网络里米家设备、摄像头、各种嵌入式设备千奇百怪,这个库是按实测不断长的。这是投入方向,不是能一步到位的功能。
相比同类,它的位置在哪
我把 MiBee Steward 和几个常见选项对了一遍,说下我的实际判断。
LibreNMS / Zabbix 是网络监控工具,做的是设备已经在网管系统里之后的持续监控。它们的模型假设是你已经知道有哪些设备;MiBee Steward 是去发现「那里到底有什么」。这两件事序列不同,所以不是替代关系。
NetBox / Snipe-IT 是 CMDB,模型是对的(资产登记、记录变更),但它们的手工录入是你的起点,你得先把设备一条条填进去。
nmap 是扫描器,它连管理界面都没有,更没有身份识别和持续登记。
MiBee Steward 占的格子是:自动发现(nmap 级)+ 身份识别(基于指纹)+ 登记/管理(CMDB-lite)+ 单二进制部署。这四个组合在一起的事,我没有见到第二个工具在同样的轻量级上做。
v0.7.0 改了什么
需要说明一下,v0.7.0 是一次有 Breaking Change 的版本,我自己的环境也在这轮重装了。
Go 版采集器退役,只剩 Rust 版
这一条影响最大。分布式采集器之前有两个实现:Go 版和 Rust 版,现在只保留 Rust 版。
退役的实测数据在 docs/zh/agent-rs.md,我把几个关键数字放这里:二进制小 4.2 倍,同一块 ARMv7 板上中位常驻内存从 54.1MB 降到 11.9MB(4.5 倍),/24 扫描快约 1.7 倍。分类器做了全语料差分测试,字节级一致。
为什么换:54MB 常驻内存在路由器上是要命的,很多路由器的可用内存就一百来兆。
好消息是 agent.yaml 配置不用改,键名兼容,直接跑。Go 版采集器本地那个 agent.db 不会带过来——它本来是个影子账本,中心的资产库才是正本,扫一次就回来了。
指纹语料开始可以在线更新
这一条是从 0.6 的「内置语料」走向「可运营」的关键一步。
现在可以在 Web 界面(设置 → 指纹)里:上传语料包、回滚到上一版、检查上游有没有更新并看新增/减少的规则差异、一键应用。每条路径都要过规则引擎自己的加载器校验——坏掉的语料会被引擎的错误拒绝,线上那份继续跑。应用后热重载,中心不用重启,语料版本号往前推,开了同步的采集器下次轮询就跟上。
对多站点部署来说,这条比听起来有用:我的机房里采集器分布在不同地方,语料更新以前得重新打包分发,现在中心改一次,各处自己跟上。
采集器扫的网络不再是拓扑盲区
之前有个别扭的限制:采集器扫回来的数据里其实有 LLDP/CDP 这类二层邻居信息,但上报格式没带这些字段,拓扑视图对采集器扫的网络是瞎的。v0.7 把邻居数组加进了上报格式,中心用和本地扫描同一条管道入库——采集器覆盖的远端网段现在也出现在拓扑里。对我这种中心在一个地方、采集器在另外几个地方的部署,这条等于把拓扑图补全了。
型号识别补完了最后一环
之前米家设备能认出品牌,认不出型号。v0.7 加了一条 hostname → model 的完整管线:从 viomi-waterheater-e13_miap5E55 这种名字里把型号 token(e13)抠出来,一路写进资产库的 model 列和上报格式。实测用 10 个真实主机名验证过,米家设备的型号覆盖从 0% 变成扫一次全带上(只填空,不覆盖你手改过的值)。
惰性正则编译,采集器常驻内存减半
指纹规则里的正则原来在启动时全部编译进内存,是一笔固定开销。现在改成惰性编译——规则被实际用到才编译。实测数据:语料加载的堆占用从约 50MB 降到约 4MB,稳态 RSS 从约 110MB 降到 45–55MB。对路由器这种内存紧张的设备,这条比任何性能优化都实在。
两个识别准确性的修复
一是 TLS 证书的 CN、NetBIOS 主机名现在也能作为识别证据;二是随机 MAC 的处理逻辑改了。之前一个手机拿随机 MAC 抢了个空闲 IoT 设备的 DHCP 租约,会把真设备的行强行覆盖掉、把一批设备标成离线、还留下重复 MAC 的行——我在 lan-62 上真见过一个隐私 MAC 连续顶掉三台设备。现在这种情况只清空 IP 占用、不动身份和历史,真设备回来自己会重新认领。厂商真实 MAC 的行为不变。
另外还有多宿主 IP 稳定性、语料资产漂移守卫、CI 加了 cargo 测试门禁这些工程侧的东西。
现在还做不到什么
这一节比上面所有功能都重要,如果你正在考虑用它,先读这段。
v0.7 升级必须重建数据库。 schema 不再原地迁移,旧库启动时直接拒绝。这不是偷懒,是把并行 DDL 那一类 bug 彻底除掉(#328/#431/#437)。升级流程是:备份数据目录 → 用新目录启动 → 扫描自动回填资产。资产会回来,但本地扫描历史和本地 SNMPv3 凭据库不带回来。如果你不想折腾,继续用 v0.6.0,v0.6 还是可用的稳定版本。
v0.7.0 的 release 安装包我还没传。 今天刚打的 tag,写这篇时 Releases 页最新可下载的是 v0.6.0。不急着装的话,等包传上去再说。
Rust 版采集器的路由器
.ipk/.apk包还没进 release,这是 tracked follow-up。tarball + procd init 路径是文档里写的安装方式(agent-rs/deploy/openwrt/mibee-agent.init),能用,但不是三种形态齐备。指纹认不出的设备还是会有。 指纹库几千条覆盖了常见厂商,但真实网络里总有奇怪的东西。我的处理方式是把这类设备的识别数据做成贡献循环,但这依赖有人愿意提 PR,不是一句话能解决的。
告警和可视化它不做,是有意的。
/metrics和/sd端点把数据交给 Prometheus 生态,告警什么、怎么告警是 Alertmanager 的事,可视化是 Grafana 的事。要用这些就一起部署,它们原生消费它的输出。别指望在它的界面上做告警。主机深度监控(CPU/内存/磁盘)也不做,node_exporter / Netdata 是那边的事。它只做发现、识别、登记、心跳。
eBPF 被动观测是可选组件,默认构建不包含。想要得自己带构建标签编译。默认的容器镜像是 non-privileged 变体,LLDP/CDP 原始帧和 eBPF 都是 no-op stub,特权变体要本地构建。
它是单人项目。GitHub 上 485 次提交全部出自我一个人。功能边界很清楚,但响应速度取决于我一个人的时间和状态。有问题可以提 issue,不保证当天回。
路由器形态要求 arm64。32 位 ARM 路由器要在本地
make build-linux-arm构建,不在 release 里。指纹语料的准确率我没有大规模实测过。我自己的环境里识别得挺准,但「在我这儿准」和「在你的网络里准」是两件事。这条我得说清楚。
怎么跑起来
从 GitHub Releases 下载对应架构的二进制(amd64/arm64),加执行权限直接跑——它是 CGO-free 的纯 Go 二进制,目标机不需要 C 工具链:
chmod +x mibee-steward./mibee-steward --config config.yaml
最小配置里有三个必填:监听地址、要扫的网段(network.cidr)、两个认证项(auth.jwt_secret 至少 32 字符;auth.initial_admin_password 不设的话服务直接退出)。
容器镜像在 ghcr.io/mi-bee-studio/mibeesteward(amd64 + arm64)。注意扫描依赖 NET_RAW/NET_ADMIN 能力,容器要用 host 网络模式——默认 bridge 在 NAT 后面,ICMP 和 ARP 探测全失效,不能用于真实盘点。
OpenWrt/iStoreOS 有 tarball / .ipk / .apk 三种形态(arm64)。
装完先跑一次 doctor 子命令,它会做一次体检(ICMP 权限、数据库状态、配置合理性),有问题它自己会说。
项目地址
仓库(AGPL-3.0):https://github.com/Mi-Bee-Studio/MiBeeSteward
项目门户(部署文档、截图都在这):https://www.mickeyzzc.tech/projects/mibeesteward
中文文档:https://github.com/Mi-Bee-Studio/MiBeeSteward/tree/main/docs/zh
产品边界文档(这篇「现在还做不到什么」的完整版,写得比我细):https://github.com/Mi-Bee-Studio/MiBeeSteward/blob/main/docs/zh/product-scope.md
如果你也在维护一堆分散在几个地方的网络,这套东西可能对你有用。star 一下我这边能收到反馈,也是我继续写的动力——尤其是「哪些设备认不出来」这类信息,对指纹库的贡献最直接。
我在「蓝宝石的傻话」写一个人维护几张异地局域网的实战:自托管、网络、开源项目的开发和踩坑。下一篇写 Rust 采集器在 OpenWrt 路由器上的部署实测,感兴趣可以关注。