using Net::SSH::Gateway to setup a tunnel (hung at

2019-09-07 14:14发布

问题:

Just as in Using net/ssh/gateway to establish ssh tunnel to mysql, I'm trying to use Net::SSH::Gateway set up a tunnel to a remote server for port forwarding. But I'm getting stuck earlier in the process! :)

TL;DR

How do I condition OpenSSL and Net::SSH::Gateway.new() for tunneling to a remote server?

what works...

I can set up a tunnel by starting an ssh process in the background as follows:

remote_addr = <some_remote_server.com>
remote_user = <some_remote_server@somehost.com>
ssh -f -N -L 3307:#{remote_addr}:3306 #{remote_user}

and in my rails code:

# config/database.yml
...
remote_db:
    adapter: mysql2
    database: <remote_db_name>
    username: <remote_db_user>
    password: <remote_db_pass>
    host: 127.0.0.1
    port: 3307

This all works.

what doesn't...

But when I try the following (without launching ssh in the background, of course), it fails with 'connection refused':

>> require 'net/ssh/gateway'
>> remote_addr = <some_remote_server.com>
>> remote_user = <some_remote_server@somehost.com>
>> gateway = Net::SSH::Gateway.new(remote_addr, remote_user, :port => 3306, :verbose => :debug)
D, [2014-12-04T07:56:50.720603 #32532] DEBUG -- net.ssh.transport.session[3fe0d1587180]: establishing connection to some_remote_server.com:3306
... then after a delay ...
Errno::ECONNREFUSED: Connection refused - connect(2) for "some_remote_server.com" port 3306

I also tried it without the port spec (so it used port 22), which results in a timeout instead:

>> gateway = Net::SSH::Gateway.new(remote_addr, remote_user, :verbose => :debug)
D, [2014-12-04T07:59:17.722649 #32532] DEBUG -- net.ssh.transport.session[3fe0d156efb8]: establishing connection to some_remote_server.com:22
Errno::ETIMEDOUT: Operation timed out - connect(2) for "some_remote_server.com" port 22

location of the keys

I have a suspicion that perhaps OpenSSL isn't finding my certificates. When I run ssh in verbose mode, I can see it offering and accepting my public key in ~/.ssh/id_rsa. But even when I explicitly passed my key file as an argument:

gateway = Net::SSH::Gateway.new(remote_addr, 
                                remote_user,
                                :keys => ['/Users/home/.ssh/id_rsa'], 
                                :port => 3306, 
                                :verbose => :debug)

... it didn't seem to make a difference.

my questions:

  • What arguments do I pass to Net::SSH:Gateway.new() so that it emulates the call to ssh -N -L ...?
  • If I'm getting the ECONNREFUSED or ETIMEDOUT responses because OpenSSL can't find my certs, how do I tell it where to look?

回答1:

Okay, it was a boneheaded problem with a simple fix. Despite my embarrassment, I'm posting the solution in case someone else finds it useful.

In short, if you've been running ssh like this:

remote_addr = <some_remote_server.com>
remote_user = <some_remote_user@somehost.com>
ssh -f -N -L 3307:#{remote_addr}:3306 #{remote_user}

you probably want:

 require 'net/ssh/gateway'
 gateway = Net::SSH::Gateway.new("somehost.com", "some_remote_user")
 port = gateway.open(remote_addr, 3306, 3307)

The reason I was getting ECONNREFUSED and ETIMEDOUT in the O.P. was simply because I was trying to connect to the wrong server.