Cloudflare Tunnel 全功能实战指南:公网发布、SSH/RDP、私有网络、Access、高可用与排错


Cloudflare Tunnel 全功能实战指南:公网发布、SSH/RDP、私有网络、Access、高可用与排错

Cloudflare Tunnel 的价值并不只是“内网穿透”。它更像一条由内网主动向 Cloudflare 建立的安全连接:服务器不必拥有公网 IP,也不必在路由器、防火墙或云安全组上开放入站端口,就能把 Web、SSH、RDP、TCP 服务甚至整段私有网段接入 Cloudflare。

我之前已经单独写过一篇 Qwen Agent + Cloudflare Tunnel SSH 的实战教程,那篇文章专门解决“临时容器没有公网端口,如何从 Windows SSH 进去”的问题。本文不会重复那篇文章,而是把 Cloudflare Tunnel 当成一个完整产品来讲,重点回答:它有哪些模式、各种功能分别怎么用、什么时候该用哪一种,以及出现故障时应该从哪一层排查。
本文的功能与命令以 2026-08-09 的 Cloudflare 官方文档为准。示例统一使用 example.com10.10.0.0/16 等保留示例值;Tunnel Token、私钥、真实内网地址都不应直接写进公开博客。

一、先把 Cloudflare Tunnel 的工作方式想清楚

传统公网访问通常是:

Internet
   │
   ▼
公网 IP:开放端口
   │
   ▼
NAT / 防火墙 / 端口映射
   │
   ▼
内网服务

Cloudflare Tunnel 则反过来:

浏览器 / SSH / RDP / WARP 客户端
              │
              ▼
       Cloudflare Edge
              ▲
              │ 加密的出站 Tunnel
              │
        cloudflared
              │
      ┌───────┼────────┐
      ▼       ▼        ▼
   Web:8080 SSH:22  LAN 10.10.0.0/16

关键变化只有一个:不是外面主动打进你的服务器,而是 cloudflared 主动从内网连接 Cloudflare。
这样做有几个直接结果:

  • 源站可以没有公网 IPv4,也可以位于家庭宽带、CGNAT、公司内网、容器或云私网中。
  • 通常不需要把 80/443/22/3389 等端口直接暴露给 Internet。
  • Web 流量可以继续使用 Cloudflare 的 DNS、TLS、WAF、Rules、Access 等能力。
  • SSH、RDP、任意 TCP 也能通过 Tunnel 转发,但客户端接入方式和普通网页不同。
  • 还可以不发布公网域名,而是把整个私有 IP/CIDR 或私有主机名交给 Cloudflare One Client 访问。

需要注意:Tunnel 解决的是连接和入口问题,不会自动修复你的应用鉴权、数据库权限、SSH 配置或 Windows RDP 安全策略。

二、Cloudflare Tunnel 到底有哪几种玩法

实际使用时,最容易混淆的是“Tunnel”这个词下面存在几种管理和接入模式。

模式 适合什么场景 是否需要域名 是否适合长期运行
Quick Tunnel 临时演示、本机开发、把 localhost 临时发给别人 不需要
Remotely-managed Tunnel 大多数正式部署,Dashboard 管理路由和参数 发布公网应用时需要 是,首选
Locally-managed Tunnel 希望配置完全放在 config.yml、CLI/Git 中管理 发布公网应用时需要
Private network routing 远程访问整个私网、IP/CIDR、私有主机名 不一定

Cloudflare 当前对大多数用户推荐 remotely-managed tunnel。它的 Tunnel 配置由 Cloudflare 控制面管理,服务器只需要持有 Tunnel Token 并运行 cloudflared

如果你只是想快速分享 localhost:8080,Quick Tunnel 最省事;如果你想做可维护的正式入口,就应该创建命名 Tunnel。

三、开始前需要准备什么

3.1 最基本的条件

正式发布自己的域名时,通常需要:

  1. 一个 Cloudflare 账号;
  2. 一个已接入 Cloudflare DNS 的域名;
  3. 一台能够主动访问 Internet 的主机;
  4. 在这台主机上运行 cloudflared
  5. 本地真正提供服务的 Web/SSH/RDP/TCP 程序。

如果只是 Quick Tunnel,则连自己的域名都不需要。

3.2 防火墙真正需要放行什么

Cloudflare Tunnel 是出站连接。当前 cloudflared 主要通过 UDP/7844(QUIC)TCP/7844(HTTP/2) 连接 Cloudflare Edge;auto 模式会优先尝试 QUIC,并在 UDP 不可用时回退到 HTTP/2。

因此企业或校园网严格限制出站时,至少要确认 DNS、TCP/UDP 7844 和 Cloudflare 管理接口所需的 HTTPS 能正常访问。

新版本 cloudflared 会在 Tunnel 启动前做连接预检。遇到建链失败时,可以直接执行:

cloudflared tunnel diag

不要只用 curl https://www.cloudflare.com 判断 Tunnel 是否可用:能访问 443 并不代表 7844 一定放行。

四、安装 cloudflared

4.1 Windows 11

如果 Windows Package Manager 中可以正常找到软件包,最方便的是:

winget install --id Cloudflare.cloudflared

安装后验证:

cloudflared --version
where.exe cloudflared

也可以直接从 Cloudflare 官方下载页获取 64 位 EXE 或 MSI。Windows 上的独立 cloudflared 不会自动更新,因此需要自行维护版本。

4.2 macOS

brew install cloudflared
cloudflared --version

4.3 Linux

Cloudflare 官方提供 Package Repository,也提供 amd64、ARM、ARM64 的二进制、.deb.rpm 包。生产环境建议优先使用包管理方式,便于升级和服务管理。

安装完成统一验证:

cloudflared --version
command -v cloudflared

五、实例 1:不用域名,30 秒启动 Quick Tunnel

Quick Tunnel 非常适合临时演示。

假设本机有一个 HTTP 服务监听 127.0.0.1:8080。没有现成服务时,可以临时启动:

python3 -m http.server 8080 --bind 127.0.0.1

另开一个终端:

cloudflared tunnel --url http://127.0.0.1:8080

启动后会得到一个随机的:

https://xxxxxxxx.trycloudflare.com

访问这个地址,请求会经过 Cloudflare 再到你的 127.0.0.1:8080

Quick Tunnel 的优点是零配置、零域名;缺点同样明显:地址随机、生命周期依赖当前进程,也不是为正式生产环境设计的。

因此它适合:临时 Demo、Webhook 调试、手机访问电脑上的开发页面、给同事短时间看一个本地站点。

不适合:长期网站、管理后台、数据库、SSH/RDP 的正式入口。

六、实例 2:正式发布一个本地 Web 服务

这是最常用的 Cloudflare Tunnel 场景。

假设:

域名:app.example.com
源站:127.0.0.1:8080
协议:HTTP

6.1 在 Dashboard 创建 Tunnel

进入 Cloudflare Dashboard 的 Tunnel 页面,创建一个新的 Cloudflare Tunnel,例如:

home-server

选择与你服务器系统对应的安装方式。Dashboard 会给出带 Tunnel Token 的启动命令。

Token 相当于这条 Tunnel 的连接凭据。不要把完整 Token 放进博客、GitHub、截图、聊天记录或 Docker Compose 仓库。

6.2 添加 Published application

在这条 Tunnel 的 Routes 中添加 Published application:

Hostname: app.example.com
Service Type: HTTP
URL: http://127.0.0.1:8080

保存后,Cloudflare 会让该 hostname 指向 Tunnel。其本质是把域名关联到 <Tunnel-UUID>.cfargotunnel.com

6.3 在服务器运行 Tunnel

临时验证时,可以直接使用 Dashboard 给出的命令:

cloudflared tunnel run --token '<TUNNEL_TOKEN>'

长期运行不要一直开着终端,后文会改成系统服务或 Docker。

6.4 分层验证,不要一上来只看公网域名

先在运行 cloudflared 的主机测试源站:

curl -v http://127.0.0.1:8080

本地返回正常后,再看 Tunnel 日志是否出现已注册连接,最后访问:

curl -I https://app.example.com

一个非常重要的排错原则是:Tunnel 显示 Healthy,只能证明 cloudflared 到 Cloudflare 的连接健康,不代表 cloudflared 一定能访问你的 127.0.0.1:8080

因此“Tunnel Healthy,但网站 502”并不矛盾,通常是最后一跳的源站地址、端口、协议或证书有问题。

七、一条 Tunnel 可以同时发布多少种服务

一条 Tunnel 不等于一个端口。你可以给同一个 Tunnel 配置多个 hostname,每个 hostname 指向不同服务。

例如:

公网入口 Tunnel 内部服务 用途
app.example.com http://127.0.0.1:8080 Web 应用
api.example.com http://127.0.0.1:3000 API
grafana.example.com http://127.0.0.1:3001 Grafana
ssh.example.com ssh://127.0.0.1:22 SSH
rdp.example.com rdp://127.0.0.1:3389 RDP
db.example.com tcp://127.0.0.1:5432 PostgreSQL/TCP

Cloudflare 当前 Published application 支持的典型 Service Type 包括:

  • HTTP:例如 http://localhost:8000
  • HTTPS:例如 https://localhost:8443
  • UNIX / UNIX+TLS:直接代理 Unix Socket
  • TCP:任意 TCP 服务
  • SSH
  • RDP
  • SMB
  • HTTP_STATUS:直接返回指定 HTTP 状态码
  • BASTION

需要记住一个边界:HTTP/HTTPS 可以直接让浏览器访问;SSH、RDP、SMB、任意 TCP 这类非 HTTP Published Application,传统客户端通常还需要客户端侧的 cloudflared,或者改用 Cloudflare One Client 的私网路由方案。

八、实例 3:源站本身就是 HTTPS,证书怎么处理

假设本地服务不是 HTTP,而是:

https://127.0.0.1:8443

Published application 的 Service Type 选择 HTTPS,并填:

https://127.0.0.1:8443

如果源站证书是给 internal.example.com 签发的,而你通过 127.0.0.1 连接,就可能出现证书名称不匹配。更合理的处理是配置 Origin Server Name,告诉 cloudflared 期望证书中的服务器名:

Origin Server Name: internal.example.com

如果是私有 CA,也可以让系统信任对应 CA,保持 TLS 验证开启。

8.1 No TLS Verify 为什么不该默认打开

Cloudflare 也提供 noTLSVerify=true,它会直接关闭 cloudflared 到源站这一跳的证书验证。这样自签名证书确实能立刻连通,但也失去了对源站身份的验证。

所以推荐顺序是:

  1. 使用正确的源站证书;
  2. 必要时配置 originServerName
  3. 私有 CA 则正确导入信任链;
  4. 只有明确接受风险时才使用 No TLS Verify

其他常用 Origin 参数还有 connectTimeouttlsTimeouthttpHostHeaderdisableChunkedEncodinghttp2Origin。遇到旧应用、反向代理 Host 头、WSGI 或源站 HTTP/2 问题时,这些参数很有用。

九、实例 4:给管理后台加 Cloudflare Access 登录

如果 app.example.com 是公开博客,直接发布即可;如果它是 Grafana、Portainer、NAS 管理页、内部面板,就不应该只依赖应用自身登录框。

这时可以给 Published Application 前面再加一层 Cloudflare Access:

用户
 │
 ▼
Cloudflare Access 身份验证/策略
 │ 通过
 ▼
Cloudflare Edge
 │
 ▼
Tunnel → 内部 Web 服务

在 Zero Trust 的 Access 中创建 Self-hosted Application,并把域名设为:

admin.example.com

然后建立 Allow 策略,只允许指定身份、用户组或其他条件通过。

这样真正的源站端口仍未公开,而访问者在请求到达内部应用前就先经过 Cloudflare 的身份策略。

9.1 机器调用不要照搬人工网页登录

浏览器用户适合交互式身份认证;CI、脚本、API 客户端等机器流量则应使用适合机器身份的 Service Token / Service Auth 方案,而不是让无人值守程序依赖弹浏览器登录。

Tunnel 与 Access 是两层不同能力:Tunnel 负责把流量送进去,Access 决定谁能进去。

十、实例 5:通过 Tunnel 使用 SSH

SSH 是最典型的非 HTTP 场景。服务端先确保 SSH 真正在本机可用,例如:

ss -lntp | grep ':22'
ssh localhost

然后给 Tunnel 添加 Published application:

Hostname: ssh.example.com
Service Type: SSH
URL: localhost:22

对于管理员入口,建议再创建对应的 Cloudflare Access 应用,而不是仅仅发布 hostname。

10.1 客户端使用 cloudflared + OpenSSH

客户端也安装 cloudflared,然后在 ~/.ssh/config 中加入:

Host ssh.example.com
    User youruser
    ProxyCommand cloudflared access ssh --hostname %h

Windows OpenSSH 同样可以使用这一思路。如果 cloudflared.exe 不在 PATH,可以在 ProxyCommand 中写绝对路径。

之后正常执行:

ssh ssh.example.com

首次访问受 Access 保护的 hostname 时,cloudflared 会启动浏览器完成身份认证,随后 SSH 数据通过 Cloudflare 转入你的内网 SSH Server。

10.2 浏览器里直接打开 SSH

Cloudflare 还支持 browser-rendered SSH。配置好 SSH Published Application 与 Access 后,用户可以从浏览器/App Launcher 打开终端,而不需要本地 SSH 客户端。

这适合临时运维或受控设备,但日常开发通常还是原生 OpenSSH 更顺手。

10.3 私网 SSH:不发布 ssh.example.com

另一种思路是后面要讲的 Private network routing:把 10.10.0.0/16server.internal 路由进 Tunnel,让电脑通过 Cloudflare One Client 接入后直接:

ssh youruser@10.10.0.10

这种方式更像传统 VPN,SSH 自己仍然使用原生密钥认证,不必为每台机器建立一个公网 hostname。

10.4 Access for Infrastructure

如果是团队化运维,还可以使用 Cloudflare Access for Infrastructure:它把目标主机、用户名和 Access 策略结合起来,并支持短期 SSH 证书、会话控制和 SSH 命令日志等能力。

需要注意当前功能边界:某些 SSH 转发能力,例如本地/远程端口转发、Agent Forwarding、X11 Forwarding,并不适用于所有 Access for Infrastructure 场景。决定替换现有堡垒机前,应先核对你的工作流。

如果只是个人服务器,通常“Tunnel + Access + OpenSSH ProxyCommand”或“Private network + 原生 SSH”已经足够。

十一、实例 6:转发任意 TCP——以 PostgreSQL 为例

假设 PostgreSQL 只监听服务器本地:

127.0.0.1:5432

给 Tunnel 添加:

Hostname: db.example.com
Service Type: TCP
URL: localhost:5432

并建议给 db.example.com 配置 Access 策略。

客户端安装 cloudflared 后,先在本机开一个临时监听端口:

cloudflared access tcp --hostname db.example.com --url localhost:15432

然后数据库客户端不再连接公网 db.example.com:5432,而是连接本机:

psql -h 127.0.0.1 -p 15432 -U postgres

链路实际上是:

psql → localhost:15432 → 客户端 cloudflared
     → Cloudflare Access/Tunnel → 服务端 cloudflared
     → localhost:5432 → PostgreSQL

同一方法也可以用于 Redis、MySQL、开发调试端口以及其他基于 TCP 的内部服务。

十二、实例 7:远程连接 Windows RDP

假设内网 Windows 主机已经开启远程桌面,RDP 监听:

localhost:3389

Tunnel 中添加:

Hostname: rdp.example.com
Service Type: RDP
URL: localhost:3389

并给这个 hostname 创建 Access 应用限制访问者。

12.1 使用本地 RDP 客户端

客户端执行:

cloudflared access rdp --hostname rdp.example.com --url rdp://localhost:13389

这里故意使用本地 13389,避免 Windows 本机 3389 已经被 Remote Desktop Service 占用。

随后在 Microsoft Remote Desktop / mstsc 中连接:

localhost:13389

Cloudflare 负责外层身份认证和传输,最终 Windows 仍会使用目标主机自己的 Windows 账号凭据登录。

12.2 直接在浏览器使用 RDP

Cloudflare 当前也支持 browser-based RDP。用户可以从 Access App Launcher 发起连接,不要求客户端安装传统 RDP 软件或 Cloudflare One Client。

这种方式适合临时运维、受限终端或不方便安装客户端的设备;长期桌面办公则要结合体验、键盘映射和组织策略选择。

十三、实例 8:把整个家庭/实验室私网接进来

如果你有很多内网设备,一个个创建 ssh.example.comnas.example.comrdp.example.com 会越来越麻烦。这时更适合 Private network routing

假设服务器所在 LAN 是:

10.10.0.0/16

其中:

10.10.0.10  Linux Server
10.10.0.20  NAS
10.10.0.30  Windows PC
10.10.0.40  PostgreSQL

在 Cloudflare Zero Trust 的 Tunnel/Routes 中创建 Private network route,把:

10.10.0.0/16

路由到这条 Tunnel。

远端电脑安装并登录组织的 Cloudflare One Client,然后确保 Split Tunnel、Gateway 网络策略等允许该网段通过 Cloudflare。

之后应用可以像在局域网里一样直接访问:

ssh user@10.10.0.10
curl http://10.10.0.20:5000
psql -h 10.10.0.40 -U postgres

Windows 远程桌面可以直接连接:

10.10.0.30

这时你不需要为每一种协议配置单独的公网 hostname,Cloudflare Tunnel 更像一个带 Zero Trust 策略的远程私网入口。

13.1 私网模式的两个关键边界

第一,cloudflared 的这条私网 Tunnel 是出站建立、用于接收远端用户请求的。内网服务器自己主动访问 Internet 时,仍然使用它原本的默认路由,不会自动从 Cloudflare Tunnel 出去。

第二,目标内网服务看到的源地址通常是运行 cloudflared 那台机器的本地源 IP,而不是远端笔记本原始地址。因此如果内部数据库或防火墙依赖 Source IP ACL,需要重新设计策略,不能假设客户端真实 LAN IP 会透明保留。

13.2 网段重叠怎么办

如果两个办公室都使用:

192.168.1.0/24

直接建立两条同 CIDR 路由会产生歧义。Cloudflare 提供 Virtual Network 来隔离重叠地址空间。对于多家庭、多实验室、多云 VPC 场景,应该在设计阶段就处理重叠,而不是等路由随机命中后再排错。

十四、实例 9:通过私有主机名访问内部服务

有些内部服务 IP 会变化,或者用户更希望访问:

git.internal.example
nas.internal.example

而不是记 10.10.0.20

Cloudflare Tunnel 支持 private hostname routing。客户端仍使用 Cloudflare One Client,通过 Zero Trust 的 Gateway/DNS 与 Tunnel 把这些私有主机名解析并路由到内部网络。

这种模式适合内部 Git、NAS、开发环境和动态地址服务。与 Published application 不同,它不是把 git.internal.example 发布成一个所有 Internet 用户都能解析并直接访问的普通公网入口。

十五、实例 10:用 Docker 运行 cloudflared

如果服务本来就在 Docker 中,把 cloudflared 也容器化通常更容易维护。

官方镜像基本用法:

docker run --rm cloudflare/cloudflared:latest \
  tunnel --no-autoupdate run --token '<TUNNEL_TOKEN>'

正式部署不建议把 Token 明文写进 Compose。可以保存为仅管理员可读文件:

mkdir -p ./cloudflared
printf '%s' '<TUNNEL_TOKEN>' > ./cloudflared/tunnel-token
chmod 600 ./cloudflared/tunnel-token

compose.yml

services:
  cloudflared:
    image: cloudflare/cloudflared:2026.7.3
    restart: unless-stopped
    command: tunnel --no-autoupdate run --token-file /run/secrets/tunnel-token
    volumes:
      - ./cloudflared/tunnel-token:/run/secrets/tunnel-token:ro

然后:

docker compose up -d
docker compose logs -f cloudflared

固定版本标签有利于可重复部署;升级时再显式修改镜像版本并验证。

15.1 Docker 最容易踩的 localhost

如果 cloudflared 自己在容器里,那么:

http://localhost:8080

指的是 cloudflared 容器自己的 8080,不是宿主机,也不是另一个业务容器。

如果业务服务也在同一个 Compose 网络中,应该直接使用服务名,例如:

services:
  web:
    image: nginx:alpine

  cloudflared:
    image: cloudflare/cloudflared:2026.7.3
    command: tunnel --no-autoupdate run --token-file /run/secrets/tunnel-token

Tunnel 的 Published application 此时可以指向:

http://web:80

如果目标在宿主机,则要使用容器能够访问宿主机的地址,而不是机械地写 127.0.0.1。不同 Linux/Windows Docker 网络模式的宿主机地址不同,应先从 cloudflared 容器内部测试连通性。

调试命令可以用临时容器进入同一网络验证:

curl -v http://web:80

先证明 Docker 网络没问题,再排查 Cloudflare。

十六、让 Tunnel 开机自启:系统服务

Cloudflare 官方建议长期运行时把 cloudflared 作为系统服务,而不是依赖一个打开的终端。

16.1 Remotely-managed Tunnel

Dashboard 为不同系统生成的命令通常会包含 Token。按照 Dashboard 当前给出的命令安装最稳妥,例如 Linux 常见形式为:

sudo cloudflared service install '<TUNNEL_TOKEN>'

安装后检查:

systemctl status cloudflared
journalctl -u cloudflared -n 100 --no-pager

Windows 则应在管理员终端按照 Dashboard/官方 Windows Service 指引安装并检查:

sc.exe query cloudflared

16.2 Locally-managed Tunnel

如果使用本地 config.yml,Linux 可以:

sudo cloudflared --config /home/USER/.cloudflared/config.yml service install
sudo systemctl start cloudflared
sudo systemctl status cloudflared

这里显式写 --config 很重要:使用 sudo$HOME 可能变成 /root,否则服务可能找不到普通用户目录中的配置文件。

十七、实例 11:完全用 config.yml 管理 Tunnel

如果你希望配置可版本化、可审计,或者想理解 Tunnel 的底层 CLI 工作流,可以使用 locally-managed tunnel。

先登录:

cloudflared tunnel login

浏览器授权后会生成账户级 cert.pem。然后创建 Tunnel:

cloudflared tunnel create home-lab
cloudflared tunnel list

记下生成的 Tunnel UUID,并创建 ~/.cloudflared/config.yml

tunnel: 11111111-2222-3333-4444-555555555555
credentials-file: /home/user/.cloudflared/11111111-2222-3333-4444-555555555555.json

ingress:
  - hostname: app.example.com
    service: http://127.0.0.1:8080
  - hostname: api.example.com
    service: http://127.0.0.1:3000
  - hostname: ssh.example.com
    service: ssh://127.0.0.1:22
  - service: http_status:404

最后一条 catch-all 规则非常重要:没有匹配前面 hostname 的请求统一返回 404。

17.1 配置写完先验证,不要直接重启生产服务

cloudflared tunnel ingress validate

还可以测试某个 URL 最终会命中哪条规则:

cloudflared tunnel ingress rule https://app.example.com
cloudflared tunnel ingress rule https://unknown.example.com

为 hostname 创建 DNS 路由:

cloudflared tunnel route dns home-lab app.example.com
cloudflared tunnel route dns home-lab api.example.com
cloudflared tunnel route dns home-lab ssh.example.com

然后运行:

cloudflared tunnel run home-lab

查看详情:

cloudflared tunnel info home-lab

DNS 记录与 Tunnel 进程是独立的:即使 Tunnel 停掉,CNAME 仍会存在。因此“DNS 有记录”不等于 Tunnel 在线。

17.2 Locally-managed Tunnel 同样可以路由私网

配置文件启用 WARP routing:

tunnel: 11111111-2222-3333-4444-555555555555
credentials-file: /home/user/.cloudflared/11111111-2222-3333-4444-555555555555.json
warp-routing:
  enabled: true

添加 CIDR:

cloudflared tunnel route ip add 10.10.0.0/16 home-lab
cloudflared tunnel route ip show

这说明“公网 Published Application”和“私网 IP routing”可以使用同一个 Cloudflare Tunnel 体系,但终端用户的接入方式不同:前者走公网 hostname,后者通常由 Cloudflare One Client 把私网流量送到 Cloudflare。

十八、Tunnel 传输协议与常用运行参数

一般情况下不要为了“优化”而盲目强制协议,默认:

cloudflared tunnel --protocol auto run ...

auto 会优先尝试 QUIC;如果 UDP/7844 不可用,可以回退 HTTP/2。排错时才适合显式测试:

cloudflared tunnel --protocol quic run ...
cloudflared tunnel --protocol http2 run ...

如果 QUIC 必定失败而 HTTP/2 正常,重点检查 UDP/7844;如果两者都失败,则继续检查 TCP/7844、DNS、代理和防火墙。
几个值得知道的运行参数:

参数 作用 使用建议
`–protocol auto quic http2`
`–loglevel info warn error
--logfile PATH 写入日志文件 服务化部署方便留存
--metrics IP:PORT 指定 Prometheus metrics 地址 只绑定可信接口
--grace-period 优雅退出等待时间 长连接服务可关注
--retries 连接失败重试次数 通常保持默认
`–edge-ip-version auto 4 6`
--token-file PATH 从文件读取 Remote Tunnel Token 比命令行明文 Token 更适合长期运行
--no-autoupdate 禁止自身自动更新 Docker/包管理安装常用
--post-quantum 强制 QUIC 使用后量子模式 仅在明确需要时启用

Cloudflare 当前的 QUIC 已具备后量子能力并允许兼容回退;--post-quantum 的意义是强制后量子而不是“开启后量子”。它也不能与 HTTP/2 Tunnel 协议一起使用,因此普通部署不需要为了追新特性盲目加入此参数。

18.1 Debug 日志也可能泄密

--loglevel debug 会记录更多请求/响应信息。公开贴日志前应检查 Authorization、Cookie、Access Header、URL Query、内部 hostname 等敏感内容。

生产环境不要长期把 debug 当默认日志等级。

十九、实例 12:给 Tunnel 做高可用

单机 cloudflared 有一个明显问题:主机重启、进程崩溃、网络断开时,这条 Tunnel 就失去 Connector。

Cloudflare 支持给同一条 Tunnel 运行多个 replica。对于 remotely-managed Tunnel,可以在第二台能够访问相同后端网络的主机上使用同一 Tunnel Token 启动另一个 cloudflared

例如:

         Cloudflare
        /          \
cloudflared-A    cloudflared-B
     │               │
     └────── LAN ────┘
            │
       app:8080

每个 cloudflared 副本自身会建立多条到不同 Cloudflare Edge 的连接。官方当前文档说明,一个副本通常建立 4 条连接,并跨至少两个数据中心;一条 Tunnel 最多可扩展到 25 个 replicas / 100 条连接。

家庭或小型实验室通常两台 Connector 已经足够,重点不是堆副本数量,而是确保:

  • 两台 Connector 都能访问同一个目标服务;
  • Token 与路由配置一致;
  • 业务服务本身也不是单点;
  • 切换时允许已有长连接中断并重新建立。

Replica 解决的是 Connector 可用性,不会自动把一个只存在于 A 本机 127.0.0.1 的服务复制到 B。

二十、监控:日志、状态和 Prometheus Metrics

20.1 先看 Tunnel 状态

Dashboard 常见状态包括 Healthy、Inactive、Down、Degraded。状态的含义应结合 Connector 日志与真实业务探测判断,不能只看一个绿色图标。

本地常用:

cloudflared tunnel info <TUNNEL_NAME_OR_UUID>
cloudflared tunnel diag

systemd:

journalctl -u cloudflared -f

Docker:

docker compose logs -f cloudflared

20.2 Prometheus Metrics

cloudflared 启动时会暴露 Prometheus 格式的 metrics endpoint。非容器环境默认尝试 127.0.0.1:20241127.0.0.1:20245 中的可用端口;容器环境默认绑定 0.0.0.0:<PORT>

具体端口应看启动日志,例如:

Starting metrics server on 127.0.0.1:20241/metrics

然后:

curl http://127.0.0.1:20241/metrics

生产环境可以让 Prometheus 抓取该端点,但不要无保护地把 metrics 端口暴露到公网。

二十一、故障排查:按链路分层,不要乱改配置

Tunnel 的完整链路至少有:

客户端
 → DNS / Access
 → Cloudflare Edge
 → Tunnel Connector
 → 本地网络
 → Origin 应用

排错时应从最靠近源站的地方开始。

21.1 Error 1033:Cloudflare 找不到健康 Tunnel Connector

1033 的核心方向是 Cloudflare Edge 无法找到这条 Tunnel 的健康 cloudflared 连接。

检查:

ps aux | grep cloudflared
systemctl status cloudflared
cloudflared tunnel diag

再检查 7844:

  • UDP/7844 是否允许 QUIC;
  • TCP/7844 是否允许 HTTP/2 fallback;
  • DNS 是否正常;
  • 代理、防火墙、校园网出口是否拦截;
  • Tunnel Token/credentials 是否属于正确 Tunnel。

如果进程根本没运行,先修进程;如果进程在持续重连,再修网络。

21.2 Error 502:Tunnel 通了,但 Origin 不通

这是最常见情况。先在 运行 cloudflared 的同一网络上下文里测试:

curl -v http://127.0.0.1:8080

如果 cloudflared 在 Docker,应该从容器网络测试业务服务,而不是在宿主机测试完就认为容器也一定可达。

重点检查:

  • 服务是否真的启动;
  • 端口是否写错;
  • HTTP/HTTPS 是否选反;
  • localhost 是否指错网络命名空间;
  • 服务只绑定 127.0.0.1,但 Connector 在另一台机器;
  • HTTPS 源站证书校验是否失败。

21.3 x509: certificate signed by unknown authority

这说明 cloudflared 连接 HTTPS Origin 时不信任证书链。

正确解决方式优先是:修复证书链、导入私有 CA、配置正确的 Origin Server Name。noTLSVerify 可以快速确认“是不是证书验证导致”,但不应该成为默认永久修复。

21.4 cloudflared service is already installed

一台机器通常只需要一个 cloudflared 系统服务。已经安装服务后,不要为了每个 hostname 再重复 service install

更合理的是在现有 Tunnel/Connector 上增加路由,或者明确卸载/替换旧服务后再重新安装。

21.5 域名解析正常,但访问还是失败

检查 DNS:

nslookup app.example.com

命名 Tunnel 的 Published Application 最终会关联到 <UUID>.cfargotunnel.com。DNS 记录存在并不证明 Connector 在线,也不证明 Origin 正常。

如果手工创建 CNAME,还要确认:

  • hostname 没有与已有 A/AAAA/CNAME 冲突;
  • Tunnel UUID 属于正确的 Cloudflare 账号;
  • Published application 的 hostname 与实际访问域名一致。

21.6 IPv4/IPv6 的 localhost 不一致

某些程序只监听:

127.0.0.1:8080

另一些只监听:

[::1]:8080

不要把 localhost 当成永远等价于 IPv4。排错时显式测试:

curl -v http://127.0.0.1:8080
curl -g -v http://[::1]:8080

在 Tunnel Service URL 中写 IPv6 literal 时必须使用方括号,例如:

http://[2001:db8::1]:8000

21.7 Private network 路由建了,但客户端访问不了

按顺序检查:

  1. Tunnel Connector 是否 Healthy;
  2. CIDR 是否真的路由到正确 Tunnel;
  3. Cloudflare One Client 是否登录正确组织并处于连接状态;
  4. Split Tunnel 是否把目标网段排除掉了;
  5. Gateway Network Policy 是否允许目标协议/端口;
  6. cloudflared 主机本身是否能访问目标 LAN IP;
  7. 内网主机防火墙是否允许来自 Connector 所在网段的连接。

最关键的本地验证,例如目标是 10.10.0.20:5000

curl -v http://10.10.0.20:5000

这条命令应该在运行 cloudflared 的主机执行。连这里都失败,就还没有到 Cloudflare One Client 那一层。

21.8 Access 登录循环或非 HTTP 长连接不稳定

先确认 Access Application 的 hostname、Policy、身份提供方和会话状态正确。

对于自动化或长期非 HTTP 连接,Cloudflare 官方特别提醒:客户端侧 cloudflared access 依赖 WebSocket,持久连接存在意外关闭的可能。长期机器到机器流量应优先考虑 Service Auth 或 WARP/Private network 路由,而不是把交互式浏览器认证硬套在守护进程上。

二十二、安全硬化:Tunnel 不开公网端口,不代表可以不做安全

推荐至少做到下面这些:

  1. Origin 能只监听 localhost 就不要监听 0.0.0.0 如果 cloudflared 与应用同机,Web/SSH 管理服务通常没必要再对整个 LAN 开放。
  2. 管理后台叠加 Access。 Tunnel 负责网络可达,Access 负责身份准入,两者不要混为一谈。
  3. Tunnel Token 按密钥处理。 泄露后应立即在 Cloudflare 侧轮换/重新生成,不要只删 Git 里的那一行。
  4. 不要公开 locally-managed credentials JSON 或 cert.pem cert.pem 具有账户级管理能力,风险甚至高于单条 Tunnel Token。
  5. SSH 继续使用密钥认证。 Tunnel 不能替代 sshd 自身的最小权限、禁用弱口令等配置。
  6. 数据库仍要保留数据库鉴权。 不要因为入口在 Access 后面就创建无密码数据库用户。
  7. HTTPS Origin 优先保持证书验证。 noTLSVerify 仅作为明确权衡后的选项。
  8. Debug 日志不要长期保留。 分享日志前先脱敏 Header、Cookie、Token、域名和内网地址。
  9. Private network 使用 Gateway Policy 做最小网络授权。 不要把整个 /8 网段无条件开放给所有设备。
  10. Quick Tunnel 不用于正式敏感服务。 它的定位就是临时开发和测试。

22.1 Git 仓库应该忽略什么

至少不要提交:

.cloudflared/cert.pem
.cloudflared/*.json
cloudflared/tunnel-token
.env

config.yml 是否可以提交,要看里面有没有秘密。纯 Tunnel UUID、hostname 和非敏感路由通常可以版本化;Token、证书、Service Token Secret 不能。

二十三、常见场景到底该选哪一种方案

场景 A:临时把本地网页发给别人

Quick Tunnel

命令:

cloudflared tunnel --url http://127.0.0.1:8080

场景 B:长期发布个人网站/API

Remotely-managed Tunnel + HTTP/HTTPS Published Application

需要身份保护的后台再加 Access。

场景 C:没有公网 IP 的服务器需要 SSH

个人少量主机:

SSH Published Application + Access + client-side cloudflared

主机很多:

Private network routing + Cloudflare One Client + 原生 SSH

场景 D:远程控制家庭 Windows

可以选择 RDP Published Application + Access,或者把家庭 LAN 作为 Private network 后直接连接内网 IP。

场景 E:远程访问 NAS、数据库和很多内网设备

优先考虑:

Private network routing + Cloudflare One Client + Gateway Policy

而不是为每一个 TCP 端口创建一个公网 hostname。

场景 F:只开放一个数据库给少数管理员

可以使用:

TCP Published Application + Access + cloudflared access tcp

如果数据库连接需要长期保持,或者应用程序是无人值守服务,更适合 Private network/WARP 或 Service Auth 架构。

场景 G:Docker 里同时有多个应用

一条 Tunnel 就可以承载多个服务。让 cloudflared 与业务容器处于可互通的 Docker Network,Published application 使用容器服务名,例如:

http://web:80
http://grafana:3000
http://api:8080

不要为每个容器都机械地运行一份 Tunnel。

二十四、cloudflared 常用命令速查

基础信息

cloudflared --version
cloudflared --help
cloudflared tunnel --help

Quick Tunnel

cloudflared tunnel --url http://127.0.0.1:8080

连接诊断

cloudflared tunnel diag

Locally-managed Tunnel

cloudflared tunnel login
cloudflared tunnel create <NAME>
cloudflared tunnel list
cloudflared tunnel info <NAME_OR_UUID>
cloudflared tunnel ingress validate
cloudflared tunnel ingress rule https://app.example.com
cloudflared tunnel route dns <NAME_OR_UUID> app.example.com
cloudflared tunnel route ip add 10.10.0.0/16 <NAME_OR_UUID>
cloudflared tunnel route ip show
cloudflared tunnel run <NAME_OR_UUID>

客户端 Access

cloudflared access ssh --hostname ssh.example.com
cloudflared access tcp --hostname db.example.com --url localhost:15432
cloudflared access rdp --hostname rdp.example.com --url rdp://localhost:13389

systemd

systemctl status cloudflared
systemctl restart cloudflared
journalctl -u cloudflared -f

二十五、版本升级与维护

Cloudflare 官方当前支持的是相对新的 cloudflared 版本,过旧版本可能错过功能、协议和安全修复。升级时不要只看“能不能启动”,还要考虑长连接会被重启中断。

查看版本:

cloudflared --version

包管理安装应优先使用对应包管理器升级;Docker 则拉取新镜像并滚动替换。

如果直接使用 cloudflared update,更新完成后通常还需要重启对应服务。高可用环境可以先升级一个 replica,确认正常后再处理另一个,从而降低整体中断窗口。

不要把自动更新与业务高可用混为一谈:任何单实例进程重启都可能影响它正在承载的 WebSocket、SSH、RDP 或其他长连接。

二十六、最终选择速查表

你的需求 推荐方案
临时分享 localhost Quick Tunnel
长期公开网站/API Remotely-managed + HTTP/HTTPS
保护 Web 管理后台 Tunnel + Access
单台/少量 SSH SSH Published App + Access + client-side cloudflared
大量 SSH/内网主机 Private network + Cloudflare One Client
单个临时 TCP 服务 TCP Published App + Access
长期数据库/机器连接 Private network 或合适的 Service Auth 架构
Windows RDP RDP Published App + Access,或 Private network
整个家庭/实验室 LAN Private IP/CIDR routing
多 Docker Web 服务 一个 Tunnel + Docker 网络内多个 Service Route
配置必须 GitOps/本地控制 Locally-managed + config.yml
Connector 不能成为单点 同 Tunnel 部署多个 replica

二十七、官方文档与继续阅读

Cloudflare Tunnel 更新较快,涉及版本、参数和产品入口时应以官方文档为最终依据。本文主要核对了以下资料:

总结

Cloudflare Tunnel 最值得掌握的不是某一条启动命令,而是它的分层模型:Connector 负责从内网主动接入 Cloudflare,Route 决定流量送到哪里,Access/Gateway 决定谁有资格访问,Origin 自己仍负责真实的应用安全。

如果只是临时分享页面,用 Quick Tunnel;如果是正式 Web 服务,用 remotely-managed Published Application;如果是 SSH/RDP/TCP 少量入口,可以配合 Access;如果要访问整段家庭、实验室或公司内网,则 Private network routing 往往比给每个端口创建公网域名更自然。

只要排错时始终沿着“客户端 → Cloudflare → Tunnel → Connector → Origin”逐层验证,Cloudflare Tunnel 的大多数问题都能快速定位,而不需要靠反复删除重建 Tunnel 碰运气。


文章作者: 0xdadream
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 0xdadream !
评论
 上一篇
SSH 完整工作流程:从安装、密钥认证到 Config、隧道与排错 SSH 完整工作流程:从安装、密钥认证到 Config、隧道与排错
从 SSH 客户端与服务端安装开始,完整讲清 Host Key、用户密钥、ssh-agent、~/.ssh/config、文件传输、VS Code Remote SSH、端口转发、跳板机、安全加固与系统化排错。
2026-08-09
下一篇 
Qwen Agent + Cloudflare Tunnel:无公网 IP/端口容器 SSH 远程访问完整教程 Qwen Agent + Cloudflare Tunnel:无公网 IP/端口容器 SSH 远程访问完整教程
以 Qwen Agent 临时容器为实战对象,使用 Cloudflare Tunnel 将本地 SSH 服务安全暴露出来,在没有公网 IP、没有开放入站端口的情况下从 Windows 11 直接 SSH 登录。
2026-08-08
  目录