Class: Arachni::HTTP::ProxyServer

Inherits:
WEBrick::HTTPProxyServer
  • Object
show all
Defined in:
lib/arachni/http/proxy_server.rb

Overview

We add our own type of WEBrick::HTTPProxyServer class that does not restrict header exchange and supports SSL interception.

SSL interception is achieved by redirecting traffic via a 2nd (SSL enabled) instance of this server by hijacking the browser’s CONNECT request.

Author:

Constant Summary collapse

INTERCEPTOR_CERTIFICATE =
File.dirname( __FILE__ ) + '/proxy_server/ssl-interceptor-cert.pem'
INTERCEPTOR_PRIVATE_KEY =
File.dirname( __FILE__ ) + '/proxy_server/ssl-interceptor-pkey.pem'

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ ProxyServer

Returns a new instance of ProxyServer.

Parameters:

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :address (String) — default: '0.0.0.0'

    Address to bind to.

  • :port (Integer)

    Port number to listen on – defaults to a random port.

  • :timeout (Integer)

    HTTP time-out for each request in milliseconds.

  • :concurrency (Integer) — default: OptionGroups::HTTP#request_concurrency

    Maximum number of concurrent connections.

  • :response_handler (Block)

    Block to be called to handle each response as it arrives – will be passed the request and response.

  • :request_handler (Block)

    Block to be called to handle each request as it arrives – will be passed the request and response.

  • :ssl_certificate (String)

    SSL certificate.

  • :ssl_private_key (String)

    SSL private key.



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/arachni/http/proxy_server.rb', line 49

def initialize( options = {} )
    @options = {
        address:              '0.0.0.0',
        port:                 Utilities.available_port,
        ssl_certificate_name: [ [ 'CN', 'Arachni' ] ]
    }.merge( options )

    @logger = WEBrick::Log.new( Arachni.null_device, 7 )
    # Will force the proxy to stfu.
    @logger.close

    super(
        BindAddress:        @options[:address],
        Port:               @options[:port],
        MaxClients:         @options[:concurrency] || Options.http.request_concurrency,
        ProxyVia:           false,
        DoNotReverseLookup: true,
        AccessLog:          [],
        Logger:             @logger,
        Timeout:            @options[:timeout],
        SSLEnable:          @options.include?( :ssl_certificate ) &&
                                @options.include?( :ssl_private_key ),
        SSLCertName:        @options[:ssl_certificate_name],
        SSLCertificate:     @options[:ssl_certificate],
        SSLPrivateKey:      @options[:ssl_private_key]
    )
end

Class Method Details

.service(request, response) ⇒ Object



213
214
215
# File 'lib/arachni/http/proxy_server.rb', line 213

def @interceptor.service( request, response )
    @options[:service_handler].call( request, response )
end

Instance Method Details

#active_connectionsInteger

Returns Amount of active connections.

Returns:

  • (Integer)

    Amount of active connections.



104
105
106
# File 'lib/arachni/http/proxy_server.rb', line 104

def active_connections
    @tokens.max - @tokens.size
end

#addressString

Returns Proxy server URL.

Returns:

  • (String)

    Proxy server URL.



92
93
94
# File 'lib/arachni/http/proxy_server.rb', line 92

def address
    "#{@options[:address]}:#{@options[:port]}"
end

#has_connections?Bool

Returns ‘true` if the proxy has active connections, `false` otherwise.

Returns:

  • (Bool)

    ‘true` if the proxy has active connections, `false` otherwise.



98
99
100
# File 'lib/arachni/http/proxy_server.rb', line 98

def has_connections?
    active_connections != 0
end

#running?Bool

Returns ‘true` if the server is running, `false` otherwise.

Returns:

  • (Bool)

    ‘true` if the server is running, `false` otherwise.



87
88
89
# File 'lib/arachni/http/proxy_server.rb', line 87

def running?
    @status == :Running
end

#start_asyncObject

Starts the server without blocking, it’ll only block until the server is up and running and ready to accept connections.



79
80
81
82
83
# File 'lib/arachni/http/proxy_server.rb', line 79

def start_async
    Thread.new { start }
    sleep 0.1 while !running?
    nil
end