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

CACHE =
{
    format_field_name: Support::Cache::LeastRecentlyPushed.new( 100 )
}
SKIP_HEADERS =
Set.new( HopByHop | ['content-encoding'] )
INTERCEPTOR_CA_CERTIFICATE =
File.dirname( __FILE__ ) + '/proxy_server/ssl-interceptor-cacert.pem'
INTERCEPTOR_CA_KEY =
File.dirname( __FILE__ ) + '/proxy_server/ssl-interceptor-cakey.pem'

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.



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/arachni/http/proxy_server.rb', line 55

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

    @interceptor_ports = {}
    @interceptors      = {}

    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

Instance Method Details

#active_connectionsInteger

Returns Amount of active connections.

Returns:

  • (Integer)

    Amount of active connections.



113
114
115
# File 'lib/arachni/http/proxy_server.rb', line 113

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

#addressString

Returns Proxy server URL.

Returns:

  • (String)

    Proxy server URL.



101
102
103
# File 'lib/arachni/http/proxy_server.rb', line 101

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.



107
108
109
# File 'lib/arachni/http/proxy_server.rb', line 107

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.



96
97
98
# File 'lib/arachni/http/proxy_server.rb', line 96

def running?
    @status == :Running
end

#shutdownObject



117
118
119
120
121
122
123
# File 'lib/arachni/http/proxy_server.rb', line 117

def shutdown
    @interceptors.each do |_, interceptor|
        interceptor.shutdown
    end

    super
end

#start_asyncObject

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



88
89
90
91
92
# File 'lib/arachni/http/proxy_server.rb', line 88

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