Howdy folks,
I think i found a problem where if a client using an existing Net::SSH
tunnel closes it''s socket, Net::SSH doesn''t clean up properly.
As a
result, it is possible that the next loop iteration will throw an
exception.
I have observed all of the following problems that all seem to be
related to the same behavior from a tcp client (web browser, for
example)
1) data for nonexistant channel causes Net::SSH::Disconnect
2) connection reset throws an Errno::ECONNRESET
3) Error: #<IOError: closed stream>
% ruby ./tunneltest.rb shellmachine httpdmz
I, [2008-07-23T15:25:45.674819 #8314] INFO -- : Starting tunnel on port 3005
I, [2008-07-23T15:25:46.071871 #8314] INFO -- : Failed at Iteration 305
I, [2008-07-23T15:25:46.071965 #8314] INFO -- : Error:
#<Net::SSH::Disconnect: disconnected: Received data for nonexistent
channel 3. (2)>
Another run:
% ruby ./tunneltest.rb shellmachine httpdmz
I, [2008-07-23T15:25:48.726165 #18271] INFO -- : Starting tunnel on port 3005
I, [2008-07-23T15:26:47.861251 #18271] INFO -- : Failed at Iteration 84257
I, [2008-07-23T15:26:47.861348 #18271] INFO -- : Error: #<IOError:
closed stream>
There is a webrowser refreshing a page through this tunnel every
second. A page load might get interrupted, and this shouldn''t crash
the ssh session.
The code:
#!/usr/bin/env ruby
require "rubygems"
require "net/ssh"
require "logger"
log = Logger.new($stdout)
username = ENV["USER"]
log.info("Starting tunnel on port 3005")
session = Net::SSH.start(ARGV[0], username)
session.forward.local("127.0.0.1", 3005, ARGV[1], 80)
d = 0
begin
session.loop do
d = d + 1
true
end
rescue StandardError => e
log.info "Failed at Iteration #{d}"
log.info "Error: #{e.inspect}"
end
Thoughts?
-Jordan