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 环境与账号准备清单
首先,确认你的装备是否齐全:
- 一台已安装DSM系统的群晖NAS:型号不限,DSM 6.x或7.x均可。本文以DSM 7.x为主要环境。
- 一个属于你自己的域名:这是必须的。你可以在Cloudflare、Namesilo、GoDaddy等任何注册商购买。我强烈推荐将域名的DNS解析服务托管到Cloudflare,因为后续配置会无缝衔接,最简单。
- 一个Cloudflare账户:免费账户即可,完全够用。
- 群晖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方案,理由如下:
- 官方原生支持:
cloudflared是Cloudflare官方维护的隧道客户端,更新最及时,功能最完整,稳定性最好。 - 环境隔离:Docker容器提供了完美的隔离环境,不会影响群晖宿主机的系统稳定性。安装、升级、卸载都极其干净。
- 灵活性高:你可以通过修改Docker容器的配置参数,轻松实现各种高级功能,例如运行多个隧道、自定义配置文件路径等。
- 学习价值:理解Docker的基础操作,对于在群晖上部署其他自助服务(如Bitwarden、HomeAssistant等)是必备技能,一举多得。
相比之下,第三方套件虽然可能有一键安装的便利,但其更新依赖于套件作者,可能存在延迟,且功能可能不是官方最新版本。因此,掌握Docker方案是更根本、更可靠的解决方案。
3. 实战部署:一步步搭建加密隧道
理论准备就绪,我们开始动手。整个过程就像组装乐高,步骤清晰,跟着做一定能成功。
3.1 第一步:在Cloudflare Zero Trust面板创建隧道
这是整个流程的“控制中心”操作,所有配置将在这里生成。
- 登录你的Cloudflare仪表板,在左侧菜单中找到或搜索“Zero Trust”并进入。
- 在Zero Trust面板中,导航到Access -> Tunnels。
- 点击“Create a tunnel”按钮。
- 给你的隧道起一个容易识别的名字,比如
my-nas-tunnel,然后点击“Save tunnel”。 - 接下来是关键步骤:选择连接器类型。由于我们使用Docker,所以选择“Docker”标签页。
- 页面上会显示一行长长的Docker运行命令,类似于:
请先不要直接在群晖上执行它!我们需要先对它进行“改造”。这个命令包含了你的隧道令牌(Token),它是隧道客户端的“身份证”。我们的目标是将这个令牌安全地保存到群晖的一个文件中,然后让Docker容器读取它。docker run -d cloudflare/cloudflared:latest tunnel --no-autoupdate run --token eyJhIjoi...
3.2 第二步:在群晖Docker中配置并运行隧道客户端
现在,我们把战场转移到群晖DSM。
准备令牌文件:
- 打开群晖的File Station。
- 建议创建一个专门的目录来存放Docker相关配置,例如在
docker文件夹下新建一个cloudflared文件夹。 - 在
cloudflared文件夹内,新建一个文本文件,命名为config.json(名称可自定,但建议用这个)。用文本编辑器打开它。 - 回到Cloudflare Zero Trust页面,在Docker命令中,找到
--token后面的那一长串字符(以eyJ开头)。这就是你的隧道令牌。 - 将令牌内容以如下JSON格式写入
config.json文件:
(请将{ "tunnel_token": "eyJhIjoi..." }eyJhIjoi...替换为你自己的完整令牌字符串) - 保存文件。
重要安全提示:这个令牌文件等同于通往你隧道的钥匙。务必妥善保管,不要泄露或上传到公开的代码仓库。通过文件方式传递令牌,比直接在命令中写入更安全,也便于后续管理。
在Docker图形界面中创建容器:
- 打开群晖的Docker套件。
- 进入“注册表”选项卡,搜索
cloudflare/cloudflared,选择官方镜像,点击“下载”,选择latest标签即可。 - 下载完成后,进入“映像”选项卡,找到
cloudflare/cloudflared:latest,选中并点击“启动”。 - 在启动向导中:
- 容器名称:起个名,如
cloudflared-tunnel。 - 点击“高级设置”。
- 容器名称:起个名,如
配置容器高级设置(关键步骤):
- 存储空间:点击“添加文件夹”。选择你刚才存放
config.json的文件夹(例如/docker/cloudflared)。将“装载路径”设置为/etc/cloudflared。这步操作将宿主机的配置文件目录映射到容器内的指定路径。 - 网络:保持默认的“bridge”网络即可,隧道客户端是出站连接,无需特殊网络模式。
- 环境变量:通常不需要额外设置。
- 命令:这是核心。我们需要覆盖默认的启动命令。在“命令”输入框中,填入:
这个命令告诉tunnel --config /etc/cloudflared/config.json runcloudflared程序,使用我们映射进去的配置文件来运行隧道。 - 其他设置(资源限制、自动重启等)可按需配置。我建议勾选“启用自动重新启动”,确保NAS重启后隧道能自动恢复。
- 存储空间:点击“添加文件夹”。选择你刚才存放
完成并运行:
- 一路点击“下一步”,最后点击“应用”。容器就会创建并启动。
- 回到Docker的“容器”选项卡,找到你刚创建的
cloudflared-tunnel,查看日志。如果看到类似INF Connection registered或INF Tunnel started的信息,恭喜你,隧道客户端已经成功连接到了Cloudflare!
3.3 第三步:配置公共主机名(将服务暴露出去)
隧道建立了,但还没有告诉Cloudflare:“我的隧道对应哪个域名,以及域名请求应该转发到内网的哪个服务”。现在回去配置。
- 回到Cloudflare Zero Trust面板的Tunnels页面,点击你刚创建的隧道(如
my-nas-tunnel)。 - 切换到“Public Hostnames”标签页,点击“Add a public hostname”。
- 这里就是配置路由规则的地方:
- Subdomain:子域名。例如,你想用
nas.yourdomain.com访问,这里就填nas。 - Domain:选择你托管在Cloudflare的域名。
- Path:路径。如果你只想暴露某个特定路径下的服务可以填写,例如
/files。对于直接访问DSM首页,这里留空。 - Service:服务类型和地址。这是最重要的部分。
- Type:选择
HTTP或HTTPS。建议选择HTTPS。 - URL:填写你群晖NAS在内网中的访问地址。注意,这里不能填
localhost或127.0.0.1,因为Docker容器有独立的网络命名空间。你需要填写群晖宿主机的局域网IP和端口。- 例如,你的群晖IP是
192.168.1.100,DSM默认端口是5000(HTTP)或5001(HTTPS)。那么这里应该填:https://192.168.1.100:5001或http://192.168.1.100:5000。 - 如果你在群晖上通过Docker或其他方式部署了其他Web服务(比如在8080端口),同理,填写对应的内网URL即可。
- 例如,你的群晖IP是
- Type:选择
- Subdomain:子域名。例如,你想用
- 点击“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的精髓之一——在服务前加一把锁。即使有人知道了你的域名,没有通过验证也无法访问。
- 在Cloudflare Zero Trust面板,进入Access -> Applications。
- 点击“Add an application”,选择“Self-hosted”。
- 在配置页面:
- Application name:起个名,如 “My NAS DSM”。
- Session Duration:设置登录会话有效期。
- Domain:选择你刚才为隧道配置的域名(如
nas.yourdomain.com)。
- 最关键的是“Policies”(策略)。点击“Add a policy”。
- Policy name:如 “Allow my email”。
- Action:选择
Allow。 - Configure rules:设置规则。例如,选择“Include”,规则选择
Emails,操作符选In list,然后在值里填入你的邮箱地址(如your-email@gmail.com)。这表示只允许这个邮箱的持有者访问。 - 你还可以添加多重验证,比如要求输入邮箱收到的一次性验证码。
- 保存应用和策略。
配置完成后,再次访问你的域名,首先会跳转到Cloudflare的登录验证页面,输入你允许的邮箱并完成验证(如接收验证码)后,才会跳转到群晖DSM的登录界面。这相当于为你的NAS入口增加了一道坚固的门禁。
4.3 配置多个服务(一个隧道,多个子域名)
一个隧道可以承载多个公共主机名,指向内网不同的服务和端口。这是非常高效的用法。
例如,你除了DSM,还在群晖上通过Docker跑了:
- Jellyfin影音服务器(端口:8096)
- Bitwarden密码库(端口:8080)
你可以在隧道的“Public Hostnames”里继续添加:
- 主机名:
jellyfin.yourdomain.com,服务URL:http://192.168.1.100:8096 - 主机名:
vault.yourdomain.com,服务URL:http://192.168.1.100:8080
这样,你只需要运行一个cloudflared容器,就能通过不同的子域名访问内网所有Web服务,管理起来非常清晰。
4.4 容器自启动与更新策略
为了确保服务可靠性,我们需要让Docker容器能随系统启动,并能方便地更新。
- 自启动:在Docker容器创建时的“高级设置” -> “资源”中,我们已经勾选了“启用自动重新启动”。这能保证容器意外停止时会重启。但要确保群晖Docker套件本身是开机启动的(默认是)。
- 更新
cloudflared:当Cloudflare发布新版本时,你需要手动更新镜像。- 在Docker套件的“注册表”中,重新下载
cloudflare/cloudflared:latest镜像。 - 停止并删除现有的
cloudflared-tunnel容器(注意:删除容器不会删除你的配置文件,因为配置文件在宿主机的挂载目录里)。 - 重新执行创建容器的步骤(3.2节),使用新的镜像和完全相同的配置(特别是存储空间映射和启动命令)。因为配置是外挂的,所以重新创建容器非常快,且配置不会丢失。
- 在Docker套件的“注册表”中,重新下载
5. 常见问题与深度排错指南
在实际搭建和使用过程中,你几乎一定会遇到一些问题。下面是我踩过坑后总结的排查清单,希望能帮你快速定位。
5.1 隧道连接成功,但访问域名显示错误(5XX错误)
这是最常见的问题。通常不是隧道本身的问题,而是隧道客户端到内网服务的连接出了问题。
- 症状:访问
nas.yourdomain.com,出现 Cloudflare 5XX 错误(如 502 Bad Gateway, 503 Service Unavailable)。 - 排查思路:
- 检查Docker容器日志:在群晖Docker套件中,查看
cloudflared容器的日志。关注是否有连接被拒绝(connection refused)或超时(timeout)的错误。这通常指向“Service URL”配置错误。 - 验证Service URL:这是重中之重。确保你在Cloudflare面板配置的“Service URL”可以从Docker容器内部访问。
- 错误示例:在URL中使用了
localhost或127.0.0.1。Docker容器有自己的网络,localhost指向容器自身,而不是宿主机(群晖)。 - 正确做法:必须使用群晖宿主机的局域网IP地址。你可以在群晖控制面板 -> 网络 -> 网络界面中查看。
- 验证方法:在群晖上开启SSH功能,用管理员账号登录。执行命令
curl -I http://192.168.1.100:5000(将IP和端口换成你的Service URL)。如果能看到返回的HTTP头(如200 OK),说明这个地址从宿主机可访问。虽然这不等同于从容器内访问,但这是第一步。
- 错误示例:在URL中使用了
- 检查端口和协议:确认你填写的端口号(如5000, 5001)确实是群晖DSM服务监听的端口。确认协议(HTTP/HTTPS)匹配。DSM默认HTTP是5000,HTTPS是5001。
- 检查群晖防火墙:确保群晖的防火墙没有阻止来自Docker网络或宿主机自身IP的访问。一个简单的测试方法是暂时关闭群晖防火墙,看问题是否解决。
- 检查Docker容器日志:在群晖Docker套件中,查看
5.2 访问域名直接跳转到路由器管理界面
- 症状:在外网访问自定义域名,打开的却是你家路由器的登录页面。
- 原因:这是因为你的路由器开启了“远程管理”功能,并且其管理地址恰好被公网请求触发了。更深层的原因是,你的域名DNS解析可能没有完全生效,或者浏览器/本地DNS有缓存,请求没有走到Cloudflare的隧道,而是走到了你宽带的公网IP(虽然无端口映射,但路由器的80/443端口管理界面可能响应了)。
- 解决:
- 在路由器设置中,关闭“远程管理”(或“从WAN口访问”)功能。这是非常重要的安全措施,本就不应开启。
- 清理浏览器缓存,或使用隐身模式访问。
- 在命令行使用
nslookup nas.yourdomain.com或dig nas.yourdomain.com检查域名是否已正确解析到Cloudflare的IP地址(通常是104.x.x.x或172.x.x.x开头的Anycast IP),而不是你的家庭公网IP。
5.3 隧道客户端频繁断开重连
- 症状:在Docker日志中看到频繁的重新连接信息,有时访问不稳定。
- 排查:
- 网络稳定性:检查群晖NAS的网络连接是否稳定。可以尝试为NAS设置静态IP,并连接到路由器信号更稳定的频段(如有线优于无线)。
- 资源限制:检查Docker容器是否设置了过低的CPU或内存限制。
cloudflared本身资源消耗极低,但也不应限制得过紧。建议在容器“资源限制”中,给予至少1个CPU核心和256MB内存的预留。 - 版本问题:尝试使用一个确定的镜像标签,而不是
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 ”体验:规划、部署、配置、排错。它不仅仅是一个工具的使用教程,更是一种现代、安全的网络访问思想的实践。一旦你跑通了整个流程,你会发现管理家庭网络服务变得前所未有的清晰和可控。这种将内部服务安全、优雅地呈现给外部世界的能力,是数字生活自理中非常值得投资的一项技能。