系列文章:

  • 第一篇:系统基础与启动流程
  • 第二篇:存储架构深挖
  • 第三篇:系统目录结构与技术栈
  • 第四篇:文件服务与用户权限体系
  • 第五篇:Web 后端架构深度解析
  • 第六篇:系统识别方法论与二次开发指南(本文 · 收官)

前五篇我们把 fnOS 从内核到应用层拆了个底朝天。这一篇是整个系列的收官,要回答两个最核心的问题:

  1. 拿到一台陌生的 NAS 设备,怎么快速判断它是不是飞牛的系统?即使对方把进程名、目录名都改了,也能判断出来?
  2. 如果要基于 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`
3ZFS 挂载参数trimacl(飞牛给 ZFS 打的内核补丁)`mount \grep zfs`
4Samba VFS 模块trim_perms、trim(自研 VFS 模块)grep vfs_objects /etc/samba/smb.conf
5Nginx 自研模块ngx_http_trim_cert_module.sogrep 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   trimafs

nodev 表示这是一个虚拟文件系统,不需要对应块设备。/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 trim

trim_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%)

这些特征需要改大量配置和代码才能去掉,贴牌厂商一般不会费这个劲。

序号识别点飞牛的特征检查命令
1Samba 服务器描述%h server (Samba TRIM)grep "server string" /etc/samba/smb.conf
2微服务架构30+ 个小服务 + rpc_broker 消息总线`systemctl list-units --type=service \grep -c trim`
3Unix Socket 通信几乎所有后端 API 走 Unix Socket`grep -r "unix:" /etc/nginx/conf.d/ \wc -l`
4Nginx 端口5666(HTTP)、5667(HTTPS)`ss -tlnp \grep 5666`
5FTP 服务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/
8Docker 镜像加速源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 服务运行:

  1. 放置二进制:放到 /usr/trim/bin/(和飞牛的程序放一起)或 /opt/你的应用/bin/(推荐,不污染系统目录)
  2. 创建 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——确保在飞牛核心服务启动后再启动,这样可以依赖飞牛的服务。

  1. 启用服务: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)。要把自己的程序固化到系统镜像里,有几种方式:

  1. 启动脚本注入:修改 /usr/trim/bin/system_startup.sh,在里面加入你的程序安装/启动逻辑。系统每次启动都会执行
  2. 修改升级包:飞牛的升级通过 liveupdate 下载升级包刷写系统分区。如果你能拿到升级包,可以修改后重新打包
  3. 不可变分区注意:飞牛的系统分区可能是只读的(类似 OTA 升级的 A/B 分区),修改后可能在升级时被覆盖。建议把程序放在数据分区(/vol1、/vol2),通过启动脚本挂载或启动

6.2 Web 界面耦合

方式一:独立页面 + API(推荐)

  1. 前端:把你的前端打包后的静态文件放到 /usr/trim/www/apps/你的应用名/
  2. 后端:写一个自己的后端服务,监听 Unix Socket(比如 /var/run/myapp.sock)
  3. 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 权限与认证集成

如果你的应用需要用户认证:

  1. 复用飞牛的登录态:你的 API 经过 Nginx 转发时,Cookie 会一起传过去。你可以验证 Cookie 是否有效(调用 accountsrv 的 /v1/accountapi 接口)
  2. 复用飞牛的用户体系:通过 /etc/passwd 获取用户列表,通过 id 命令获取用户组
  3. 文件权限:如果你的程序需要操作文件,直接用 Linux 系统权限即可。如果需要飞牛的 trimacl 权限,需要通过 Samba 或飞牛的 API 间接操作

6.4 二次开发注意事项

  1. 不要修改 /usr/trim/ 下的系统文件——升级时可能被覆盖。自己的东西放 /opt/ 或数据分区
  2. 不要用 TCP 端口——尽量用 Unix Socket 和 Nginx 通信,和飞牛的架构保持一致
  3. 服务依赖要写对——After=trim_main.service 确保核心服务先启动
  4. 日志要规范——输出到 syslog 或 /var/log/,方便排查
  5. 测试升级兼容性——系统升级后,你的程序是否还能正常运行

七、系列总结

经过六篇文章的深度解析,我们对飞牛 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 设备,按照这个顺序来:

  1. 先看系统基础(发行版、内核、硬件)
  2. 再看启动流程(systemd 服务、启动时间)
  3. 然后深挖存储(RAID、LVM、文件系统、挂载)
  4. 接着看目录结构(厂商的东西放哪了)
  5. 再看文件服务和用户权限
  6. 最后看 Web 后端架构(Nginx、API、微服务)
  7. 全程记录可识别特征,总结成方法论

写在最后

这个系列的起源是一个很朴素的需求——"我要搞懂这个系统,然后基于它做二次开发,还要能快速判断其他机器是不是它的贴牌"。

六篇文章写下来,最大的感受是:真正的技术深度藏在细节里。 不是看界面有多好看,而是看内核模块的名字、挂载参数里的一个选项、Nginx 配置里的一个 location、服务间通信用的是 Socket 还是端口。这些细节拼起来,就是一个系统的完整画像。

希望这个系列对你有帮助。如果你也在解构某个系统,欢迎交流。

—— 完 ——