
Cloudflare Tunnel 反向代理配置指南
在本地开发或自建服务时,我们经常遇到反向代理的需求,如果说有什么比较省心的方案那就是 Cloudflare Tunnel 了,本文就讲讲基于 Cloudflare Tunnel 的反向代理配置。
为什么需要 Cloudflare Tunnel
在本地开发或自建服务时,我们经常遇到这些问题:
- 没有公网 IP:家庭宽带通常是动态 IP,无法直接从外网访问
- 端口映射麻烦:需要在路由器上配置端口转发,且暴露真实 IP
- HTTPS 证书:自签名证书不被信任,申请证书又要域名验证
Cloudflare Tunnel 可以解决这些问题:通过 cloudflared 在本地建立出站连接到 Cloudflare,外部访问通过 Cloudflare 的边缘网络转发到本地服务,全程加密且无需暴露本地 IP。
准备工作
前提条件
- 一个托管在 Cloudflare 的域名(免费账号即可)
- 本地运行的服务(如 Web 服务、API、MCP 服务等)
- macOS 或 Linux 系统
安装 cloudflared
macOS(通过 Homebrew):
1brew install cloudflared
Ubuntu/Debian(推荐方法 - 官方 APT 仓库):
1 2 3 4 5 6 7 8 9 10# 添加 Cloudflare GPG key sudo mkdir -p --mode=0755 /usr/share/keyrings curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null # 添加仓库(以 Ubuntu 22.04 jammy 为例) echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared jammy main' | sudo tee /etc/apt/sources.list.d/cloudflared.list # 更新并安装 sudo apt update sudo apt install cloudflared
注意:如果不是 Ubuntu 22.04,将 jammy 替换为你的发行版代号:
- Ubuntu 20.04:
focal - Ubuntu 24.04:
noble - Debian 11:
bullseye - Debian 12:
bookworm
查看发行版代号:lsb_release -cs
Ubuntu/Debian(备选方法 - 直接下载 deb 包):
1 2wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb sudo dpkg -i cloudflared-linux-amd64.deb
其他 Linux 发行版(直接下载二进制):
1 2 3 4 5 6 7 8 9# AMD64 wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 sudo mv cloudflared-linux-amd64 /usr/local/bin/cloudflared sudo chmod +x /usr/local/bin/cloudflared # ARM64 wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64 sudo mv cloudflared-linux-arm64 /usr/local/bin/cloudflared sudo chmod +x /usr/local/bin/cloudflared
验证安装:
1cloudflared --version
配置步骤
1. 登录 Cloudflare
1cloudflared tunnel login
执行后会打开浏览器,选择要使用的域名并授权。授权成功后,会在 ~/.cloudflared/ 目录下生成 cert.pem 证书文件。
2. 创建 Tunnel
1cloudflared tunnel create my-tunnel
记下输出中的 Tunnel ID(格式:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx),执行成功后会在 ~/.cloudflared/ 目录下生成对应的凭证文件:<tunnel-id>.json。
3. 创建配置文件
在 ~/.cloudflared/ 目录下创建 config.yaml:
1 2mkdir -p ~/.cloudflared vim ~/.cloudflared/config.yaml
单个服务配置示例:
1 2 3 4 5 6 7tunnel: <your-tunnel-id> credentials-file: /home/username/.cloudflared/<tunnel-id>.json ingress: - hostname: app.yourdomain.com service: http://localhost:8080 - service: http_status:404
多个服务配置示例:
1 2 3 4 5 6 7 8 9 10 11tunnel: <your-tunnel-id> credentials-file: /home/username/.cloudflared/<tunnel-id>.json ingress: - hostname: api.yourdomain.com service: http://localhost:8080 - hostname: admin.yourdomain.com service: http://localhost:8081 - hostname: mcp.yourdomain.com service: http://localhost:8087 - service: http_status:404
注意:
- 将
<your-tunnel-id>替换为实际的 Tunnel ID - 将
<tunnel-id>.json替换为实际的凭证文件名 - macOS 路径通常是
/Users/username/.cloudflared/ - Linux 路径通常是
/home/username/.cloudflared/ - 最后一条
service: http_status:404是必需的兜底规则
4. 配置 DNS 路由
为每个域名配置 DNS CNAME 记录:
1 2cloudflared tunnel route dns <tunnel-id> app.yourdomain.com cloudflared tunnel route dns <tunnel-id> api.yourdomain.com
或者手动在 Cloudflare Dashboard 添加:
- 类型:
CNAME - 名称:
app(子域名) - 目标:
<tunnel-id>.cfargotunnel.com - 代理状态:已代理(橙色云朵)
5. 测试运行
手动启动 tunnel 测试:
1cloudflared tunnel run <tunnel-id>
或者使用配置文件名称:
1cloudflared tunnel run my-tunnel
访问配置的域名,确认能正常访问本地服务。测试无误后按 Ctrl+C 停止。
6. 配置自启动服务
macOS 方案
重要提示:macOS 上的已知问题
macOS 上 cloudflared service install 命令存在长期已知 bug(Issue #327、Issue #589、Issue #1200):
- 生成的 plist 文件缺少
tunnel run参数 - 服务启动后会循环报错:
Use cloudflared tunnel run to start tunnel <tunnel-id> - 官方安装命令不可靠
因此建议手动创建 plist 文件而不使用 cloudflared service install。
手动创建 LaunchAgent 配置文件:
1vim ~/Library/LaunchAgents/com.cloudflare.cloudflared.plist
内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.cloudflare.cloudflared</string> <key>ProgramArguments</key> <array> <string>/opt/homebrew/bin/cloudflared</string> <string>tunnel</string> <string>--config</string> <string>/Users/username/.cloudflared/config.yaml</string> <string>run</string> <string>my-tunnel</string> </array> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>StandardOutPath</key> <string>/tmp/cloudflared.out.log</string> <key>StandardErrorPath</key> <string>/tmp/cloudflared.err.log</string> </dict> </plist>
关键配置说明:
- 必须包含
tunnel和run参数:这是官方service install命令生成的 plist 文件缺失的部分 - Intel Mac 的 cloudflared 路径:
/usr/local/bin/cloudflared - Apple Silicon (M1/M2/M3/M4) 的路径:
/opt/homebrew/bin/cloudflared - 使用
which cloudflared确认实际路径 - 将
username替换为实际用户名 - 将
my-tunnel替换为创建 tunnel 时使用的名称
验证配置文件语法:
1plutil -lint ~/Library/LaunchAgents/com.cloudflare.cloudflared.plist
加载服务:
1launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.cloudflare.cloudflared.plist
检查状态:
1 2launchctl list | grep cloudflared tail -f /tmp/cloudflared.out.log
管理命令:
1 2 3 4 5# 停止服务 launchctl bootout gui/$(id -u)/com.cloudflare.cloudflared # 重启服务 launchctl kickstart -k gui/$(id -u)/com.cloudflare.cloudflared
Ubuntu/Linux 方案
创建 systemd 服务文件:
1sudo vim /etc/systemd/system/cloudflared.service
内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13[Unit] Description=Cloudflare Tunnel After=network.target [Service] Type=simple User=your-username ExecStart=/usr/local/bin/cloudflared tunnel --config /home/your-username/.cloudflared/config.yaml run my-tunnel Restart=always RestartSec=5 [Install] WantedBy=multi-user.target
注意:
- 将
your-username替换为实际用户名 - 将
my-tunnel替换为 tunnel 名称 - 确认
cloudflared路径正确(用which cloudflared确认)
启用并启动服务:
1 2 3 4 5 6 7 8 9 10 11 12 13 14# 重新加载 systemd 配置 sudo systemctl daemon-reload # 启用开机自启 sudo systemctl enable cloudflared # 启动服务 sudo systemctl start cloudflared # 查看状态 sudo systemctl status cloudflared # 查看日志 sudo journalctl -u cloudflared -f
管理命令:
1 2 3 4 5 6 7 8 9 10 11 12 13 14# 停止服务 sudo systemctl stop cloudflared # 重启服务 sudo systemctl restart cloudflared # 禁用自启 sudo systemctl disable cloudflared # 卸载服务 sudo systemctl stop cloudflared sudo systemctl disable cloudflared sudo rm /etc/systemd/system/cloudflared.service sudo systemctl daemon-reload
常见问题
1. 服务启动失败
检查步骤:
1 2 3 4 5# macOS tail -20 /tmp/cloudflared.err.log # Linux sudo journalctl -u cloudflared -n 50
常见原因:
- 配置文件路径错误(绝对路径 vs 相对路径)
- Tunnel ID 或名称不匹配
- 凭证文件路径错误
- config.yaml 语法错误(缩进问题)
2. 无法访问服务
排查方法:
1 2 3 4 5 6 7 8# 检查本地服务是否运行 curl http://localhost:8080 # 检查 DNS 配置 nslookup app.yourdomain.com # 查看 tunnel 连接状态 cloudflared tunnel info <tunnel-id>
3. macOS 服务加载报错
如果遇到 Operation not permitted 或其他权限问题:
1 2 3 4 5 6 7 8# 确保文件权限正确 chmod 644 ~/Library/LaunchAgents/com.cloudflare.cloudflared.plist # 如果之前有残留,先清理 launchctl bootout gui/$(id -u)/com.cloudflare.cloudflared 2>/dev/null # 重新加载 launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.cloudflare.cloudflared.plist
4. 配置文件 YAML 格式错误
YAML 对缩进非常敏感,必须使用空格而非 Tab:
1 2 3 4 5 6 7 8 9# 正确 ✓ ingress: - hostname: app.domain.com service: http://localhost:8080 # 错误 ✗(Tab 缩进) ingress: - hostname: app.domain.com service: http://localhost:8080
5. 端口冲突
如果本地服务未启动或端口不对,tunnel 会报错。确保:
1 2 3# 检查端口占用 lsof -i :8080 # macOS netstat -tlnp | grep 8080 # Linux
进阶配置
配置 HTTPS 后端
如果本地服务使用 HTTPS:
1 2 3 4 5ingress: - hostname: secure.yourdomain.com service: https://localhost:8443 originRequest: noTLSVerify: true # 忽略自签名证书
配置非 HTTP 服务(SSH、RDP 等)
1 2 3 4 5ingress: - hostname: ssh.yourdomain.com service: ssh://localhost:22 - hostname: rdp.yourdomain.com service: rdp://localhost:3389
添加自定义 HTTP 头
1 2 3 4 5ingress: - hostname: api.yourdomain.com service: http://localhost:8080 originRequest: httpHostHeader: api.yourdomain.com
总结
Cloudflare Tunnel 提供了一个简单、安全的方式将本地服务暴露到公网:
优点:
- ✅ 无需公网 IP 和端口转发
- ✅ 自动 HTTPS 证书
- ✅ 隐藏真实 IP
- ✅ 免费且无流量限制
- ✅ 支持多种协议(HTTP/HTTPS/SSH/RDP/WebSocket)
适用场景:
- 本地开发环境外网访问
- 自建服务(博客、API、数据库管理工具)
- IoT 设备远程控制
- 临时演示和测试
注意事项:
- Tunnel 本身免费,但流量会经过 Cloudflare CDN
- 配置文件包含敏感凭证,注意权限保护
- 生产环境建议启用 Cloudflare Access 进行访问控制
完整文档参考:
- Cloudflare Tunnel 官方文档:https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/
- MCP 服务配置:https://modelcontextprotocol.io/
本文基于 2026 年 2 月的实践经验整理,部分命令和配置可能随版本更新有所变化。



