Cloudflare Tunnel 实践教程

📋 一、 方案概述

Cloudflare Tunnel(原 Argo Tunnel)是一种安全的内网穿透解决方案,它通过在你的内网服务器和 Cloudflare 全球网络之间建立加密隧道,将内网服务安全地暴露到公网。本教程针对 Docker 部署的 MySQL 服务,详细介绍如何通过 Cloudflare Tunnel 实现安全远程访问。

✅ 核心优势

  • 无需公网 IP:服务器可完全位于 NAT 后方
  • 内置安全层:流量在 Cloudflare 网络内加密传输
  • 隐藏源站 IP:外部攻击者无法获取真实服务器地址
  • 免费使用:个人项目和小型团队基本无需付费
  • 支持多种协议:HTTP/HTTPS、TCP、SSH、RDP 等

🔧 二、 准备工作

2.1 必要条件

  1. Cloudflare 账号:免费注册即可
  2. 自有域名 :已接入 Cloudflare DNS 托管(本文以 purelylab.com 为例)
  3. 内网服务器:运行 Docker MySQL 服务的机器
  4. 出站网络:服务器能够访问 Cloudflare 服务(通常无限制)

2.2 检查 Docker MySQL 服务

确保 Docker MySQL 服务正常运行:

bash 复制代码
# 检查 Docker MySQL 容器状态
docker ps | grep mysql

# 检查 MySQL 服务是否监听
docker exec -it mysql mysql -h 127.0.0.1 -P 3306 -u root -p

在您的 Docker 宿主机上执行上述命令


🏗️ 三、 服务端配置(Docker 宿主机)

3.1 创建 Cloudflare Tunnel

  1. 登录 one.dash.cloudflare.com/
  2. 进入 NetworksTunnels
  3. 点击 Create a tunnel
  4. 选择 Cloudflared 作为连接器类型,点击 Next
  5. 输入隧道名称(如 docker-mysql-tunnel),点击 Save tunnel

3.2 安装 cloudflared 客户端

根据服务器系统选择安装方式:

CentOS/RHEL 系统

bash 复制代码
# 下载最新版 cloudflared
wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -O cloudflared

# 添加执行权限
chmod +x cloudflared

# 移动到系统路径
sudo mv cloudflared /usr/local/bin/

# 验证安装
cloudflared --version

Ubuntu/Debian 系统

bash 复制代码
# 添加 Cloudflare 官方源
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /etc/apt/keyrings/cloudflare-main.gpg >/dev/null

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

# 安装 cloudflared
sudo apt-get update
sudo apt-get install cloudflared

3.3 认证并运行隧道

  1. 在 Tunnel 创建页面,复制安装命令(类似以下格式):

    bash 复制代码
    sudo cloudflared service install <YOUR_TUNNEL_TOKEN>
  2. 在服务器上执行该命令,cloudflared 将作为系统服务安装并自动启动

  3. 返回 Cloudflare 控制台,点击 Next ,隧道状态应显示为 Active (HEALTHY)

3.4 配置 MySQL 隧道路由

  1. 在隧道配置页面,切换到 Public Hostnames 标签
  2. 点击 Add a public hostname
  3. 按以下配置填写:
    • Subdomain : mysql(或自定义前缀,如 dbmysql-prod
    • Domain : 选择你的域名(如 purelylab.com
    • Type : TCP关键:必须选择 TCP,不是 HTTP
    • URL : tcp://127.0.0.1:3306(如果 Docker MySQL 映射到宿主机 3306 端口)
      • 如果 MySQL 容器映射到其他端口:tcp://127.0.0.1:<映射端口>
  4. 点击 Save endpoint

💻 四、 客户端配置(访问端)

4.1 安装 cloudflared 客户端

Windows 系统

  1. 访问 github.com/cloudflare/...
  2. 下载 cloudflared-windows-amd64.exe
  3. 将文件重命名为 cloudflared.exe
  4. 复制到系统路径:C:\Windows\System32\
  5. 验证安装:打开 PowerShell 或 CMD,输入 cloudflared --version

macOS 系统

bash 复制代码
brew install cloudflare/cloudflare/cloudflared

Linux 系统

参考服务端安装步骤。

4.2 建立本地 TCP 代理

powershell 复制代码
# 在任意 PowerShell 或 CMD 窗口中执行
cloudflared access tcp --hostname mysql.purelylab.com --listener 127.0.0.1:3306

参数说明

  • --hostname: Cloudflare 控制台中配置的完整域名
  • --listener: 本地监听的地址和端口

4.3 创建便捷启动脚本

Windows 一键启动脚本

创建 启动MySQL隧道.bat

bash 复制代码
@echo off
echo 正在启动 MySQL Cloudflare 隧道...
cloudflared access tcp --hostname mysql.purelylab.com --listener 127.0.0.1:3306
pause

创建 后台启动MySQL隧道.bat(无窗口):

bash 复制代码
@echo off
start /B cloudflared access tcp --hostname mysql.purelylab.com --listener 127.0.0.1:3306
echo 隧道已在后台启动,可关闭此窗口
timeout /t 3

Linux/macOS 后台服务

bash 复制代码
# 创建服务文件
sudo tee /etc/systemd/system/cloudflared-mysql.service > /dev/null << EOF
[Unit]
Description=Cloudflare Tunnel for MySQL
After=network.target

[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/cloudflared access tcp --hostname mysql.purelylab.com --listener 127.0.0.1:3306
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

# 启用并启动服务
sudo systemctl daemon-reload
sudo systemctl enable cloudflared-mysql
sudo systemctl start cloudflared-mysql

🔌 五、 连接 MySQL 数据库

5.1 验证代理状态

bash 复制代码
# 查看 cloudflared 进程
ps aux | grep cloudflared

5.2 使用命令行连接

bash 复制代码
# 通过本地代理连接
mysql -h 127.0.0.1 -P 3306 -u 用户名 -p

5.3 使用图形化工具连接

  1. Navicat/DataGrip/DBeaver/MySQL Workbench 等工具
  2. 连接配置:
    • 主机/Host : 127.0.0.1
    • 端口/Port : 3306
    • 用户名/Username: 你的 MySQL 用户名
    • 密码/Password: 你的 MySQL 密码

5.4 验证连接

执行简单查询验证连接是否正常:

sql 复制代码
SHOW DATABASES;
SELECT VERSION();
SELECT @@hostname as '主机名';

📁 六、 Docker Compose MySQL 配置最佳实践

6.1 Docker Compose 配置示例

创建 docker-compose.yml 文件:

yaml 复制代码
version: '3.8'

services:
  mysql:
    image: mysql:8.0
    container_name: mysql_server
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-StrongPassword123!}
      MYSQL_DATABASE: ${MYSQL_DATABASE:-myapp}
      MYSQL_USER: ${MYSQL_USER:-appuser}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD:-AppUserPass123!}
      TZ: Asia/Shanghai
    ports:
      - "3306:3306"
    volumes:
      - /opt/mysql/data:/var/lib/mysql
      - /opt/mysql/conf:/etc/mysql/conf.d
      - /opt/mysql/logs:/var/log/mysql
      - /opt/mysql/init:/docker-entrypoint-initdb.d
    command: 
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
      - --default-authentication-plugin=mysql_native_password
      - --max_connections=1000
      - --innodb_buffer_pool_size=1G
    networks:
      - mysql_network
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      timeout: 20s
      retries: 10

networks:
  mysql_network:
    driver: bridge

6.2 目录结构说明

csharp 复制代码
/opt/mysql/
├── data/          # MySQL 数据文件
├── conf/          # 配置文件
│   └── custom.cnf # 自定义配置
├── logs/          # 日志文件
├── init/          # 初始化脚本
│   └── 01-init.sql
└── backup/        # 备份目录

6.3 自定义配置文件

创建 /opt/mysql/conf/custom.cnf

ini 复制代码
[mysqld]
# 字符集设置
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

# 连接设置
max_connections = 1000
max_connect_errors = 1000
connect_timeout = 60
wait_timeout = 28800
interactive_timeout = 28800

# 日志设置
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2
log_error = /var/log/mysql/error.log

# InnoDB 设置
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
innodb_flush_log_at_trx_commit = 1
innodb_file_per_table = 1

# 安全设置
skip_name_resolve = 1
local_infile = 0
symbolic-links = 0

6.4 启动 Docker MySQL

bash 复制代码
# 创建目录
sudo mkdir -p /opt/mysql/{data,conf,logs,init,backup}
sudo chmod -R 755 /opt/mysql

# 启动服务
docker-compose up -d

# 查看日志
docker-compose logs -f mysql

🔐 七、 安全最佳实践

7.1 MySQL 权限管理

sql 复制代码
-- 创建专用隧道用户
CREATE USER 'tunnel_user'@'%' IDENTIFIED BY 'StrongTunnelPass123!';

-- 仅授予必要权限
GRANT SELECT, INSERT, UPDATE, DELETE ON your_database.* TO 'tunnel_user'@'%';

-- 创建只读用户(用于监控)
CREATE USER 'monitor_user'@'%' IDENTIFIED BY 'MonitorPass123!';
GRANT SELECT, PROCESS, REPLICATION CLIENT ON *.* TO 'monitor_user'@'%';

-- 查看用户权限
SHOW GRANTS FOR 'tunnel_user'@'%';

7.2 Docker 安全配置

bash 复制代码
# 设置正确的目录权限
sudo chown -R 999:999 /opt/mysql/data
sudo chown -R 999:999 /opt/mysql/logs
sudo chmod 755 /opt/mysql/conf

# 创建专用 Docker 网络
docker network create --subnet=172.20.0.0/16 mysql_network

# 使用非 root 用户运行容器
docker run --name mysql \
  --user 999:999 \
  --network mysql_network \
  --ip 172.20.0.2 \
  --restart unless-stopped \
  -v /opt/mysql/data:/var/lib/mysql \
  -p 127.0.0.1:3306:3306 \
  -e MYSQL_ROOT_PASSWORD=your_secure_password \
  -d mysql:8.0

7.3 Cloudflare Access 策略

  1. 进入 Zero TrustAccessApplications
  2. 点击 Add an application ,选择 Self-hosted
  3. 配置应用:
    • Application name : Docker MySQL Database
    • Domain : mysql.purelylab.com
    • Session Duration: 24h
  4. 创建访问策略:
    • Policy name : Restrict MySQL Access
    • Action : Allow
    • Configure rules :
      • Email matches your-email@domain.com
      • Country equals CN(可选)
  5. 保存后,访问 MySQL 前需通过 Cloudflare Access 验证

7.4 定期维护任务

bash 复制代码
# 备份数据库
docker exec mysql mysqldump -u root -p your_database > /opt/mysql/backup/backup_$(date +%Y%m%d_%H%M%S).sql

# 清理旧备份(保留7天)
find /opt/mysql/backup -name "*.sql" -mtime +7 -delete

# 检查容器健康状态
docker ps --filter "name=mysql" --format "table {{.Names}}\t{{.Status}}"

# 查看资源使用
docker stats mysql --no-stream

🔧 八、 故障排查

8.1 常见问题及解决方案

问题 可能原因 解决方案
隧道状态不健康 cloudflared 服务未运行 sudo systemctl status cloudflared
Docker 容器未启动 端口冲突或配置错误 docker-compose logs mysql
MySQL 连接被拒绝 权限不足或防火墙 检查 MySQL 用户权限和 Docker 端口映射
域名无法解析 DNS 配置错误 检查 Cloudflare DNS 记录
代理连接超时 隧道配置错误 检查 Tunnel 的 Public Hostname 配置
数据目录权限问题 文件系统权限错误 sudo chown -R 999:999 /opt/mysql/data

8.2 检查网络连接

bash 复制代码
# 检查 Docker 网络
docker network inspect mysql_network

# 检查端口监听
sudo netstat -tlnp | grep 3306

# 测试本地连接
mysql -h 127.0.0.1 -P 3306 -u 用户名 -p -e "SELECT 1;"

8.3 查看日志文件

bash 复制代码
# Docker MySQL 日志
docker logs mysql --tail 50

# Cloudflared 服务日志
sudo journalctl -u cloudflared -f

# MySQL 错误日志
docker exec mysql tail -f /var/log/mysql/error.log

8.4 调试命令

bash 复制代码
# 测试 Cloudflare Tunnel
cloudflared tunnel list
cloudflared tunnel info docker-mysql-tunnel

# 验证 DNS 解析
nslookup mysql.purelylab.com
dig mysql.purelylab.com

# 测试 TCP 连接
nc -zv 127.0.0.1 3306

📊 九、 性能监控

9.1 Docker 监控命令

bash 复制代码
# 查看容器资源使用
docker stats mysql

# 查看容器日志大小
docker exec mysql du -sh /var/log/mysql/

# 查看数据库连接数
docker exec mysql mysql -u root -p -e "SHOW STATUS LIKE 'Threads_connected';"

9.2 MySQL 性能监控

sql 复制代码
-- 查看当前连接
SHOW PROCESSLIST;

-- 查看性能指标
SHOW STATUS LIKE 'Connections';
SHOW STATUS LIKE 'Max_used_connections';
SHOW STATUS LIKE 'Threads_connected';

-- 查看慢查询
SHOW VARIABLES LIKE 'slow_query_log';
SHOW VARIABLES LIKE 'long_query_time';

-- 查看 InnoDB 状态
SHOW ENGINE INNODB STATUS\G

9.3 监控脚本示例

创建 /opt/mysql/scripts/monitor.sh

bash 复制代码
#!/bin/bash
# MySQL 监控脚本

DATE=$(date +%Y%m%d_%H%M%S)
LOG_FILE="/opt/mysql/logs/monitor_${DATE}.log"

echo "=== MySQL 监控报告 ===" > $LOG_FILE
echo "时间: $(date)" >> $LOG_FILE
echo "" >> $LOG_FILE

# 检查容器状态
echo "1. Docker 容器状态:" >> $LOG_FILE
docker ps --filter "name=mysql" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" >> $LOG_FILE
echo "" >> $LOG_FILE

# 检查数据库连接
echo "2. 数据库连接状态:" >> $LOG_FILE
docker exec mysql mysql -u monitor_user -pMonitorPass123! -e "SHOW STATUS LIKE 'Threads_connected';" >> $LOG_FILE
echo "" >> $LOG_FILE

# 检查磁盘使用
echo "3. 磁盘使用情况:" >> $LOG_FILE
df -h /opt/mysql >> $LOG_FILE
echo "" >> $LOG_FILE

# 清理旧日志(保留7天)
find /opt/mysql/logs -name "monitor_*.log" -mtime +7 -delete

添加定时任务:

bash 复制代码
# 每天凌晨检查
0 2 * * * /opt/mysql/scripts/monitor.sh

📁 十、 备份与恢复

10.1 自动备份脚本

创建 /opt/mysql/scripts/backup.sh

bash 复制代码
#!/bin/bash
# MySQL 自动备份脚本

BACKUP_DIR="/opt/mysql/backup"
DATE=$(date +%Y%m%d_%H%M%S)
MYSQL_CONTAINER="mysql"
MYSQL_USER="root"
MYSQL_PASS="your_secure_password"

# 创建备份目录
mkdir -p $BACKUP_DIR

echo "开始备份 MySQL 数据库..."

# 备份所有数据库
docker exec $MYSQL_CONTAINER mysqldump \
  -u $MYSQL_USER \
  -p$MYSQL_PASS \
  --all-databases \
  --single-transaction \
  --routines \
  --triggers \
  --events \
  > $BACKUP_DIR/full_backup_$DATE.sql

# 压缩备份文件
gzip $BACKUP_DIR/full_backup_$DATE.sql

# 清理旧备份(保留30天)
find $BACKUP_DIR -name "*.gz" -mtime +30 -delete

echo "备份完成: $BACKUP_DIR/full_backup_${DATE}.sql.gz"

10.2 恢复数据库

bash 复制代码
# 解压备份文件
gunzip /opt/mysql/backup/full_backup_20250101_120000.sql.gz

# 恢复数据库
docker exec -i mysql mysql -u root -p < /opt/mysql/backup/full_backup_20250101_120000.sql

10.3 备份策略

备份类型 频率 保留时间 存储位置
完整备份 每天 30天 本地 /opt/mysql/backup
增量备份 每小时 7天 本地 + 远程存储
逻辑备份 每周 90天 云端存储(可选)

🎯 总结

通过 Cloudflare Tunnel 结合 Docker MySQL,您可以获得一个安全、稳定、易于管理的远程数据库访问解决方案。关键优势包括:

✅ 主要优点

  1. 安全可靠:端到端加密,隐藏源站 IP
  2. 配置简单:无需公网 IP,无需配置路由器
  3. 易于维护:Docker 容器化部署,数据持久化存储
  4. 完全免费:Cloudflare 提供免费套餐

🔧 核心配置步骤

  1. 准备环境:部署 Docker MySQL,配置数据持久化
  2. 创建隧道:在 Cloudflare 控制台创建 Tunnel
  3. 安装代理:在服务器安装 cloudflared
  4. 配置路由:设置 TCP 类型的 Public Hostname
  5. 客户端连接:通过本地代理访问数据库
  6. 安全加固:配置访问策略和权限控制

📁 目录结构总结

bash 复制代码
/opt/mysql/
├── data/          # 数据文件(持久化)
├── conf/          # 配置文件
├── logs/          # 日志文件
├── init/          # 初始化脚本
├── backup/        # 备份文件
├── scripts/       # 管理脚本
└── docker-compose.yml

🚀 进阶功能

  • 多环境部署:开发、测试、生产环境分离
  • 自动备份:定时备份,防止数据丢失
  • 监控告警:实时监控数据库状态
  • 高可用方案:主从复制,读写分离
  • 性能优化:根据业务需求调整配置
相关推荐
倒流时光三十年1 小时前
PostgreSQL VACUUM 清理机制详解
后端
折哥的程序人生 · 物流技术专研2 小时前
《Java面试85题图解版(二)》进阶深化中篇:Spring核心 + 数据库进阶
java·后端·spring·面试
TeamDev2 小时前
在 Excel 加载项中嵌入 Web 视图
前端·后端·.net
Mr_愚人派2 小时前
redis_点评详解(02.短信登录-验证码登录注册)
后端
Xidaoapi2 小时前
5分钟让你的Python项目接入GPT-4:从配置到上线的完整指南
后端
SamDeepThinking2 小时前
写代码不考虑前后兼容,迟早要还的
java·后端·程序员
庞轩px3 小时前
第四篇:SpringBoot自动配置——约定大于配置的底层原理
java·spring boot·后端·spring·自动配置·注解开发
追逐时光者3 小时前
C#/.NET/.NET Core技术前沿周刊 | 第 70 期(2026年5.01-5.10)
后端·.net
程序员清风3 小时前
科普一下:大模型Token的收费逻辑!
java·后端·面试