Cloudflare Tunnel 网络问题排查指南
问题现象
日志中出现以下错误:
ERR failed to dial to edge with quic: timeout: no recent network activity
ERR TLS handshake with edge error: EOF
ERR there are no free edge addresses left to resolve to
ERR Connection terminated error="there are no free edge addresses left to resolve to"
原因分析
这是典型的国内网络访问 Cloudflare 边缘节点困难的问题:
- QUIC 协议被限制:Cloudflare 默认使用 QUIC(HTTP/3),但在某些网络环境下连接不稳定
- TLS 握手失败:网络延迟或防火墙导致 TLS 握手超时
- 边缘节点不可达:Cloudflare 的边缘节点 IP 可能被限制访问
解决方案(按优先级)
方案 1:使用 HTTP/2 协议(已配置,推荐)
已自动配置:所有 docker-compose 文件已添加 --protocol http2 参数。
HTTP/2 比 QUIC 更稳定,在国内网络环境下连接成功率更高。
验证:
# 重启容器以应用新配置
docker restart mbe-tunnel-dev
docker restart mbe-cloudflared
# 查看日志,应该看到使用 http2 协议
docker logs mbe-tunnel-dev --tail 20
方案 2:检查并优化 Docker 网络配置
确保容器能正确访问后端服务:
# 检查开发版网络
docker network inspect mbe-dev-network
# 检查生产版网络
docker network inspect mbe-monorepo_default
# 测试容器间通信
docker exec mbe-tunnel-dev ping -c 2 mbe-api-dev
docker exec mbe-cloudflared ping -c 2 mbe-api
方案 3:配置代理(如果需要)
如果您的网络环境需要代理访问外网:
3.1 在 docker-compose 中配置代理
编辑 docker-compose.dev.cloudflare.yml 或 docker-compose.cloudflare.yml:
environment:
- TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN_DEV}
- HTTP_PROXY=http://proxy.example.com:8080
- HTTPS_PROXY=http://proxy.example.com:8080
- NO_PROXY=localhost,127.0.0.1,mbe-api-dev
3.2 配置 Docker 代理
创建或编辑 ~/.docker/config.json:
{
"proxies": {
"default": {
"httpProxy": "http://proxy.example.com:8080",
"httpsProxy": "http://proxy.example.com:8080",
"noProxy": "localhost,127.0.0.1"
}
}
}
方案 4:使用 Cloudflare WARP 客户端(最佳方案)
Cloudflare WARP 是 Cloudflare 提供的 VPN 服务,可以优化访问 Cloudflare 网络。
4.1 安装 WARP
Windows:
- 下载:https://1.1.1.1/
- 安装并启动 WARP
- 启用连接
macOS:
brew install cloudflare-warp
warp-cli register
warp-cli connect
Linux:
# Ubuntu/Debian
curl https://pkg.cloudflareclient.com/pubkey.gpg | sudo gpg --yes --dearmor --output /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/cloudflare-warp-archive-keyring.gpg] https://pkg.cloudflareclient.com/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflare-client.list
sudo apt update
sudo apt install cloudflare-warp
sudo warp-cli register
sudo warp-cli connect
4.2 Docker 使用 WARP 网络
如果 WARP 在宿主机运行,Docker 容器会自动使用 WARP 网络。
验证:
# 重启容器
docker restart mbe-tunnel-dev
docker restart mbe-cloudflared
# 查看日志,应该看到连接成功
docker logs mbe-tunnel-dev --tail 20
方案 5:增加重试和超时配置
创建配置文件 deploy/cloudflared/config-dev.yml:
tunnel: <TUNNEL_ID>
credentials-file: /root/.cloudflared/<TUNNEL_ID>.json
# 使用 HTTP/2 协议
protocol: http2
# 重试配置
retries: 10
grace-period: 30s
# 连接超时配置
originRequest:
connectTimeout: 30s
tcpKeepAlive: 15s
keepAliveConnections: 100
keepAliveTimeout: 90s
noHappyEyeballs: false
ingress:
- hostname: dev.hi-maker.com
service: http://mbe-api-dev:8000
- service: http_status:404
然后在 docker-compose 中使用:
volumes:
- ./deploy/cloudflared/config-dev.yml:/etc/cloudflared/config.yml:ro
command: tunnel --config /etc/cloudflared/config.yml run
方案 6:使用 Cloudflare 的 Argo Tunnel(高级)
如果以上方案都无效,可以考虑使用 Cloudflare 的 Argo Tunnel 服务,它提供更好的网络连接。
验证修复
1. 检查 Tunnel 日志
# 开发版
docker logs mbe-tunnel-dev --tail 50
# 生产版
docker logs mbe-cloudflared --tail 50
成功标志:
INF Registered tunnel connection connIndex=0 connection=xxx event=0 ip=xxx location=xxx protocol=http2
失败标志:
ERR failed to dial to edge
ERR TLS handshake with edge error
2. 检查 Cloudflare Dashboard
- 访问:https://one.dash.cloudflare.com/
- 进入:Networks > Tunnels
- 查看 Tunnel 状态应为 HEALTHY
3. 测试访问
# 测试开发版
curl https://dev.hi-maker.com/api/health
# 测试生产版
curl https://mbe.hi-maker.com/api/health
常见问题
Q1: 重启后仍然连接失败
解决:
- 检查环境变量是否正确加载
- 检查 Token 是否有效
- 尝试使用 WARP 客户端
Q2: 开发版正常,生产版失败
检查:
- 生产版 Token 是否正确
- 生产版 API 服务是否运行
- Cloudflare Dashboard 中的 Service URL 是否正确
Q3: 间歇性连接失败
原因: 网络不稳定
解决:
- 使用 WARP 客户端
- 增加重试次数
- 使用配置文件方式,设置更长的超时时间
推荐配置顺序
- ✅ 使用 HTTP/2 协议(已配置)
- ✅ 检查 Docker 网络配置
- 🔄 如果仍然失败,安装 WARP 客户端
- 🔄 如果 WARP 不可用,配置代理
- 🔄 最后考虑使用配置文件方式
监控建议
定期检查 Tunnel 状态:
# 每天检查一次
docker logs mbe-tunnel-dev --tail 100 | Select-String "ERR"
docker logs mbe-cloudflared --tail 100 | Select-String "ERR"
如果发现大量错误,及时应用上述解决方案。