0

如何使用 Ruby Net::SSHNet::SSH::Gateway gems 和密钥(而不是密码)身份验证远程(从基于云的应用程序)连接到基于 VPS 的 MySQL 数据库?

然后使用 Sequel 或 DataMapper 连接到数据库。我假设在我设法使 SSH 连接正常工作后,我只需设置一个到 'sql_user@localhost:3306/database' 的 Sequel/DM 连接。

我确实在这里找到了几个类似的问题,但它们都使用密码身份验证,而不是密钥,并且只演示了执行原始命令来查询数据库。

更新:我似乎无法让这个(Net::SSH with key manager)工作。

UPDATE2:好的,当我从具有存储在用户本地 .ssh 文件夹中的授权密钥的计算机登录时,我已经设法获得授权,具有以下内容(端口是我在 VPS 上的自定义 SQL 端口):

 sql_gate = Net::SSH::Gateway.new('192.xxx.xxx.xx','sqluser', port: 26000)

但是,我将无法.ssh在应用程序的 VM 中创建文件夹,因此我需要以某种方式传递路径和文件名(我将为指定用户的 SQL 访问创建一个公钥)作为一个选项......但是没有无法弄清楚如何。

更新:现在只需要弄清楚 DataMapper 的访问权限。当前正在测试的代码(remote_user_sql是我的 Ubuntu 用户,是具有特权sql_user的 MySQL 数据库用户):localhost/127.0.0.1

require 'net/ssh/gateway'
require 'data_mapper'
require 'dm-mysql-adapter'

class User
  include DataMapp......
  .
  .
end

ssh_gate = Net::SSH::Gateway.new('192.n.n.n','remote_user_sql', {port: 25000, keys: ["sql_rsa"], keys_only: true})

port = ssh_gate.open('localhost',3306,3307)
  child = fork do
    DataMapper.setup(:default, {
      adapter: 'mysql',
      database: 'sql_test',
      username: 'sql_user',
      password: 'passwd',
      host: 'localhost',
      port: port})
    DataMapper.auto_upgrade!
    exit
  end
  puts "child: #{child}"
  Process.wait

ssh_gate.close(port)
4

1 回答 1

1

我的解决方案,分为两部分:

好吧,我已经想出了如何使用指定的密钥文件制作 Net::SSH::Gateway gem,然后通过 ssh 通过 22 以外的端口连接到 VPS:

第 1 部分:Net::SSH::Gateway 密钥认证

首先,您必须生成要使用的密钥文件,将其复制.pub到删除服务器并将其附加到~/.ssh/authorized_keys文件 ( cat sql_rsa.pub >> authorized_keys),然后确保user_sql(我在 VPS 上创建的仅用于此目的的用户)已添加到AllowUsers中列出sshd_config。记下用于 ssh 的端口(本例中为 25000)并使用以下代码建立连接:

ssh_gate = Net::SSH::Gateway.new('192.n.n.n','user_sql', {port: 25000, keys: ["sql_rsa"], keys_only: true})

这将读取与sql_rsa脚本文件相同目录中的密钥文件,然后在端口 25000 上为 'user_sql'@'192.nnn' 创建一个新的 ssh 网关。

我可以通过以下方式在删除 VPS 上成功执行原始 shell 命令:

ssh_gate.exec("ls -la")

关闭:

ssh_gate.shutdown!

不幸的是,我在使用 DataMapper(do-mysql-adapter)来使用网关时仍然遇到问题。如果我弄清楚那部分,我会更新这个答案,但至少问题的前半部分已经解决。

这些是 DataMapper::Logger 报告的错误:

何时127.0.0.1使用:

Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) (code: 2002, sql state: HY000, query: , uri: )

何时localhost使用:

Access denied for user 'user_sql'@'localhost' (using password: YES) (code: 1045, sql state: 28000, query: , uri: )

使用 VPShostname时:

Unknown MySQL server host 'hostname' (25) (code: 2005, sql state: HY000, query: , uri: )

更新(尚未成功):到目前为止,我可以访问远程 MySQL 数据库的唯一方法是使用 Net::SSH::Gateway 建立网关,然后使用该.ssh方法打开一个新的 Net::SSH 连接。网关,像这样:

ssh_gate.ssh('192.n.n.n','user_sql',{port: 25000, keys: ["sql_rsa"], keys_only: true}) do |ssh|
    ssh.exec("mysql -u sql_user -p'passwd' -h localhost -P 3306 -e 'SELECT DATABASE();'")
end

也就是说,我只能使用mysql命令行执行SQL命令。我无法弄清楚如何让 Sequel 或 DataMapper 使用网关进行连接。

第 2 部分:通过 Net::SSH::Gateway 连接 DataMapper/Sequel/mysql2

确保您的 MySQL 服务器绑定到 127.0.0.1 中/etc/mysql/my.cnf,设置您的连接 - DataMapper 示例:

DataMapper.setup(:default, {
  adapter: 'mysql',
  database: 'DATABASE',
  username: 'username',
  password: 'passwd',
  host: '127.0.0.1',
  port: 3307}) # local port being forwarded via Net::SSH:Gateway

如果需要,后跟任何class表定义。请注意,DataMapper 在执行、或 查询DataMapper.finalize之前实际上并没有连接到远程 MySQL 服务器,因此还不需要创建转发端口。auto_upgrade!auto_migrate!

然后新建一个 Net::SSH::Gateway,然后每当需要 DataMapper/Sequel 访问远程数据库时,只需为进程打开一个端口,如下所示:

port = ssh_gate.open('127.0.0.1',3306,3307)
  child = fork do
    DataMapper.auto_upgrade! # DM call that accesses MySQL server
    exit
  end
  Process.wait
ssh_gate.close(port)

您可能希望将 Net::SSH::Gateway/.open 代码放在一个begin..ensure..end块中,ensure以关闭端口和关闭网关。

我必须使用forkandProcess.wait来建立连接,没有它,方法就会挂起。

于 2013-04-27T02:50:59.583 回答