Class: Rex::Proto::Ssh::Server
- Inherits:
-
Object
- Object
- Rex::Proto::Ssh::Server
- Includes:
- Rex::Proto
- Defined in:
- lib/rex/proto/ssh/server.rb
Overview
Acts as an SSH server, accepting clients and extending them with Connections
Instance Attribute Summary collapse
-
#clients ⇒ Object
Returns the value of attribute clients.
-
#comm ⇒ Object
Returns the value of attribute comm.
-
#context ⇒ Object
Returns the value of attribute context.
-
#listen_host ⇒ Object
Returns the value of attribute listen_host.
-
#listen_port ⇒ Object
Returns the value of attribute listen_port.
-
#listener ⇒ Object
Returns the value of attribute listener.
-
#monitor_thread ⇒ Object
Returns the value of attribute monitor_thread.
-
#on_client_connect_proc ⇒ Object
Returns the value of attribute on_client_connect_proc.
-
#on_client_data_proc ⇒ Object
Returns the value of attribute on_client_data_proc.
-
#server_options ⇒ Object
Returns the value of attribute server_options.
Class Method Summary collapse
-
.hardcore_alias(*args) ⇒ Object
Returns the hardcore alias for the SSH service.
Instance Method Summary collapse
-
#alias ⇒ Object
SSH server.
-
#close_client(cli) ⇒ Object
Closes the supplied client, if valid.
-
#enqueue_client(cli) ⇒ Object
protected
Waits for SSH client to “grow a pair” of FDs and adds a ChannelFD object derived from the client's Connection Channel's FDs to the Ssh::Server's clients array.
-
#initialize(port = 22, listen_host = '0.0.0.0', context = {}, comm = nil, ssh_opts = Ssh::Connection.default_options, cc_cb = nil, cd_cb = nil) ⇒ Server
constructor
Initializes an SSH server as listening on the provided port and hostname.
-
#inspect ⇒ String
More readable inspect that only shows the url and resources.
-
#monitor_clients ⇒ Object
protected
Watches FD channel abstractions, removes closed instances, checks for read data on clients if client data callback is defined, invokes the callback if possible, sleeps otherwise.
-
#on_client_connect(cli) ⇒ Object
protected
Extends new clients with the ServerClient module and initializes them.
-
#start(srvsock = nil) ⇒ Object
Listens on the defined port and host and starts monitoring for clients.
-
#stop ⇒ Object
Terminates the monitor thread and turns off the listener.
-
#wait ⇒ Object
Waits for the SSH service to terminate.
Constructor Details
#initialize(port = 22, listen_host = '0.0.0.0', context = {}, comm = nil, ssh_opts = Ssh::Connection.default_options, cc_cb = nil, cd_cb = nil) ⇒ Server
Initializes an SSH server as listening on the provided port and hostname.
47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/rex/proto/ssh/server.rb', line 47 def initialize(port = 22, listen_host = '0.0.0.0', context = {}, comm = nil, ssh_opts = Ssh::Connection., cc_cb = nil, cd_cb = nil) self.listen_host = listen_host self.listen_port = port self.context = context self.comm = comm self.listener = nil self. = ssh_opts self.on_client_connect_proc = cc_cb self.on_client_data_proc = cd_cb end |
Instance Attribute Details
#clients ⇒ Object
Returns the value of attribute clients
133 134 135 |
# File 'lib/rex/proto/ssh/server.rb', line 133 def clients @clients end |
#comm ⇒ Object
Returns the value of attribute comm
133 134 135 |
# File 'lib/rex/proto/ssh/server.rb', line 133 def comm @comm end |
#context ⇒ Object
Returns the value of attribute context
133 134 135 |
# File 'lib/rex/proto/ssh/server.rb', line 133 def context @context end |
#listen_host ⇒ Object
Returns the value of attribute listen_host
133 134 135 |
# File 'lib/rex/proto/ssh/server.rb', line 133 def listen_host @listen_host end |
#listen_port ⇒ Object
Returns the value of attribute listen_port
133 134 135 |
# File 'lib/rex/proto/ssh/server.rb', line 133 def listen_port @listen_port end |
#listener ⇒ Object
Returns the value of attribute listener
134 135 136 |
# File 'lib/rex/proto/ssh/server.rb', line 134 def listener @listener end |
#monitor_thread ⇒ Object
Returns the value of attribute monitor_thread
133 134 135 |
# File 'lib/rex/proto/ssh/server.rb', line 133 def monitor_thread @monitor_thread end |
#on_client_connect_proc ⇒ Object
Returns the value of attribute on_client_connect_proc
134 135 136 |
# File 'lib/rex/proto/ssh/server.rb', line 134 def on_client_connect_proc @on_client_connect_proc end |
#on_client_data_proc ⇒ Object
Returns the value of attribute on_client_data_proc
134 135 136 |
# File 'lib/rex/proto/ssh/server.rb', line 134 def on_client_data_proc @on_client_data_proc end |
#server_options ⇒ Object
Returns the value of attribute server_options
134 135 136 |
# File 'lib/rex/proto/ssh/server.rb', line 134 def @server_options end |
Class Method Details
.hardcore_alias(*args) ⇒ Object
Returns the hardcore alias for the SSH service
69 70 71 |
# File 'lib/rex/proto/ssh/server.rb', line 69 def self.hardcore_alias(*args) "#{(args[0])}#{(args[1])}" end |
Instance Method Details
#alias ⇒ Object
SSH server.
76 77 78 |
# File 'lib/rex/proto/ssh/server.rb', line 76 def alias super || "SSH Server" end |
#close_client(cli) ⇒ Object
Closes the supplied client, if valid.
127 128 129 130 |
# File 'lib/rex/proto/ssh/server.rb', line 127 def close_client(cli) clients.delete(cli) listener.close_client(cli.parent) end |
#enqueue_client(cli) ⇒ Object (protected)
Waits for SSH client to “grow a pair” of FDs and adds a ChannelFD object derived from the client's Connection Channel's FDs to the Ssh::Server's clients array
182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/rex/proto/ssh/server.rb', line 182 def enqueue_client(cli) Rex::ThreadFactory.spawn("ChannelFDWaiter", false) do begin Timeout::timeout(15) do while cli.connection.open_channel_keys.empty? do sleep 0.02 end self.clients.push(Ssh::ChannelFD.new(cli)) end rescue Timeout::Error elog("Unable to find channel FDs for client #{cli}") end end end |
#inspect ⇒ String
More readable inspect that only shows the url and resources
62 63 64 |
# File 'lib/rex/proto/ssh/server.rb', line 62 def inspect "#<#{self.class} ssh://#{listen_host}:#{listen_port}>" end |
#monitor_clients ⇒ Object (protected)
Watches FD channel abstractions, removes closed instances, checks for read data on clients if client data callback is defined, invokes the callback if possible, sleeps otherwise.
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/rex/proto/ssh/server.rb', line 157 def monitor_clients loop do self.clients.delete_if {|c| c.closed? } if self.on_client_data_proc if clients.any? { |cli| cli.has_read_data? and self.on_client_data_proc.call(cli)} next else sleep 0.05 end else sleep 0.5 end end rescue => e wlog(e) end |
#on_client_connect(cli) ⇒ Object (protected)
Extends new clients with the ServerClient module and initializes them.
141 142 143 144 145 146 147 148 149 150 |
# File 'lib/rex/proto/ssh/server.rb', line 141 def on_client_connect(cli) cli.extend(ServerClient) cli.init_cli(self) if self.on_client_connect_proc self.on_client_connect_proc.call(cli) else enqueue_client(cli) end end |
#start(srvsock = nil) ⇒ Object
Listens on the defined port and host and starts monitoring for clients.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/rex/proto/ssh/server.rb', line 84 def start(srvsock = nil) self.listener = srvsock.is_a?(Rex::Socket::TcpServer) ? srvsock : Rex::Socket::TcpServer.create( 'LocalHost' => self.listen_host, 'LocalPort' => self.listen_port, 'Context' => self.context, 'Comm' => self.comm ) # Register callbacks self.listener.on_client_connect_proc = Proc.new { |cli| on_client_connect(cli) } # self.listener.on_client_data_proc = Proc.new { |cli| # on_client_data(cli) # } self.clients = [] self.monitor_thread = Rex::ThreadFactory.spawn("SshServerClientMonitor", false) { monitor_clients } self.listener.start end |
#stop ⇒ Object
Terminates the monitor thread and turns off the listener.
110 111 112 113 114 |
# File 'lib/rex/proto/ssh/server.rb', line 110 def stop self.listener.stop self.listener.close self.clients = [] end |
#wait ⇒ Object
Waits for the SSH service to terminate
120 121 122 |
# File 'lib/rex/proto/ssh/server.rb', line 120 def wait self.listener.wait if self.listener end |