Net-SSH Threaded PortForward Script Problems

Greetings to all
attempting to get a working script here
that portforwards across multiple hosts
and executes commands on the final host in the
hops

i located suggested design pattern posted by Jamis Buck
the developer of the ruby net-ssh module

the following code seems to be syntatically correct
if anyone else has time to test the following script
please provide some feedback

i am not sure if i simply do not have the ssh server setup correctly
on all systems along the hop path
i have in sshd_config

AllowTcpForwarding yes

when i run the below code i get the following error messages
in my ssh log file
on the system the script is started from
which leads me to believe
the script is not even portforwarding to the first hop in the script

tail -f /var/log/ssh.log

···

-------

Sep 11 08:02:16 falcon1 sshd[12308]: Connection from ::ffff:127.0.0.1
port 39495
Sep 11 08:02:16 falcon1 sshd[12308]: Did not receive identification
string from ::ffff:127.0.0.1

-------

when i placed the code in irb

and the code is running into problems at this point in the script
which is the final hop in the code
the error message is Connection Refused Authentication error
which again leads me to believe the script is not opening the tcp
portforwarding gateways to facilitate the hops properly

--------------
Net::SSH.start( 'localhost', 1236, 'jello', 'passwd' ) do |session|
result = session.exec("hostname")
puts result.data, "\n\n"
result = session.exec("date")
puts result.data, "\n\n"
result = session.exec("uptime")
puts result.data, "\n\n"
end

--------------

when i run the script i get the following error message:

-------

../threads_ssh.rb
/usr/local/lib/ruby/site_ruby/1.8/net/ssh/transport/session.rb:132:in
`initialize': Connection refused - connect(2) (Errno::ECONNREFUSED)
from
/usr/local/lib/ruby/site_ruby/1.8/net/ssh/transport/session.rb:132:in
`open'
from
/usr/local/lib/ruby/site_ruby/1.8/net/ssh/transport/session.rb:132:in
`initialize'
from /usr/local/lib/ruby/site_ruby/1.8/net/ssh.rb:175:in `new'
from /usr/local/lib/ruby/site_ruby/1.8/net/ssh.rb:175:in `open'
from /usr/local/lib/ruby/site_ruby/1.8/net/ssh.rb:93:in `start'
from ./threads_ssh.rb:36
---------

NOTE i have other scripts using the net-ssh ruby module that are
working
so i know this is not a problem with openssl

it seems to be server side sshd_config problem or something along those
lines
as stated before if anyone can test on their end
and post any ideas
greatly appreciated
and a thanks to everyone in advance

BEGIN CODE 4 host Hop
----------

#!/usr/local/bin/ruby

require 'thread'
require 'net/ssh'
require 'net/ssh/service/forward'

threads = []

t = Thread.new do
Net::SSH.start( 'host1', 'jello', 'pass' ) do |session|
mgr = PortForwardManager.new( session )
mgr.forward_local( 1234, 'host2', 22 )
session.main_loop
end
end

t = Thread.new do
Net::SSH.start( 'localhost', 1234, 'jello', 'pass' ) do |session|
mgr = PortForwardManager.new( session )
mgr.forward_local( 1235, 'host3', 22 )
session.main_loop
end
end

t = Thread.new do
Net::SSH.start( 'localhost', 1235, 'jello', 'pass' ) do |session|
mgr = PortForwardManager.new( session )
mgr.forward_local( 1236, 'host4', 22 )
session.main_loop
end
end

Net::SSH.start( 'localhost', 1236, 'jello', 'passwd' ) do |session|
result = session.exec("hostname")
puts result.data, "\n\n"
result = session.exec("date")
puts result.data, "\n\n"
result = session.exec("uptime")
puts result.data, "\n\n"
end

threads.push( t )

---------
END CODE

I haven't actually tried running your script, but it looks to me like the problem is in your script that does the port forwarding:

BEGIN CODE 4 host Hop
----------

#!/usr/local/bin/ruby

require 'thread'
require 'net/ssh'
require 'net/ssh/service/forward'

threads =

t = Thread.new do
Net::SSH.start( 'host1', 'jello', 'pass' ) do |session|
mgr = PortForwardManager.new( session )
mgr.forward_local( 1234, 'host2', 22 )
session.main_loop
end

t = Thread.new do
Net::SSH.start( 'localhost', 1234, 'jello', 'pass' ) do |session|
mgr = PortForwardManager.new( session )
mgr.forward_local( 1235, 'host3', 22 )
session.main_loop
end

t = Thread.new do
Net::SSH.start( 'localhost', 1235, 'jello', 'pass' ) do |session|
mgr = PortForwardManager.new( session )
mgr.forward_local( 1236, 'host4', 22 )
session.main_loop
end

Net::SSH.start( 'localhost', 1236, 'jello', 'passwd' ) do |session|
result = session.exec("hostname")
puts result.data, "\n\n"
result = session.exec("date")
puts result.data, "\n\n"
result = session.exec("uptime")
puts result.data, "\n\n"
end

threads.push( t )

---------
END CODE

You aren't doing a "join" on the threads, so the Ruby interpreter is exiting immediately--killing all running threads on the way. Which means none of the ports are being forwarded, which means your attempt to connect to a forwarded port fails with "connection refused." So,

   1) make sure you add *each thread* to the threads array

   2) make sure you join *each thread*, something like this:

      threads.each { |t| t.join }

See if that helps. If it doesn't, post again and I'll see if I can dig deeper.

- Jamis

···

--
Jamis Buck
jgb3@email.byu.edu
http://www.jamisbuck.org/jamis

"I use octal until I get to 8, and then I switch to decimal."

Jamis,

first thank you for responding

still no luck using an even smaller code block
and i am going over in detail the Programming Ruby section:
Threads and Processes

http://www.ruby-doc.org/docs/ProgrammingRuby/

BEGIN CODE

···

---------
#!/usr/local/bin/ruby

require 'thread'
require 'net/ssh'
require 'net/ssh/service/forward'

threads =

t = Thread.new do
Net::SSH.start( 'localhost', 'jello', 'passwd' ) do |session|
mgr = PortForwardManager.new( session )
mgr.forward_local( 1236, 'remotehost', 22 )
session.main_loop
end
end

Net::SSH.start( 'localhost', 1236, 'remoteuser', 'passwd' ) do

session>

result = session.exec("hostname")
puts result.data, "\n\n"
result = session.exec("date")
puts result.data, "\n\n"
result = session.exec("uptime")
puts result.data, "\n\n"
end

threads.each { |t| t.join }
threads.push( t )

---------
END CODE

otaku wrote:

Jamis,

first thank you for responding

still no luck using an even smaller code block
and i am going over in detail the Programming Ruby section:
Threads and Processes

Programming Ruby: The Pragmatic Programmer's Guide

BEGIN CODE
---------
#!/usr/local/bin/ruby

require 'thread'
require 'net/ssh'
require 'net/ssh/service/forward'

threads =

t = Thread.new do
Net::SSH.start( 'localhost', 'jello', 'passwd' ) do |session|
mgr = PortForwardManager.new( session )
mgr.forward_local( 1236, 'remotehost', 22 )
session.main_loop
end

Net::SSH.start( 'localhost', 1236, 'remoteuser', 'passwd' ) do
>session>
result = session.exec("hostname")
puts result.data, "\n\n"
result = session.exec("date")
puts result.data, "\n\n"
result = session.exec("uptime")
puts result.data, "\n\n"
end

threads.each { |t| t.join }
threads.push( t )

You did the join and the push in the wrong order. You were joining on an empty array, which finished immediately, and then pushed the thread on, after which the program terminated before the thread had a chance to really stretch its wings.

Try reversing the order of those last two statements and see what happens.

- Jamis

···

--
Jamis Buck
jgb3@email.byu.edu
http://www.jamisbuck.org/jamis

"I use octal until I get to 8, and then I switch to decimal."