diff --git a/lib/ssh_scan/client.rb b/lib/ssh_scan/client.rb index cf7eb3dc..ac83c227 100644 --- a/lib/ssh_scan/client.rb +++ b/lib/ssh_scan/client.rb @@ -1,4 +1,5 @@ require 'socket' +require 'timeout' require 'ssh_scan/constants' require 'ssh_scan/protocol' require 'ssh_scan/banner' @@ -43,12 +44,15 @@ def connect() @error = nil begin - @sock = Socket.tcp(@ip, @port, connect_timeout: @timeout) - @raw_server_banner = @sock.gets + Timeout::timeout(@timeout) { + @sock = Socket.tcp(@ip, @port, connect_timeout: @timeout) + @raw_server_banner = @sock.gets + } rescue SocketError => e @error = SSHScan::Error::ConnectionRefused.new(e.message) @sock = nil - rescue Errno::ETIMEDOUT => e + rescue Errno::ETIMEDOUT, + Timeout::Error => e @error = SSHScan::Error::ConnectTimeout.new(e.message) @sock = nil rescue Errno::ECONNREFUSED => e @@ -94,23 +98,28 @@ def get_kex_result(kex_init_raw = @kex_init_raw) return nil end - begin - @sock.write(kex_init_raw) - resp = @sock.read(4) + kex_exchange_init = nil - if resp.nil? - @error = SSHScan::Error::NoKexResponse.new( - "service did not respond to our kex init request" - ) - @sock = nil - return nil - end - - resp += @sock.read(resp.unpack("N").first) - @sock.close + begin + Timeout::timeout(@timeout) { + @sock.write(kex_init_raw) + resp = @sock.read(4) + + if resp.nil? + @error = SSHScan::Error::NoKexResponse.new( + "service did not respond to our kex init request" + ) + @sock = nil + return nil + end + + resp += @sock.read(resp.unpack("N").first) + @sock.close - kex_exchange_init = SSHScan::KeyExchangeInit.read(resp) - rescue Errno::ETIMEDOUT => e + kex_exchange_init = SSHScan::KeyExchangeInit.read(resp) + } + rescue Errno::ETIMEDOUT, + Timeout::Error => e @error = SSHScan::Error::ConnectTimeout.new(e.message) @sock = nil return nil diff --git a/lib/ssh_scan/scan_engine.rb b/lib/ssh_scan/scan_engine.rb index 6b45eda8..b1b67a5f 100644 --- a/lib/ssh_scan/scan_engine.rb +++ b/lib/ssh_scan/scan_engine.rb @@ -107,7 +107,7 @@ def scan_target(socket, opts) net_ssh_session.close rescue Net::SSH::ConnectionTimeout => e result.error = SSHScan::Error::ConnectTimeout.new(e.message) - rescue Net::SSH::Disconnect => e + rescue Net::SSH::Disconnect, Errno::ECONNRESET => e result.error = SSHScan::Error::Disconnected.new(e.message) rescue Net::SSH::Exception => e if e.to_s.match(/could not settle on/)