本方案通过反向 SSH 隧道(Reverse SSH Tunnel)将 Windows 平台本地 MySQL 数据库暴露到云服务器指定端口(如 23456),从而实现安全、无需公网 IP 的远程数据库访问能力。
〇、架构图
[公网客户端] – 访问1.2.3.4:23456 – [云服务器 (端口转发)] – [反向SSH到本地] – [本地MySQL (127.0.0.1:3306)]
(假设云服务器ip为1.2.3.4
,通过访问云服务器 23456
端口访问本地(Windows)MySQL)
一、准备工作
在云服务器上安装 SSH(大多数 Linux 云主机默认已经启用),确认云服务器的 SSH 是开放的,假设 IP 是 1.2.3.4
,用户名是 ubuntu
。
在本地 Windows 安装 PuTTY 工具包,并确保本地 MySQL 正常运行。
二、端口设置
首先,开放云服务器的 23456
端口。
其次,让 SSH 允许远程端口监听,修改云服务器的 /etc/ssh/sshd_config
,找到或添加这一行:
GatewayPorts yes
然后重启 SSH 服务:
sudo systemctl restart sshd
三、生成 .ppk
私钥文件
将已有的可以连接云服务器的私钥转换为 plink
使用的 .ppk
文件。可以使用 PuTTY 工具包中的 puttygen.exe
把它转换成 .ppk 格式:
打开 puttygen.exe 点击 “Load” → 选择可以连接到云服务器的私钥文件(注意文件类型要选“All Files”),然后点击 “Save private key” 保存为 .ppk
文件。
做好这一步之后,就可以使用 plink.exe
建立反向SSH隧道,公网客户端即可访问到本地的 MySQL 服务器:
plink.exe -ssh ubuntu@1.2.3.4 -i path\to\your_private_key.ppk -N -batch -R 23456:127.0.0.1:3306
其中:
- -ssh ubuntu@1.2.3.4:连接你的云服务器
- -i:指定私钥(.ppk 文件)
- -N:不执行命令,只建立通道
- -batch: 禁止 plink 等待交互
- -R 23456:127.0.0.1:3306:将云服务器的 23456 转发到你本机的 MySQL 端口
通过这行命令已经可以实现本地 MySQL 服务器的远程访问,可以作为临时性的解决方案。
然而,每次都需要在终端中输入命令很是不便,而且通过 plink 的连接也有可能会出现掉线等问题。因此,可以进一步做持久化。
四、持久化运行
本地下载并安装 nssm,注意根据提示下载最新的 prelease build 2.24-101 版本。
配置 nssm 服务,以管理员运行命令行,输入:
nssm install MySQLReverseTunnel
在弹出的窗口中设置:
- Path:plink.exe 路径
- Arguments:
-ssh ubuntu@1.2.3.4 -i C:\path\to\your_key.ppk -N -batch -R 23456:127.0.0.1:3306
- 在”Log on” 标签页勾选 “This account”,设置为你当前的 Windows 用户(比如
.\yourusername
),填入当前用户密码。
设置完成后,在命令行中输入以下命令,防止频繁失败导致 nssm 停止:
nssm set MySQLReverseTunnel AppThrottle 5000
完成后,可以使用以下命令控制 MySQL 反向代理服务的启动和停止:
nssm start MySQLReverseTunnel
nssm stop MySQLReverseTunnel
接下来,创建一个脚本 check_tunnel.ps1
定时检测 SSH 连接是否掉线,在掉线时自动重启服务:
# 强制使用ANSI编码保存此文件(PowerShell 5.1对UTF-8 BOM敏感)
$remoteHost = "1.2.3.4"
$remotePort = 23456
$serviceName = "MySQLReverseTunnel"
$logPath = "<Your-Log-Path>.log"
function Log {
param ([string]$msg)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logDir = Split-Path -Path $logPath -Parent
if (-not (Test-Path -Path $logDir -PathType Container)) {
New-Item -ItemType Directory -Path $logDir -Force | Out-Null
}
Add-Content -Path $logPath -Value "[$timestamp] $msg" -Encoding UTF8
}
try {
$tcp = New-Object System.Net.Sockets.TcpClient
$connectResult = $tcp.BeginConnect($remoteHost, $remotePort, $null, $null)
$waitResult = $connectResult.AsyncWaitHandle.WaitOne(5000, $false) # 5秒超时
if (-not $waitResult) {
throw "连接超时"
}
$tcp.EndConnect($connectResult)
$tcp.Close()
Log "OK 隧道正常(${remoteHost}:${remotePort})"
}
catch {
Log "ERROR 隧道不可达,重启服务:${serviceName}。错误:$($_.Exception.Message)"
& nssm restart $serviceName
}
创建定时任务脚本 setup_task.bat
:
@echo off
set SCRIPT_PATH=<Your-Path-Of-check_tunnel.ps1>
set VBS_PROXY=<Your-Path-Of-run_hidden.vbs>
REM 创建VBScript代理文件(用于彻底隐藏窗口)
echo Set objShell = WScript.CreateObject("WScript.Shell") > "
echo objShell.Run "powershell.exe -ExecutionPolicy Bypass -WindowStyle Hidden -File ""
REM 定时任务调用VBScript而非直接调用PowerShell
schtasks /create /tn "CheckMySQLTunnel" /sc minute /mo 5 /tr "wscript.exe ""
echo 定时任务创建完成(VBS代理无窗口模式)。
pause
其中,set VBS_PROXY=
可以填写任意路径,这个脚本运行时会在你填写的位置生成一个 .vbs
文件。
保存后,运行 setup_task.bat
,Windows 系统中会创建定时检测是否掉线的定时任务,如果掉线的话会自动重启 MySQLReverseTunnel
服务。并且会在设置的路径生成 .log
文件,定期记录检测结果。
之后,如果想要启动和停止 SSH 反向代理 + 定时检查可以用下面两个脚本:
@echo off
echo === 启动 MySQL 反向 SSH 代理 ===
echo [1] 启动服务 MySQLReverseTunnel...
nssm start MySQLReverseTunnel
echo [2] 启用定时任务 CheckMySQLTunnel...
schtasks /change /tn "CheckMySQLTunnel" /enable
echo 启动完成。
pause
@echo off
echo === 停止 MySQL 反向 SSH 代理 ===
echo [1] 停止服务 MySQLReverseTunnel...
nssm stop MySQLReverseTunnel
echo [2] 暂停定时任务 CheckMySQLTunnel...
schtasks /change /tn "CheckMySQLTunnel" /disable
echo 停止完成。
pause
五、图形界面工具
以上内容已经可以实现MySQL的反向SSH代理、定时检测和自动重启功能。如果想要更加直观的话,可以使用 Python 的 PySide6 等库创建图形界面工具,管理 MySQL 的云转发、查看日志等。