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 Attribute Summary collapse

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/?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.



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
109
110
111
112
113
# File 'lib/ssrf_proxy/server.rb', line 60

def initialize(ssrf, interface = '127.0.0.1', port = 8081)
  @banner = 'SSRF Proxy'
  @server = nil
  @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.url.host, @ssrf.url.port)
      print_good('Connected to remote host ' \
                 "#{@ssrf.url.host}:#{@ssrf.url.port} successfully")
    else
      raise SSRFProxy::Server::Error::RemoteHostUnresponsive.new,
            'Could not connect to remote host ' \
            "#{@ssrf.url.host}:#{@ssrf.url.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 Attribute Details

#loggerLogger (readonly)

Returns logger.

Returns:

  • (Logger)

    logger



19
20
21
# File 'lib/ssrf_proxy/server.rb', line 19

def logger
  @logger
end

Instance Method Details

#serveObject

Run proxy server asynchronously



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

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