banner
约 4,200 字
14 分钟

Cloudflare Tunnel 完全指南:从零搭建到进阶玩法

摘要

本文详细介绍了 Cloudflare Tunnel 内网穿透方案,涵盖从基础操作(Quick Tunnel、Dashboard、配置文件)到进阶玩法(身份认证、SSH 隧道、动态 IP 白名单、速度优化、负载均衡)。文章对比了其优势,并提供了避坑清单,适合希望安全、便捷地暴露内网服务的开发者参考。

前言

一条命令就能让内网服务拥有公网地址,还有自动 HTTPS 和 DDoS 防护——Cloudflare Tunnel 可能是你用过的最省心的内网穿透方案。但这只是冰山一角。本文从最基础的操作开始,逐步解锁多服务路由、身份认证、SSH 隧道、动态 IP 白名单、配置文件模式和速度优化等进阶玩法。

如果你只是想了解Cloudflare Tunnel 最基本的用法,看我之前的文章就可以了,五分钟就可以设置完成,这篇文章主要是为了记录我最近的学习成果,现在用不到的功能以后也许就用到了。

无公网ip免费内网穿透最安全方案-cloudflare-tunnel-增加加速方案


一、它到底是什么

传统内网穿透的逻辑是"打洞"——开放端口,让外部流量直接钻进来。Cloudflare Tunnel 反过来:你的服务器主动往外连,和 Cloudflare 全球边缘网络建立加密长连接;外部用户访问域名时,流量先到 Cloudflare,再沿这条隧道转发回你的本机。
这意味着:

  • 不需要公网 IP

  • 不需要路由器端口映射

  • 源站地址天然隐藏(攻击者扫不到你的真实 IP)

  • 自动 HTTPS(Cloudflare 自动签证书)

  • 自带 WAF + DDoS 防护 + Bot 管理
    一个直觉上的对比:frp / ngrok 是你自己租了一辆出租车,司机是你,路线你定;Cloudflare Tunnel 是你搭上了 Cloudflare 的全球公交系统,免费,班次密,车身自带装甲。


二、基础教程:三种上手路径

根据你的需求急迫程度,有三种起步方式。建议按顺序体验:先用 Quick Tunnel 感受效果,再用 Dashboard 创建正式隧道,最后用配置文件管理多服务。

2.1 Quick Tunnel——30 秒体验

不需要域名,不需要账号,一条命令就能拿到一个临时公网地址。

bash
# 在本地运行一个 Web 服务(比如 Python 起一个静态服务器)
python -m http.server 8080
# 启动 Quick Tunnel
cloudflared tunnel --url http://localhost:8080

输出类似:

纯文本
INF Your quick Tunnel has been created!
Visit it at: https://random-words-trycloudflare.com

浏览器打开这个地址,就能访问你的本地服务了。
适合场景:临时演示、本地调试 webhook、给同事看开发中的页面。
三个限制必须知道

  1. 域名每次重启都会变(随机生成)

  2. 不支持长连接(WebSocket 等可能不稳定)

  3. 并发请求有限制
    所以 Quick Tunnel 只适合临时测试,正式服务请走下一步

2.2 Dashboard 创建正式隧道——绑定自己的域名

这是最推荐的入门方式。全程在 Cloudflare 控制台操作,不需要写配置文件。
前置条件

  • Cloudflare 账号

  • 一个已托管在 Cloudflare 的域名

  • 本机能访问互联网(如果防火墙严格,需确认出站端口 7844 可达)
    步骤
    ① 创建隧道
    进入 Cloudflare Dashboard → Zero Trust → Networks → Tunnels → Create Tunnel
    选择 "Cloudflared",给隧道起个名字(比如 nosp),保存。
    ② 安装 cloudflared
    页面会根据你选择的操作系统生成安装命令。几种常见方式:

bash
# Debian/Ubuntu — 直接用包管理器安装
sudo apt-get update && sudo apt-get install -y cloudflared
# Red Hat / Rocky Linux — RPM 包安装
sudo dnf install -y cloudflared
# macOS — Homebrew
brew install cloudflared
# Windows — 下载 exe 放到 PATH 中
# https://github.com/cloudflare/cloudflared/releases

③ 启动隧道
复制页面给的 Token 命令,在本机执行:

bash
cloudflared service install <TUNNEL_TOKEN>

或者用 Docker(更干净,推荐):

bash
docker run -d --name cloudflared --restart unless-stopped \
  cloudflare/cloudflared:latest tunnel --no-autoupdate run --token <TUNNEL_TOKEN>

Docker Compose 写法更方便管理:

YAML
services:
  cloudflared:
    image: cloudflare/cloudflared:latest
    container_name: cloudflared
    restart: unless-stopped
    command: tunnel --no-autoupdate run --token <YOUR_TUNNEL_TOKEN>

⚠️ TUNNEL_TOKEN 是高危凭据。拿到它的人可以把自己的 cloudflared 接到你的隧道上。绝不提交到公开仓库,绝不截图发到公共论坛。

④ 配置公共主机名
回到 Dashboard,选择你刚创建的隧道,点击 "Configure" → "Public Hostname" → "Add a public hostname"。
填写:

字段

示例

Subdomain

nas

Domain

yourdomain.com

Type

HTTP

URL

localhost:5000

保存后,Cloudflare 自动创建一条 CNAME DNS 记录,把 nas.yourdomain.com 指向 <TUNNEL_ID>.cfargotunnel.com
浏览器打开 https://nas.yourdomain.com ——你的 NAS 面板已经在公网上了,自带 HTTPS。
⑤ 验证隧道健康
Dashboard 上隧道状态变成 Healthy(绿色),说明 cloudflared 已经成功和 Cloudflare 建立连接。

2.3 配置文件模式——管理多服务的最佳方式

当你有超过 2-3 个服务要暴露时,在 Dashboard 上逐个点 "Add hostname" 就变得繁琐。这时候切换到配置文件模式,一切都在 YAML 里管理。
① 登录授权

bash
cloudflared tunnel login

浏览器会打开授权页面,选择你的域名。授权后本地生成 ~/.cloudflared/cert.pem
② 创建隧道

bash
cloudflared tunnel create nosp
# 输出:Tunnel credentials written to ~/.cloudflared/<TUNNEL_ID>.json

记下输出的 <TUNNEL_ID>(UUID 格式)。
③ 写配置文件
创建 ~/.cloudflared/config.yml

YAML
tunnel: <TUNNEL_ID>
credentials-file: ~/.cloudflared/<TUNNEL_ID>.json
ingress:
  # NAS 管理面板
  - hostname: nas.yourdomain.com
    service: http://192.168.1.20:5000
  # Git 服务
  - hostname: git.yourdomain.com
    service: http://192.168.1.30:3000
  # 监控面板
  - hostname: monitor.yourdomain.com
    service: http://localhost:9090
  # AI 本地推理 API
  - hostname: ai.yourdomain.com
    service: http://localhost:11434
  # ⚠️ 兜底规则——必须存在,否则配置校验不通过
  - service: http_status:404

关键规则ingress 按顺序匹配,最后一条必须是兜底规则(没有 hostname 的 catch-all)。官方文档要求如此,否则 cloudflared tunnel ingress validate 会报错。
④ 注册 DNS

bash
cloudflared tunnel route dns nosp nas.yourdomain.com
cloudflared tunnel route dns nosp git.yourdomain.com
cloudflared tunnel route dns nosp monitor.yourdomain.com
cloudflared tunnel route dns nosp ai.yourdomain.com

每条命令会在 Cloudflare DNS 里自动创建 CNAME 记录。
⑤ 验证配置 + 启动

bash
# 先验证配置文件语法
cloudflared tunnel ingress validate
# 前台运行(调试阶段)
cloudflared tunnel run nosp
# 确认正常后,安装为系统服务
cloudflared service install

Linux 上会自动注册为 systemd 服务(/etc/systemd/system/cloudflared.service),支持开机自启和自动重启。


三、进阶玩法一:给服务加身份认证

暴露到公网的服务如果没有任何认证,等于裸奔。Cloudflare Tunnel 解决的是"怎么安全连到源站",但不等于自动给你的应用加了登录系统。
NAS 面板、Git 后台、数据库管理界面这类敏感服务,必须加一层 Cloudflare Access。

3.1 邮箱认证——最简单的门槛

步骤

  1. Zero Trust → Access → Applications → Add application → Self-hosted

  2. 填写应用名称,添加公共主机名(如 nas.yourdomain.com

  3. 创建访问策略:

    • Action:Allow

    • Include:Emails → 填入允许访问的邮箱地址

  4. 保存策略,关联到应用程序
    效果:访问 nas.yourdomain.com 时,先跳转到 Cloudflare 的认证页面,输入邮箱后收到验证码,验证通过才能进入。不在这个邮箱列表里的人,连页面都看不到。

3.2 OAuth 认证——Google / GitHub 一键登录

策略里把 Include 改为 Identity Provider Groups,选择 Google 或 GitHub 等 IdP。用户一键登录,比邮箱验证码体验更好,也更安全(自带 MFA)。

3.3 多层策略——白名单 + 认证组合

你可以给同一个应用配置多条策略,按优先级执行:

优先级

策略类型

效果

1

Bypass(IP List)

白名单 IP 直接放行,不弹认证

2

Allow(Email)

其他 IP 需邮箱验证

这样做的好处:家里局域网的 IP 可以免认证直通,在外面则必须验证身份。


四、进阶玩法二:SSH 隧道——远程运维的隐藏大招

Cloudflare Tunnel 不只能转发 HTTP。把 SSH 也接进来,你的服务器就不需要开放 22 端口,跨境连接也更稳定。

4.1 服务端配置

bash
# 创建 SSH 阵道
cloudflared tunnel create ssh-tunnel
# 写配置文件
cat > ~/.cloudflared/config.yml <<EOF
tunnel: <TUNNEL_ID>
credentials-file: ~/.cloudflared/<TUNNEL_ID>.json
ingress:
  - hostname: ssh.yourdomain.com
    service: ssh://localhost:22
  - service: http_status:404
EOF
# 注册 DNS
cloudflared tunnel route dns ssh-tunnel ssh.yourdomain.com
# 启动阵道
cloudflared tunnel run ssh-tunnel

4.2 客户端配置

本机安装 cloudflared,然后修改 ~/.ssh/config

纯文本
Host my-server-cf
  HostName ssh.yourdomain.com
  User root
  ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h

之后直接:

bash
ssh my-server-cf

流程是这样的

  1. SSH 客户端调用 cloudflared access ssh 作为 ProxyCommand

  2. 本地 cloudflared 拉起浏览器,完成 Zero Trust 认证

  3. 认证通过后签发访问令牌

  4. 流量沿 Tunnel 到达服务器 localhost:22
    为什么比直连 SSH 更稳定:跨境链路(比如德国到中国联通)经常出现 Connection reset by peer。Tunnel 把 SSH 流量包在 HTTPS 长连接里,绕过了运营商对 22 端口的干扰。
    安全层面:配合 Zero Trust Access,只有指定邮箱 / IdP 账号才能拿到令牌。就算有人知道 ssh.yourdomain.com,也连不上。


五、进阶玩法三:动态 IP 白名单——适配不支持认证的客户端

有些客户端(比如某些 IoT 设备、旧版 App)不支持浏览器认证弹窗。这时候可以用 Cloudflare Worker 做动态 IP 白名单:用户先在浏览器完成一次认证,IP 就被加入白名单,后续请求自动放行。

5.1 原理

  1. 用户访问一个 Worker 注册页面(如 register.yourdomain.com

  2. 完成邮箱 / IdP 认证后,Worker 把用户当前 IP 写入 Cloudflare IP List + KV 存储(带过期时间)

  3. 原服务的 Access 策略里加一条 Bypass(IP List)

  4. 白名单 IP 请求直通,其他 IP 需认证

5.2 部署步骤(使用开源项目)

项目地址:cloudflare_dynamic_ip_list

bash
# 克隆项目
git clone https://github.com/AinzRimuru/cloudflare_dynamic_ip_list.git
# 创建 KV Namespace(存 IP 过期状态)
wrangler kv namespace create IP_WHITELIST
# 在 Zero Trust → Lists → 创建 IP List,记下 ID
# 在 Workers & Pages → 获取 Account ID
# 编辑 wrangler.toml,填入 ID
# 部署 Worker
npx wrangler login
npx wrangler deploy --config config/wrangler.toml

然后在 Zero Trust 里配置:

  1. 原服务的 Access 策略,优先级最高加一条 Bypass(IP List)

  2. Worker 注册页面的 Access 策略,用邮箱或 IdP 认证
    使用方式:浏览器访问注册页面,认证一次,IP 自动入白名单。对于不支持认证的客户端,可以用 iOS 快捷指令 / cron 任务带 CF-Access-Client-IdCF-Access-Client-Secret 请求头自动注册。

    注意:自动化任务可能无法控制 IPv 4 / IPv 6 地址,建议多请求几次确保两种地址都被注册。


六、进阶玩法四:速度优化——优选 IP 加速

国内直连 Cloudflare 边缘节点的延迟有时不理想。社区流传的"优选 IP"方案,利用 Cloudflare for SaaS 功能,让用户通过自选的快速 IP(或第三方优选域名)接入你的 Tunnel 服务。

6.1 原理

正常流程:用户 → Cloudflare 边缘(就近节点)→ Tunnel → 源站
优选流程:用户 → 自选快速 IP / 优选域名 → Cloudflare for SaaS 回退到你的域名 → Tunnel → 源站
核心是 Cloudflare for SaaS 的 "Fallback Origin" 机制:你可以把一个域名作为 SaaS 客户的回退源,当外部域名(优选域名)解析到 Cloudflare IP 时,Cloudflare 会把请求路由到你的回退源域名,再沿 Tunnel 转发。

6.2 配置步骤

① 在 Cloudflare 控制台开启 SaaS

  1. 进入 SSL/TLS → Custom SSL/TLS → Edge Certificates → Cloudflare for SaaS

  2. 添加回退源(Fallback Origin):填你的主域名(如 yourdomain.com

  3. 添加自定义主机名(Custom Hostname):填优选域名(如 cdn.bestcf.one
    ② DNS 配置

  • 优选域名的 CNAME 指向你自选的 Cloudflare IP(社区有大量优选 IP 列表)

  • 或者 CNAME 指向已验证的优选域名
    ③ 验证
    Cloudflare for SaaS 会给自定义主机名发一个验证 TXT 记录,按提示在优选域名的 DNS 里添加即可。
    ④ Nginx 反向代理(可选)
    如果想在本机做更细的路由控制,可以在 cloudflared 和源站之间加一层 Nginx:

纯文本
用户 → 优选 IP → Cloudflare for SaaS → Tunnel → Nginx(本机)→ 各服务

Nginx 配置示例:

nginx
server {
    listen 80;
    server_name nas.yourdomain.com git.yourdomain.com;
    location / {
        proxy_pass http://192.168.1.20:5000;  # NAS
    }
}
server {
    listen 80;
    server_name git.yourdomain.com;
    location / {
        proxy_pass http://192.168.1.30:3000;  # Gitea
    }
}

注意:Tunnel 公共主机名里的 URL 填 Nginx 地址(如 http://localhost:80),而不是直接填服务地址。这样 Nginx 做中间层,可以统一管理路由、缓存和 WebSocket 代理。


七、进阶玩法五:负载均衡与高可用

一个 Tunnel 默认维护多条长连接,连到不同的 Cloudflare 数据中心。但你还可以更进一步。

7.1 多实例冗余

原理:多个 cloudflared 实例可以连接到同一个隧道 UUID。Cloudflare 会自动在多个实例之间分发流量。

bash
# 在服务器 A 上
cloudflared tunnel run nosp
# 在服务器 B 上(相同配置、相同 Token)
cloudflared tunnel run nosp

Dashboard 上会显示两个连接都 Healthy。如果 A 挂了,流量自动走 B。

7.2 多隧道分工

不同环境用不同隧道,互不影响:

bash
cloudflared tunnel create dev-tunnel    # 开发环境
cloudflared tunnel create prod-tunnel   # 生产环境

每个隧道有独立的 config.yml、独立的 credentials-file、独立的 DNS 路由。


八、避坑清单

踩过的坑都帮你整理好了:

8.1 本地服务监听地址不对

如果你的服务只监听容器内部地址(如 127.0.0.1:8080 而非 0.0.0.0:8080),cloudflared 在另一个容器里可能连不上。
排查:在运行 cloudflared 的机器上 curl 你的服务地址,如果本机都访问不了,Tunnel 也转发不了。

8.2 防火墙拦了出站连接

Tunnel 不需要入站端口,但 cloudflared 需要主动连出去。公司网络、云安全组如果拦截了出站流量(尤其是端口 7844),隧道会一直显示 Unhealthy。
排查:检查出站策略,确认能访问 Cloudflare 的连接端口。

8.3 域名没托管在 Cloudflare

公共主机名需要域名托管在 Cloudflare 才能自动创建 DNS 路由。如果你的域名在别处管理,要么迁移到 Cloudflare,要么手动在原 DNS 服务商添加 CNAME 记录指向 <TUNNEL_ID>.cfargotunnel.com

8.4 Docker 容器网络隔离

cloudflared 容器和服务容器在不同的 Docker network 里时,localhost 互相不通。
解决方案

YAML
# 方案一:同一个 docker-compose 文件,共享网络
services:
  cloudflared:
    image: cloudflare/cloudflared:latest
    network_mode: host  # 直接用宿主机网络
    command: tunnel --no-autoupdate run --token <TOKEN>
# 方案二:手动指定服务容器地址
# ingress 里 URL 写 http://myapp:8080(容器名),不用 localhost

8.5 WebSocket 连不上

某些服务(如 Home Assistant、n8n)依赖 WebSocket。Cloudflare Tunnel 默认支持,但如果中间有 Nginx 代理,需要显式配置 WebSocket 升级头:

nginx
location / {
    proxy_pass http://localhost:8123;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

8.6 Tunnel Token 泄露

Token 一旦泄露,攻击者可以把自己的 cloudflared 接到你的隧道上。建议:

  • 不提交到 Git 仓库

  • 用环境变量传递,不硬编码在 docker-compose.yml 里

  • 定期在 Dashboard 上检查隧道连接数是否异常


九、常用命令速查表

bash
# 创建隧道
cloudflared tunnel create <name>
# 列出所有隧道
cloudflared tunnel list
# 查看隧道详情
cloudflared tunnel info <name>
# 注册 DNS
cloudflared tunnel route dns <name> <hostname>
# 删除隧道
cloudflared tunnel delete <name>
# 前台运行(调试)
cloudflared tunnel run <name>
# 验证配置文件语法
cloudflared tunnel ingress validate
# 测试某条路由规则
cloudflared tunnel ingress rule https://app.yourdomain.com
# 实时查看隧道日志
cloudflared tunnel tail <name>
# Quick Tunnel(临时测试)
cloudflared tunnel --url http://localhost:8080

十、方案对比:什么时候选 Cloudflare Tunnel

特性

Cloudflare Tunnel

frp

Tailscale

是否需要公网 IP

❌ 不需要

✅ 中继服务器需要

❌ 不需要

是否需要域名

✅ 推荐有

❌ 不需要

❌ 不需要

自动 HTTPS

✅ 自动

❌ 需自配

❌ 需自配

DDoS 防护

✅ 自带

❌ 无

❌ 无

身份认证

✅ Access

️ 需自配

✅ 内置

非 HTTP 服务

✅ 需客户端 cloudflared

✅ 原生支持

✅ 原生支持

速度(国内)

中等(可优选 IP 加速)

快(自选节点)

快(P 2 P+DERP)

适合场景

公开 Web 服务 + 安全暴露

私有内网穿透

私有网络互连

搭配建议:Tailscale 负责私有设备互连(手机连 NAS、开发机连服务器),Cloudflare Tunnel 负责把特定服务公开到域名上(博客、API、演示站)。两者互补,不冲突。


写在最后

Cloudflare Tunnel 的门槛极低——一条命令就能拿到公网地址。但它的天花板远不止于此:

  • Quick Tunnel 是体验入口

  • Dashboard + Docker 是日常用法

  • config.yml + Access 是生产标配

  • SSH 隧道 + 动态 IP 白名单 + 优选 IP 是深度玩家的领地
    从"让本地服务能被外部访问"到"让外部只能以你允许的方式访问",中间的每一步,Cloudflare 都已经把工具准备好了。剩下的,就是你怎么组合它们。


END