From 8ae32708076efdf2bf88f5bb288e90c871eeec21 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Fri, 15 Jun 2012 09:47:04 +1200 Subject: [PATCH] Basic transparent mode. --- libmproxy/proxy.py | 23 +++++++++++++++++------ test/test_server.py | 2 +- test/tutils.py | 31 +++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/libmproxy/proxy.py b/libmproxy/proxy.py index fa8d10622..bcbc8ea5a 100644 --- a/libmproxy/proxy.py +++ b/libmproxy/proxy.py @@ -34,8 +34,8 @@ class ProxyError(Exception): class ProxyConfig: - def __init__(self, certfile = None, cacert = None, clientcerts = None, cert_wait_time=0, upstream_cert=False, body_size_limit = None, reverse_proxy=None, transparent_mode=None): - assert not (reverse_proxy and transparent_mode) + def __init__(self, certfile = None, cacert = None, clientcerts = None, cert_wait_time=0, upstream_cert=False, body_size_limit = None, reverse_proxy=None, transparent_proxy=None): + assert not (reverse_proxy and transparent_proxy) self.certfile = certfile self.cacert = cacert self.clientcerts = clientcerts @@ -44,7 +44,7 @@ class ProxyConfig: self.upstream_cert = upstream_cert self.body_size_limit = body_size_limit self.reverse_proxy = reverse_proxy - self.transparent_mode = transparent_mode + self.transparent_proxy = transparent_proxy def read_headers(fp): @@ -490,8 +490,20 @@ class ProxyHandler(SocketServer.StreamRequestHandler): if line == "": return None - if self.config.transparent_mode: - pass + if self.config.transparent_proxy: + host, port = self.config.transparent_proxy["resolver"].original_addr(self.connection) + if port in self.config.transparent_proxy["sslports"]: + scheme = "https" + certfile = self.find_cert(host, port) + self.convert_to_ssl(certfile) + else: + scheme = "http" + method, path, httpversion = parse_init_http(line) + headers = read_headers(self.rfile) + content = read_http_body_request( + self.rfile, self.wfile, headers, httpversion, self.config.body_size_limit + ) + return flow.Request(client_conn, httpversion, host, port, "http", method, path, headers, content) elif self.config.reverse_proxy: scheme, host, port = self.config.reverse_proxy method, path, httpversion = parse_init_http(line) @@ -519,7 +531,6 @@ class ProxyHandler(SocketServer.StreamRequestHandler): self.convert_to_ssl(certfile) self.proxy_connect_state = (host, port, httpversion) line = self.rfile.readline(line) - if self.proxy_connect_state: host, port, httpversion = self.proxy_connect_state method, path, httpversion = parse_init_http(line) diff --git a/test/test_server.py b/test/test_server.py index e54d35595..8878cf32e 100644 --- a/test/test_server.py +++ b/test/test_server.py @@ -32,7 +32,7 @@ class TestReverse(tutils.ReverseProxTest, SanityMixin): reverse = True -class _TestTransparent(): +class TestTransparent(tutils.TransparentProxTest, SanityMixin): transparent = True diff --git a/test/tutils.py b/test/tutils.py index 2556a57b2..5d96d934f 100644 --- a/test/tutils.py +++ b/test/tutils.py @@ -147,6 +147,37 @@ class HTTPProxTest(ProxTestBase): ) +class TResolver: + def __init__(self, port): + self.port = port + + def original_addr(self, sock): + return ("127.0.0.1", self.port) + + +class TransparentProxTest(ProxTestBase): + ssl = None + @classmethod + def get_proxy_config(cls): + return dict( + transparent_proxy = dict( + resolver = TResolver(cls.server.port), + sslports = [] + ) + ) + + def pathod(self, spec): + """ + Constructs a pathod request, with the appropriate base and proxy. + """ + r = hurl.get( + "http://127.0.0.1:%s"%self.proxy.port + "/p/" + spec, + validate_cert=False, + #debug=hurl.utils.stdout_debug + ) + return r + + class ReverseProxTest(ProxTestBase): ssl = None @classmethod