用 Cloudflare Tunnel 把家里 NAS 的管理页面和相册安全地发布到
nas.你的域名,家里不需要公网 IP、不用在路由器上开任何端口,再用 Cloudflare Access 加一道邮箱验证码登录,只有你和家人的邮箱能打开。
先看清成品
成品是一个运行在家里的
cloudflared容器,它主动连到 Cloudflare,外面的人访问https://nas.example.com时先看到 Cloudflare 的登录页,输入白名单邮箱收到的验证码后才会进入 NAS。本文在 Linux 上实际运行了 cloudflared 2026.10.2 的规则校验:配置文件校验通过,三条访问地址分别匹配到 NAS、相册和兜底 404 规则,并演示了缺少兜底规则时的报错。创建隧道和 Access 应用需要登录 Cloudflare 后台,这部分没有在本文环境中操作。
注意:只发布你自己的设备和服务。公司内网服务在发布前要得到公司 IT 的书面许可,私自打通内网可能违反公司规定。Tunnel 用来发布网站和服务,不要拿它搭建翻墙代理或其他违反当地法律法规的用途。
做完之后你会得到什么?
| 成果 | 说明 |
|---|---|
| 隧道 | 家里主动连出,路由器不开端口 |
| 公网地址 | nas.example.com、photos.example.com,自动 HTTPS |
| 登录保护 | Access 邮箱验证码,只放行白名单 |
| 容器化 | cloudflared 用 Docker 运行,开机自启 |
需要准备哪些硬件和环境?
| 项目 | 要求 | 说明 |
|---|---|---|
| 常开设备 | NAS 本身(支持 Docker 的型号)、迷你主机或树莓派 | 运行 cloudflared |
| 网络 | 能访问外网,出站 7844 端口不被拦截 | 官方建议先做连通性检查 |
| 域名 | 已添加到 Cloudflare 并使用其 DNS | example.com 换成你的域名 |
| Cloudflare One | 首次进入时创建团队名,可选免费计划 | Access 登录页需要 |
| NAS 服务 | 例如管理页 https://192.168.1.10:5001,相册 http://192.168.1.10:2342 |
换成你实际的地址和端口 |
第一步:怎样创建隧道?
1. 在后台创建
登录 Cloudflare 后台,进入 Networking → Tunnels,点 Create a tunnel,起名 home-nas。
2. 复制令牌
选择 Docker 作为运行环境,页面会给出一条带 --token 的命令。只复制令牌部分,保存到项目的 .env:
TUNNEL_TOKEN=粘贴后台给出的隧道令牌
注意:令牌等同于隧道的钥匙,拿到它的人可以冒充你的隧道。不要截图外传,不要提交到 Git。
3. 用 Compose 运行
services:
cloudflared:
image: cloudflare/cloudflared:2026.10.2
command: tunnel --no-autoupdate run
environment:
# 在 Cloudflare 后台创建隧道时给出的令牌,写在 .env 里
TUNNEL_TOKEN: ${TUNNEL_TOKEN}
restart: unless-stopped
# 和 NAS 网页服务在同一台机器时,用 host 网络最简单:路由里填 http://localhost:端口
network_mode: host
docker compose up -d
docker compose logs -f cloudflared
日志里出现 Registered tunnel connection 字样,后台隧道状态变为 Healthy,说明连接成功。
第二步:怎样把 NAS 页面发布出去?
1. 添加路由
在隧道详情页的 Routes 标签点 Add route → Published application:
| 字段 | NAS 管理页 | 相册 |
|---|---|---|
| Subdomain | nas |
photos |
| Domain | example.com |
example.com |
| Service URL | https://192.168.1.10:5001 |
http://192.168.1.10:2342 |
NAS 管理页通常是自签名证书,需要在该路由的 TLS 设置里开启 No TLS Verify,否则 cloudflared 会拒绝连接。
2. 先别急着打开
官方文档说明:添加路由后,互联网上任何人都能访问这个地址。所以下一步必须先加 Access,再把地址告诉家人。
第三步:怎样加上登录保护?
1. 开启邮箱验证码登录
进入 Cloudflare One(Zero Trust)后台,在身份提供方设置(新版后台位于 Integrations → Identity providers)里添加或确认 One-time PIN 登录方式已启用。
2. 创建 Access 应用
在 Access controls → Applications 添加 Self-hosted 应用:
| 设置 | 填写 |
|---|---|
| 应用名称 | 家庭 NAS |
| 应用域名 | nas.example.com,再添加 photos.example.com |
| 会话时长 | 按需要,例如 24 小时 |
| 策略名称 | 家人 |
| 动作 | Allow |
| 规则 | Emails:你和家人的邮箱 |
3. 检查结果
| 操作 | 期望 |
|---|---|
手机关掉 Wi-Fi,用流量打开 https://nas.example.com |
出现 Cloudflare Access 登录页 |
| 输入白名单邮箱 | 收到验证码,登录后进入 NAS |
| 输入其他邮箱 | 收不到验证码或被拒绝 |
访问 https://abc.example.com |
不会进入任何家里的服务 |
后台的隧道和 Access 菜单名称会随版本调整,找不到时用后台顶部的搜索。
第四步:本地管理的配置文件怎么写?
如果你更喜欢把路由规则写在文件里(方便备份和版本管理),可以用本地管理的隧道:
cloudflared tunnel login
cloudflared tunnel create home-nas
cloudflared tunnel route dns home-nas nas.example.com
create 会输出隧道 ID 并生成凭据 JSON 文件。然后编写 config.yml:
# 方式二:本地管理的隧道(cloudflared tunnel create 生成凭据后使用)
tunnel: 6ff42ae2-765d-4adf-8112-31c55c1551ef
credentials-file: /etc/cloudflared/6ff42ae2-765d-4adf-8112-31c55c1551ef.json
ingress:
# NAS 管理页面
- hostname: nas.example.com
service: https://192.168.1.10:5001
originRequest:
noTLSVerify: true # NAS 用的是自签名证书
# 家庭相册
- hostname: photos.example.com
service: http://192.168.1.10:2342
# 兜底规则:其他请求一律 404,必须放在最后
- service: http_status:404
1. 校验规则
cloudflared tunnel --config config.yml ingress validate
cloudflared tunnel --config config.yml ingress rule https://nas.example.com/
本文实际输出:
Validating rules from config.yml
OK
Matched rule #0 hostname: nas.example.com service: https://192.168.1.10:5001
https://photos.example.com/album 匹配到规则 #1,https://other.example.com/ 匹配到兜底的 404 规则 #2。
2. 运行
cloudflared tunnel --config config.yml run home-nas
本地管理和后台管理二选一即可,不要对同一条隧道混用。
出问题时该怎么调?
1. 校验报错 The last ingress rule must match all URLs
本文故意删掉兜底规则后得到:
Validation failed: The last ingress rule must match all URLs (i.e. it should not have a hostname or path filter)
在 ingress 最后加一条不带 hostname 的规则,例如 - service: http_status:404。
2. 打开网页显示 502 Bad Gateway
| 原因 | 检查 |
|---|---|
| 服务地址写错 | 在运行 cloudflared 的机器上 curl -k https://192.168.1.10:5001 |
| 容器网络隔离 | 用 network_mode: host,或确保容器能访问 NAS 的局域网地址 |
| 自签名证书 | 开启 No TLS Verify |
| HTTP 和 HTTPS 写反 | 按 NAS 实际协议填写 |
3. 隧道一直是 Inactive 或 Down
查看 docker compose logs cloudflared。常见原因是令牌复制不完整,或者网络拦截了出站的 7844 端口。按官方“连通性预检查”文档排查。
4. 家人收不到验证码
检查邮箱是否在策略的 Emails 列表里、是否被归入垃圾邮件。不在白名单的邮箱不会收到验证码,这是正常的安全行为。
常见问题怎么处理?
| 现象 | 原因 | 解决方法 |
|---|---|---|
| 证书错误 | 用了多级子域名如 a.b.example.com |
用一级子域名,或按文档申请高级证书 |
| 登录后又跳回登录页 | 浏览器拦截第三方 Cookie | 允许该域名的 Cookie |
| NAS 的手机 App 连不上 | App 不支持 Access 登录页 | App 只在家里用局域网地址,或查官方的服务令牌方案 |
| 上传大文件失败 | 经过 Cloudflare 有请求体大小限制 | 大文件在局域网内传 |
| 想临时关闭外网访问 | 不需要时 | docker compose stop cloudflared |
| 视频卡顿 | 经过隧道多绕一段路 | 局域网内直接访问 NAS 地址 |
项目资源
建议先发布一个不重要的服务(比如 Homepage 首页),走完“隧道 → 路由 → Access”三步,用手机流量确认必须登录才能打开。
确认保护生效后,再把 NAS 管理页和相册加进同一个 Access 应用。