OpenList 文件共享:从 Copyparty 迁移与去指纹加固
摘要
文件共享站 file.028000.xyz 原来跑的是 Copyparty,用户一句话:"太丑了,换。"于是有了这次迁移:CT701 上部署 OpenList v4.2.6(systemd 自启),三个存储卷(/NAS920 读写、/维保管理 只读、/归档 只读),nps 隧道公网化,nginx 全套去指纹(meta、版本号、外链本地化、隐藏游客入口),登录接口限流 + fail2ban。这篇把迁移决策、OpenList 的存储模型、品牌隐藏的完整清单、以及"admin set 被忽略"这个大坑一次写清楚。
目录
- 一、为什么迁移:颜值即正义
- 二、部署:CT701 上的 OpenList
- 三、OpenList 的存储模型:Local、云盘与聚合
- 四、三个存储卷:读写只读要分清
- 五、用户与权限:admin、nas 与访客
- 六、公网化:nps 隧道 + nginx
- 七、品牌隐藏:nginx 抹指纹的完整清单
- 八、安全加固:限流 + fail2ban
- 九、踩坑记录
- 十、总结
一、为什么迁移:颜值即正义
原来的文件共享是 Copyparty,功能没问题,但界面实在拿不出手。用户的原话是"太丑了",这个理由充分且必要——文件站是会分享给别人用的门面,颜值就是生产力。选型 OpenList(原 Alist 的社区延续),界面现代,功能覆盖本地存储、云盘聚合,一个顶多个。
迁移前先做清理:Copyparty 彻底卸载,配置文件备份留档。旧服务不留尾巴,这是基本 hygiene。
二、部署:CT701 上的 OpenList
OpenList 跑在 CT701(LXC 容器)上,版本 v4.2.6,安装在 /opt/openlist,用 systemd 管理自启:
# systemd 服务(示意)
# /etc/systemd/system/openlist.service
[Service]
WorkingDirectory=/opt/openlist
ExecStart=/opt/openlist/openlist server
Restart=always
WorkingDirectory 必须设对,这是后面大坑的根源(见第九节)。OpenList 监听 5244 端口,nps 隧道打到 192.168.0.122:5244(CT701 的内网 IP)。
三、OpenList 的存储模型:Local、云盘与聚合
OpenList 的核心概念是"存储"(Storage):它本身不存文件,而是把各种后端(本地目录、云盘、WebDAV、S3……)挂载成统一的虚拟文件树对外提供。这个设计决定了它的用法:
| 存储类型 | 说明 | 本次用到的 |
|---|---|---|
| Local | 本地目录,直接挂宿主路径 | 三个卷全是 Local |
| 云盘(Google Drive 等) | OAuth 接入云盘 | 待办:/影视 卷计划接 Google Drive |
| 聚合/别名 | 把多个存储拼成一棵树 | 暂未用 |
理解这个模型,后面的"三个卷"就好懂了:它们都是 Local 类型的存储,区别只在挂载路径和读写权限。以后要加 Google Drive(/影视 卷的规划),就是新增一个云盘类型的存储,不影响现有三个。
四、三个存储卷:读写只读要分清
| 卷 | 挂载路径 | 类型 | 权限 | 说明 |
|---|---|---|---|---|
| /NAS920 | /srv/nas920 | Local | 读写 | 主力文件区 |
| /维保管理 | /srv/weibao | Local | 只读 | 挂载时加 ro,应用层再加访问密码 |
| /归档 | /srv/archive | Local | 只读 | 挂载时加 ro,应用层再加访问密码 |
只读卷做了双层保护:挂载层 ro(即使应用被攻破,底层也写不进去)+ 应用层访问密码。/维保管理 和 /归档 的访问密码是 p_sub,密码用户自设,不记录明文。
权限设计的原则:默认只读,读写是例外。/NAS920 需要上传所以给读写,另外两个是资料库,只读就够了。权限给多了就是攻击面。
五、用户与权限:admin、nas 与访客
| 用户 | 权限 | 说明 |
|---|---|---|
| admin | 管理员 | 已改密,密码用户自设 |
| nas | 日常使用 | base_path=/,去掉了"免密码访问"位(8189=8191 去掉 bit1),日常用这个 |
| nasadmin | — | 已删除,不留多余账号 |
| 访客 | 默认禁用 | 未登录访问直接 401 |
账号 hygiene:admin 改密、nas 去免密码、nasadmin 删除、访客默认 401。每个账号都要有存在的理由,多余的就删。访客 401 而不是 403,是为了不泄露"这里有个文件站"的细节(见品牌隐藏)。
六、公网化:nps 隧道 + nginx
链路:
公网用户 → https://file.028000.xyz
→ VPS 443(nginx:去指纹、限流、TLS 1.2/1.3)
→ nps 隧道(VPS 端口 → 192.168.0.122:5244)
→ CT701 OpenList
nps 侧任务 9:VPS 端口 → 192.168.0.122:5244。nginx 反代配置和全家其他站点同构:HTTP 301 跳 HTTPS、TLS 仅 1.2/1.3、登录接口限流。
七、品牌隐藏:nginx 抹指纹的完整清单
这是用户明确提的要求:file.028000.xyz 不能暴露任何构建它的软件信息,降低被针对性扫描和爆破的风险。攻击者看到"Powered by OpenList v4.2.6",就能去搜这个版本的 CVE;看不到,就只能盲扫。品牌隐藏不是"安全的主要手段",是"让攻击者多花成本"的纵深一层。
完整清单:
| 指纹点 | 处理方式 |
|---|---|
| HTML 里的 generator meta 标签 | nginx 抹掉 |
| 页面上的版本号 | 抹掉,不显示 |
| res.oplist.org 外链 | 本地化,不向官方域发请求 |
| 游客入口 / 忘记密码入口 | 隐藏 |
| 页脚 | 按用户要求替换为自定义内容 |
| HTTP 响应头 | 抹掉服务器指纹 |
残留:window.OPENLIST_CONFIG 这个 JS 全局变量还留着。它是前端运行必需的,硬抹会把页面搞坏。目前的取舍是:能抹的都抹了,抹了会坏功能的留着。安全是成本收益权衡,不是洁癖。
验证方法:curl 取首页 HTML,grep "openlist"/"alist"/版本号,确认无残留;浏览器开发者工具看网络请求,确认没有向 res.oplist.org 发请求。
八、安全加固:限流 + fail2ban
| 措施 | 配置 |
|---|---|
| 登录接口限流 | 5 次/分钟 |
| 全站 API 限流 | 60 次/分钟 |
| fail2ban | openlist-limit jail,10 分钟 8 次 429 封 1 小时 |
和 vaultwarden、Halo 同一套模式。nps 后端端口(28392/28443/28100)确认未公网暴露——之前体检曾误判过,这次是二次验证过的结论。
九、踩坑记录
坑 1:admin set 会被忽略,数据目录只认进程工作目录
这是 OpenList 最大的坑,值得置顶。openlist admin set 这个命令不会按 --data 参数去改指定目录的数据库,它只认进程当前工作目录下的数据。表象:命令执行成功了,密码却没改,登录还是旧密码(或随机密码)。
正确姿势:
# 必须先 cd 到数据目录,再执行
cd /opt/openlist
./openlist admin set --new-password 'xxx'
如果在 /root 下执行,它会在 /root/data/ 下建一个"野库",改的是那个野库的密码,主库纹丝不动。排查时看到 /root/data/data.db 这种莫名其妙的路径,就是中了这个坑。改完密码,用 /api/auth/login 真实登录验证,别信命令的输出。
坑 2:systemd 的 WorkingDirectory 必须设对
和坑 1 同源。systemd 服务的 WorkingDirectory 如果没设成 /opt/openlist,服务启动后数据目录就错了,表现为"配置丢了"或"密码不对"。部署时第一件事就是检查 WorkingDirectory。
坑 3:体检曾误判 nps 后端端口公网暴露
之前体检结论说 nps 后端端口暴露了,复查发现是误判。这次迁移时二次验证:28392/28443/28100 确认未公网暴露。教训:负面结论("暴露了"、"坏了")发布前必须二次验证,误报消耗信任。
日常使用场景
OpenList 搭好后,日常就三个动作:
| 场景 | 操作 |
|---|---|
| 分享文件给朋友 | 把文件放 /NAS920,生成外链发过去,阅后即焚的可设过期 |
| 家人看资料 | /维保管理、/归档 只读 + 访问密码,告诉他们密码,一次说清 |
| 自己传文件 | nas 账号登录 /NAS920,直接上传 |
外链分享注意:默认外链是长期有效的,敏感文件分享时设过期时间。OpenList 的外链带签名,猜不到,但"发出去的链接"本身要当一次性口令看。
/影视 卷规划:接 Google Drive
待办里有一项:新增 /影视 卷,接 Google Drive(OAuth 授权后配)。这是 OpenList"云盘存储"类型的用武之地:
- Google 账号做一次 OAuth 授权,拿到 refresh token;
- OpenList 里新增存储,类型选 Google Drive,填 token;
- 挂载为 /影视,和现有三个 Local 卷并列。
这样 qBittorrent 下载的影视(经 rclone 搬到 Google Drive 后),直接在文件站里看,不用再下回来。存储类型混搭(Local + 云盘)正是 OpenList 的强项,一个入口,背后多个后端。
文件共享的安全边界:分享与暴露的一线之隔
文件共享是这套家庭数据中心里"最危险"的服务,不是因为它技术复杂,而是因为它的用途就是"把文件给别人看"。别的服务(博客、密码库)是"防人看",文件站是"给人看",安全边界天然更薄。所以它的安全设计,要比别的服务多想一层。
第一层:默认不分享。 OpenList 里,访客默认 401,不登录什么都看不到。分享是"主动动作":你要把文件放进分享目录、生成外链、发给对方,对方才能看。没有"我顺手开了个目录,忘了关"这种默认暴露。这是设计原则:分享是 opt-in,不是 opt-out。
第二层:分享即过期。 发出去的外链,能设过期就设过期。给朋友传个安装包,设 7 天过期;家人看资料,走账号密码,不走外链。外链一旦发出就失控了——对方可能转发、可能存书签。过期时间是"失控"的安全阀。重要的文件,宁可让对方"过期了再找你要",也别留一个永久有效的口子。
第三层:只读是底线。 /维保管理 和 /归档 只读,是因为它们是"资料库",不需要任何人往里写。/NAS920 给读写,是因为它是"工作区",需要上传。但即使是工作区,也要想清楚:谁可以删?删了能恢复吗?NAS 的快照在这里是最后一道防线。分享的权限,永远按"最小够用"给:能只读就不给读写,能限时就不给永久。
第四层:指纹隐藏。 品牌隐藏(第七节)是"别告诉攻击者你是谁"。文件站是公网服务,扫描器天天路过。不暴露软件指纹,攻击者就不知道该用什么 CVE 来打你。这不是"主要防线",是"纵深"。纵深的每一层都不贵(改个 nginx 配置),但加起来让攻击者的成本翻倍。
四层下来,文件站的安全观是:分享是业务,安全是边界。业务要顺滑(一点就分享),边界要清晰(默认不分享、分享有过期、权限最小化、指纹隐藏)。这套边界,用户定的红线是"NAS 文件绝不能暴露给别人",所有设计都从这条红线倒推。红线先行,设计跟上,这是家庭数据中心做任何对外分享的顺序。
迁移后的回访:Copyparty 真的删干净了吗
迁移最容易烂尾的地方是"旧服务没删干净"。Copyparty 卸载后,回访检查三件事:端口还在监听吗(ss -tlnp 看旧端口),systemd 还有残留服务吗(systemctl list-units | grep copy),数据目录删了吗(配置文件备份留档后,程序和数据删干净)。
旧服务不删干净的危害:占着端口(新服务起不来)、占着资源(还在跑)、留着攻击面(旧版本有 CVE)。迁移的定义是"新服务上线 + 旧服务下线",只上不下,叫"堆叠",不叫"迁移"。堆叠的系统,半年后没人敢动——不知道哪个是活的,哪个是死的。
回访清单(迁移后一周):旧端口无监听、旧服务无残留、旧数据已备份后删除、Dashy 导航页的旧入口已更新、文档里的旧地址已替换。五项全过,迁移才算闭环。
写在最后:迁移是手段,体验是目的
回头看,Copyparty 到 OpenList 的迁移,技术动作只占三成,七成是"体验":界面好看了,分享顺了,品牌隐藏了,家人愿意用了。技术选型时,"好不好用"和"好不好看"一样重要,尤其当用户不只是你自己。颜值是生产力,这句话在这次迁移里,得到了充分验证。
十、总结
OpenList 迁移的完整链条:Copyparty 卸载清理 → CT701 部署 v4.2.6(systemd,WorkingDirectory 设对)→ 三个 Local 存储卷(读写只读分清、双层保护)→ 用户权限 hygiene → nps 隧道 + nginx 公网化 → 品牌隐藏(抹指纹清单)→ 限流 + fail2ban。最大的坑是 admin set 只认工作目录,改密码必须 cd /opt/openlist 再执行。待办:/影视 卷接 Google Drive(OAuth 后配),那时 OpenList 的云盘存储类型就派上用场了。
相关阅读:《家庭数据中心架构总览:VPS、PVE、NAS 三方分工》、《fail2ban 实战:从 SSH 到 Web 登录接口的防护》。