Windows平台MySQL基于反向SSH的云端转发

本方案通过反向 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 的云转发、查看日志等。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注