Cloudflare Tunnel 可以让外部请求通过 Cloudflare 到达运行在内网的服务,而不必在家用路由器上直接开放入站端口。本文用 NAS、Homelab 和开发服务说明基本流程,并区分 Tunnel 的网络连通能力与 Cloudflare Access 的身份访问控制。
资料核对日期:2026-10-22。 Cloudflare Dashboard 与 Zero Trust 菜单可能调整,请以官方文档为准。示例中的域名、服务地址和容器名称都需要替换成自己的值。
工作方式与边界
| 组件 | 解决的问题 | 不能替代什么 |
|---|---|---|
| Cloudflare Tunnel | 把外部 hostname 的流量转发到内网 origin | 不负责判断访问者身份 |
| Cloudflare Access | 根据应用与策略控制哪些身份可访问 | 不负责让 cloudflared 到达 origin |
| Origin 应用认证 | 限制应用内的具体操作和账户权限 | 不替代补丁、网络隔离与备份 |
Cloudflare Tunnel 由内网运行的 cloudflared 主动建立到 Cloudflare 网络的出站连接。配置公开 hostname 后,Cloudflare 可把该 hostname 的请求转发到你指定的本地服务,例如 http://localhost:8080。它不等于把源站变成只对你开放:公开 hostname 默认可能允许任何互联网用户访问。需要登录限制时,另行配置 Cloudflare Access 应用和策略。
这类方案适用于个人网站、NAS Web 控制台前的受控访问、Homelab 服务或临时开发预览。不要把“没有路由器端口转发”误解为“应用自动安全”。应用自身的认证、补丁、最小权限、备份和网络隔离仍然重要。
创建 remotely-managed Tunnel
- 以下步骤专指 Dashboard 管理的 remotely-managed Tunnel;本地管理 Tunnel 的配置流程不同。在 Cloudflare Zero Trust 中进入 Networks / Tunnels(菜单名称可能变化),创建一个 remotely-managed Tunnel。
- 选择运行环境,按 Dashboard 给出的安装说明在 NAS、Linux 主机或容器中运行 cloudflared。
- 对敏感服务,先创建并验证 Cloudflare Access 应用和身份策略,再添加 Published application route;该 route 将 hostname 指向正确的协议和内网地址,例如 http://localhost:8080。公开 hostname 可能允许任何人访问,切勿把“路由已工作”当成访问保护。
- 从外部网络访问 hostname,检查 DNS、证书、应用主机名配置和响应状态。
Dashboard 生成的运行命令或 token 属于敏感凭证:不要粘贴进教程评论、截图、公共仓库或 shell 日志。需要轮换时按 Cloudflare 官方流程处理。
Docker 运行 cloudflared
Cloudflare 官方给出的容器方式可用于运行 remotely-managed Tunnel。生产环境应从 Dashboard 或 Releases 核对当前镜像版本并固定可复现的 tag;不要把真实 token 硬编码进仓库的 Compose 文件。较新的 cloudflared 支持从文件读取 token,可将只读 secret 文件挂载给容器:
export CLOUDFLARED_TAG="替换为已核实的镜像版本"
docker run -d --name cloudflared --restart unless-stopped \
-v /安全存放路径/tunnel-token:/run/secrets/tunnel-token:ro \
"cloudflare/cloudflared:${CLOUDFLARED_TAG}" tunnel --no-autoupdate run \
--token-file /run/secrets/tunnel-token
示例路径需要替换为本机 secret 文件的位置;文件应仅允许管理员读取,并通过安全渠道从 Dashboard 获取和轮换。若当前镜像版本不支持 token-file,按当前官方 Docker 指引选择兼容方式,不要把 token 粘贴到公开终端录屏或提交到版本控制。使用 Compose 时也要避免在仓库提交含凭证的环境文件。
容器启动后,在 Zero Trust Dashboard 查看 Tunnel 连接状态。显示连接正常只说明连接器在线,仍需单独验证 hostname route 和 Access 策略。若源站与连接器都在 Docker 中,把两者放入最小权限的共享网络,以服务名连接应用;不要把不必要的数据库、管理端口一并暴露。
Route 与 Origin 核对
把公开 hostname 映射到服务前,先在 cloudflared 所在主机或容器网络内测试 origin。HTTP origin 例如 http://localhost:8080;若应用启用了 TLS,可按应用证书配置使用 HTTPS origin。Tunnel 终止外部 HTTPS 并代理到内网服务,不代表内网链路与应用本身的认证可以忽略。确认应用允许对应 Host header,生成的链接也使用正确的外部域名。
公网服务上线前,用无登录状态检查目标路径:公开网站可以按预期开放;NAS、开发面板和管理 API 则应先验证 Access 登录与拒绝策略,再开放 hostname。对敏感入口,还要清点其他 DNS 名称、直连公网 IP、端口转发、IPv6 和局域网访问路径,避免只保护其中一个入口。
Cloudflare Access:限制谁可以访问
若管理面板或个人服务不应公开,创建 Access Application,匹配准确的 hostname/path,并配置允许的身份或组策略。发布前至少验证:未登录访问会被拦截或跳转到身份验证;允许的账号登录后才能到达服务;其他 hostname、路径和直连入口不会绕过保护。
Access 和 Tunnel 是两层不同功能:Tunnel 把流量送到服务,Access 根据身份策略决定请求是否放行。只创建 Tunnel 和公开 hostname,不会自动要求访问者登录。对于敏感管理界面,也要检查服务是否还可从 LAN、VPN 或其他公网地址直接访问。
排错:常见 502
Tunnel 显示已连接,但页面是 502
先在运行 cloudflared 的同一网络环境测试 origin URL。确认协议匹配(HTTP/HTTPS)、端口正确,目标进程正在监听,容器网络可达。错误地把容器服务写成 localhost 是常见原因。
连接器无法上线
检查主机时间、DNS、出站防火墙及官方文档要求的连接端口。更新后查看 cloudflared 日志,但分享日志前先移除 hostname、IP、token 和其他敏感信息。
能打开页面,但没有登录保护
检查 Access Application 的 hostname/path 覆盖和策略顺序,并从无会话的浏览器验证。不要只靠 Tunnel 的“已连接”状态判断访问已受限。
上线前检查清单
- 只发布需要的服务和路径,删除不再使用的公开 hostname。
- 管理界面配置 Access 身份策略,并实际测试未认证路径。
- 不在仓库或日志中保存 Tunnel token。
- 检查 origin 应用认证、更新、备份和最小权限。
- 验证从外部网络访问正常,也验证不应访问的身份确实被拒绝。
相关教程
- ai-memory:跨编程助手共享项目记忆:示例展示了把 Homelab 服务与开发客户端连接时需要考虑的访问边界。
官方资料
从一项低风险服务开始,确认 origin 可达、hostname 路由正确,再独立验证身份策略。把连接能力与访问授权分开设计,能更清楚地发现公网暴露风险。