记一次打通连接 MySQL Server 堵点的组合拳

- 引 -

月黑风高,凌晨三点,屏幕报错:

- 起 -

由于某些原因,我需要从外网访问内网的 MySQL Server。

最直接的方式当然是在路由器配个端口映射,直接将 MySQL 端口暴露出来,但这样风险较大,可能有潜在的 MySQL 漏洞或者弱密码,导致被坑(是的,10 年前被坑过)。

所以对于这类需求我通常会绕一道:

先在网关服务器上搭建一个 shadowsocks server 用于转发:

$ gost -L ss://aes-256-cfb:123456@:8388

注:gost 命令详见 https://github.com/go-gost/gost/

然后在本地起一个 client 做将本地 3309 端口映射到目标服务器的 3306 端口:

$ gost -L tcp://127.0.0.1:3309/mysql.xxx.com:3306 \  -F ss://aes-256-cfb:123456@gateway.xxx.com:8388

最后用 MySQL Client 发起连接,于是就见到了开头的报错:

$ mysql -h 127.0.0.1 -P 3309 -uroot -p123456ERROR 2013 (HY000): Lost connection to server at 'handshake: reading initial communication packet', system error: 11

gost 这个工具我用了好多年,属于轻车熟路了,没想到还能翻车,属实奇怪,必须得查个明白。

- 查 -

首先使用排除法。

先排除链路的连通性问题:目标服务器上也有 Redis,用相同的套路转发了 6379 端口,本地的 Redis Client 可以正常 GET、SET。

$ gost -L tcp://127.0.0.1:6379/mysql.xxx.com:6379 \  -F ss://aes-256-cfb:123456@gateway.xxx.com:8388

然后再使用 socks5 作为网关代理:

# @Gateway$ gost -L socks5://user:pass@:1080

# @Client$ gost -L tcp://127.0.0.1:3309/mysql.xxx.com:3306 \    -F socks5://user:pass@gateway.xxx.com:1080

—— 也能够正常转发。

于是问题就被缩小到了「MySQL协议 + 使用 Shadowsocks 协议转发」这个组合身上了。

然后使用 strace 搞一把:

$ strace mysql -h 127.0.0.1 -P 3309 -uroot -p123456

可以看到,MySQL Client 在创建连接以后,就调用 recv 等待服务端的推送。

MySQL 的官方文档是这么说的:

The initial handshake starts with the server sending the Protocol::Handshake packet.

https://dev.mysql.com/doc/dev/mysql-server/9.1.0/page_protocol_connection_phase.html

符合预期。

然后再看一下 gost 的 log:

- 本地的 gost 确实收到了请求

- 但是 gateway 上的 gost shadowsocks server 却没有收到请求。

也就是说,问题已经被初步定位了:在使用 shadowsocks 协议作为转发代理时,如果客户端不发送消息,实际上并没有和 shadowsocks server 真正建立连接,因此自然无法收到 MySQL Server 的响应(handshake packet)。

那么该如何解决该问题呢?——逃げるは恥だが役に立つ。改用 socks5 转发,立竿见影。

本文完。

socks5 协议虽然不存在上述问题,但其标准实现中,用户名和密码默认是明文传输的,也是个坑。gost 某个较早的版本扩展了一个 tls-auth 方法,一定程度上解决了这个问题,但并不保险 —— 要是遇到个神人用了个早期版本,依然会坑。

这就是一根筋变成两头堵了啊,所以我决定还是得继续磕这个问题。

- 解 -

兵分两路,饱和式救援:一方面给 gost 提 issue(#680),一方面自己也修改代码尝试解决这个问题。

在 gost 加了个几个断点,找到了 foward.go 155 行(就是前面日志截图的位置):

log.Logf("[tcp] %s <-> %s", conn.RemoteAddr(), addr)transport(conn, cc)log.Logf("[tcp] %s >-< %s", conn.RemoteAddr(), addr)

既然客户端不主动发包,我们只要稍稍越俎代庖一下,主动发点啥给服务端,gost 就不得不和 shadowsocks server 建立连接了。但是如果发的报文不符合 MySQL 规范,又会导致服务端报错;以及如果要用这个方案解决其他协议,那就更麻烦了。

不过好在 TCP 协议是允许发送“空报文”的,只发送一个 tcp 头,但是数据为 0 字节:

Image

实测管用。

正准备整理整理,完善下方案(加个参数),给 gost 提个 fix 混个 contributor,issue #680 也收到了 gost 作者 ginuerzh 大佬的回复:

试试加上nodelay参数:https://gost.run/tutorials/protocols/ss/#shadowsocks_1

关联:#319 (comment), #439

https://github.com/go-gost/gost/issues/680

gost 文档的 shadowsocks 章节开头写着:

默认情况下shadowsocks协议会等待请求数据,当收到请求数据后会把协议头部信息与请求数据一起发给服务端。当客户端nodelay选项设为true后,协议头部信息会立即发给服务端,不再等待用户的请求数据。当通过代理连接的服务端会主动发送数据给客户端时(例如FTP,VNC,MySQL)需要开启此选项,以免造成连接异常。

https://gost.run/tutorials/protocols/ss/#shadowsocks_1

- 完 -

这个故事的教训:RTFM —— Return To the F*cking Manual。

<think>嗯,用户想了解通过青鸟云平台后台使用FinalShell连接MySQL的具体配置方法。从用户提供的引用来看,他们可能已经尝试过在虚拟机中安装MySQL并创建远程访问账户的操作,但不确定青鸟云平台的后台是否支持这种操作。用户的核心困惑点应该是:在青鸟云平台环境下,如何打通FinalShell和MySQL连接通路。这需要分两部分解决:连接服务器本身和配置MySQL访问权限。我将在回复中拆解这个问题。从用户给出的参考引用[^1]来看,他们已经掌握部分MySQL配置知识(比如创建远程用户),但对网络架构层面不太熟悉。这里需要特别说明青鸟云和ECS的关系,因为云主机通过虚拟化技术实现了类似物理机的体验,但网络规则更复杂。在回复架构上,我计划先确认可行性(增强用户信心),然后分云主机配置(含端口安全组)、MySQL权限设置、FinalShell连接测试三个步骤说明。对于用户提供的引用[^1],我会转化为适合青鸟云场景的具体命令。考虑到用户技术需求明确,我会在配置步骤加入参数替换说明(比如{ip_address}占位符),避免直接复制出错。最后的测试环节特别重要,因为云环境防火墙规则容易形成隐性障碍。相关问题的设计要覆盖上下游场景:端口修改(云平台常见问题)、root访问风险(安全提醒)、替代工具(扩展认知),这样能形成知识闭环。用户明显是运维/开发角色,问题都集中在工具链使用上,暂时不需要深入讲解原理。</think> 好的,我们详细解释一下如何通过**青鸟云平台**的云主机(ECS)后台,使用**FinalShell**连接其上面安装的**MySQL**数据库。 **核心概念澄清:** 1. **FinalShell**:这是一个强大的**SSH客户端、FTP客户端**和**SFTP客户端**工具,主要用于**连接和管理Linux/Windows服务器本身(操作系统)**。 2. **MySQL**:这是一个**数据库服务**,运行在服务器(操作系统)内部。它有自己的访问协议(默认端口3306)。 3. **青鸟云平台后台**:云平台的管理控制台,提供对云主机(ECS实例)的管理功能(如开关机、查看监控、管理磁盘/安全组/快照等),并**不直接等同于**云主机内部的系统环境。 4. **连接逻辑**: * 你需要先在**青鸟云的ECS实例(虚拟机)**中**安装并运行MySQL**服务。 * **FinalShell**连接到的是这台**ECS实例的操作系统(Linux)**。 * 连接到Linux系统后,你需要在**FinalShell的终端里**使用MySQL命令行客户端(如`mysql`命令)或配置GUI数据库工具(如DataGrip)去连接**本机(localhost)或同网络内其他主机上运行的MySQL服务**。 --- **配置步骤 (通过青鸟云ECS后台 + FinalShell 连接 MySQL):** 1. **在青鸟云ECS实例上安装并运行MySQL服务**: * 登录青鸟云平台后台,找到你的目标云主机(ECS实例)。 * 使用青鸟云提供的“VNC登录”、“WebShell登录”或提前配置好密钥/密码。 * 在**云主机内部的Linux操作系统**上,按照官方文档或通用流程(如用`yum`或`apt`包管理器)安装MySQL服务器(如`mysql-server`或`mariadb-server`)。 * 启动MySQL服务并设置开机自启: ```bash # 适用于 systemd 的系统 (如 CentOS 7+, Ubuntu 16.04+) sudo systemctl start mysqld # 启动服务, 根据安装的包名可能是 mysql 或 mariadb sudo systemctl enable mysqld # 设置开机自启 sudo systemctl status mysqld # 检查状态 ``` 2. **配置MySQL允许远程连接 (关键!)**: * 默认情况下,MySQL的`root`用户通常只允许从`localhost`(即服务器本机)连接。你需要创建一个新用户或修改现有用户允许远程登录(用户提供的引用[^1])。 * 在ECS实例的Linux终端里 (可以通过VNC或WebShell登录),登录MySQL命令行: ```bash mysql -u root -p # 输入初始密码(安装时设定的或查看日志获取临时密码) ``` * **创建/授权远程访问用户 (两种方式二选一):** * **方法一 (推荐):创建新用户并授权** (例如 `remote_user`): ```sql -- 创建用户'remote_user',允许从任何主机('%')连接,使用密码'your_strong_password' CREATE USER 'remote_user'@'%' IDENTIFIED WITH mysql_native_password BY 'your_strong_password'; -- 授予用户所有数据库的所有权限 (根据实际安全要求缩小范围,如 GRANT SELECT ON dbname.* TO ...) GRANT ALL PRIVILEGES ON *.* TO 'remote_user'@'%' WITH GRANT OPTION; -- 刷新权限使设置生效 FLUSH PRIVILEGES; ``` * **方法二 (较简单但安全性稍低):允许root远程访问 (慎用!)**: ```sql -- 修改'root'用户允许从任何主机('%')连接 (替换'your_strong_password'为你的root密码) ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'your_strong_password'; -- 或者,如果'root'@'%'用户不存在,则创建它 (如引用[^1]做法) -- CREATE USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '1234'; -- GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION; FLUSH PRIVILEGES; ``` > **重要安全提示:** 允许`root`用户远程访问是非常高风险的操作,强烈建议仅用于测试或内网安全环境。生产环境务必使用创建专用用户的方式。 3. **配置青鸟云安全组 (核心!)**: * **这是实现远程连接的最关键一步。** 安全组是云平台的虚拟防火墙,控制进出云主机ECS实例的网络流量。 * 登录**青鸟云平台后台**。 * 找到你的目标**ECS实例**。 * 查看该实例关联的**安全组规则**。 * **添加入站规则(Inbound) **: * **协议/端口:** 选择 **`TCP`** 协议,端口填写MySQL服务的默认端口 **`3306`**。 * **授权对象 (源):** * 如果你知道客户端的公网IP,填写 `/32` (例如 `123.123.123.123/32`)。 * 如果客户端IP会变或者测试方便,可以暂时设置成 `0.0.0.0/0` (允许**任何IP访问**)。 **(注意:这是非常不安全的设置!仅用于快速测试,生产环境务必指定具体IP范围!)** * 保存安全组规则。通常新规则会立即生效,如有问题可尝试重启ECS实例。 4. **获取ECS实例公网IP地址**: * 在青鸟云平台后台的ECS实例详情页中,找到该实例的**公网IP地址 (Public IP)**或**弹性公网IP地址 (EIP)**。下这个IP地址。 5. **使用FinalShell连接MySQL (需要在FinalShell中使用数据库客户端)**: * **FinalShell 本身不能像数据库工具那样“连接MySQL”,它必须先连接操作系统。** * **步骤5a: 用FinalShell连接ECS实例 (Linux服务器):** * 打开FinalShell。 * 新建一个 **SSH连接 (Linux)**: * **主机(H):** 填入步骤4获取的 **ECS公网IP地址**。 * **端口(P):** `22` (SSH默认端口)。 * **用户名(U):** Linux系统的用户名 (如 `root`, `ubuntu`, `ecs-user` 等,参考云主机信息)。 * **认证方法:** 选择你配置好的认证方式(密码 或 SSH密钥)。 * 点击连接。成功连接后,你就进入了ECS实例的Linux命令行环境。 * **步骤5b: 在FinalShell的SSH终端里使用MySQL客户端连接本机MySQL服务**: * 连接Linux成功后,在FinalShell打开的终端窗口中,可以直接使用`mysql`命令行客户端连接**本机(127.0.0.1/localhost)上运行的MySQL服务**: ```bash mysql -u remote_user -p # 或者 mysql -u root -p (如果在第2步允许了root远程访问本机) # 然后输入你在第2步设置的密码 ``` * 或者,你可以在FinalShell里使用`sftp/ftp`功能上传/下载文件。但**管理数据库本身**的操作需要在FinalShell提供的终端窗口里执行数据库命令,或者... * **步骤5c (推荐):在FinalShell连接后,使用本地数据库GUI工具连接MySQL**: * 在你的本地电脑(运行FinalShell的电脑)上安装一个**数据库管理工具**(如MySQL Workbench、Navicat、DataGrip、DBeaver等)。 * 在数据库工具中新建一个MySQL连接: * **主机名/IP地址(Host/IP):** 填入步骤4获取的**ECS公网IP地址**。 * **端口(Port):** `3306`。 * **用户名(Username):** 你在第2步创建的远程访问用户 (如 `remote_user`) 或者 `root`(如果允许了)。 * **密码(Password):** 该用户对应的密码。 * 测试并连接。如果安全组(步骤3)和MySQL用户权限(步骤2)配置正确,通常就能成功连接。 **总结关键路径:** 1. **在青鸟云ECS上安装运行MySQL。** 2. **在MySQL中创建/配置允许远程连接的用户(授权+密码)。** 3. **在青鸟云平台后台配置该ECS关联的安全组,开放3306端口入站,并授权给客户端IP范围。** 4. **用FinalShell以SSH方式登录ECS获取Linux操作权限(命令行访问/文件传输)。** 5. **(a) 在FinalShell的SSH终端里用mysql命令访问本机MySQL(通过localhost)** **(b) 在本地用数据库GUI工具访问ECS公网IP:3306上的MySQL(最常用方式)。** **
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值