My target oracle database server exists beyond a firewall. I use an ssh tunnel to connect to a server beyond the firewall, call it friendly-server. Then from my localhost, I use DBI to connect to the target database which exists on the another server, call it target-dbserver. Similar question recommends using command line below.
This is the ssh command i use to set up the tunnel:
ssh -nN -L 1520:target-dbserver:1520 friendly-server
I want to implement this in Ruby so I am using the net-ssh-gateway gem. I'm probably just not understanding how ssh tunneling works because I do not see how once I establish the gateway and then the subsequent ssh to friendly-server, I'm not seeing how to then establish the DBI connection to the db on target-dbserver.
# 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
Tried this which fails because how does the DBI call know to use the tunnel?
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
Using the gateway.open
method. This seems logical to me but it always hangs when I try to connect via DBI to the target db via the localhost (gateway). I think maybe its because the .open
method establishes an ssh connection to the targetdb which I don't want. I want the only contact with the dbtarget to be with the DBI connection.
# 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
UPDATE
Couldn't get the gateway or net-ssh forward_local to work for me. Frustrated I opted to fork
the ssh tunnel. Not ideal but works for the time being. If the local port is taken then I'd like to trap that error but don't know how with this method.
tunnel = fork do
exec 'ssh -nN -L 1520:targetdb:1520 friendly-server'
end
Process.detach(tunnel)
#do stuff
Process.kill('HUP', tunnel) if tunnel