class Rex::Proto::Proxy::Socks4a::Client
A client connected to the Socks4a
server.
Constants
- COMMAND_BIND
- COMMAND_CONNECT
- HOST
- PORT
- REPLY_VERSION
- REQUEST_GRANTED
- REQUEST_REJECT_CONNECT
- REQUEST_REJECT_FAILED
- REQUEST_REJECT_USERID
- REQUEST_VERSION
Public Class Methods
new( server, sock )
click to toggle source
Create a new client connected to the server.
# File lib/rex/proto/proxy/socks4a.rb, line 222 def initialize( server, sock ) @server = server @lsock = sock @rsock = nil @client_thread = nil @mutex = ::Mutex.new end
Public Instance Methods
start()
click to toggle source
Start handling the client connection.
# File lib/rex/proto/proxy/socks4a.rb, line 233 def start # create a thread to handle this client request so as to not block the socks4a server @client_thread = Rex::ThreadFactory.spawn("SOCKS4AProxyClient", false) do begin @server.add_client( self ) # get the initial client request packet request = Packet.recv( @lsock ) raise "Invalid Socks4 request packet received." if not request # handle the request begin # handle socks4a conenct requests if( request.is_connect? ) # perform the connection request params = { 'PeerHost' => request.dest_ip, 'PeerPort' => request.dest_port, } params['Context'] = @server.opts['Context'] if @server.opts.has_key?('Context') @rsock = Rex::Socket::Tcp.create( params ) # and send back success to the client response = Packet.new response.version = REPLY_VERSION response.command = REQUEST_GRANTED @lsock.put( response.to_r ) # handle socks4a bind requests elsif( request.is_bind? ) # create a server socket for this request params = { 'LocalHost' => '0.0.0.0', 'LocalPort' => 0, } params['Context'] = @server.opts['Context'] if @server.opts.has_key?('Context') bsock = Rex::Socket::TcpServer.create( params ) # send back the bind success to the client response = Packet.new response.version = REPLY_VERSION response.command = REQUEST_GRANTED response.dest_ip = '0.0.0.0' response.dest_port = bsock.getlocalname()[PORT] @lsock.put( response.to_r ) # accept a client connection (2 minute timeout as per spec) begin ::Timeout.timeout( 120 ) do @rsock = bsock.accept end rescue ::Timeout::Error raise "Timeout reached on accept request." end # close the listening socket bsock.close # verify the connection is from the dest_ip origionally specified by the client rpeer = @rsock.getpeername raise "Got connection from an invalid peer." if( rpeer[HOST] != request.dest_ip ) # send back the client connect success to the client # # sf: according to the spec we send this response back to the client, however # I have seen some clients who bawk if they get this second response. # response = Packet.new response.version = REPLY_VERSION response.command = REQUEST_GRANTED response.dest_ip = rpeer[HOST] response.dest_port = rpeer[PORT] @lsock.put( response.to_r ) else raise "Unknown request command received #{request.command} received." end rescue # send back failure to the client response = Packet.new response.version = REPLY_VERSION response.command = REQUEST_REJECT_FAILED @lsock.put( response.to_r ) # raise an exception to close this client connection raise "Failed to handle the clients request." end # setup the two way relay for full duplex io @lsock.extend( Relay ) @rsock.extend( Relay ) # start the socket relays... @lsock.relay( self, @rsock ) @rsock.relay( self, @lsock ) rescue wlog( "Client.start - #{$!}" ) self.stop end end end
stop()
click to toggle source
Stop handling the client connection.
# File lib/rex/proto/proxy/socks4a.rb, line 326 def stop @mutex.synchronize do if( not @closed ) begin @lsock.close if @lsock rescue end begin @rsock.close if @rsock rescue end @client_thread.kill if( @client_thread and @client_thread.alive? ) @server.remove_client( self ) @closed = true end end end