From d06b4bfa4e4cc51e903b49e246d7771726a3e3a4 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Mon, 8 Sep 2014 14:32:42 +0200 Subject: remove proxy mode abstraction: always be clear which mode we are in --- libmproxy/proxy/config.py | 32 +++++++--------------- libmproxy/proxy/primitives.py | 64 ++++++++++++++++++++++++++++++++++++------- libmproxy/proxy/server.py | 6 ++-- 3 files changed, 68 insertions(+), 34 deletions(-) (limited to 'libmproxy/proxy') diff --git a/libmproxy/proxy/config.py b/libmproxy/proxy/config.py index 0ff08c6f..441e05f1 100644 --- a/libmproxy/proxy/config.py +++ b/libmproxy/proxy/config.py @@ -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) diff --git a/libmproxy/proxy/primitives.py b/libmproxy/proxy/primitives.py index 8c674381..23d089d3 100644 --- a/libmproxy/proxy/primitives.py +++ b/libmproxy/proxy/primitives.py @@ -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() -class ConstUpstreamServerResolver(UpstreamServerResolver): - def __init__(self, dst): - self.dst = dst + def __str__(self): + return self.name - def __call__(self, conn): - return self.dst + 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 RegularProxyMode(ProxyMode): + http_form_in = "absolute" + http_form_out = "relative" + + 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 diff --git a/libmproxy/proxy/server.py b/libmproxy/proxy/server.py index 31c50fce..f4a978ca 100644 --- a/libmproxy/proxy/server.py +++ b/libmproxy/proxy/server.py @@ -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) -- cgit v1.2.3