一、背景与目标
-
环境:本地虚拟机运行 Rocky Linux,已安装宝塔面板。
-
需求:通过 Cloudflare Tunnel(CF 穿透)实现外网访问宝塔面板及宝塔面板里部署的应用和项目,无需公网 IP、无需开放端口。
-
最终目标:域名
bt.域名.com访问宝塔管理后台,test.域名.com访问宝塔内的网站。
二、基础部署步骤
1. 安装 Docker 与 Docker Compose(宝塔内也可一键安装)
A.登录宝塔面板安装Docker(安装完成后 Docker 和 Docker Compose 会自动安装并启动)。
B.在宝塔面板的 Docker → 设置 中,检查或配置镜像加速地址(例如 https://docker.1ms.run),确保能正常拉取 cloudflare/cloudflared 镜像。
docker pull cloudflare/cloudflared:latest
C.启动宝塔的“容器编排”
-
进入宝塔 → Docker → 容器编排
-
点击 添加编排
-
填入你之前准备的
docker-compose.yaml内容
services:
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared-tunnel
restart: unless-stopped
network_mode: host
environment:
- TUNNEL_TOKEN=你的完整token
command: tunnel --no-autoupdate run
-
点击 保存 并 启动。(注意项目名不要用中文)
2. 获取 Cloudflare Tunnel 的 Token
-
登录 Cloudflare 打开侧边栏的Zero Trust,也可以直接打开链接 Cloudflare Zero Trust
-
点击侧边栏的 网络 → 概述 → 快速操作里的查看全部 → 右侧的弹窗里的创建新 cloudflared 隧道 (网络 → 连接器 → 您的Cloudflare Tunnels页面 → 创建隧道)
-
命名隧道(这个随意填写),点击 保存
-
在 配置 页面中 → 安装并运行连接器 → 选择 Docker → 复制
--token后面的完整字符串(即TUNNEL_TOKEN的值)。
3. 验证隧道是否连接
在 SSH 中查看容器日志:
docker logs cloudflared-tunnel
如果看到 Connected to Cloudflare 或 Registered tunnel,说明隧道已成功连接。
补充:CF这里显示--token后会进入下一页也就是配置添加已发布应用程序路由可以留着不关闭第三步会用到
三、宝塔面板配置(关键点)
1. 记住宝塔的端口与面板口令
-
端口:默认
8888(这个看你安装时自动分配的端口是多少,后期添加已发布应用程序路由时填写在上面) -
面板口令:登录宝塔后台时,网址后面跟着的一串随机字符(如
/590e925e),访问面板必须带上这个口令,否则会显示 404。
2. 面板不要开启 SSL
核心原则:宝塔面板本身不要开启 SSL,不要开启“强制 HTTPS”。否则会导致隧道循环重定向,会一直打不开页面。
3.宝塔内创建项目进行穿透(面板的穿透也要像这样填写)
A.宝塔内创建项目选择端口
创建项目时端口的选择,未被占用的端口即可,因为项目是内网这个随意
B. 隧道中添加 Public Hostname(添加已发布应用程序路由)
网络 → 连接器 → 您的Cloudflare Tunnels页面 → 您创建的连接器隧道 → 配置 → 已发布应用程序路由 → 点击添加已发布应用程序路由正确填写信息
填写以下内容:
C. 宝塔内创建项目进行穿透
C1 创建项目时选择端口
-
在宝塔 网站 列表中创建项目,端口选择未被占用的即可(例如
81、8080)。 -
项目端口随意,内网使用没有限制。
C2 隧道中添加 Public Hostname(添加已发布应用程序路由)
-
进入 Cloudflare Zero Trust → 网络 → 连接器 → 您的 Cloudflare Tunnels 页面 → 点击你创建的连接器隧道
-
进入 配置 → 已发布应用程序路由 → 点击 添加已发布应用程序路由
-
填写以下内容:
| 字段 | 填写内容 |
|---|---|
| 子域名 | test(例如) |
| 域 | 域名.com |
| 完整域名 | test.域名.com |
| 类型 | HTTP(不要选 HTTPS) |
| URL | http://localhost:81(端口号根据你的项目实际端口填写) |
| 路径 | 留空(匹配所有路径) |
注意:
-
类型一定选 HTTP,因为 CF 隧道自带 HTTPS,选 HTTPS 会导致无限重定向。
-
路径留空即可。
-
面板本身的穿透也要这样单独配置一个(子域名例如
bt,URL 填http://localhost:19066),访问时需要在域名后面带上面板口令(如https://bt.域名.com/590e925e),否则会 404。
最后:点击 保存
四、常见错误与解决方案
| 错误现象 | 原因 | 解决 |
|---|---|---|
502 Bad Gateway |
宝塔开启了强制 HTTPS 或证书问题 | 关闭宝塔 SSL,保持 HTTP;CF 设为 Flexible |
404 NOT FOUND |
Nginx 配置错误或面板后端未启动 | bt 22 → bt restart;删除 domain.conf |
DNS_PROBE_FINISHED_NXDOMAIN |
子域名未绑定到隧道 | 进入 CF的DNS 页面,检查 CNAME 记录是否存在且代理状态为“已代理” |
| 容器编排报错“invalid project name” | 项目名包含中文(如“隧道”) | 改英文名(如 suidao) |
拉取镜像卡在 Pulling fs layer |
Docker Hub 网络慢 | 配置镜像加速(如 https://docker.1ms.run) |
| 访问面板显示 404 | 未在域名后加面板口令 | 访问 https://bt.域名.com/面板口令 |
五、关键经验总结
-
本地服务始终用 HTTP,所有 HTTPS 交给 Cloudflare。
-
Cloudflare SSL/TLS 模式选 Flexible(灵活)(对外 HTTPS,对内 HTTP)。
-
隧道内 URL 必须写
http://localhost:端口,不能漏http://。 -
宝塔面板不要配置 SSL,不要开启“强制 HTTPS”。
-
每个要穿透的项目,在隧道中添加一条 Public Hostname(应用程序路由),端口对应项目的端口。
-
使用 Docker 部署隧道时推荐
network_mode: host,避免端口映射麻烦。 -
面板访问需带上口令(如
/590e925e),否则 404。
解释:
network_mode: host 是 Docker Compose 中的一个网络配置项,它的意思是:让容器与宿主机共享同一个网络命名空间。
简单来说,开启这个模式后:
-
容器里的
localhost就是宿主机的localhost。 -
容器可以直接访问宿主机上监听的端口(例如宝塔面板的
19066或项目的81端口),而不需要做端口映射(比如不需要写ports: - 80:80)。 -
容器对外暴露的端口,也等同于宿主机直接暴露该端口。
六、进阶玩法:通过 Cloudflare Tunnel 实现 SSH 远程连接与 WinSCP 文件传输
除了穿透 Web 服务(如宝塔面板),Cloudflare Tunnel 同样可以支持 SSH 远程登录和 SFTP 文件传输,让你像在局域网一样管理服务器。
1. 核心原理:添加 TCP 路由
在 Cloudflare 后台为 SSH 专门添加一条 TCP 类型的 Public Hostname:
-
类型:
TCP -
URL:
tcp://localhost:22(如果服务器 SSH 端口已修改,需改为对应端口,如tcp://localhost:2222) -
子域名:例如
ssh,完整域名为ssh.[您的域名]
2. 本地客户端配置(Windows)
下载 cloudflared-windows-amd64.exe,建议重命名为 cloudflared.exe 并放入 C:\Windows\System32\ 目录,以便全局调用。
-
下载地址:https://github.com/cloudflare/cloudflared/releases/latest
-
在 Assets 列表中找到
cloudflared-windows-amd64.exe,点击下载。
3. 连接 SSH 的命令
方式一:一次性直连(适合临时使用)
方式二:本地端口转发(推荐,连接更稳定)
步骤 A:在 PowerShell 中运行以下命令(保持窗口开启):
cloudflared access tcp --hostname [您的域名] --destination localhost:22 --listener localhost:10022
步骤 B:打开一个新的 PowerShell 窗口,直接连接:
ssh -p 10022 root@localhost
这种方式连接速度更快,无需每次输入长命令,且兼容 WinSCP 等图形化工具。
4. WinSCP 图形化文件传输
通过方式二开启本地端口转发后,在 WinSCP 中填写:
-
WinSCP 官方下载地址:https://winscp.net/
-
文件协议:
SFTP(不要选 FTP) -
主机名:
localhost -
端口:
10022 -
用户名:
root -
密码:服务器的 root 密码
5. SSH 登录自动显示系统信息(美化)
在服务器上安装 neofetch 并设置条件判断,使 SSH 登录时显示彩色系统信息,且不干扰 WinSCP 的 SFTP 握手。
dnf install neofetch -y
echo 'if [ -n "$SSH_TTY" ]; then neofetch; fi' >> ~/.bashrc && source ~/.bashrc
说明:-n "$SSH_TTY" 确保只有交互式 SSH 登录时显示图形,WinSCP 等 SFTP 连接时不会输出字符画,从而避免握手失败报错(如“收到了太大的 SFTP 包”)。
6. 将本地端口转发注册为 Windows 服务(开机自启)
若希望无需手动维护 PowerShell 窗口,可将隧道注册为 Windows 服务(需管理员权限):
New-Service -Name "cloudflared-tunnel" -BinaryPathName "C:\Users\123\Downloads\cloudflared.exe access tcp --hostname [您的域名] --destination localhost:22 --listener localhost:10022" -DisplayName "Cloudflare Tunnel for SSH" -StartupType Automatic
Start-Service -Name "cloudflared-tunnel"
此后,本地 10022 端口将始终可用,任何终端均可通过 ssh -p 10022 root@localhost 直接连接。
7. 常见 SSH/SFTP 问题与解决
| 错误现象 | 原因 | 解决 |
|---|---|---|
websocket: bad handshake |
本地 cloudflared 登录凭证失效或网络握手失败 |
运行 cloudflared tunnel login 重新授权 |
ssh_exchange_identification: Connection closed by remote host |
CF 后台 URL 端口与本地 --destination 端口不一致 |
确保两者端口号完全匹配(默认 22) |
| WinSCP 报错“收到了太大的 SFTP 包” | 登录脚本(如 neofetch)输出了字符画 |
使用条件判断 if [ -n "$SSH_TTY" ]; then ... fi 限制图形仅在交互式 SSH 中显示 |
| 连接速度慢 | 使用了 ProxyCommand 直连方式(每次新建连接) |
改用本地端口转发(--listener),速度可跑满上行带宽 |
8. 关键经验总结
-
端口必须一致:Cloudflare 后台 URL 中的端口(如
tcp://localhost:22)必须与本地命令中的--destination localhost:22完全一致,否则连接会被拒绝。 -
本地转发更适合长期使用:使用
--listener进行本地端口转发后,可通过ssh -p 10022 root@localhost连接,此方式更稳定、连接速度更快,也兼容 WinSCP 等图形化工具。 -
登录脚本需加条件判断:如果配置了
neofetch等登录信息显示工具,务必在~/.bashrc中添加if [ -n "$SSH_TTY" ]判断,避免在 WinSCP 的 SFTP 连接时输出字符画导致握手失败。 -
注册为服务可免手动维护:将本地转发命令注册为 Windows 服务后,每次开机会自动运行,无需每次手动打开窗口,适合长期使用。
-
本地服务用 HTTP,HTTPS 交给 Cloudflare:所有本地服务(如宝塔面板、网站项目)保持 HTTP 协议,Cloudflare 隧道会自动为其添加 HTTPS 加密。
9. 补充
A.上传速度慢的原因
用内网穿透的域名访问宝塔面板上传文件时,速度较慢甚至经常失败,原因如下:
-
流量走 HTTP 代理:宝塔面板的文件上传走的是 HTTP 协议,Cloudflare 免费版对 HTTP 请求大小有限制(通常每个请求不能超过 100MB),且经过 CF 边缘节点中转时会有额外的握手和确认开销。
-
TCP 隧道无此限制:使用 WinSCP 通过 SSH 隧道(SFTP)传输文件时,走的是 TCP 长连接,不经过 HTTP 代理层,不受 CF 上传大小限制,能够直接利用本地带宽,速度更快。
-
内网链接速度正常:如果在内网环境直接访问宝塔面板(如
http://192.168.x.x:8888),不走 Cloudflare 隧道,自然没有上述限制,上传速度就是本地局域网的速度。 -
结论:如果需要远程上传大文件,建议使用 WinSCP 通过 SSH 隧道连接,而不是通过 HTTP 域名访问宝塔面板的文件管理功能。