为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用 go-sql-driver 通过标准 TCP/IP 通过 SSH 连接到 MySQL?

如何使用 go-sql-driver 通过标准 TCP/IP 通过 SSH 连接到 MySQL?

Go
冉冉说 2021-11-22 16:48:07
我目前正在 Windows 8.1 上使用 MySQL Workbench,通过 SSH 使用标准 TCP/IP 访问 Linux 服务器上的远程 MySQL 数据库。基本上我有以下信息:SSH 主机名:dbserver.myorg.com:ssh-portSSH 用户名:myRemoteLoginUsernameSSH 密码:(存储在保险库中)SSH 密钥文件:本地 .ppk 文件的路径MySQL 主机名:127.0.0.1MySQL 服务器端口:3306用户名:myRemoteDbUsername密码:(存储在保险库中)默认架构:myRemoteDatabaseName如何使用 github.com/go-sql-driver/mysql 从 Go 命令应用程序连接到数据库?我的 sql.Open 语句中的 DataSourceName 字符串应该是什么样的?    db, err := sql.Open("mysql", <DataSourceName> ) {}准备工作 DataSourceName 字符串是否需要任何额外的工作?在我的 Windows PC 上,我安装了腻子。我阅读了隧道并为端口 3306 (D3306) 添加了动态隧道。我希望这能让我使用到 localhost:3306 的连接进行连接,并在我使用腻子连接到远程主机时自动将请求转发到远程数据库,但这也没有按预期工作。
查看完整描述

2 回答

?
牧羊人nacy

TA贡献1862条经验 获得超7个赞

我答应提供我的例子,它来了。基本上我的解决方案建立了一个到远程服务器的 ssh 隧道并通过这个隧道查询远程数据库。ssh 隧道是解决方案的一部分。

我必须做的第一件事是将 PuTTY .ppk 私钥文件转换为有效的 OpenSSH .pem 密钥文件。这可以使用 PuTTYgen 中的导出功能轻松完成。因为我想支持密码加密的私钥,所以我还需要一个函数来解密密钥并将其从解密的原始格式重新格式化为 golang.org/x/crypto/ssh/ParsePrivateKey 接受的有效格式,这是获取用于身份验证的签名者列表。

解决方案本身由包含在两个文件中的包组成。应用程序的主要部分在 main.go 中完成,其中包含所有相关的数据分配以及与数据库查询相关的代码。与 ssh 隧道和密钥处理相关的所有内容都包含在 sshTunnel.go 中。

该解决方案不提供安全密码存储的机制,也不要求输入密码。密码在代码中提供。但是,实现密码请求的回调方法并不会太复杂。

请注意:从性能角度来看,这不是一个理想的解决方案。它还缺乏适当的错误处理。我已经提供了这个例子。

该示例是一个经过测试且有效的示例。我在 Windows 8.1 PC 上开发并使用了它。数据库服务器位于远程 Linux 系统上。您需要更改的只是 main.go 中的数据和查询部分。


查看完整回答
反对 回复 2021-11-22
?
慕田峪7331174

TA贡献1828条经验 获得超13个赞

好吧,我认为你可以做到“全围棋”。

SSH 部分和端口转发

我喜欢的东西就这样(我没有谷歌更好的例子)。

请注意此代码的两个问题:

  1. 它实际上并不正确:它接受客户端连接之前连接到远程套接字 而它应该相反:接受客户端连接到端口转发的本地套接字,然后使用活动的 SSH 会话连接到远程套接字,如果成功, 生成两个 goroutines 以在这两个套接字之间铲除数据。

  2. 在配置 SSH 客户端时,它出于未知原因明确允许基于密码的身份验证。您不需要这个,因为您使用的是基于公钥的身份验证。

一个可能会绊倒您的障碍是管理对您的 SSH 密钥的访问。它的问题在于一个好的密钥应该受密码保护。

你说密钥的密码“存储在价值中”,老实说,我不知道“价值”是什么。

在我使用的系统上,SSH 客户端要么要求输入密码来解密密钥,要么使用所谓的“SSH 代理”:

  • 在基于 Linux 的系统上,它通常是ssh-agent在后台工作的 OpenSSH二进制文件,它通过 Unix 域套接字访问,并通过检查名为SSH_AUTH_SOCK.

  • 在 Windows 上,我使用 PuTTY,它有自己的代理pageant.exe. 我不知道 PuTTY SSH 客户端使用哪种方式来定位它。

要访问 OpenSSH 代理,golang.org/x/crypto/ssh提供agent可用于定位代理并与之通信的子包。如果您需要从 获取密钥pageant,恐怕您需要弄清楚使用什么协议并实现它。

MySQL部分

下一步是将其与go-sql-driver.

我会以最简单的方式开始:

  1. 当您的 SSH 端口转发工作时,让它在本地主机上的随机端口上侦听传入连接。当连接打开时,从返回的连接对象中获取端口。

  2. 使用该端口号构建连接字符串以传递给sql.DB您将创建以使用的实例go-sql-driver

然后驱动程序将连接到您的端口转发端口,您的 SSH 层将完成剩下的工作。

在您完成这项工作后,我将探讨您选择的驱动程序是否允许进行一些更细粒度的调整,例如允许您直接将一个io.ReadWriter(打开的套接字)的实例传递给它,以便您可以完全跳过端口转发设置和只需生成通过 SSH 转发的新 TCP 连接,即跳过“本地侦听”步骤。


查看完整回答
反对 回复 2021-11-22
  • 2 回答
  • 0 关注
  • 220 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信