系列文章:

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

在前三篇里,我们从系统基础、启动流程、存储底层到目录结构,把 fnOS 的"骨架"摸了一遍。这一篇我们深入到文件服务和用户权限——这是 NAS 最核心的功能,也是用户每天都在用的东西。

飞牛在文件服务上做了大量定制,尤其是 SMB 协议,加了好几个自研的 VFS 模块。用户权限方面,飞牛自研了一套叫 trimacl 的 ACL 机制,能跨 ZFS、ext4 等不同文件系统统一权限。我们一个个来看。


一、SMB/CIFS:飞牛定制最深的协议

SMB(Server Message Block)是 Windows 世界的文件共享协议,也是 NAS 最常用的协议。fnOS 用的是 Samba,但做了深度定制。

1.1 主配置文件

Samba 的主配置在 /etc/samba/smb.conf,我们先看全局配置:

[global]
  workgroup = WORKGROUP
  server string = %h server (Samba TRIM)
  security = user
  client min protocol = NT1
  server min protocol = NT1
  vfs objects = trim_perms full_audit
  full_audit:prefix = %u
  full_audit:syslog = true
  full_audit:success = create_file mkdirat renameat mknodat unlinkat pwrite_recv pwrite_send pread_recv pread_send
  server multi channel support = yes
  socket options = TCP_NODELAY IPTOS_LOWDELAY
  use sendfile = yes
  read raw = yes
  write raw = yes
  min receivefile size = 16384
  aio read size = 1
  aio write size = 1
  max xmit = 65536
  large readwrite = yes
  fruit:model = TimeCapsule
  passdb backend = tdbsam
  unix password sync = yes
  passwd program = /usr/bin/passwd %u
  pam password change = yes
  include = /etc/samba/smb.custom.conf
  include = /etc/samba/users/%Y.share.conf
  include = /etc/samba/users/%Y.timas.conf

这里面有几个飞牛特有的标识,也是判断一台设备是不是飞牛系统的重要证据:

标识一:server string = %h server (Samba TRIM)

服务器描述里直接写了 "Samba TRIM"。即使有人把进程名、目录名都改了,这个配置里的 TRIM 也会暴露身份。

标识二:vfs objects = trim_perms full_audit

Samba 的 VFS(Virtual File System,虚拟文件系统)是一个插件机制,可以在文件操作的各个环节插入自定义逻辑。飞牛加了两个自研模块:

  • trim_perms —— 飞牛自研的权限管理模块,是 trimacl 在 Samba 层的实现
  • full_audit —— 完整审计模块,记录所有文件操作

在后面的自定义配置里,还会看到第三个 VFS 模块 trim。

标识三:include = /etc/samba/users/%Y.timas.conf

timas 应该是 TRIM Samba 的缩写,这也是飞牛特有的命名。

1.2 完整的文件操作审计

full_audit:prefix = %u
full_audit:syslog = true
full_audit:success = create_file mkdirat renameat mknodat unlinkat pwrite_recv pwrite_send pread_recv pread_send

飞牛开启了 full_audit 模块,审计以下操作:

操作含义
create_file创建文件
mkdirat创建目录
renameat重命名
mknodat创建设备文件
unlinkat删除文件
pwrite_recv/pwrite_send写入
pread_recv/pread_send读取

所有文件操作都会记录到 syslog 里,带用户名前缀(%u)。这是飞牛的安全审计功能——谁在什么时候对哪个文件做了什么操作,都有日志可查。

1.3 性能优化:飞牛做了大量调优

socket options = TCP_NODELAY IPTOS_LOWDELAY
use sendfile = yes
read raw = yes
write raw = yes
aio read size = 1
aio write size = 1
max xmit = 65536
large readwrite = yes
server multi channel support = yes
参数作用
TCP_NODELAY IPTOS_LOWDELAY降低网络延迟,小包立即发送
use sendfile零拷贝发送,大文件传输不经过用户态
aio read/write size = 1所有 IO 都走异步(AIO),提升并发性能
server multi channel support = yesSMB 多通道,多网卡聚合提速
large readwrite支持大读写块

飞牛对 Samba 的性能优化做得很细,几乎把能调的参数都调了。

1.4 苹果支持:Time Machine 备份

fruit:model = TimeCapsule

fruit 是 Samba 的苹果兼容模块,这里模拟成 Time Capsule(苹果的时间胶囊路由器),让 Mac 可以直接用 fnOS 做 Time Machine 备份。

1.5 自定义配置:又多了一个 trim VFS 模块

主配置里 include 了 /etc/samba/smb.custom.conf,内容如下:

[global]
workgroup = WORKGROUP
oplocks = yes
durable handles = yes
smb encrypt = auto
max connections = 2000
create mask = 0766
directory mask = 0777
server signing = auto
server multi channel support = yes
min protocol = SMB2_10
wins support = no
veto files = /._*/.DS_Store/
vfs objects = trim_perms full_audit trim
aio read size = 1
aio write size = 32768

重大发现:这里的 VFS 模块又多了一个 trim!加上主配置里的 trim_perms 和 full_audit,一共三个飞牛相关的 VFS 模块:

VFS 模块作用推测
trim_perms权限管理(trimacl 的 Samba 实现)
full_audit操作审计
trim飞牛核心 VFS 模块,负责和 trimafs/trimacl 的底层交互

另外注意 min protocol = SMB2_10,这覆盖了主配置里的 NT1,说明实际最小协议是 SMB2.1,不是 SMB1。主配置里写 NT1 可能是为了兼容某些老设备,但自定义配置里提升到了 SMB2.1。

还有一个细节:wins support = no 关闭了 WINS。这解释了我们在第一篇里发现的 nmbd 启动慢 1 分 30 秒的问题——nmbd 是 NetBIOS 服务,WINS 关了但 nmbd 可能还在尝试 WINS 相关的网络操作,导致超时等待。

1.6 共享配置:动态生成,按用户分文件

主配置里没有写死任何共享,而是通过 include 动态包含:

include = /etc/samba/users/%Y.share.conf

我们看一下这个目录:

$ ls /etc/samba/users/
1000.share.conf  1001.share.conf  1002.share.conf

每个用户(按 UID)有独立的共享配置文件。我们看用户 1000(dio)的配置:

[Photos]
        path = /vol1/1000/Photos
        browseable = yes
        available = yes
        writeable = yes
        hide special files = yes
        oplocks = yes
        hide unreadable = yes
        vfs objects = full_audit shadow_copy2 trim
        shadow:format = UTC%z-%Y.%m.%d-%H.%M.%S
        shadow:snapdir = /vol1/@snapshot/1000
        veto files = /._*/.DS_Store/.@#local/

[share]
        path = /vol3/1000/share
        ...
        vfs objects = full_audit shadow_copy2 trim
        shadow:snapdir = /vol3/@snapshot/1000

[团队文件-home]
        path = /vol2/@team/home
        ...
        hide unreadable = no
        vfs objects = trim_perms full_audit shadow_copy2 trim
        shadow:snapdir = /vol2/.zfs/snapshot

用户 1000 一共有 7 个共享,分布在不同的卷上:

共享名路径所在卷
Photos/vol1/1000/Photosvol1(NVMe SSD)
beta/vol1/1000/betavol1(NVMe SSD)
video/vol1/1000/videovol1(NVMe SSD)
share/vol3/1000/sharevol3(RAID0)
来自:百度网盘/vol3/1000/来自:百度网盘vol3(RAID0)
测试/vol3/1000/测试vol3(RAID0)
团队文件-home/vol2/@team/homevol2(ZFS)

重大发现:所有共享都支持 Windows "以前的版本"(VSS 快照)

每个共享的 VFS 模块里都有 shadow_copy2:

vfs objects = full_audit shadow_copy2 trim
shadow:format = UTC%z-%Y.%m.%d-%H.%M.%S
shadow:snapdir = /vol1/@snapshot/1000

shadow_copy2 是 Samba 的 VSS(卷影复制服务)模块,让 Windows 用户可以右键文件 → "以前的版本",查看和恢复历史版本。

注意快照目录的差异:

  • ZFS 卷(vol2):/vol2/.zfs/snapshot(ZFS 原生快照目录)
  • 非 ZFS 卷(vol1、vol3):/vol1/@snapshot/1000、/vol3/@snapshot/1000

这说明:飞牛在非 ZFS 的卷上也实现了快照功能,快照存在 @snapshot 目录下。不管底层是什么文件系统,都能提供统一的快照和 VSS 功能。这是飞牛存储的一个重要特性。

个人共享 vs 团队共享的差异

对比项个人共享团队共享(团队文件-home)
VFS 模块full_audit shadow_copy2 trimtrim_perms full_audit shadow_copy2 trim
hide unreadableyes(隐藏不可读文件)no(不隐藏)

团队共享多了一个 trim_perms 模块,说明团队空间需要更复杂的权限管理(多用户权限、部门权限等)。个人空间里用户看不到自己没权限的文件,团队空间里能看到所有文件但打不开没权限的——这是合理的设计,团队空间需要让成员知道有哪些文件存在。


二、NFS:当前未配置共享

NFS(Network File System)是 Unix/Linux 世界的标准文件共享协议。fnOS 的 NFS 配置在 /etc/exports:

$ cat /etc/exports
# /etc/exports: the access control list for filesystems which may be exported
#               to NFS clients.  See exports(5).
#
# Example for NFSv2 and NFSv3:
# /srv/homes       hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
#
# Example for NFSv4:
# /srv/nfs4        gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
# /srv/nfs4/homes  gss/krb5i(rw,sync,no_subtree_check)
#

只有注释,没有实际的共享配置。但 NFS 服务在运行(2049 端口在监听),说明是按需启用的——用户在 Web 界面创建 NFS 共享时,系统会动态写入 /etc/exports 并 reload NFS 服务。

NFS 和 SMB 的主要区别:

对比项SMB/CIFSNFS
起源微软Sun/Unix
主要客户端WindowsLinux/Unix
认证方式用户密码(tdbsam)基于 IP/主机名 + UID 映射
状态有状态无状态(NFSv4 之前)
端口4452049
功能丰富度高(权限、锁、打印)低(配置简单,性能好)

三、FTP:用的是 smbftpd,不是 vsftpd

FTP 是最古老的文件传输协议,现在用得少了,但很多老设备和自动化脚本还在用。fnOS 用的不是常见的 vsftpd 或 proftpd,而是 smbftpd。

smbftpd 是一个开源 FTP 服务器(作者 Wang, Chun-Pin),它的特点是支持 SMB 模式——可以复用 Samba 的共享配置和权限。配置文件在 /usr/trim/etc/smbftp.conf。

3.1 关键配置

Port 21
PassiveModePortRange 55536-55899
VirtualUserAuthMethod unix
RequireValidShell No
ChrootSet @     /fs/%U/ftp
SupportUTF8Client Yes
UsingUTF8FileSystem Yes
CharsetEncoding UTF-8
TransferLog /var/log/smbftpd.log
SecurityPolicy both
SSLCertFile /usr/trim/var/trim_connect/ssls/fnOS/1782808384/fnOS.crt
SSLKeyFile /usr/trim/var/trim_connect/ssls/fnOS/1782808384/fnOS.key
配置说明
Port 21FTP 控制端口
PassiveModePortRange 55536-55899被动模式数据端口范围(NAT 环境需要转发)
VirtualUserAuthMethod unix用 Unix 系统用户认证,不是虚拟用户
RequireValidShell No不要求有效 shell——nologin 用户也能登录 FTP
ChrootSet @ /fs/%U/ftp所有用户 chroot 到 /fs/用户名/ftp,只能访问自己的 ftp 目录
SecurityPolicy both同时支持明文和 SSL/TLS
SSLCertFile/SSLKeyFileSSL 证书,和飞牛互联(trim_connect)共用

3.2 几个值得注意的点

1. 认证和 SMB 统一

VirtualUserAuthMethod unix 表示 FTP 用 Unix 系统用户认证,和 SMB 用的是同一套用户。RequireValidShell No 表示即使是 nologin 用户(不能 SSH 登录的普通用户)也能登录 FTP。

2. chroot 隔离

ChrootSet @ /fs/%U/ftp 表示所有用户登录后都被 chroot 到自己的 ftp 目录,看不到系统其他部分。这是安全设计,防止 FTP 用户浏览系统文件。

3. SSL 证书统一管理

FTP 的 SSL 证书路径是 /usr/trim/var/trim_connect/ssls/fnOS/...,和飞牛互联(trim_connect)共用同一套证书。说明飞牛的证书是统一管理的,不是每个服务各自生成。

4. smbftpd 的 SMB 模式

smbftpd 有一个独特的功能:DefaultMode SMB,可以复用 Samba 的共享配置和权限。但当前配置里这个选项被注释了,默认是 Normal 模式。如果启用 SMB 模式,FTP 用户看到的共享和 SMB 用户完全一样,权限也一致。


四、WebDAV:飞牛自研服务

WebDAV 是基于 HTTP 的文件共享协议,适合跨网络访问和移动端使用。fnOS 的 WebDAV 是自研服务,配置非常简单:

[server]
        infinity = true
        max_sub_dirs = 10000
        http = true
        http_port = 5005
        https = true
        https_port = 5006
        cert = /usr/trim/var/trim_connect/ssls/fnOS/1782808384/fnOS.crt
        key = /usr/trim/var/trim_connect/ssls/fnOS/1782808384/fnOS.key
配置说明
http_port = 5005WebDAV HTTP 端口
https_port = 5006WebDAV HTTPS 端口
infinity = true支持无限深度目录
max_sub_dirs = 10000最大子目录数
SSL 证书和飞牛互联共用

WebDAV 的二进制程序应该是 /usr/trim/bin/webdav,配置文件只有几行,说明大部分逻辑是硬编码在程序里的。


五、四协议对比总结

协议实现方式端口认证方式配置文件飞牛定制程度
SMB/CIFSSamba(深度定制)445tdbsam + 系统用户/etc/samba/smb.conf + users/UID.share.conf★★★★★(4个VFS模块)
NFS内核 NFS2049基于 IP/主机名/etc/exports(动态生成)★☆☆☆☆
FTPsmbftpd21 + 55536-55899Unix 系统用户/usr/trim/etc/smbftp.conf★★☆☆☆
WebDAV飞牛自研5005/5006未知/usr/trim/etc/webdav.conf★★★★☆

统一认证:四个协议都用同一套系统用户,没有各自维护用户数据库。SMB 用 tdbsam 存密码但和系统密码同步,FTP 直接用系统用户认证。


六、用户权限体系

搞清楚了文件服务,我们来看用户权限——这是 NAS 安全的核心。

6.1 系统用户

$ cat /etc/passwd | grep -v nologin | grep -v false
root:x:0:0:root:/root:/bin/bash
sync:x:4:65534:sync:/bin:/bin/sync
postgres:x:107:113:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
dio:x:1000:1001::/home/dio:/bin/bash

可登录的系统用户只有 4 个,其中只有 dio(UID 1000) 是 Web 界面创建的用户。

但注意:我们之前在 /fs/、/vol2/、/vol3/ 下都看到了 1000、1001、1002 三个用户目录,说明系统里有三个用户。1001 和 1002 被 grep -v nologin 过滤掉了——它们的 shell 是 /usr/sbin/nologin,不能 SSH 登录。

结论:飞牛创建的用户,管理员才有登录 shell(/bin/bash),普通用户是 nologin(不能 SSH 登录)。 这是合理的安全设计——普通用户只能通过 Web、SMB、FTP 访问文件,不能登录系统命令行。

6.2 用户组

$ cat /etc/group | grep -E '100[0-9]'
Administrators:x:1000:dio
Users:x:1001:
G1:x:1002:dio,D
组名GID成员说明
Administrators1000dio管理员组
Users1001(dio 是主组)普通用户组
G11002dio, D用户自定义组

看当前用户 dio 的信息:

$ id dio
uid=1000(dio) gid=1001(Users) groups=1001(Users),1000(Administrators),1002(G1)
  • UID 1000,主组是 Users(GID 1001)
  • 附属组包括 Administrators(管理员)和 G1(自定义组)
  • Administrators 的 GID 是 1000,比 Users 的 1001 还小,说明管理员组是系统先创建的

6.3 Samba 密码数据库

$ ls /var/lib/samba/private/
netlogon_creds_cli.tdb  passdb.tdb  secrets.tdb

Samba 的用户密码存在 passdb.tdb 里(tdbsam 后端),和系统密码(/etc/shadow)是分开的,但通过 unix password sync = yes 保持同步。

也就是说,Web 界面修改用户密码时,会同时改:

  1. Linux 系统密码(/etc/shadow)
  2. Samba 密码(passdb.tdb)

6.4 用户信息主存储:PostgreSQL

我们在系统里找了一圈,没有找到用户相关的 SQLite 数据库:

$ find /usr/trim -name "*.db" -o -name "*.sqlite"
/usr/trim/var/downloadcenter/downloadcenter.db
/usr/trim/var/minidlna/files.db

只有下载中心和 DLNA 的数据库,没有用户数据库。而系统里有 PostgreSQL 15 在运行(postgresql@15-main.service),且只监听 127.0.0.1:5432(不对外暴露)。

结论:用户信息、权限配置、共享设置等主要数据存在 PostgreSQL 里。 由于我们没有 postgres 用户的密码,无法直接查看表结构,但可以通过 Web 界面操作 + 观察文件变化来推断。

6.5 trimacl:飞牛自研的统一权限机制

在第二篇存储架构里我们提到过,飞牛给 ZFS 打了一个叫 trimacl 的内核补丁,ZFS 的挂载参数里有这个选项:

trim_6c71e3b3-... on /vol2 type zfs (rw,noatime,xattr,trimacl,casesensitive)

trimacl 是飞牛自研的 ACL(访问控制列表)机制,它的核心作用是:跨文件系统统一权限。

普通 Linux 系统里,ext4 用 POSIX ACL,ZFS 用自己的 ACL,NFSv4 又是另一套 ACL,各不相同。飞牛的 trimacl 把这些统一起来——不管底层是 ZFS 还是 ext4,都用同一套权限模型,Web 界面设置的权限能在所有卷上生效。

在 SMB 层,trimacl 通过 trim_perms VFS 模块对接——Samba 的权限请求被 trim_perms 拦截,转换成 trimacl 的权限检查。

6.6 用户创建流程推测

基于以上信息,Web 界面创建用户时的流程大概是:

Web 界面创建用户
    ↓
调用 /usr/trim/bin/useradd(飞牛自己的 useradd,不是系统的)
    ↓
1. 创建 Linux 系统用户(/etc/passwd、/etc/shadow、/etc/group)
   - 管理员:shell = /bin/bash
   - 普通用户:shell = /usr/sbin/nologin
2. 创建 Samba 用户(passdb.tdb),设置密码同步
3. 在 PostgreSQL 里写入用户信息和权限配置
4. 在各存储卷上创建用户目录(/vol1/UID/、/vol2/UID/、/vol3/UID/)
5. 设置 trimacl 权限
6. 生成 Samba 共享配置(/etc/samba/users/UID.share.conf)
7. reload Samba 服务

七、端口监听全景

最后看一下所有文件服务和管理端口的监听情况:

$ ss -tlnp | grep -E '2049|21|22|80|443|5666'
LISTEN 0  511  0.0.0.0:5666   ← fnOS Web 管理界面(HTTP)
LISTEN 0  511  0.0.0.0:443    ← HTTPS(重定向到 5667)
LISTEN 0  128  0.0.0.0:22     ← SSH
LISTEN 0  32   0.0.0.0:21     ← FTP(smbftpd)
LISTEN 0  511  0.0.0.0:80     ← HTTP(重定向到 5666)
LISTEN 0  4096 0.0.0.0:8080   ← 内部服务
LISTEN 0  64   0.0.0.0:2049   ← NFS

加上 WebDAV 的 5005/5006,SMB 的 445,完整的端口列表:

端口服务
22SSH
21FTP(smbftpd)
80HTTP(→ 5666)
443HTTPS(→ 5667)
445SMB/CIFS
2049NFS
5005/5006WebDAV(HTTP/HTTPS)
5666/5667fnOS Web 管理(HTTP/HTTPS)
8080/8005内部服务

八、本章小结

这一篇我们深入解析了 fnOS 的文件服务和用户权限体系,核心发现:

  1. SMB 是飞牛定制最深的协议——加了 4 个 VFS 模块(trim_perms、full_audit、shadow_copy2、trim),共享配置动态生成,所有卷都支持 Windows VSS 快照
  2. FTP 用的是 smbftpd,不是常见的 vsftpd,支持 SMB 模式复用共享配置
  3. WebDAV 是飞牛自研,配置极简
  4. NFS 按需启用,当前未配置共享
  5. 四协议统一认证,都用同一套系统用户
  6. 用户权限核心是 trimacl——飞牛自研的跨文件系统统一 ACL,通过 trim_perms VFS 模块对接 SMB
  7. 用户信息主存储是 PostgreSQL,系统用户和 Samba 密码是衍生数据

下一篇我们将进入 Web 后端架构——解析 Nginx 的反向代理规则、30+ 微服务的路由映射、Unix Socket 通信机制,以及飞牛自研的 Nginx 模块。这是二次开发最核心的部分,敬请期