Cloudflare Tunnel 完整方案
Cloudflare Tunnel 完整方案
本文涵盖两种 tunnel 管理方式:Dashboard 远程管理(推荐)和本地文件管理。两种方式功能等价,区别仅在于配置的存储和维护位置。
相关文档:
- 多入口容灾架构参见 Oracle 多机集群零公网架构方案
- Tunnel 与 Tailscale 配合使用参见 Tailscale 零公网暴露方案
两种方式对比
| 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
- 打开 Cloudflare Zero Trust
- 左侧菜单进入 Networks → Connectors → Cloudflare Tunnels
- 点击右上角 + Add a tunnel
- Connector type 选择 Cloudflared,点击 Next
- 填写 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 泄露或需要定期轮换时:
- Dashboard → Tunnel → Edit → Refresh token
- 复制新 token
- 更新 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