Class: Arachni::HTTP::ProxyServer

Inherits:
Object
  • Object
show all
Includes:
UI::Output
Defined in:
lib/arachni/http/proxy_server.rb,
lib/arachni/http/proxy_server/tunnel.rb,
lib/arachni/http/proxy_server/connection.rb,
lib/arachni/http/proxy_server/ssl_interceptor.rb

Overview

Author:

  • Tasos “Zapotek” Laskos <tasos.laskos@arachni-scanner.com>

Defined Under Namespace

Classes: Connection, SSLInterceptor, Tunnel

Constant Summary collapse

DEFAULT_CONCURRENCY =
4

Instance Method Summary collapse

Methods included from UI::Output

#debug?, #debug_level_1?, #debug_level_2?, #debug_level_3?, #debug_level_4?, #debug_off, #debug_on, #disable_only_positives, #included, #mute, #muted?, #only_positives, #only_positives?, #print_bad, #print_debug, #print_debug_backtrace, #print_debug_level_1, #print_debug_level_2, #print_debug_level_3, #print_debug_level_4, #print_error, #print_error_backtrace, #print_exception, #print_info, #print_line, #print_ok, #print_status, #print_verbose, #reroute_to_file, #reroute_to_file?, reset_output_options, #unmute, #verbose?, #verbose_on

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: DEFAULT_CONCURRENCY

    Amount of origin requests to be active at any given time.

  • :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.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/arachni/http/proxy_server.rb', line 41

def initialize( options = {} )
    @reactor = Arachni::Reactor.new(
        # Higher than the defaults to keep object allocations down.
        select_timeout:    0.1,
        max_tick_interval: 0.1
    )
    @options = options

    @active_connections = Concurrent::Map.new

    @options[:concurrency] ||= DEFAULT_CONCURRENCY
    @options[:address]     ||= '127.0.0.1'
    @options[:port]        ||= Utilities.available_port

    @concurrency_control_tokens = @reactor.create_queue
end

Instance Method Details

#active_connectionsObject



129
130
131
# File 'lib/arachni/http/proxy_server.rb', line 129

def active_connections
    @active_connections.keys
end

#get_request_token(&block) ⇒ Object



82
83
84
# File 'lib/arachni/http/proxy_server.rb', line 82

def get_request_token( &block )
    @concurrency_control_tokens.pop( &block )
end

#has_available_request_tokens?Boolean

Returns:

  • (Boolean)


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

def has_available_request_tokens?
    @concurrency_control_tokens.empty?
end

#has_pending_requests?Bool

Returns `true` if the proxy has pending requests, `false` otherwise.

Returns:

  • (Bool)

    `true` if the proxy has pending requests, `false` otherwise.



119
120
121
# File 'lib/arachni/http/proxy_server.rb', line 119

def has_pending_requests?
    pending_requests != 0
end

#mark_connection_active(connection) ⇒ Object



133
134
135
# File 'lib/arachni/http/proxy_server.rb', line 133

def mark_connection_active( connection )
    @active_connections.put_if_absent( connection, nil )
end

#mark_connection_inactive(connection) ⇒ Object



137
138
139
# File 'lib/arachni/http/proxy_server.rb', line 137

def mark_connection_inactive( connection )
    @active_connections.delete connection
end

#pending_requestsInteger

Returns Amount of active requests.

Returns:

  • (Integer)

    Amount of active requests.



125
126
127
# File 'lib/arachni/http/proxy_server.rb', line 125

def pending_requests
    @active_connections.size
end

#return_request_token(token) ⇒ Object



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

def return_request_token( token )
    @concurrency_control_tokens << token
end

#running?Bool

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

Returns:

  • (Bool)

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



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

def running?
    @reactor.running?
end

#shutdownObject



94
95
96
97
98
99
100
101
102
103
# File 'lib/arachni/http/proxy_server.rb', line 94

def shutdown
    print_debug_level_2 'Shutting down...'

    @thread_pool.kill if @thread_pool

    @reactor.stop
    @reactor.wait

    print_debug_level_2 '...shutdown.'
end

#start_asyncObject

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



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/arachni/http/proxy_server.rb', line 60

def start_async
    print_debug_level_2 'Starting...'

    @reactor.run_in_thread

    @options[:concurrency].times do |i|
        @concurrency_control_tokens << i
    end

    @reactor.on_error do |_, e|
        print_exception e
    end

    @reactor.listen(
        @options[:address], @options[:port], Connection,
        @options.merge( parent: self )
    )

    print_debug_level_2 "...started at: #{url}"
    nil
end

#urlString

Returns Proxy server URL.

Returns:

  • (String)

    Proxy server URL.



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

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