家庭 NAS 远程访问终极方案:Docker + Cloudflare Tunnel 实战教程

其他杂项67字数 5322阅读17分44秒阅读模式

家庭 NAS 远程访问终极方案:Docker + Cloudflare Tunnel 实战教程

前言:为什么写这篇文章

家里的 NAS 跑了一堆 Docker 服务——WordPress 博客、Homepage 导航页、Aria2 下载器、微信文章采集器、直播数据工具……在家用着很爽,但一出门就全断了。

想从外面访问?传统方案是端口转发 + DDNS。但现实很骨感:

  • 运营商封了 80 和 443 端口,HTTP/HTTPS 直接死路一条
  • 公网 IP 虽然有,但只有一个非标端口勉强能通
  • DDNS + 非标端口的方式,每个服务都要记一个 域名:端口,丑且难用
  • STUN 穿透不稳定,连着连着就断了

折腾了一圈后,我找到了一个零成本、零端口依赖、自动 HTTPS的方案:Cloudflare Tunnel

本文记录完整的部署过程、踩过的坑、以及最终的架构设计。


一、架构概览

互联网用户
    │
    ▼
Cloudflare Edge(自动 HTTPS + CDN)
    │
    ▼ Cloudflare Tunnel(加密隧道)
    │
NAS 上的 cloudflared 客户端
    │
    ├── wp.example.com     → WordPress (端口 8080)
    ├── home.example.com   → Homepage  (端口 3000)
    ├── sync.example.com   → 微信文章采集 (端口 9000)
    └── ...更多服务

核心思路:不需要打开任何入站端口。cloudflared 从 NAS 内部主动向 Cloudflare 建立出站连接(就像你打开一个网页一样),然后 Cloudflare 通过这条隧道把外部请求转发到内网服务。

优势
- ✅ 不依赖任何端口:运营商封 80、443、甚至全封都没关系
- ✅ 自动 HTTPS:Cloudflare 边缘节点自动提供证书,零配置
- ✅ 标准域名访问wp.example.com 而不是 nas.example.com:12345
- ✅ 零成本:Cloudflare Tunnel 免费额度完全够用
- ✅ 安全:NAS 没有任何端口暴露在公网上


二、准备工作

你需要的东西

项目 说明
一台 NAS 能跑 Docker 就行。我用的是群晖 + Lucky 管理面板
一个域名 需要托管在 Cloudflare(免费)。我用 example.com
Cloudflare 账号 免费注册即可
Docker 服务 你想从外面访问的任何服务

我的环境

  • NAS IP192.168.x.x(内网地址)
  • 管理面板:Lucky 2.26.2(内置 Docker 管理和 cloudflared 模块)
  • 已有服务:WordPress(:8080)、Homepage(:3000)、微信文章采集(:9000) 等
  • 域名example.com,DNS 托管在 Cloudflare

三、部署步骤

第 1 步:在 Cloudflare 创建 Tunnel

  1. 登录 Cloudflare Zero Trust
  2. 进入 Networks → Tunnels
  3. 点击 Create a tunnel
  4. 选择 Cloudflared 类型
  5. 给 Tunnel 起个名字,比如 nas-tunnel
  6. 创建后会生成一个 Token(很长的一串 Base64 字符串),保存好

也可以用 API 创建(适合自动化):

curl -X POST "https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}/cfd_tunnel" \
  -H "Authorization: Bearer {API_TOKEN}" \
  -H "Content-Type: application/json" \
  --data '{"name":"nas-tunnel","tunnel_secret":"YOUR_32BYTE_SECRET_BASE64"}'

第 2 步:配置 Tunnel 路由

告诉 Tunnel 把哪些域名转发到哪些内网服务:

curl -X PUT "https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}/cfd_tunnel/{TUNNEL_ID}/configurations" \
  -H "Authorization: Bearer {API_TOKEN}" \
  -H "Content-Type: application/json" \
  --data '{
    "config": {
      "ingress": [
        {"hostname": "wp.example.com", "service": "http://192.168.x.x:8080"},
        {"hostname": "home.example.com", "service": "http://192.168.x.x:3000"},
        {"hostname": "sync.example.com", "service": "http://192.168.x.x:9000"},
        {"service": "http_status:404"}
      ]
    }
  }'

注意:最后一条 http_status:404 是 catch-all 规则,必须有,否则 cloudflared 会报错。

第 3 步:配置 DNS

为每个子域名创建 CNAME 记录,指向 Tunnel 地址:

# 格式:{TUNNEL_ID}.cfargotunnel.com
# 必须开启 Cloudflare 代理(橙色云朵)

curl -X POST "https://api.cloudflare.com/client/v4/zones/{ZONE_ID}/dns_records" \
  -H "Authorization: Bearer {API_TOKEN}" \
  -H "Content-Type: application/json" \
  --data '{
    "type": "CNAME",
    "name": "wp",
    "content": "YOUR-TUNNEL-ID.cfargotunnel.com",
    "proxied": true
  }'

对每个子域名(wp、home、wpsync……)重复这一步。

第 4 步:在 NAS 上部署 cloudflared

这一步有两种方式:

方式 A:用 Lucky 内置模块(推荐)

如果你的 NAS 用 Lucky 管理面板:

  1. 进入 Lucky → 内网穿透Cloudflared
  2. 填入上一步获得的 Token
  3. 点击启动

Lucky 会自动管理 cloudflared 进程,开机自启,断线重连。

方式 B:Docker 部署

docker run -d --name cloudflared \
  --restart always \
  cloudflare/cloudflared:latest \
  tunnel --no-autoupdate run --token YOUR_TUNNEL_TOKEN

方式 C:Docker Compose

version: "3.9"
services:
  cloudflared:
    image: cloudflare/cloudflared:latest
    container_name: cloudflared
    command: tunnel --no-autoupdate run --token YOUR_TUNNEL_TOKEN
    restart: always

第 5 步:验证

# 检查 WordPress
curl -sI https://wp.example.com
# 应该返回 HTTP/2 200

# 检查 Homepage
curl -sI https://home.example.com
# 应该返回 HTTP/2 200 或 307(跳转到登录页)

在浏览器里直接打开 https://wp.example.com,看到 WordPress 页面就成功了!🎉


四、踩坑记录

坑 1:端口写错,页面打不开

症状:配置了 Tunnel 但页面一直加载不出来。

原因:我一开始把 Homepage 的端口写成了 XX(Lucky 管理面板的端口),实际应该是 3000(Homepage 服务本身的端口)。

教训service 里填的是内网服务的真实端口,不是管理面板的端口。先用 curl http://192.168.x.x:端口 在内网确认能通,再填到 Tunnel 配置里。

坑 2:旧 DNS 记录冲突

症状:配置了 CNAME 但域名解析异常。

原因wp.example.com 之前有一条 A 记录指向旧的公网 IP,和新的 CNAME 冲突了。

教训:添加 Tunnel CNAME 之前,先删掉同名的旧 A 记录

坑 3:换域名后服务内部配置没跟着改

症状:微信文章采集服务(sync.example.com)能打开 API 文档,但同步文章到 WordPress 时一直超时。

原因:这个服务的环境变量 WP_URL 被设成了 https://sync.example.com(它自己的地址),而不是 WordPress 的地址 https://wp.example.com。它在尝试向自己发 XML-RPC 请求,当然 404。

报错信息

ERROR - WP: XML-RPC 发布失败: <ProtocolError for sync.example.com/xmlrpc.php: 404 Not Found>

教训:换域名后,不只要改 Tunnel 和 DNS,还要检查所有服务内部的配置文件和环境变量中是否引用了旧域名。特别是服务之间互相调用的地址。

最佳实践:服务间互相调用尽量用内网 IP(如 http://192.168.x.x:8080),而不是走公网域名绕一圈。走内网更快、更稳、不受 Tunnel 状态影响。

坑 4:cloudflared 配置更新不即时生效

症状:在 Cloudflare 后台更新了 Tunnel 路由(新增了 sync.example.com),但访问一直返回 404。

原因:NAS 上的 cloudflared 实例是在几小时前建立连接的,新的路由配置需要等 cloudflared 下一次心跳拉取。

解决:等几分钟自动生效,或者重启 cloudflared 容器/服务强制拉取最新配置。

坑 5:Lucky GUI 的 CodeMirror 编辑器无法自动化

症状:想通过浏览器自动化(Playwright)在 Lucky 的 Docker Compose 编辑器里填写 YAML,但怎么都注入不进去。

原因:Lucky 2.26.2 的 YAML 编辑器使用了 CodeMirror(contentEditable div),标准的 DOM InputEvent、clipboard paste 操作都不生效,cmView 属性也不暴露。

教训:遇到这类富文本编辑器,放弃 GUI 自动化,直接 SSH 进终端操作更快更稳。


五、进阶:重流量服务怎么办?

Cloudflare Tunnel 非常适合轻量级 Web 服务(博客、导航页、API 等),但对于重带宽场景(远程看电影、大文件传输),有两个限制:

  1. 带宽瓶颈:所有流量都经过 Cloudflare 边缘节点中转
  2. ToS 限制:Cloudflare 免费版不鼓励大量非 HTML 内容的代理

推荐方案:Tailscale

对于重流量需求,建议在 NAS 上额外部署 Tailscale

version: "3.9"
services:
  tailscale:
    image: tailscale/tailscale:latest
    container_name: tailscale
    hostname: nas-tailscale
    network_mode: host
    privileged: true
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    environment:
      - TS_STATE_DIR=/var/lib/tailscale
      - TS_ACCEPT_DNS=true
      - TS_USERSPACE=false
    volumes:
      - ./tailscale-state:/var/lib/tailscale
      - /dev/net/tun:/dev/net/tun
    restart: always

分工原则
- Cloudflare Tunnel:轻量 Web 服务、需要公开访问的页面
- Tailscale:看电影、传文件、远程桌面等重流量私密访问

两者互不冲突,可以同时运行。


六、最终架构总结

域名 内网服务 访问方式 用途
wp.example.com 192.168.x.x:8080 Cloudflare Tunnel WordPress 博客
home.example.com 192.168.x.x:3000 Cloudflare Tunnel Homepage 导航
sync.example.com 192.168.x.x:9000 Cloudflare Tunnel 微信文章采集
NAS 内网 IP 所有端口 Tailscale P2P 重流量/私密访问

成本

  • Cloudflare Tunnel:免费
  • Tailscale:免费(个人使用 100 台设备额度)
  • 域名:约 ¥50/年
  • 总计:几乎零成本

安全性

  • NAS 零端口暴露在公网上
  • 所有 Web 流量自动 HTTPS(Cloudflare 边缘证书)
  • 私密服务走 Tailscale 端到端加密
  • 比传统端口转发 + DDNS 安全得多

七、写在最后

折腾 NAS 远程访问这件事,我走过不少弯路:DDNS + 端口转发 → STUN 穿透 → frp/nps 内网穿透 → 最终落地到 Cloudflare Tunnel + Tailscale。

这套方案的核心优势是简单稳定

  • 不需要公网 IP
  • 不需要端口转发
  • 不需要自建中转服务器
  • 不需要折腾证书
  • 运营商随便封端口,完全不受影响

如果你也在为 NAS 远程访问发愁,强烈推荐试试这个方案。有问题欢迎留言交流。

 
  • 本文由 asdfasd 发表于 2026-04-0801:11:24
  • 转载请务必保留本文链接:http://wp.fangfa.me/other-note/a44b3b15873db3cf2c781254e3837cbb.html