三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

零成本实现群晖NAS外网访问:Cloudflare Tunnel内网穿透实战指南

零成本实现群晖NAS外网访问:Cloudflare Tunnel内网穿透实战指南

1. 项目概述与核心价值

如果你和我一样,家里有一台群晖NAS,想随时随地访问里面的照片、文档或者部署的轻量服务,但又被“没有公网IP”这个老大难问题卡住,那今天聊的这个方案,你一定会感兴趣。折腾过DDNS、内网穿透的朋友都知道,要么不稳定,要么收费不菲,要么配置复杂得让人头大。而利用Cloudflare Tunnel(隧道)来实现免费、安全的内网穿透,可以说是近年来对个人和小团队最友好的解决方案之一。它完全绕开了公网IP的需求,通过建立一个加密的、出站的、持续的连接,将你的本地服务安全地暴露到Cloudflare的全球网络上。

简单来说,这个过程就像给你的群晖NAS请了一位专属的、24小时在线的“快递员”。这位快递员(Cloudflare Tunnel客户端)主动从你家(内网)出发,连接到Cloudflare在全球的“中转站”(边缘节点)。当外面的人(访问者)想找你时,他们不是直接敲你家那扇没有门牌号(无公网IP)的门,而是去Cloudflare的中转站。中转站通过那位专属快递员建立好的加密通道,把请求安全地转交到你手上,再把你的回应送回去。整个过程,你的家庭网络对外是完全“隐身”的,只有出站连接,极大提升了安全性。

这个方案的核心价值在于:零成本、高安全、易配置。它不依赖任何第三方穿透软件,直接与Cloudflare这个全球性的CDN和安全服务商对接,稳定性有保障。无论是访问DSM管理界面、File Station文件管理,还是你部署的Bitwarden密码库、Jellyfin影音服务器,都能通过一个自定义的域名(如nas.yourname.com)安全访问。接下来,我会把我从零开始搭建的完整过程、关键配置的深层逻辑、以及踩过的几个坑,毫无保留地分享给你。

2. 前期准备与核心概念解析

在动手之前,我们需要把“战场”打扫干净,把“武器”准备好,更重要的是,理解我们即将使用的核心“战术”是什么。盲目操作只会事倍功半。

2.1 环境与账号准备清单

首先,确认你的装备是否齐全:

  1. 一台已安装DSM系统的群晖NAS:型号不限,DSM 6.x或7.x均可。本文以DSM 7.x为主要环境。
  2. 一个属于你自己的域名:这是必须的。你可以在Cloudflare、Namesilo、GoDaddy等任何注册商购买。我强烈推荐将域名的DNS解析服务托管到Cloudflare,因为后续配置会无缝衔接,最简单。
  3. 一个Cloudflare账户:免费账户即可,完全够用。
  4. 群晖NAS能够正常访问互联网:这是隧道建立的基础。

这里有一个关键决策点:域名DNS托管在哪里?如果你的域名不在Cloudflare,你需要将其DNS服务器修改为Cloudflare提供的NS地址。这个过程(称为“接入Cloudflare”)可能需要几小时到48小时全球生效。如果你的域名已经在Cloudflare购买或已接入,那么恭喜你,跳过了最耗时的等待环节。

2.2 理解Cloudflare Tunnel与Zero Trust

Cloudflare Tunnel 是Cloudflare Zero Trust 平台中的一个核心组件。别被“Zero Trust”(零信任)这个词吓到,它并不是一个遥不可及的企业级概念。在这里,你可以简单理解为一种更安全的访问方式。

传统的端口转发(Port Forwarding)像是你在家里的墙上开了一个洞(端口),让外界能直接看到并访问里面的服务。这带来了安全风险:暴露了你的真实IP,需要管理防火墙规则,服务直接面对互联网的攻击。

而Cloudflare Tunnel是一种反向隧道。它颠覆了传统模式:

  • 出站连接:隧道客户端(安装在你的群晖上)主动向外连接Cloudflare。这意味着你无需在路由器上设置任何端口转发规则,防火墙默认阻止所有入站连接的策略依然有效,这是本质上的安全提升。
  • 加密通道:客户端与Cloudflare边缘节点之间的所有通信默认使用TLS加密,数据安全有保障。
  • 身份验证集成:你可以轻松为服务添加额外的访问保护,例如要求输入邮箱验证码、使用GitHub账号登录等,即使服务本身没有密码功能,也能获得安全加固。

注意:Cloudflare Tunnel的免费套餐对于个人使用完全足够,它包含了无限流量的隧道。但需要注意,免费套餐下,通过隧道传输的非HTTP/HTTPS流量(如RDP、SSH、游戏服务器等原始TCP/UDP流量)无法使用。不过对于访问群晖DSM(HTTP/HTTPS)、Web服务、文件管理页面等场景,这没有任何影响。

2.3 工具选型:为什么选择cloudflaredDocker方案?

在群晖上运行Cloudflare Tunnel客户端,主要有两种方式:通过Docker容器运行cloudflared,或者使用社区开发的第三方套件。我强烈推荐Docker方案,理由如下:

  1. 官方原生支持cloudflared是Cloudflare官方维护的隧道客户端,更新最及时,功能最完整,稳定性最好。
  2. 环境隔离:Docker容器提供了完美的隔离环境,不会影响群晖宿主机的系统稳定性。安装、升级、卸载都极其干净。
  3. 灵活性高:你可以通过修改Docker容器的配置参数,轻松实现各种高级功能,例如运行多个隧道、自定义配置文件路径等。
  4. 学习价值:理解Docker的基础操作,对于在群晖上部署其他自助服务(如Bitwarden、HomeAssistant等)是必备技能,一举多得。

相比之下,第三方套件虽然可能有一键安装的便利,但其更新依赖于套件作者,可能存在延迟,且功能可能不是官方最新版本。因此,掌握Docker方案是更根本、更可靠的解决方案。

3. 实战部署:一步步搭建加密隧道

理论准备就绪,我们开始动手。整个过程就像组装乐高,步骤清晰,跟着做一定能成功。

3.1 第一步:在Cloudflare Zero Trust面板创建隧道

这是整个流程的“控制中心”操作,所有配置将在这里生成。

  1. 登录你的Cloudflare仪表板,在左侧菜单中找到或搜索“Zero Trust”并进入。
  2. 在Zero Trust面板中,导航到Access -> Tunnels
  3. 点击“Create a tunnel”按钮。
  4. 给你的隧道起一个容易识别的名字,比如my-nas-tunnel,然后点击“Save tunnel”
  5. 接下来是关键步骤:选择连接器类型。由于我们使用Docker,所以选择“Docker”标签页。
  6. 页面上会显示一行长长的Docker运行命令,类似于:
    docker run -d cloudflare/cloudflared:latest tunnel --no-autoupdate run --token eyJhIjoi...
    请先不要直接在群晖上执行它!我们需要先对它进行“改造”。这个命令包含了你的隧道令牌(Token),它是隧道客户端的“身份证”。我们的目标是将这个令牌安全地保存到群晖的一个文件中,然后让Docker容器读取它。

3.2 第二步:在群晖Docker中配置并运行隧道客户端

现在,我们把战场转移到群晖DSM。

  1. 准备令牌文件

    • 打开群晖的File Station
    • 建议创建一个专门的目录来存放Docker相关配置,例如在docker文件夹下新建一个cloudflared文件夹。
    • cloudflared文件夹内,新建一个文本文件,命名为config.json(名称可自定,但建议用这个)。用文本编辑器打开它。
    • 回到Cloudflare Zero Trust页面,在Docker命令中,找到--token后面的那一长串字符(以eyJ开头)。这就是你的隧道令牌。
    • 将令牌内容以如下JSON格式写入config.json文件:
      { "tunnel_token": "eyJhIjoi..." }
      (请将eyJhIjoi...替换为你自己的完整令牌字符串)
    • 保存文件。

    重要安全提示:这个令牌文件等同于通往你隧道的钥匙。务必妥善保管,不要泄露或上传到公开的代码仓库。通过文件方式传递令牌,比直接在命令中写入更安全,也便于后续管理。

  2. 在Docker图形界面中创建容器

    • 打开群晖的Docker套件。
    • 进入“注册表”选项卡,搜索cloudflare/cloudflared,选择官方镜像,点击“下载”,选择latest标签即可。
    • 下载完成后,进入“映像”选项卡,找到cloudflare/cloudflared:latest,选中并点击“启动”
    • 在启动向导中:
      • 容器名称:起个名,如cloudflared-tunnel
      • 点击“高级设置”
  3. 配置容器高级设置(关键步骤)

    • 存储空间:点击“添加文件夹”。选择你刚才存放config.json的文件夹(例如/docker/cloudflared)。将“装载路径”设置为/etc/cloudflared。这步操作将宿主机的配置文件目录映射到容器内的指定路径。
    • 网络:保持默认的“bridge”网络即可,隧道客户端是出站连接,无需特殊网络模式。
    • 环境变量:通常不需要额外设置。
    • 命令:这是核心。我们需要覆盖默认的启动命令。在“命令”输入框中,填入:
      tunnel --config /etc/cloudflared/config.json run
      这个命令告诉cloudflared程序,使用我们映射进去的配置文件来运行隧道。
    • 其他设置(资源限制、自动重启等)可按需配置。我建议勾选“启用自动重新启动”,确保NAS重启后隧道能自动恢复。
  4. 完成并运行

    • 一路点击“下一步”,最后点击“应用”。容器就会创建并启动。
    • 回到Docker的“容器”选项卡,找到你刚创建的cloudflared-tunnel,查看日志。如果看到类似INF Connection registeredINF Tunnel started的信息,恭喜你,隧道客户端已经成功连接到了Cloudflare!

3.3 第三步:配置公共主机名(将服务暴露出去)

隧道建立了,但还没有告诉Cloudflare:“我的隧道对应哪个域名,以及域名请求应该转发到内网的哪个服务”。现在回去配置。

  1. 回到Cloudflare Zero Trust面板的Tunnels页面,点击你刚创建的隧道(如my-nas-tunnel)。
  2. 切换到“Public Hostnames”标签页,点击“Add a public hostname”
  3. 这里就是配置路由规则的地方:
    • Subdomain:子域名。例如,你想用nas.yourdomain.com访问,这里就填nas
    • Domain:选择你托管在Cloudflare的域名。
    • Path:路径。如果你只想暴露某个特定路径下的服务可以填写,例如/files。对于直接访问DSM首页,这里留空
    • Service:服务类型和地址。这是最重要的部分。
      • Type:选择HTTPHTTPS。建议选择HTTPS
      • URL:填写你群晖NAS在内网中的访问地址。注意,这里不能填localhost127.0.0.1,因为Docker容器有独立的网络命名空间。你需要填写群晖宿主机的局域网IP和端口。
        • 例如,你的群晖IP是192.168.1.100,DSM默认端口是5000(HTTP)或5001(HTTPS)。那么这里应该填:https://192.168.1.100:5001http://192.168.1.100:5000
        • 如果你在群晖上通过Docker或其他方式部署了其他Web服务(比如在8080端口),同理,填写对应的内网URL即可。
  4. 点击“Save hostname”

配置完成后,Cloudflare会为你配置的域名(如nas.yourdomain.com)签发一个SSL证书(通常需要1-2分钟)。之后,你就可以尝试在外部网络(比如关闭手机Wi-Fi,用蜂窝数据)访问这个域名了。如果一切顺利,你将看到群晖DSM的登录界面。

4. 高级配置与优化要点

基础隧道打通只是开始,要让服务更好用、更安全,还需要一些优化配置。这部分是区分“能用”和“好用”的关键。

4.1 配置自定义域名与SSL证书

默认情况下,Cloudflare会为你的子域名提供一个通配符SSL证书。访问是加密的,但浏览器可能会显示证书是由“Cloudflare Inc”签发的。如果你希望证书显示为自己的域名,或者需要根域名证书,可以配置“自定义主机名”或“源服务器证书”,但这通常涉及上传自己的证书到Cloudflare,对于个人使用,默认的通用证书在安全和便利性上已完全足够,不建议初学者额外折腾。

4.2 为服务添加额外安全层(Access策略)

这是Cloudflare Zero Trust的精髓之一——在服务前加一把锁。即使有人知道了你的域名,没有通过验证也无法访问。

  1. 在Cloudflare Zero Trust面板,进入Access -> Applications
  2. 点击“Add an application”,选择“Self-hosted”
  3. 在配置页面:
    • Application name:起个名,如 “My NAS DSM”。
    • Session Duration:设置登录会话有效期。
    • Domain:选择你刚才为隧道配置的域名(如nas.yourdomain.com)。
  4. 最关键的是“Policies”(策略)。点击“Add a policy”
    • Policy name:如 “Allow my email”。
    • Action:选择Allow
    • Configure rules:设置规则。例如,选择“Include”,规则选择Emails,操作符选In list,然后在值里填入你的邮箱地址(如your-email@gmail.com)。这表示只允许这个邮箱的持有者访问。
    • 你还可以添加多重验证,比如要求输入邮箱收到的一次性验证码。
  5. 保存应用和策略。

配置完成后,再次访问你的域名,首先会跳转到Cloudflare的登录验证页面,输入你允许的邮箱并完成验证(如接收验证码)后,才会跳转到群晖DSM的登录界面。这相当于为你的NAS入口增加了一道坚固的门禁。

4.3 配置多个服务(一个隧道,多个子域名)

一个隧道可以承载多个公共主机名,指向内网不同的服务和端口。这是非常高效的用法。

例如,你除了DSM,还在群晖上通过Docker跑了:

  • Jellyfin影音服务器(端口:8096)
  • Bitwarden密码库(端口:8080)

你可以在隧道的“Public Hostnames”里继续添加:

  1. 主机名:jellyfin.yourdomain.com,服务URL:http://192.168.1.100:8096
  2. 主机名:vault.yourdomain.com,服务URL:http://192.168.1.100:8080

这样,你只需要运行一个cloudflared容器,就能通过不同的子域名访问内网所有Web服务,管理起来非常清晰。

4.4 容器自启动与更新策略

为了确保服务可靠性,我们需要让Docker容器能随系统启动,并能方便地更新。

  • 自启动:在Docker容器创建时的“高级设置” -> “资源”中,我们已经勾选了“启用自动重新启动”。这能保证容器意外停止时会重启。但要确保群晖Docker套件本身是开机启动的(默认是)。
  • 更新cloudflared:当Cloudflare发布新版本时,你需要手动更新镜像。
    1. 在Docker套件的“注册表”中,重新下载cloudflare/cloudflared:latest镜像。
    2. 停止并删除现有的cloudflared-tunnel容器(注意:删除容器不会删除你的配置文件,因为配置文件在宿主机的挂载目录里)。
    3. 重新执行创建容器的步骤(3.2节),使用新的镜像和完全相同的配置(特别是存储空间映射和启动命令)。因为配置是外挂的,所以重新创建容器非常快,且配置不会丢失。

5. 常见问题与深度排错指南

在实际搭建和使用过程中,你几乎一定会遇到一些问题。下面是我踩过坑后总结的排查清单,希望能帮你快速定位。

5.1 隧道连接成功,但访问域名显示错误(5XX错误)

这是最常见的问题。通常不是隧道本身的问题,而是隧道客户端到内网服务的连接出了问题。

  • 症状:访问nas.yourdomain.com,出现 Cloudflare 5XX 错误(如 502 Bad Gateway, 503 Service Unavailable)。
  • 排查思路
    1. 检查Docker容器日志:在群晖Docker套件中,查看cloudflared容器的日志。关注是否有连接被拒绝(connection refused)或超时(timeout)的错误。这通常指向“Service URL”配置错误。
    2. 验证Service URL:这是重中之重。确保你在Cloudflare面板配置的“Service URL”可以从Docker容器内部访问
      • 错误示例:在URL中使用了localhost127.0.0.1。Docker容器有自己的网络,localhost指向容器自身,而不是宿主机(群晖)。
      • 正确做法:必须使用群晖宿主机的局域网IP地址。你可以在群晖控制面板 -> 网络 -> 网络界面中查看。
      • 验证方法:在群晖上开启SSH功能,用管理员账号登录。执行命令curl -I http://192.168.1.100:5000(将IP和端口换成你的Service URL)。如果能看到返回的HTTP头(如200 OK),说明这个地址从宿主机可访问。虽然这不等同于从容器内访问,但这是第一步。
    3. 检查端口和协议:确认你填写的端口号(如5000, 5001)确实是群晖DSM服务监听的端口。确认协议(HTTP/HTTPS)匹配。DSM默认HTTP是5000,HTTPS是5001。
    4. 检查群晖防火墙:确保群晖的防火墙没有阻止来自Docker网络或宿主机自身IP的访问。一个简单的测试方法是暂时关闭群晖防火墙,看问题是否解决。

5.2 访问域名直接跳转到路由器管理界面

  • 症状:在外网访问自定义域名,打开的却是你家路由器的登录页面。
  • 原因:这是因为你的路由器开启了“远程管理”功能,并且其管理地址恰好被公网请求触发了。更深层的原因是,你的域名DNS解析可能没有完全生效,或者浏览器/本地DNS有缓存,请求没有走到Cloudflare的隧道,而是走到了你宽带的公网IP(虽然无端口映射,但路由器的80/443端口管理界面可能响应了)。
  • 解决
    1. 在路由器设置中,关闭“远程管理”(或“从WAN口访问”)功能。这是非常重要的安全措施,本就不应开启。
    2. 清理浏览器缓存,或使用隐身模式访问。
    3. 在命令行使用nslookup nas.yourdomain.comdig nas.yourdomain.com检查域名是否已正确解析到Cloudflare的IP地址(通常是104.x.x.x172.x.x.x开头的Anycast IP),而不是你的家庭公网IP。

5.3 隧道客户端频繁断开重连

  • 症状:在Docker日志中看到频繁的重新连接信息,有时访问不稳定。
  • 排查
    1. 网络稳定性:检查群晖NAS的网络连接是否稳定。可以尝试为NAS设置静态IP,并连接到路由器信号更稳定的频段(如有线优于无线)。
    2. 资源限制:检查Docker容器是否设置了过低的CPU或内存限制。cloudflared本身资源消耗极低,但也不应限制得过紧。建议在容器“资源限制”中,给予至少1个CPU核心和256MB内存的预留。
    3. 版本问题:尝试使用一个确定的镜像标签,而不是latest。例如使用cloudflare/cloudflared:2024.5.0。这可以避免因自动更新到有bug的新版本而导致的不稳定。你可以在Cloudflare的GitHub Release页面找到稳定版本号。

5.4 如何查看和管理更详细的日志

默认的Docker日志输出信息可能不够详细。你可以通过修改容器的启动命令来增加日志级别,帮助诊断复杂问题。

在创建或编辑容器时,在“命令”输入框中,将原来的:

tunnel --config /etc/cloudflared/config.json run

修改为:

tunnel --config /etc/cloudflared/config.json run --loglevel debug

这样容器会输出DEBUG级别的详细日志。注意,这会产生大量日志,仅在排查问题时使用,问题解决后建议改回默认级别或使用info级别。

搭建并稳定运行Cloudflare Tunnel的过程,是一个典型的“ DevOps ”体验:规划、部署、配置、排错。它不仅仅是一个工具的使用教程,更是一种现代、安全的网络访问思想的实践。一旦你跑通了整个流程,你会发现管理家庭网络服务变得前所未有的清晰和可控。这种将内部服务安全、优雅地呈现给外部世界的能力,是数字生活自理中非常值得投资的一项技能。

← 返回列表