我是一个有存储癖好的人。从我 2014 年拥有自己的第一台电脑开始,产生过的所有数据、记录和存档都被我携带至今。在这期间陆陆续续换过 3 台电脑 4 台手机,每次更新设备都要花大量的时间去做数据迁移和合并,尤其是阿龙,聊天记录从我最开始的 1+一代,一路迁到现在的 iPhone ,总容量高达 140+GB ,每次换手机迁移都要浪费自己 7 个小时以上的时间。然而,长久以来自己的数据都是放在单点系统中,无非就是从一个硬盘到另一个硬盘,很难想象这种单点模式坚持了将近 10 年却没有产生一些重大的数据灾难。
(其实是有过的,12 年的时候我还在用家里的电脑,根据网上的一些教程在试玩 Windows 的软链接和硬链接,然后我给自己的资料文件夹建了一个硬链接,再把这个硬链接直接 Shift+Delete 删除,结果是反应过来按下取消键的时候我的东西已经少了将近一半……不过那个时候年龄还太小,数据并没有什么多大的价值)
我现在的职业是一名 DBA ,为 GaussDB 工作。对这种大型的分布式数据库系统的了解越多,越能够体会到我自己个人的数据存储方案可靠性是有多差,再加上自己现在电脑里的那块 HC320 8TB 都快被我下载的各种各样的东西填满,自己又攒下了一点钱,所以决定在双十一给自己搭一套 NAS 。
在问过身边组 NAS 朋友的经验,以及权衡各种情况之后,我决定入手绿联的 DX4600 Pro 。原因大概有以下那么几个点:
不过这篇文章并不是什么开箱、分享、功能介绍的软文。绿联 UGNAS 的这些文章网上遍地都是,也不差我一个。这篇文章我要来讲一些硬核一点的东西,包含你在公网甚至绿联论坛都找不到的、独此一家的一些系统分析和工具教学。
在开始之前我想要着重、着重感谢一下绿联私有 DH2600 、DX4600 、DX4600+这些产品的老前辈用户。我到手的时候固件已经是最新的 v4.7.0 ,我这两个星期的体验后,实在很难想象这些老用户们早期系统是如何坚持下来的,是他们在一无所有的时期对绿联的支持与付出才让它发展到如今这个勉强可用的系统,并且仍旧有非常多的问题,这些老用户的地位堪比华为寒意传递时期还愿意掏 7999 买 P50 、P60 的铁血花粉,Respect !
如果绿联私有云团队真的会在各大社区听取用户意见的话,那他们看完这篇文章我应该会被封号吧?
绿联的宣发口径其实非常鸡贼,到现在他们依旧把自己的产品线称作“私有云”而非“NAS”,它的产品定位和体系确实和传统意义上的 NAS 有所不同。具体来讲:
这个东西放在我的家里,我家有 4 口人,各自使用 DX4600 Pro 的感觉就像是 4 个合租在一起的陌生人一样。每个人手机上都登录着自己的“XX 云网盘”,管理自己的数据,只是他们恰好都存在这台 DX4600 Pro 里面罢了。
从我在网上搜集到的资料来看,这台 NAS 的 SSH 权限大概经历了 3 个阶段,一开始是 Docker 提权,然后是网页端请求抓包,现在 v4.7.0 版本的固件已经完全开放了 SSH 功能,仅需要管理员打开设备管理-调试功能,验证短信之后会生成一个临时有效期 3 天的密码,依靠这个密码直接登录到 NAS 的 922 端口即可,用户是 root 。
至于 SSH 工具什么的不需要再教,VSCode 、Xshell 、Tabby 等软件随处可见。
来自绿联云技术支持的温馨提示
您好,目前最新固件已支持用户开启调试服务哟,但是绿联私有云系统是在特定的环境和配置下进行测试,如果贸然进行底层系统的修改会破坏系统完整性,从而导致系统运行不稳定和其他不可预测的结果。
温馨提示:
①不建议个人进行 SSH 的操作,由于个人操作导致的异常,绿联私有云无法提供技术服务; ②由于个人 SSH 操作导致的异常问题,类似系统崩溃/宕机,需要自行支付费用进行售后维修。
在购买之前我已经有所耳闻,这个逆天的 UGOS NAS 系统用的是 OpenWrt ,一个面向嵌入式设备的残核 Linux 。配套 shell 是 Busybox+ash ,Debian 系的相当多工具和内核功能在这是没有的,比如 sudo 、getent 、file ,尤其是 systemd 。
不过在我看来,使用 OpenWrt 有可能唯一的好处是,这台机器背面是有 Reset 键的,除非手贱折腾引导,那么系统绝大部分时候人为弄出的错误可以通过长按 Reset 键进行 Hard Reset 恢复出厂解决。在我使用这台机器的两个星期里,就有一次因为我不小心打了不兼容的 kernel mod 导致系统崩溃,机器都开不起来,官方在网站上根本没有提供任何固件包,最后通过长按 Reset 重置系统救了回来。
既然用的是 OpenWrt ,那么必然就会有 opkg 包管理器。UGOS 的 OpenWrt 是自编译系统和内核,因此只挂载了 Snapshot 源,通过 opkg 安装的绝大多数包都会因为内核 fingerprint 不匹配导致安装中断,需要使用--force-depends 参数强制安装。
当然,我们可以编辑/etc/opkg/distfeeds.conf 添加源,但是源的软件兼容性有一些问题。通过外部引入packages-22.03
源安装的所有包都无法执行释放到/usr/*bin 下的二进制可执行文件,会提示Not found
/No such file or directory
。
这个问题我花了大概 3 天的时间尝试去弄明白为什么,最后在 V2EX 论坛一位叫做 listenerri 的用户在其它 Linux 开发的帖子里提到了关键点:
安装下来的二进制可执行文件在系统目录里是真实存在的,使用 which 语句也能精确定位到可执行文件的信息。那么出了问题的就不是程序本身,而是程序的依赖。我们通过strace
跟踪运行程序时的调用堆栈,ldd
检查程序运行依赖库,结果会发现所有自行安装的程序都以错误ENOENT
退出,ldd
检查得知所有自行安装但无法运行的程序都缺少一个库:libc.so
libc 是 Linux 系统最基础的 C 运行库,是个正常的系统都应当编译时就携带。我一开始以为是我之前弄炸内核强行 reset 系统导致的意外丢失,跑去问技术支持,得到的答复是,他们的系统镜像“编译时就没有这个库”。
我们可以通过以下命令进行验证:
ll /lib/libc* # Overlay 级别/lib 搜索
find / -name "libc*" ! -path /mnt/dm-0/ # 全盘搜索,硬盘区除外
find /rom -name "libc*" # 系统镜像层搜索
然后会发现真的没有。
根据 listenerri 的说法,在 Genaral x86_64 Linux 系统里,
一般情况下 Linux 系统具体小版本的 so 库文件都是未带版本号的 so 库文件的原始文件
执行如下命令创建 libc.so.6 到 libc.so 的符号链接:
cd /lib/ ln -sf libc.so.6 libc.so
按说是立即生效,不行就重启试试
对 Openwrt 是无效的。Openwrt 是一个面向路由器等低容量 ROM 低功耗设备的 Linux 分支,它的很多系统机制都是以牺牲通用性为前提尽量地降低系统的资源占用,包括包管理:绝大多数在 opkg 发行的应用程序会把所有的底层库抽掉,进而使用系统环境提供的动态链接库,以节省空间,所以系统一旦库出现问题会导致大面积的程序失控。
libc.so
作为最底层最基础的库,对于用惯了 x86 计算机的我们来说,从同 CPU 甚至是同 CPU 架构的系统中直接 copy 一个过来也能用是很符合直觉的,因此我就这个问题去 Openwrt 论坛问了一下,核心开发者给我的解答如此:
libc.so 对 x86_64 的 Openwrt 设备是通用的吗?
不是的,尤其是在涉及供应商提供的固件时(他们似乎选择了非默认的 glibc 构建,而不是 OpenWrt 默认使用 musl )。即使在不同版本的 OpenWrt 之间也不存在二进制包的兼容性(更别提 libc ),当涉及到第三方或私有构建时,所有的可能性都不存在。
没戏。我们想要安装一些软件时,最好期望它在别的 release 渠道有面向 General Linux System 的二进制包,因为他们大多数都内部集成了所有的运行库,不需要依赖操作系统提供,否则寄希望于 opkg 什么都跑不起来。
坦白来讲,我在网上早期了解的时候发现 DX4600 (非 Pro 版)用的是 ext4 文件系统,当时已经萌生了如果到手发现还是 ext4 我就退货换 QNAP 的念头。但是好在到手查阅了 4600Pro 的说明书后发现这台新机器已经用上了 XFS 文件系统,不奢求这类新派 NAS 厂商玩得明白 Btrfs 和 ZFS ,XFS 相比 ext4 已经好很多,还算是能够接受。
UGOS 目前在创建阵列的时候不支持指定文件系统,支持的 raid 有 0, 1, 5, 10 ,并且在创建好 Raid 后会立马进行全盘校验。我自己买了 4 块希捷 X18 16TB ,代表做好存储空间后,系统会全盘满速读整整 1 天时间,在这期间基本上干不了任何事情。
通过 parted print all 能够看到,这台 NAS 的系统数据存在一颗三星 BJTD4R 的 EMMC 上,容量 32GB ,分区格式 ext4 ,一旦搞坏 boot 是真的要返厂的,魔改党建议尽量别碰 boot 相关的东西。同时,EMMC 使用的是 Openwrt 特有的 ROM+Overlay 机制,除非闪存出现了物理级的错误,无论对系统进行什么改动都伤不到原厂的镜像分区( mmcblk0p4, mounted at /rom ),把 Overlay 层一清空又是崭新出厂
建立好存储区后查询得到的 Raid 信息:
值得一提的是,我创建这个存储空间时漫长的 CC (一致性校验)进行到 48%左右系统被我玩崩溃了,不得不重置。重置结束后存储空间依旧能够使用。我询问技术支持,说这种情况还要继续校验吗?技术支持说要的。我问入口在哪里?他说没有入口,系统会每 3 天自动执行。但是截至目前 NAS 已经跑 7 天了,我依旧没有见到系统有任何准备做/在做 CC 的痕迹。
这台机器和真正”生产力“有关的所有东西都在一个叫”网络服务“的应用下,你可以操作开启 SMB 、AFP 、FTP 、WebDAV 和本地帐号登录,那么考虑到因为 AFP 和 FTP 已经是过时的网络协议,四舍五入这台 NAS 只支持 2 种主流网络协议,不支持最专业的 iSCSI 。
并且其中有一个很奇怪的点是,想要开启任意一个网络服务,管理员必须,必须建立一个”账号“,并且这个账号与什么登录绿联云的手机号是无关的,从属于管理员名下,使用的是管理员的存储空间。
同时,这个”账号“修改密码必须要输入旧密码,一旦忘记密码就没办法修改,但是可以直接通过”修改账号“建立一个新的(甚至是同名的)账号强行把忘记密码的旧帐号顶掉(伏笔,后面会知道原因)
SMB 服务是我对这台 NAS 系统了解的突破口。我就是依靠 SMB 的配置文件定位到了文件与物理硬盘之间的对应关系。通过cat /etc/samba/smb.conf
获得:
在这里,SMB 开放的路径就是 UGOS 对应的存储空间,并且仅授权给我们创建的”账号“使用。同时,UGOS 依靠 smb4 提供了删除文件的回收能力,删除的文件会被移动到一个中文的隐藏文件夹中。
我们都知道,SMB 在传输速度高于 2.5Gbps 后对 CPU 的资源消耗显著,速度达到 10Gbps 后多数普通家用 CPU 无法承担。与此相比,NFS 通过直接寻址的方式提供文件传输,大幅度降低 CPU 开销和延迟,是下一代的网络文件传输协议,对于工作室和重度生产力用户而言是最强大的 NAS 协议选择。
NFS 在 Linux 已经普及,Windows 平台在 Pro 以上 1607 版本以后原生支持 NFS Client ,需要在”启用或关闭 Windows 功能“中手动开启。
我在购买这台 NAS 之前曾经广泛地搜索了相关的软文和评测,所有的文章都提到这台东西支持 NFS ,放心买回来才发现事情有坑:
这台机器只支持做 NFS Client 端,即挂载其它 NFS 网络位置,但是并不支持 NFS Server!
经过深入的调查发现,UGOS 系统已经安装好了 NFS 相关所有的 kernel mod 、驱动、服务以支持 NFS Client 运行,但是唯独把[内核]nfsd
、[服务]nfs-kernel-server
、[内核模块]kmod-fs-nfsd
抠掉了,说明他们是故意屏蔽了 nfsd 功能,具体原因我问客服只得到”不方便透露“的解答。
所以我就想自己尝试把kmod-fs-nfsd
打上去然后安装nfs-kernel-server
。由于 UGOS 编译选用了 Snapshot 路线,22.03 版本的 snapshot kernel 已经刷到了 150 多。查询本机得知,kernel 版本为5.10.120-1-fa9766b60e358499f4a6b9ef8f360e07
,即使他们使用官方内核,snapshot 编译记录也早已被删除。
因此,本着”反正大家都是 x86 ,兼容性强得很,直接强打内核补丁试试“的想法,我去找了个内核版本近似的 release (具体来说,是22.03.0-rc4
,内核版本5.10.120-1-3136c8a0893fac7c59d0a669ad504887
),下载kmod-fs-nfsd
的包,然后通过篡改内核 hash 的方式用 opkg 强制安装……
结果,系统当即就炸了,所有东西全部宕机无响应,蜂鸣器报警,重启发现根本开不了机,HDMI 无输出。本来我已经做好了送回厂家刷机的决心,结果看 PC 端的提示才发现这机器有 Reset 键,照着说明拿卡针捅到重启,还真复活了。
那怎么办呢,手动安装 nfsd 的想法就此作罢,现阶段只能等官方更新了。论坛的建议区几百条帖子鲜有官方的人回答,并且据消息说官方在年底的任务是用 Debian 重构 UGOS 系统……我能信吗?
我对绿联云一直宣传的自动 P2P 内网穿透方案很感兴趣。不是因为它是什么新鲜事物,而是因为它是第一个大规模宣传自己穿透是基于 P2P 而非中转的(也有可能某个竞争对手的宣发预算不够,没传到我的微博信息流里)。作为一个 ZeroTier 和 Tailscale 的重度使用者,深知 P2P 打洞这个事情在当前公网环境下的重要性,以及对普通用户而言的驱动力——让他们享受 P2P 的成果是很乐意的,但是一旦要操作一些他们不认识的工具,即使是 Tailscale 这种简单到只要安装客户端再登陆一下并且保持开启的软件,普通用户就不乐意了。
绿联私有云客户端的连接和穿透仅限 APP 内,但是不需要打开任何的∨PN ,直接连接,看看库存影片什么的已经足够方便。根据实地测试,绿联云内置的远程穿透能力尚可(至少在同一个城市里,跨 IPC 以及多层 NAT 内网并不是什么问题),但是穿透的速度非常慢。多数时候可能要等待 1 到 2 分钟才能够远程连接到家里的 NAS 。有这个时间换 Tailscale 东西已经下载好了。
在 NAS 帮助教程里日志中心的文章有句话特别有意思,说127.0.0.1
是来自于 P2P 的连接,说明 UGNAS 的 P2P 方案应当不是类似上面两位那种基于 Tun 虚拟组网隧道的。
在一次查进程的时候偶然注意到运行的进程中有一个名为 p2px 的进程,来自于/data/nas_server 文件夹——这是 UGOS 服务模块存放的地方,所以我基本上锁定这个模块用于负责内网穿透:
这个进程运行的时候甚至会上报本机的 SN ,于是围绕 P2P 进行全盘搜索,能够找到 p2px 的配置文件、日志、相关依赖和二进制可执行文件:
p2px 组件使用了libmosquitto
库,这是一个 eclipse 开源的 mqtt broker ,推测是拿 MQTT 用于 STUN 。同时,在 conf 文件夹中找到了关于 p2pTunnel 的若干配置文件,显示其会指向ugreengroup.com
域名,与我在 QX 的网络活动观察到的结果一致:
配置文件中的 AccountCode 直接揭晓了答案,使用了 pptun 的方案,顺藤摸瓜搜过去,是一家名为深圳穿透科技的公司的产品,这家公司从头到尾只做一件事,就是搞 P2P 穿透的各种生态。其中 pptun 是 PaaS 级别的,也提供 SDK 二开和自部署。
通过查询 p2px 的日志,穿透信息确实由该公司的pgLibTunnel
和pgLibConnect
提供,至于这个ugreengroup.com
域名是绿联自部署还是直接解析到 pptun 的 PaaS 就不得而知了,但很大概率是直接用了 pptun 的服务。
我推测这台 NAS 的内网穿透是以设备 SN 作为唯一标识符的,客户端的连接请求在 MQTT 队列中传播,MQTT 充当 STUN ,p2px 则监听面向自己 SN 的连接请求,交换 IP 信息和信令,直到双方逐步穿透成功,连接设备。pptun 即使穿透失败也能够用 Tunnel 中转维持连接,但是我怀疑,连接耗时 1-2 分钟的原因是,APP 直到能够成功建立 P2P 连接才允许进入主页,而在这个过程当中中转隧道已经早就建立好了,但毕竟服务器跑中转流量还是耗钱嘛,所以不让在中转模式下使用。
(以上内容只是推测,不代表真实情况,因为我也没有去抓包分析)
这部分知识我是通过 Tailscale 团队的一篇文章《 NAT 穿透是如何工作的:技术原理及企业级实践》学习到的,真的很有意思,我很推荐大家都去读一读。
我通过 SMB 的配置文件获取到了存储空间的物理目录,进而能够一探究竟:
存储空间下的所有文件都存放在 raid 阵列中名为.ugreen_nas 的隐藏文件夹,并且划分了好几个区域。我认为掌握了这些信息,即使在 NAS 机体损坏的情况下,我们也依旧有希望能够取出硬盘中的数据。经过我的测试,这些文件夹大概的作用如下:
6 位数数字的文件夹是每个用户自己的存储空间
1 是公共空间
2 暂时未知,应该是某个服务,我目前还未使用过”共享空间“,可能是它
3 是回收站
6 是 docker 数据区域
7 是 hls cache ,怀疑与云影院/在线播放器有关
ai_sevr 存储相册的人脸识别数据
album_sevr 存储相册其它信息,包括索引、元数据等
category_sevr 存储用户名下文件分类数据,就是”文件管理“中左侧分类查看“图片、视频、文档、压缩包……”的索引
data/data 存储 nas 套件部分服务数据,比如说全局搜索、日志中心、云音乐、壁纸,并且按用户分文件夹存储好
UGOS 的权限模式非常的奇葩,我在一个正常的 Linux 系统上从来没有见过这样的用法,并且这个系统软件的很多功能缺陷都是由权限模式导致的。
我把 UGOS 面向用户的服务套件叫做nas_server
,暂且把它当作一个 service 级别的东西,那么我们有以下几个结论:
套件的所有用户事务(登录、权限管理、软件数据隔离、存储区区分等)全部交由 nas_server 托管,与 Linux 系统的 user-group 机制脱钩
nas_server 自始至终在 UGOS 中以 root 身份运行
每个登录到绿联私有云 APP 、并且连接到某台 NAS 上面的用户,会被 nas_server 单独分配一个用户 uid 数字,nas_server 依据此数字来管理用户对应的物理存储、维护用户私有数据,并且这个 uid 对用户不可见
(注意,这里说的 uid 和 Linux user 的 userid 没有任何关系,我们后续会将这个 id 称为ug_uid
)
nas_server 在文件管理时,只负责目录级别的可见性,不会负责 rwx 权限。严格来说,整个系统都没有对 rwx 做任何管理,默认都是 777 。
目录级别的可见性,指的是它只会把你用户在/mnt/dm-0 存储空间中对应的文件夹单独展示出来,而不管文件夹中是否有任何权限不对、owner 不匹配的内容
nas_server 对文件的错误权限有恢复机制,当用户尝试通过套件访问存储空间里不属于它/权限不足的文件时,文件的权限会被强行修改为 root 777
测试样例:root 登录 ssh 创建一个文本文件,将其 owner 修改为某个别的用户,权限修改为 755 ,移动到某个共享成员的存储空间内。成员通过套件内置的金山 WPS 打开文本后在 ssh 窗口 ls -l ,会发现文件被重置为 root 777
这个问题是从我邀请家庭成员进入 nas 后探索目录时发现的。一开始我以为 nas_server 管理/mnt/dm-0 是简单地把所有文件都设为 root777 ,却惊奇地发现好像其他成员的文件夹 owner 并不一样,他们与文件夹同名,对应一串长长的数字,具体而言是ug_uid+0000
。凭借着我对 Linux 浅薄的经验,去/etc/passwd ,以及其他地方找了很久都没有找到 username ,经过了大量的实验和思考之后我认识到了一件事情:
只有管理员开设的“网络服务”中的“账户”在 Linux 下是真实存在的,其它用户在 Linux 系统中不存在!
当你开通网络服务的账户后,你自己的 ug_uid 才在 Linux 系统下有真正的实体 user 对应,uid 和其他用户一样,都是ug_uid+0000
,而包括 SMB 在内的大量功能,需要依赖 Linux 的实体用户运行。因此,只有管理员能够开设 SMB ,并且出于隐私原因 SMB 也只能提供管理员的私人空间和公共空间。幸亏我家四口确实只有我在用 SMB ,多一个有需求的人,立马就要退货。
所有想要折腾绿联 NAS 的人都必须记住这个结论,这个结论可以解释后面非常多不合理的地方。
nas_server 会自动将其它用户创建的文件 owner 设置成一个**没有实体用户对应的ug_uid+0000
**,以区分存储区 owner ,因为 Linux 系统是可以强制用 id 数字指派文件 owner 的。然而对文件指派 owner 似乎没有任何用处,可能是给内部其它服务进行区分,因为上面提到了,“文件管理”APP 只根据目录提供内容,根本不管 owner 是谁,错了就重置成 root 777 。
这套容错机制可以保证用户通过套件使用绿联私有云的时候不会出现奇怪的权限问题,但是对于 SMB 等严格遵守 Linux 用户权限规范的服务来说并非如此。举个例子,我现在使用 root 在自己的存储空间里创建了一个文本并填充了内容,将其权限改写成 755 ,通过 SMB 访问文件,修改并保存,会发现没有保存权限,记事本弹出“另存为”窗口。
这种情况会更多出现在某些 docker 镜像中,他们支持通过 PGID 和 PUID 环境变量指定 bind volume 产生文件的用户映射,并且假设默认的 permission mask 是 022 的话,产生的数据和配置文件通过“网络账户”登录的 SMB 是没有修改权限( 755 )的。
很显然,这套权限模式经不起系统级的全面开放访问,所以聪明的绿联产品经理想出了一个解决方案,那就是:
禁止非管理员使用 docker 和 smb 就好了,再在 docker 镜像管理页面里加上一条免责声明,出了问题不怪我哦。
在 UGOS ,每个服务组件都有自己要忙的事,他们对外提供了各自的服务端口供套件内部分别访问。所以他们写了一个极其、极其、极其冗长的 Nginx 配置文件,把所有 web 地址、端口、socket 、url 跳转聚合起来,反向代理到自己的 web 登陆端口(也就 9999 ),活生生用 Nginx 写出了一个 API Gateway 。
可以理解,把所有端口聚合在一起方便内部服务统一调用,避免访问自己东西的时候配置端口东一个西一个,而且内网穿透用的 P2Px 程序可能也难远程实现多端口访问。
问题是,这些套件(除了迅雷和百度云等第三方)怎么全都在监听0.0.0.0
而非localhost
呢?而且我在iptables
和/etc/config/firewall
也没看到拦截来自外网对这些服务端口的请求,猛地一看这些端口好像还是能公网访问是怎么回事呢?一旦有心之人掌握了服务组件的接口格式,他们是不是能够直接跳过 9999 端口的 Auth Header 校验,往我的设备发 reset 请求?我不是在渲染焦虑,而是连我这种曾经把自己机器放到 DMZ 公网上被打了 2 个 T 流量的、对网络安全毫无概念的人都感觉这样的处理方式有安全隐患,需要一个确认。
另外,用户远程访问 web 端 9999 ,所有的静态资源都被标记为no-cache, no-store
禁止缓存,导致用户每次刷新和访问都要从上行速率本就不高的家宽从头加载你那些 js 库和媒体,这又是何意啊?
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.