1

So here's my setup:

Laptop -> Host 1 -> Host 2 -> Host 3

Laptop can reach Host 1, but not Host 2 or Host 3
Host 1 can reach Host 2, but not Host 3
Host 3 can reach Host 2, but not Host 1

What I'm trying to do is set up remote forwards so that a process running on Host 3 will be routed to running service on Laptop. I've successfully done this using the following code:

Run from Laptop:

require 'rubygems'
require 'net/ssh'

threads = []
config = {:user => "user", :remote_port => 3333, :service_port => 2222}

threads << Thread.new{
Net::SSH.start("host1", config[:user]) do |ssh|
  puts "Forwarding port #{config[:remote_port]} on host1 to #{config[:service_port]} on localhost"
  ssh.forward.remote(config[:service_port], "localhost", config[:remote_port], "127.0.0.1")
  ssh.exec! "ssh #{config[:user]}@host2 -R #{config[:remote_port]}:localhost:#{config[:remote_port]}"
  ssh.loop {true}
end
}

threads << Thread.new{
Net::SSH.start("host3", config[:user]) do |ssh|
  puts "Creating local forward for port #{config[:service_port]} on host3 to port #{config[:remote_port]} on host2"
  ssh.exec! "ssh #{config[:user]}@host2 -L #{config[:service_port]}:localhost:#{config[:remote_port]}"
  ssh.loop {true}
end
}

threads.each {|t| t.join}

In one thread, I'm setting up a remote forward from Laptop to Host 1 and then another remote forward from Host 1 to Host 2. In a separate thread, I'm starting another connection from Laptop to Host 3, then running a local forward from Host 3 to Host 2.

The only way I can connect from Laptop to Host 3 is because of my .ssh/config file, which automatically routes me through Host 1 and Host 2 when I try to connect to Host 3 from Laptop.

What I want to do is cut out the second thread where I'm connecting from Laptop to Host 3 so that I can remove the dependency on the .ssh/config file. I want to do all of my connections from within the first thread.

So basically I need to do multiple hops that originate from Laptop. I can initiate the first connection from Laptop to Host 1 and then execute a command on Host 1, but after that I can't get any further. What I need to do is initiate the connection from Laptop to Host 1, set up the forward on Host 1, connect to Host 2 from Host 1 and then set up the second forward on Host 2.

Is this possible to do with net/ssh?

Thanks for your help!

1 Answer 1

2

I fixed this by writing out an SSH config file, then specifying the config file when initiating the connection. The config file contains proxy commands that will automatically route through the necessary hosts to reach my destination.

Example:

def write_config_file

    File.open('confi_file', 'w') { |f|
      f << "host host1\n"
      f << "HostName host1.something.net\n"
      f << "user user_name\n"
      f << "\n"
      f << "host host2\n"
      f << "HostName host2.something.net\n"
      f << "ProxyCommand ssh host1 nc %h %p 2> /dev/null\n"
      f << "user user_name\n"
      f << "\n"
      f << "host host3\n"
      f << "HostName host3.something.net\n"
      f << "ProxyCommand ssh host2 nc %h %p 2> /dev/null\n"
      f << "user user_name\n"
    } 

end

write_config_file

Net::SSH.start("host3", "user_name", :config => './config_file') do |ssh|
  #whatever you need to do...
end

I wrapped the connection in a begin/rescue blocked and trapped ctrl+c input, and in the trap block I delete the config file and shut down the connection.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.