飞牛 NAS 外网安全访问完整方案:Cloudflare + NPM + Authelia + Tailscale
前言
折腾了一周,终于把飞牛 NAS 的外网安全访问方案跑通了,记录一下完整过程,希望对其他飞牛玩家有参考价值。
我的需求很简单:
- 在外面用手机/电脑浏览器直接访问 Vaultwarden(密码管理器)和 Memos(笔记),不想每次连 VPN
- 在外面用飞牛 App 看相册、管影视
- 安全第一,成本尽量低
最终效果:
- 浏览器直接访问
https://vault.example.cn 和 https://notes.example.cn,体验和访问普通网站一样
- 飞牛 App 通过 Tailscale 外网可用,延迟 70-180ms,看相册没问题
- 每年成本:域名费 30-60 元,其他全免费
硬件和网络环境
| 设备 |
说明 |
| 飞牛 NAS |
x86 小主机,8G 内存 |
| 光猫 |
联通,路由模式 |
| 路由器 |
普通家用路由器 |
| 阿里云 ECS |
按量付费,本来就在跑其他业务 |
- 联通宽带,已申请公网 IPv4(动态)
- 有一个 .cn 域名
- 家宽 80/443 端口被封(国内常态)
整体架构
外网浏览器访问 Vaultwarden / Memos:
手机浏览器 → Cloudflare(隐藏家庭 IP + 防护)
→ Origin Rules 回源端口重写为 8443
→ 光猫(8443 转发给路由器)
→ 路由器(8443 转发到 NAS:443)
→ NPM(按域名分发 + mTLS 验证 + SSL)
→ vault.example.cn → Vaultwarden
→ notes.example.cn → Memos(经过 Authelia 2FA 认证)
→ auth.example.cn → Authelia 登录页
外网飞牛 App 访问相册/影视:
手机飞牛 App → Tailscale → 阿里云 ECS(Peer Relay 国内中继)→ NAS
安全层级(6 层)
| 层级 |
组件 |
作用 |
| 1 |
Cloudflare |
隐藏家庭真实 IP + DDoS 防护 |
| 2 |
mTLS 双向认证 |
非 Cloudflare 流量直接拒绝 |
| 3 |
路由器防火墙 + NAS iptables |
仅 8443 开放,管理端口仅内网/Tailscale 可达 |
| 4 |
Nginx Proxy Manager |
统一入口,强制 HTTPS,/admin 外网屏蔽 |
| 5 |
Authelia |
密码 + TOTP 2FA 保护 Memos |
| 6 |
服务自身认证 |
Vaultwarden 主密码 |
Docker 服务清单
所有服务通过一个 docker-compose.yml 管理,容器之间用自定义 bridge 网络互通:
| 容器 |
作用 |
内存限制 |
| Nginx Proxy Manager |
反向代理统一入口 |
256MB |
| Authelia |
统一认证 + 2FA |
256MB |
| Vaultwarden |
密码管理器 |
512MB |
| Memos |
笔记服务 |
512MB |
| ddns-go |
动态域名更新 |
128MB |
| Watchtower |
容器更新通知(仅通知模式) |
128MB |
Tailscale 装在宿主机上(不用 Docker),原因后面会说。
关键配置细节
1. 绕过家宽 443 封锁
国内家宽几乎都封了入站 80/443 端口。解决方案:
- 光猫和路由器转发 8443 端口到 NAS 的 443
- Cloudflare Origin Rules 把回源端口重写为 8443
- 用户访问时仍然是标准的
https://域名,不需要手动输端口号
这样只需要在光猫和路由器上各配一条转发规则,非常干净。
2. Cloudflare mTLS 双向认证
开启 Cloudflare 的 Authenticated Origin Pulls 后,NPM 会验证请求是否携带 Cloudflare 的客户端证书。即使攻击者知道你家的真实 IP,直接访问也会被拒绝(返回 400)。
NPM 每个 Proxy Host 的 Advanced 配置最前面加两行:
ssl_client_certificate /etc/nginx/cloudflare-origin-pull-ca.pem;
ssl_verify_client on;
3. Authelia + NPM 的坑(重点!)
这个踩了很多坑,记录一下:
失败的方案:
- 在 NPM Advanced 中用 server 级别的
auth_request + error_page 401 =302 → 500 错误
- NPM 的
error_page 和内部错误处理冲突
成功的方案: 在 Advanced 中完整定义 location /authelia(内部认证端点)和 location /(覆盖 NPM 默认的 proxy_pass),不依赖 NPM 自动生成的配置。关键点:
location /authelia 中用 set 变量 + proxy_pass 的方式连接 Authelia
location / 中完整定义 proxy_pass、auth_request、所有 headers
- 用容器的固定 IP(Docker 自定义网络分配的),不用容器名
如果你也遇到 NPM + Authelia 的 500 错误,大概率是 location / 和 NPM 默认配置冲突,或者 error_page 指令冲突。
4. Vaultwarden /admin 外网屏蔽
NPM 的 Advanced 中加一个 location block,只允许内网和 Tailscale 网段访问 /admin:
location /admin {
allow 192.168.0.0/16;
allow 10.0.0.0/8;
allow 172.16.0.0/12;
allow 100.64.0.0/10;
deny all;
proxy_pass http://容器IP:80;
# ... headers ...
}
外网访问 /admin 返回 403,内网和 Tailscale 正常访问。
5. 飞牛 App 外网访问:Tailscale + Peer Relay
飞牛相册和影视是 NAS 管理界面的一部分(共用端口),没法单独暴露到公网。暴露管理界面 = 暴露系统级权限,风险太大。
解决方案:Tailscale VPN
- NAS 上宿主机直装 Tailscale(不用 Docker,穿透成功率更高)
- 手机装 Tailscale App
- 飞牛 App 服务器地址填 Tailscale 分配的内网 IP
问题:国内手机流量是对称 NAT,Tailscale 无法直连,走默认 DERP 中继(**),延迟 200-700ms,很慢。
优化:阿里云 ECS 上启用 Tailscale Peer Relay
Peer Relay 是 Tailscale 2025 年底推出的新功能,比自建 DERP 简单太多:
# ECS 上装 Tailscale(Docker 方式)
docker run -d --name tailscale --restart unless-stopped --privileged --net=host \
-v /var/lib/tailscale:/var/lib/tailscale -v /dev/net/tun:/dev/net/tun \
-e TS_STATE_DIR=/var/lib/tailscale tailscale/tailscale:latest
# 登录
docker exec tailscale tailscale up --accept-dns=false
# 开启 Peer Relay
docker exec tailscale tailscale set --relay-server-port=41641
ECS 安全组放行 UDP 41641,Tailscale ACL 中加一条 grant 策略即可。
效果:延迟从 200-700ms 降到 73-186ms,飞牛 App 看相册体验明显改善。而且 ECS 本来就在跑其他服务,零额外成本。
6. NAS 防火墙加固
飞牛默认 INPUT 链是 ACCEPT ALL,所有端口对内网完全开放。写了一个 iptables 脚本:
- DOCKER-USER 链:443 端口只允许 Cloudflare IP 段访问
- INPUT 链:所有管理端口只允许内网(192.168.0.0/16)和 Tailscale(100.64.0.0/10)访问,外部默认 DROP
设为 systemd 服务开机自启。注意不要直接改 INPUT 的默认策略为 DROP,会和 Docker、Tailscale 的规则冲突。
7. SSH 密钥登录
禁用密码登录,只用 ed25519 密钥。改之前一定确保密钥登录已经测试通过,否则会把自己锁在外面。
每日自动备份
写了一个备份脚本,crontab 每天凌晨 3 点执行:
- 打包 Vaultwarden 数据、Authelia 配置和数据库、NPM 配置
- GPG 对称加密(AES256)
- 保留最近 30 天
- 加密密码记在纸上(不能只存在 Vaultwarden 里,否则**蛋在一个篮子里)
踩过的坑总结
| 坑 |
解决方案 |
| NPM + Authelia 500 错误 |
不用 server 级别 auth_request,在 Advanced 完整定义 location / 和 location /authelia |
| Authelia 注册 2FA 设备失败 |
NTP 检查超时,配置中加 ntp.disable_startup_check: true |
| Authelia 密码重置邮件收不到 |
用 filesystem notifier,链接写到本地文件 /config/notification.txt |
| Tailscale Docker 版穿透失败 |
改为宿主机直装,穿透成功率一样但系统级服务更稳定 |
| Tailscale 走 DERP **中继太慢 |
阿里云 ECS 启用 Peer Relay,国内中继延迟降 3-5 倍 |
| 备份脚本 crontab 执行失败 |
忘了加执行权限:chmod +x backup.sh |
| curl 测试 NPM 时无输出 |
需要用 --resolve参数指定 SNI:curl -k --resolve domain:443:127.0.0.1 https://domain/ |
安全自查清单
部署完成后逐项检查(我的实际检查结果):
费用
| 项目 |
费用 |
| 域名 |
30-60 元/年 |
| Cloudflare |
免费 |
| Tailscale |
免费(含 2 个 Peer Relay) |
| 所有 Docker 服务 |
免费开源 |
| 阿里云 ECS Peer Relay |
本来就在跑,零额外费用 |
| 总计 |
约 30-60 元/年 |
定期维护
- 每周:看一眼容器状态和 Authelia 登录日志
- 每月:检查 SSL 证书、硬盘健康、备份恢复演练
- 每季度:Cloudflare API Token 轮换、防火墙 Cloudflare IP 段核对
- 每半年:Authelia 密钥轮换、Vaultwarden ADMIN_TOKEN 轮换
写在最后
整套方案的核心思路是分层防御:即使某一层被突破,后面还有其他层兜底。Cloudflare 隐藏 IP、mTLS 验证来源、防火墙限制端口、Authelia 二次认证、服务自身认证——五六层叠在一起,对于家用场景已经很安全了。
飞牛相册和影视因为跟管理界面共用端口,没法单独暴露,用 Tailscale + Peer Relay 是目前最好的折中:安全性最高,延迟也能接受。
如果你也在折腾飞牛外网访问,希望这篇能帮到你。有问题欢迎交流。
以上方案基于飞牛 fnOS(Debian 12 底层)实测,Docker Compose 部署,2026 年 3 月。