← 返回笔记

Cloudflare Tunnel 完整方案

Cloudflare Tunnel 完整方案

本文涵盖两种 tunnel 管理方式:Dashboard 远程管理(推荐)和本地文件管理。两种方式功能等价,区别仅在于配置的存储和维护位置。

相关文档:


两种方式对比

Dashboard 管理(推荐) 本地管理
配置存储位置 Cloudflare 云端 服务器本地 config.yml
增删路由规则 Dashboard 网页操作,实时生效 修改 config.yml,需重启服务
服务器上的文件 仅 systemd service 文件 config.yml + credentials 文件
多机器管理 任意设备登录 Dashboard 即可 需 SSH 进服务器操作
适合场景 绝大多数场景 需要版本控制(GitOps)/离线环境

推荐使用 Dashboard 方式。本地管理方式在需要通过 Git 管理配置、或服务器无法访问 Cloudflare 控制平面等特殊场景下仍有其价值。


前置条件

要求 说明
Cloudflare 账户 已登录 dash.cloudflare.com
域名托管 域名已添加到 Cloudflare(NS 已切换)
服务器 Linux 服务器,能访问外网(无需开放入站端口)
cloudflared 已安装(或按下文步骤安装)

第一步:清理旧环境(如有)

如果之前运行过 cloudflared,先彻底清理再重新配置:

# 停止并卸载旧 systemd 服务
sudo systemctl stop cloudflared
sudo cloudflared service uninstall

# 删除本地配置文件
sudo rm -rf /etc/cloudflared/
rm -rf ~/.cloudflared/

然后进入 Cloudflare Zero Trust → Networks → Tunnels,手动删除 Dashboard 中的旧 tunnel 条目。


第二步:安装 cloudflared

Debian / Ubuntu

# 添加 Cloudflare APT 源
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg \
  | sudo tee /usr/share/keyrings/cloudflare-main.gpg > /dev/null

echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] \
  https://pkg.cloudflare.com/cloudflared $(lsb_release -cs) main" \
  | sudo tee /etc/apt/sources.list.d/cloudflared.list

sudo apt update && sudo apt install cloudflared -y

RHEL / CentOS / Rocky

curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg \
  | sudo tee /usr/share/keyrings/cloudflare-main.gpg > /dev/null

sudo tee /etc/yum.repos.d/cloudflared.repo <<EOF
[cloudflared]
name=Cloudflare
baseurl=https://pkg.cloudflare.com/cloudflared/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkg.cloudflare.com/cloudflare-main.gpg
EOF

sudo yum install cloudflared -y

验证安装

cloudflared --version

方式一:Dashboard 远程管理(推荐)

第三步:在 Dashboard 创建 Tunnel

  1. 打开 Cloudflare Zero Trust
  2. 左侧菜单进入 Networks → Connectors → Cloudflare Tunnels
  3. 点击右上角 + Add a tunnel
  4. Connector type 选择 Cloudflared,点击 Next
  5. 填写 Tunnel name(例如 my-server),点击 Save tunnel

页面会显示安装命令,其中包含你的 tunnel token(eyJ... 开头的长字符串)。

⚠️ 不要直接运行 Dashboard 给出的完整安装命令,它会重新下载 cloudflared。你已经安装好了,只需要复制 token,按下一步操作。

第四步:注册为 systemd 服务

# 将 <TOKEN> 替换为你从 Dashboard 复制的完整 token
sudo cloudflared service install --token <TOKEN>

# 启动并设置开机自启
sudo systemctl start cloudflared
sudo systemctl enable cloudflared
sudo systemctl status cloudflared

状态显示 active (running) 即成功。此时 Dashboard 上 Tunnel 状态应变为 Healthy

service 文件内容示例(自动生成,无需手动编写):

[Service]
ExecStart=/usr/local/bin/cloudflared tunnel run --token eyJ...

第五步:在 Dashboard 配置路由规则

回到 Dashboard,在 Tunnel 详情页选择 Public Hostname 标签 → Add a public hostname

字段 说明 示例
Subdomain 子域名 app
Domain 选择你的域名 example.com
Service Type 本地服务协议 HTTP / HTTPS / SSH
URL 本地服务地址 localhost:8080

点击 Save hostname,Cloudflare 会自动创建 CNAME DNS 记录,无需手动操作。规则实时生效,无需重启 cloudflared

常见 Service 配置示例

# Web 应用(HTTP)
Type: HTTP    URL: localhost:3000

# 反向代理(HTTPS,忽略本地自签名证书)
Type: HTTPS   URL: localhost:443
Additional Settings → TLS → No TLS Verify: 开启

# SSH 远程访问
Type: SSH     URL: localhost:22

# 多个服务:添加多条 hostname,使用不同子域名即可

Token 轮换

当 token 泄露或需要定期轮换时:

  1. Dashboard → Tunnel → EditRefresh token
  2. 复制新 token
  3. 更新 service 文件:
sudo systemctl edit cloudflared --full
# 找到 ExecStart 行,替换 --token 后面的值

sudo systemctl daemon-reload
sudo systemctl restart cloudflared

方式二:本地文件管理

本地管理方式将所有配置保存在服务器上,适合需要 Git 版本控制或 IaC 管理配置的场景。注意:每次修改配置后都需要重启 cloudflared 才能生效。

第三步:登录并授权

cloudflared tunnel login

执行后会打开浏览器,登录 Cloudflare 账户并选择要使用的域名。成功后会在 ~/.cloudflared/cert.pem 生成账户证书。

第四步:创建 Tunnel

# <NAME> 替换为你想要的 tunnel 名称,例如 my-server
cloudflared tunnel create <NAME>

执行后会输出 tunnel UUID,并在 ~/.cloudflared/<UUID>.json 生成 credentials 文件。记录这个 UUID,后续配置会用到。

# 确认 tunnel 已创建
cloudflared tunnel list

第五步:编写 config.yml

/etc/cloudflared/config.yml 创建配置文件:

sudo mkdir -p /etc/cloudflared
sudo nano /etc/cloudflared/config.yml

配置文件内容:

# Tunnel UUID(从上一步获取)
tunnel: <UUID>

# credentials 文件路径
credentials-file: /root/.cloudflared/<UUID>.json

# 日志级别(可选)
loglevel: info

# 路由规则(ingress)
ingress:
  # Web 应用
  - hostname: app.example.com
    service: http://localhost:3000

  # HTTPS 服务(忽略本地证书)
  - hostname: secure.example.com
    service: https://localhost:443
    originRequest:
      noTLSVerify: true

  # SSH 访问
  - hostname: ssh.example.com
    service: ssh://localhost:22

  # 必须有一条 catch-all 规则作为最后一条
  - service: http_status:404

⚠️ ingress 规则按顺序匹配,最后一条 catch-all(无 hostname)是必填项,否则 cloudflared 启动会报错。

常用 originRequest 参数

ingress:
  - hostname: app.example.com
    service: http://localhost:3000
    originRequest:
      connectTimeout: 30s        # 连接超时
      noTLSVerify: false         # 是否跳过证书验证
      httpHostHeader: ""         # 自定义 Host Header
      keepAliveTimeout: 90s      # 长连接保持时间

第六步:创建 DNS 记录

# 为每个 hostname 创建 CNAME 记录,指向 tunnel
cloudflared tunnel route dns <NAME> app.example.com
cloudflared tunnel route dns <NAME> ssh.example.com

这条命令等价于在 DNS 里添加:app.example.com CNAME <UUID>.cfargotunnel.com

第七步:注册为 systemd 服务

# cloudflared 会读取 /etc/cloudflared/config.yml
sudo cloudflared service install

sudo systemctl start cloudflared
sudo systemctl enable cloudflared
sudo systemctl status cloudflared

修改配置后重启

本地管理方式每次修改 config.yml 后必须重启服务才能生效:

sudo systemctl restart cloudflared

(可选)配置 Private Network

两种方式均支持通过 WARP 客户端访问内网 IP 段。

Dashboard 方式:在 Tunnel 详情页选择 Private Network 标签 → Add a private network,填写 CIDR。

本地管理方式:在 config.yml 中添加路由,并执行命令:

# 将内网网段路由到 tunnel
cloudflared tunnel route ip add 10.0.0.0/24 <NAME>

验证访问

# 查看 tunnel 连接状态
sudo journalctl -u cloudflared -f

# 测试域名是否可达
curl -I https://app.example.com

日常运维命令

# 查看服务状态
sudo systemctl status cloudflared

# 查看实时日志
sudo journalctl -u cloudflared -f

# 重启服务
sudo systemctl restart cloudflared

# 更新 cloudflared
sudo apt upgrade cloudflared      # Debian/Ubuntu
sudo yum update cloudflared       # RHEL/CentOS

# 【本地管理】列出所有 tunnel
cloudflared tunnel list

# 【本地管理】删除 tunnel
cloudflared tunnel delete <NAME>

故障排查

现象 排查方向
Dashboard 显示 Inactive 检查 systemctl status cloudflared,查看日志
Dashboard 显示 Down 检查服务器是否能访问 region1.v2.argotunnel.com:7844
502 Bad Gateway 检查本地服务是否在运行,URL 和端口是否正确
SSL 证书错误 开启 noTLSVerify: true 或检查本地证书
端口被拒绝 确认本地服务监听地址(0.0.0.0 vs 127.0.0.1
本地管理:启动报错 检查 ingress 是否缺少 catch-all 规则,credentials 路径是否正确
# 开启 debug 日志排查问题

# Dashboard 方式
sudo cloudflared tunnel --loglevel debug run --token <TOKEN>

# 本地管理方式
sudo cloudflared tunnel --loglevel debug run

架构说明

用户浏览器
    │
    ▼
Cloudflare 边缘节点(全球 CDN)
    │  ← cloudflared 主动建立出站连接,无需开放入站端口
    ▼
cloudflared 守护进程(你的服务器)
    │
    ├── Dashboard 方式:路由规则由 Cloudflare 云端下发
    └── 本地管理方式:路由规则读取本地 config.yml
    │
    ▼
本地服务(localhost:端口)

两种方式共同优势:

  • 无需开放防火墙端口,cloudflared 主动向外建立连接
  • 无需公网 IP,服务器在 NAT 后面也能正常工作
  • 自动 TLS,Cloudflare 边缘负责 HTTPS 证书,origin 可以是纯 HTTP