使用Ruby通过网关连接到远程数据库

时间:2013-03-13 16:05:44

标签: ruby oracle ssh

我的目标oracle数据库服务器存在于防火墙之外。我使用ssh隧道连接到防火墙之外的服务器,称之为 friendly-server 。然后从我的localhost,我使用DBI连接到另一台服务器上存在的目标数据库,称之为 target-dbserver Similar question建议使用下面的命令行。

这是我用来设置隧道的ssh命令:

ssh -nN -L 1520:target-dbserver:1520 friendly-server

我想在Ruby中实现它,所以我使用的是net-ssh-gateway gem。 我可能只是不了解ssh隧道是如何工作的,因为我没有看到一旦我建立网关然后后续ssh到友好服务器,我没有看到如何建立DBI连接到 target-dbserver上的db。

# Set up the gateway. The gem will find an unused port.
gateway = Net::SSH::Gateway.new('friendly-server', 'user')
# Establish ssh connection
gateway.ssh('friendly-server', 'user') do |ssh|
# now how to make DBI connection to target-dbserver ?
end

尝试失败,因为DBI调用如何知道使用隧道?

gateway = Net::SSH::Gateway.new('friendly-server', 'user')
gateway.ssh('friendly-server', 'user') do |ssh|
  db = DBI.connect('target server connection string', 'user','password')
end

使用gateway.open方法。这对我来说似乎合乎逻辑,但当我尝试通过localhost(网关)通过DBI连接到目标数据库时,它总是挂起。我想也许是因为.open方法建立了一个我不想要的与targetdb的ssh连接。我希望与dbtarget的唯一联系是与DBI连接。

# open gateway from localhost to bastion
gateway = Net::SSH::Gateway.new('friendly-server', 'user')
# Opens a new port on the local host and forwards it to the given host/port
# via the gateway host.
gateway.open(targetdb, 1520) do |port|
  db = DBI.connect(localhost, port, sid)
end

更新

无法让网关或net-ssh forward_local为我工作。我感到沮丧,选择了fork ssh隧道。不理想但暂时有效。如果采用本地端口,那么我想捕获该错误,但不知道如何使用此方法。

tunnel = fork do
  exec 'ssh -nN -L 1520:targetdb:1520 friendly-server'
end
Process.detach(tunnel)
#do stuff
Process.kill('HUP', tunnel) if tunnel

1 个答案:

答案 0 :(得分:1)

我的解决方案是fork一个ssh命令,然后在我完成时杀死那个ssh进程。

# obj_hash contains remote db details and a flag for when a tunnel is needed
local_port = 3535
if obj_hash[:tunnel]
  tunnel = fork do
    exec "ssh -nN -L #{local_port}:#{obj_hash[:server]}:#{obj_hash[:port]} #{obj_hash[:tunnel]} 2> /dev/null; "
  end
  Process.detach(tunnel)
end
# do stuff
Process.kill('HUP', tunnel) if tunnel

目前我不知道如何检查隧道是否已经在local_port上,所以不是一个完美的解决方案。