飞牛 fnOS 深度解析(六):系统识别方法论与二次开发指南
系列文章:
- 第一篇:系统基础与启动流程
- 第二篇:存储架构深挖
- 第三篇:系统目录结构与技术栈
- 第四篇:文件服务与用户权限体系
- 第五篇:Web 后端架构深度解析
- 第六篇:系统识别方法论与二次开发指南(本文 · 收官)
前五篇我们把 fnOS 从内核到应用层拆了个底朝天。这一篇是整个系列的收官,要回答两个最核心的问题:
- 拿到一台陌生的 NAS 设备,怎么快速判断它是不是飞牛的系统?即使对方把进程名、目录名都改了,也能判断出来?
- 如果要基于 fnOS 做二次开发(把自研程序烧进系统、Web 界面耦合进去),应该怎么做?
这两个问题来自实际工作需求——我们需要解构奥睿科(ORICO)的机器,判断它是不是飞牛贴牌,同时要把自研的存证程序集成到 fnOS 里。
一、为什么需要系统识别方法论?
在开始之前,先讲一下背景。我的导师黄老师问了我一个问题:
"你拿到这个箱子,是不是可以马上判断出来是不是飞牛的?"
我回答说可以,因为飞牛有很多 trim_ 开头的自研进程。然后老师追问了一个关键问题:
"但是如果他把这个换了呢?能判断出来吗?"
这个问题问得非常好。贴牌厂商(比如奥睿科)如果用了飞牛的系统,很可能会把表面的东西都改掉:
- 把
trim_开头的进程名改成自己的品牌名 - 把
/usr/trim/目录改成/usr/orico/ - 把 Web 界面的标题、logo 换掉
- 把版本号文件改名
如果只看这些表面特征,就会被蒙蔽。所以我们需要一套不依赖命名、基于行为和结构的多维度识别方法。
核心思路是:名字可以改,但内核、文件系统、整体架构改不了。 贴牌厂商可以改进程名,但不会去改内核模块、不会去改 ZFS 补丁、不会去重构 30+ 微服务的架构——改这些等于重新开发一套系统。
二、三级证据体系
我把飞牛系统的识别特征按可靠性分为三级:
🔴 一级证据:改不掉的硬特征(可靠性 95%+)
这些特征是内核级或文件系统级的,是飞牛的核心技术,贴牌厂商几乎不可能改。
| 序号 | 识别点 | 飞牛的特征 | 检查命令 | |
|---|---|---|---|---|
| 1 | 内核模块名 | trimafs2(自研联合文件系统内核模块) | `lsmod \ | grep trim` |
| 2 | 文件系统类型 | trimafs(nodev,/fs 挂载点) | `cat /proc/filesystems \ | grep trim` |
| 3 | ZFS 挂载参数 | trimacl(飞牛给 ZFS 打的内核补丁) | `mount \ | grep zfs` |
| 4 | Samba VFS 模块 | trim_perms、trim(自研 VFS 模块) | grep vfs_objects /etc/samba/smb.conf | |
| 5 | Nginx 自研模块 | ngx_http_trim_cert_module.so | grep load_module /usr/trim/nginx/conf/nginx.conf | |
| 6 | 内核版本后缀 | cXXX-trim(如 6.18.18.c1032-trim) | uname -a |
详细说明
1. trimafs2 内核模块
这是飞牛自研的联合文件系统,纯内核模块(不是 FUSE),大小只有约 76KB。它把多个存储卷联合挂载成 /fs 统一入口。
$ lsmod | grep trim
trimafs2 77824 1
spl 131072 1 zfs
zfs 5849088 28只要看到 trimafs2,99% 是飞牛的系统。因为这是飞牛自己写的内核模块,其他 NAS 厂商不会有。
2. trimafs 文件系统类型
$ cat /proc/filesystems | grep trim
nodev trimafsnodev 表示这是一个虚拟文件系统,不需要对应块设备。/fs 挂载点用的就是这个类型:
$ mount | grep ' /fs '
trimafs on /fs type trimafs (rw,relatime,trimacl)3. trimacl(ZFS 补丁)
飞牛给 ZFS 打了一个叫 trimacl 的补丁,实现跨文件系统统一权限。原生 ZFS 没有这个挂载参数:
$ mount | grep zfs
trim_6c71e3b3-... on /vol2 type zfs (rw,noatime,xattr,trimacl,casesensitive)只要 ZFS 挂载参数里有 trimacl,基本就能确定是飞牛。
4. Samba 自研 VFS 模块
飞牛给 Samba 加了 trim_perms 和 trim 两个自研 VFS 模块:
vfs objects = trim_perms full_audit trimtrim_perms 是 trimacl 在 Samba 层的实现,trim 是核心 VFS 模块。标准 Samba 没有这两个模块。
5. Nginx 自研模块
飞牛编译了自己的 Nginx 模块 ngx_http_trim_cert_module,用于动态证书管理:
load_module modules/ngx_http_trim_cert_module.so;🟡 二级证据:很难改的结构特征(可靠性 80-90%)
这些特征需要改大量配置和代码才能去掉,贴牌厂商一般不会费这个劲。
| 序号 | 识别点 | 飞牛的特征 | 检查命令 | |
|---|---|---|---|---|
| 1 | Samba 服务器描述 | %h server (Samba TRIM) | grep "server string" /etc/samba/smb.conf | |
| 2 | 微服务架构 | 30+ 个小服务 + rpc_broker 消息总线 | `systemctl list-units --type=service \ | grep -c trim` |
| 3 | Unix Socket 通信 | 几乎所有后端 API 走 Unix Socket | `grep -r "unix:" /etc/nginx/conf.d/ \ | wc -l` |
| 4 | Nginx 端口 | 5666(HTTP)、5667(HTTPS) | `ss -tlnp \ | grep 5666` |
| 5 | FTP 服务 | smbftpd(不是 vsftpd/proftpd) | which smbftpd 或 ls /usr/*/bin/smbftpd | |
| 6 | 自研 useradd | 飞牛自己的 useradd,不是系统的 | ls -la /usr/*/bin/useradd | |
| 7 | 应用命名格式 | trim.应用名(如 trim.photos) | ls /usr/local/apps/@appcenter/ | |
| 8 | Docker 镜像加速源 | https://docker.fnnas.com | 查看 Docker 配置 | |
| 9 | 前端组件库 | Semi Design(CSS 变量 --semi-color-*) | 查看网页源码 | |
| 10 | 单盘 RAID1 | 系统盘做单盘 RAID1(方便加盘) | cat /proc/mdstat |
详细说明
微服务 + Unix Socket 架构是飞牛非常鲜明的特征:
- 30+ 个后台服务,每个负责一个功能
- 几乎全部通过 Unix Socket 和 Nginx 通信
- 有一个
rpc_broker作为服务间消息总线
这种架构不是一朝一夕能形成的,贴牌厂商如果要改,等于把整个后端重写一遍。
🟢 三级证据:容易改的命名特征(可靠性 50-70%)
这些特征贴牌厂商可能会改,但改了会留下痕迹。可以作为辅助判断,不能作为唯一依据。
| 识别点 | 飞牛的特征 |
|---|---|
| 进程名前缀 | trim_ 开头的服务 |
| 安装目录 | /usr/trim/ |
| 服务描述 | 带 "trim" 字样 |
| 版本号文件 | /usr/trim/etc/version |
| 主机名 | 可能带 "fnOS" 或 "trim" |
三、5 分钟识别流程
拿到一台陌生设备,按以下步骤操作,5 分钟内判断是不是飞牛系统:
第一步:lsmod | grep trim
├─ 有 trimafs2 → ✅ 99% 是飞牛(或基于飞牛的贴牌)
└─ 没有 → 继续下一步
第二步:cat /proc/filesystems | grep trim
├─ 有 trimafs → ✅ 99% 是飞牛
└─ 没有 → 继续下一步
第三步:mount | grep -E 'trimacl|trimafs'
├─ 有 → ✅ 95% 是飞牛
└─ 没有 → 继续下一步
第四步:grep vfs_objects /etc/samba/smb.conf
├─ 有 trim_perms 或 trim → ✅ 90% 是飞牛
└─ 没有 → 继续下一步
第五步:grep -r "load_module" /etc/nginx/ /usr/*/nginx/ 2>/dev/null
├─ 有 ngx_http_trim_cert_module → ✅ 90% 是飞牛
└─ 没有 → 继续下一步
第六步:uname -a | grep trim
├─ 有 cXXX-trim 后缀 → ✅ 80% 是飞牛
└─ 没有 → 继续下一步
第七步:检查二级证据(微服务数量、Unix Socket、5666端口、smbftpd)
├─ 命中 3 个以上 → ✅ 大概率是飞牛(深度贴牌)
└─ 命中少 → 可能不是飞牛,或者是完全自研的系统核心原则:先查一级证据(内核和文件系统),只要有一个命中,基本就能确定。一级证据全部没命中,再查二级和三级证据综合判断。
四、fnOS 完整系统架构图
经过六篇的深度解析,我们可以画出 fnOS 的完整架构图:
┌─────────────────────────────────────────────────────────────────┐
│ Web 前端(React SPA) │
│ React + TypeScript + Semi Design + Rolldown + i18next │
│ /usr/trim/www/ │
└──────────────────────────────┬──────────────────────────────────┘
│ HTTP/HTTPS (5666/5667)
┌──────────────────────────────▼──────────────────────────────────┐
│ Nginx(自编译 + 自研模块) │
│ ngx_http_trim_cert_module(动态证书管理) │
│ 反向代理 → 30+ 后端服务(几乎全部 Unix Socket) │
│ 全局安全访问码(auth_request) │
│ Cookie v2→v1 转换 │
└──────────────────────────────┬──────────────────────────────────┘
│
┌──────────────────────────────▼──────────────────────────────────┐
│ 后端微服务集群(30+ 个) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │trim_http │ │accountsrv│ │trim_ │ │trim_ │ │
│ │_cgi(核心)│ │(账户) │ │photos │ │media │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │trim_share│ │trim_ │ │trim_sync │ │trim_seek │ │
│ │(分享) │ │snapshots │ │(同步) │ │(搜索) │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │dockermgr │ │trim_vm │ │trim_ │ │trim_open │ │
│ │(Docker) │ │(虚拟机) │ │license │ │_gateway │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ ... 还有更多专项服务 │
│ │ │ │ │
│ │ Unix Socket │ gRPC │ TCP(少数) │
└─────────┼──────────────────┼────────────────────┼────────────────┘
│ │ │
┌─────────▼──────────────────▼────────────────────▼────────────────┐
│ 数据层 │
│ PostgreSQL 15(127.0.0.1:5432) SQLite(下载中心/DLNA) │
│ /etc/passwd + tdbsam(用户) /var/lib/samba/(SMB密码) │
└──────────────────────────────┬──────────────────────────────────┘
│
┌──────────────────────────────▼──────────────────────────────────┐
│ 存储层(飞牛核心技术) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ vol1 │ │ vol2 │ │ vol3 │ │
│ │ NVMe SSD │ │ SATA HDD │ │ 2×SATA HDD │ │
│ │ RAID1+LVM │ │ ZFS │ │ RAID0+LVM │ │
│ │ ext4 │ │ +trimacl │ │ ext4 │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └────────────────┼────────────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ trimafs2 │ ← 飞牛自研联合文件系统 │
│ │ (内核模块) │ 把多卷合并为 /fs 统一入口 │
│ └─────────────────┘ │
└──────────────────────────────────────────────────────────────────┘五、镜像定制与升级机制
5.1 内核多版本保留(支持升级回滚)
/boot/ 里保留了 6 个内核版本:
| 版本 | 说明 |
|---|---|
| 6.18.18.c1032-trim | 当前运行(最新) |
| 6.18.18.c952-trim | 上一版本 |
| 6.18.18.c938-trim | 更早版本 |
| 6.18.18.c877-trim | 更早版本 |
| 6.18.18.c788-trim | 更早版本 |
| 6.18.18-trim | 基础版本(无 cXXX 后缀) |
每个版本都有完整的 config、initrd.img、System.map、vmlinuz,对应的内核模块在 /usr/trim/modules/ 下也有 6 个版本目录。
这说明飞牛的升级机制是:保留最近 N 个版本,升级失败可以回滚到任意旧版本。 这是企业级 NAS 的标准做法。
5.2 升级相关程序
| 程序 | 路径 | 作用 |
|---|---|---|
| updatemgr | /usr/trim/bin/updatemgr | 升级管理服务(systemd 服务) |
| liveupdate | /usr/trim/bin/liveupdate | 在线升级程序 |
5.3 版本号
- 系统版本:
1.2.0505(/usr/trim/etc/version) - 内核版本:
6.18.18.c1032-trim
六、二次开发指南
基于我们的深度解析,如果你要基于 fnOS 做二次开发(比如把自研存证程序集成进去),以下是完整的路径。
6.1 底层程序集成
方式一:独立服务(推荐)
把你的程序编译成二进制,作为独立的 systemd 服务运行:
- 放置二进制:放到
/usr/trim/bin/(和飞牛的程序放一起)或/opt/你的应用/bin/(推荐,不污染系统目录) - 创建 systemd 服务:在
/etc/systemd/system/下创建你的服务.service:
[Unit]
Description=My Custom Service
After=trim_main.service
After=network.target
[Service]
Type=simple
ExecStart=/opt/myapp/bin/myapp
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target注意 After=trim_main.service——确保在飞牛核心服务启动后再启动,这样可以依赖飞牛的服务。
- 启用服务:
systemctl enable --now 你的服务
方式二:调用飞牛现有服务
如果你的程序需要和飞牛的功能交互(比如获取用户信息、操作文件),可以通过以下方式调用:
- HTTP API:调用
http://127.0.0.1:5666/cgi/...或/app/...(需要认证) - Unix Socket:直接连接
/var/run/trim_xxx.sock(需要知道协议格式) - gRPC:调用
trim_open_gateway(需要 proto 文件)
关于"烧到 flash"
飞牛的系统安装在 NVMe 的系统分区(nvme0n1p2)。要把自己的程序固化到系统镜像里,有几种方式:
- 启动脚本注入:修改
/usr/trim/bin/system_startup.sh,在里面加入你的程序安装/启动逻辑。系统每次启动都会执行 - 修改升级包:飞牛的升级通过
liveupdate下载升级包刷写系统分区。如果你能拿到升级包,可以修改后重新打包 - 不可变分区注意:飞牛的系统分区可能是只读的(类似 OTA 升级的 A/B 分区),修改后可能在升级时被覆盖。建议把程序放在数据分区(/vol1、/vol2),通过启动脚本挂载或启动
6.2 Web 界面耦合
方式一:独立页面 + API(推荐)
- 前端:把你的前端打包后的静态文件放到
/usr/trim/www/apps/你的应用名/ - 后端:写一个自己的后端服务,监听 Unix Socket(比如
/var/run/myapp.sock) - Nginx 配置:在
/usr/trim/nginx/conf/conf.d/下创建myapp.conf:
# 前端页面
location ^~ /apps/myapp {
root /usr/trim/www;
add_header cache-control "no-cache";
index index.html;
try_files $uri /apps/myapp/index.html;
}
# 后端 API
location /myapp/api/ {
proxy_pass http://unix:/var/run/myapp.sock:;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}这样用户访问 http://NAS:5666/apps/myapp 就能看到你的页面,API 请求走 /myapp/api/ 转发到你的后端。
方式二:嵌入现有界面
如果要把你的功能嵌入飞牛的现有界面(比如在文件管理器里加一个按钮),需要修改 /usr/trim/www/ 下的前端文件。但这些是打包后的代码(压缩混淆过的),修改困难,不推荐。建议用方式一,做独立页面。
6.3 权限与认证集成
如果你的应用需要用户认证:
- 复用飞牛的登录态:你的 API 经过 Nginx 转发时,Cookie 会一起传过去。你可以验证 Cookie 是否有效(调用 accountsrv 的
/v1/accountapi接口) - 复用飞牛的用户体系:通过
/etc/passwd获取用户列表,通过id命令获取用户组 - 文件权限:如果你的程序需要操作文件,直接用 Linux 系统权限即可。如果需要飞牛的 trimacl 权限,需要通过 Samba 或飞牛的 API 间接操作
6.4 二次开发注意事项
- 不要修改
/usr/trim/下的系统文件——升级时可能被覆盖。自己的东西放/opt/或数据分区 - 不要用 TCP 端口——尽量用 Unix Socket 和 Nginx 通信,和飞牛的架构保持一致
- 服务依赖要写对——
After=trim_main.service确保核心服务先启动 - 日志要规范——输出到 syslog 或
/var/log/,方便排查 - 测试升级兼容性——系统升级后,你的程序是否还能正常运行
七、系列总结
经过六篇文章的深度解析,我们对飞牛 fnOS 有了全面的认识:
| 维度 | 核心结论 |
|---|---|
| 系统基础 | 基于 Debian 12 深度定制,飞牛自研内核 6.18.18.c1032-trim,x86_64 |
| 启动流程 | 网络 4.3 秒就绪,Web 约 20 秒可用,nmbd 拖慢整体到 1 分 41 秒 |
| 存储架构 | 混合架构(ZFS + ext4 + RAID + LVM)+ trimafs2 自研联合文件系统 + trimacl 自研 ACL |
| 目录结构 | /usr/trim/ 为安装根目录,100+ 自研程序,前端 React + Semi Design |
| 文件服务 | SMB 深度定制(4个VFS模块),FTP 用 smbftpd,WebDAV 自研,四协议统一认证 |
| 用户权限 | PostgreSQL 主存储 + 系统用户 + Samba 密码同步,trimacl 跨文件系统统一权限 |
| Web 后端 | 30+ 微服务,几乎全部 Unix Socket 通信,Nginx 自研模块,gRPC 支持 |
| 应用生态 | Docker + 原生 FPK 应用,应用中心管理,Docker 数据在 ZFS 卷上 |
| 升级机制 | 保留 6 个内核版本,支持升级回滚,liveupdate + updatemgr |
| 系统识别 | 三级证据体系,5 分钟判断,核心看 trimafs2 和 trimacl |
fnOS 的技术水平:作为一个相对新的 NAS 系统,fnOS 的架构设计相当成熟——微服务解耦、Unix Socket 安全高效、自研文件系统和 ACL、统一认证、前后端分离。特别是存储层的 trimafs2 + trimacl,是真正的自研技术,不是简单套壳 Debian。
给后来者的建议:如果你也要解构一台 NAS 设备,按照这个顺序来:
- 先看系统基础(发行版、内核、硬件)
- 再看启动流程(systemd 服务、启动时间)
- 然后深挖存储(RAID、LVM、文件系统、挂载)
- 接着看目录结构(厂商的东西放哪了)
- 再看文件服务和用户权限
- 最后看 Web 后端架构(Nginx、API、微服务)
- 全程记录可识别特征,总结成方法论
写在最后
这个系列的起源是一个很朴素的需求——"我要搞懂这个系统,然后基于它做二次开发,还要能快速判断其他机器是不是它的贴牌"。
六篇文章写下来,最大的感受是:真正的技术深度藏在细节里。 不是看界面有多好看,而是看内核模块的名字、挂载参数里的一个选项、Nginx 配置里的一个 location、服务间通信用的是 Socket 还是端口。这些细节拼起来,就是一个系统的完整画像。
希望这个系列对你有帮助。如果你也在解构某个系统,欢迎交流。
—— 完 ——
仅有 1 条评论
jxzugzkwytdrsnxvtthpxvzmsiqxln