Class: SSRFProxy::Server

Inherits:
Object
  • Object
show all
Includes:
Celluloid::IO
Defined in:
lib/ssrf_proxy/server.rb

Overview

SSRFProxy::Server takes a SSRFProxy::HTTP object, interface and port, and starts a HTTP proxy server on the specified interface and port. All client HTTP requests are sent via the specified SSRFProxy::HTTP object.

Defined Under Namespace

Modules: Error

Instance Method Summary collapse

Constructor Details

#initialize(ssrf, interface = '127.0.0.1', port = 8081) ⇒ Server

Start the local server and listen for connections

Examples:

Start SSRF Proxy server with the default options

ssrf_proxy = SSRFProxy::Server.new(
  SSRFProxy::HTTP.new('http://example.local/index.php?url=xxURLxx'),
  '127.0.0.1',
  8081)
ssrf_proxy.serve

Parameters:

  • ssrf (SSRFProxy::HTTP)

    A configured SSRFProxy::HTTP object

  • interface (String) (defaults to: '127.0.0.1')

    Listen interface (Default: 127.0.0.1)

  • port (Integer) (defaults to: 8081)

    Listen port (Default: 8081)

Raises:

  • (SSRFProxy::Server::Error::InvalidSsrf)

    Invalid SSRFProxy::SSRF object provided.

  • (SSRFProxy::Server::Error::ProxyRecursion)

    Proxy recursion error. SSRF Proxy cannot use itself as an upstream proxy.

  • (SSRFProxy::Server::Error::RemoteProxyUnresponsive)

    Could not connect to remote proxy.

  • (SSRFProxy::Server::Error::AddressInUse)

    Could not bind to the port on the specified interface as address already in use.



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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/ssrf_proxy/server.rb', line 59

def initialize(ssrf, interface = '127.0.0.1', port = 8081)
  @banner = 'SSRF Proxy'
  @server = nil
  @max_request_len = 8192
  @logger = ::Logger.new(STDOUT).tap do |log|
    log.progname = 'ssrf-proxy-server'
    log.level = ::Logger::WARN
    log.datetime_format = '%Y-%m-%d %H:%M:%S '
  end
  # set ssrf
  unless ssrf.class == SSRFProxy::HTTP
    raise SSRFProxy::Server::Error::InvalidSsrf.new,
          'Invalid SSRF provided'
  end
  @ssrf = ssrf

  # check if the remote proxy server is responsive
  unless @ssrf.proxy.nil?
    if @ssrf.proxy.host == interface && @ssrf.proxy.port == port
      raise SSRFProxy::Server::Error::ProxyRecursion.new,
            "Proxy recursion error: #{@ssrf.proxy}"
    end
    if port_open?(@ssrf.proxy.host, @ssrf.proxy.port)
      print_good("Connected to remote proxy #{@ssrf.proxy.host}:#{@ssrf.proxy.port} successfully")
    else
      raise SSRFProxy::Server::Error::RemoteProxyUnresponsive.new,
            "Could not connect to remote proxy #{@ssrf.proxy.host}:#{@ssrf.proxy.port}"
    end
  end

  # if no upstream proxy is set, check if the remote server is responsive
  if @ssrf.proxy.nil?
    if port_open?(@ssrf.host, @ssrf.port)
      print_good("Connected to remote host #{@ssrf.host}:#{@ssrf.port} successfully")
    else
      raise SSRFProxy::Server::Error::RemoteHostUnresponsive.new,
            "Could not connect to remote host #{@ssrf.host}:#{@ssrf.port}"
    end
  end

  # start server
  logger.info "Starting HTTP proxy on #{interface}:#{port}"
  begin
    print_status "Listening on #{interface}:#{port}"
    @server = TCPServer.new(interface, port.to_i)
  rescue Errno::EADDRINUSE
    raise SSRFProxy::Server::Error::AddressInUse.new,
          "Could not bind to #{interface}:#{port} - address already in use"
  end
end

Instance Method Details

#loggerLogger

Logger accessor

Returns:

  • (Logger)

    class logger object



163
164
165
# File 'lib/ssrf_proxy/server.rb', line 163

def logger
  @logger
end

#serveObject

Run proxy server asynchronously



170
171
172
# File 'lib/ssrf_proxy/server.rb', line 170

def serve
  loop { async.handle_connection(@server.accept) }
end