remove proxy mode abstraction: always be clear which mode we are in

This commit is contained in:
Maximilian Hils
2014-09-08 14:32:42 +02:00
parent 6dbe431c5e
commit d06b4bfa4e
8 changed files with 94 additions and 71 deletions

View File

@@ -3,7 +3,7 @@ import os
import re
from netlib import http_auth, certutils
from .. import utils, platform
from .primitives import ConstUpstreamServerResolver, TransparentUpstreamServerResolver
from .primitives import RegularProxyMode, TransparentProxyMode, UpstreamProxyMode, ReverseProxyMode
TRANSPARENT_SSL_PORTS = [443, 8443]
CONF_BASENAME = "mitmproxy"
@@ -26,25 +26,17 @@ class ProxyConfig:
self.body_size_limit = body_size_limit
if mode == "transparent":
get_upstream_server = TransparentUpstreamServerResolver(platform.resolver(), TRANSPARENT_SSL_PORTS)
http_form_in_default, http_form_out_default = "relative", "relative"
self.mode = TransparentProxyMode(platform.resolver(), TRANSPARENT_SSL_PORTS)
elif mode == "reverse":
get_upstream_server = ConstUpstreamServerResolver(upstream_server)
http_form_in_default, http_form_out_default = "relative", "relative"
self.mode = ReverseProxyMode(upstream_server)
elif mode == "upstream":
get_upstream_server = ConstUpstreamServerResolver(upstream_server)
http_form_in_default, http_form_out_default = "absolute", "absolute"
elif upstream_server:
get_upstream_server = ConstUpstreamServerResolver(upstream_server)
http_form_in_default, http_form_out_default = "absolute", "relative"
self.mode = UpstreamProxyMode(upstream_server)
else:
get_upstream_server, http_form_in_default, http_form_out_default = None, "absolute", "relative"
http_form_in = http_form_in or http_form_in_default
http_form_out = http_form_out or http_form_out_default
self.mode = RegularProxyMode()
self.mode.http_form_in = http_form_in or self.mode.http_form_in
self.mode.http_form_out = http_form_out or self.mode.http_form_out
self.get_upstream_server = get_upstream_server
self.http_form_in = http_form_in
self.http_form_out = http_form_out
self.ignore = parse_host_pattern(ignore)
self.authenticator = authenticator
self.confdir = os.path.expanduser(confdir)
@@ -74,13 +66,9 @@ def process_proxy_options(parser, options):
c += 1
mode = "upstream"
upstream_server = options.upstream_proxy
if options.manual_destination_server:
c += 1
mode = "manual"
upstream_server = options.manual_destination_server
if c > 1:
return parser.error("Transparent mode, reverse mode, upstream proxy mode and "
"specification of an upstream server are mutually exclusive.")
return parser.error("Transparent mode, reverse mode and upstream proxy mode "
"are mutually exclusive.")
if options.clientcerts:
options.clientcerts = os.path.expanduser(options.clientcerts)

View File

@@ -11,28 +11,54 @@ class ProxyServerError(Exception):
pass
class UpstreamServerResolver(object):
def __call__(self, conn):
class ProxyMode(object):
http_form_in = None
http_form_out = None
def get_upstream_server(self, conn):
"""
Returns the address of the server to connect to.
Returns None if the address needs to be determined on the protocol level (regular proxy mode)
"""
raise NotImplementedError # pragma: nocover
raise NotImplementedError() # pragma: nocover
@property
def name(self):
return self.__class__.__name__.replace("ProxyMode", "").lower()
def __str__(self):
return self.name
def __eq__(self, other):
"""
Allow comparisions with "regular" etc.
"""
if isinstance(other, ProxyMode):
return self is other
else:
return self.name == other
def __ne__(self, other):
return not self.__eq__(other)
class ConstUpstreamServerResolver(UpstreamServerResolver):
def __init__(self, dst):
self.dst = dst
class RegularProxyMode(ProxyMode):
http_form_in = "absolute"
http_form_out = "relative"
def __call__(self, conn):
return self.dst
def get_upstream_server(self, conn):
return None
class TransparentUpstreamServerResolver(UpstreamServerResolver):
class TransparentProxyMode(ProxyMode):
http_form_in = "relative"
http_form_out = "relative"
def __init__(self, resolver, sslports):
self.resolver = resolver
self.sslports = sslports
def __call__(self, conn):
def get_upstream_server(self, conn):
try:
dst = self.resolver.original_addr(conn)
except Exception, e:
@@ -45,6 +71,24 @@ class TransparentUpstreamServerResolver(UpstreamServerResolver):
return [ssl, ssl] + list(dst)
class _ConstDestinationProxyMode(ProxyMode):
def __init__(self, dst):
self.dst = dst
def get_upstream_server(self, conn):
return self.dst
class ReverseProxyMode(_ConstDestinationProxyMode):
http_form_in = "relative"
http_form_out = "relative"
class UpstreamProxyMode(_ConstDestinationProxyMode):
http_form_in = "absolute"
http_form_out = "absolute"
class Log:
def __init__(self, msg, level="info"):
self.msg = msg

View File

@@ -73,14 +73,16 @@ class ConnectionHandler:
# Can we already identify the target server and connect to it?
client_ssl, server_ssl = False, False
if self.config.get_upstream_server:
upstream_info = self.config.get_upstream_server(self.client_conn.connection)
upstream_info = self.config.mode.get_upstream_server(self.client_conn.connection)
if upstream_info:
self.set_server_address(upstream_info[2:])
client_ssl, server_ssl = upstream_info[:2]
if self.check_ignore_address(self.server_conn.address):
self.log("Ignore host: %s:%s" % self.server_conn.address(), "info")
self.conntype = "tcp"
client_ssl, server_ssl = False, False
else:
pass # No upstream info from the metadata: upstream info in the protocol (e.g. HTTP absolute-form)
self.channel.ask("clientconnect", self)