From a82ac9eaf0ccc0f7c9f9588e8f76e213a6a5330b Mon Sep 17 00:00:00 2001 From: Heikki Hannikainen Date: Thu, 16 Feb 2012 16:33:27 +0200 Subject: [PATCH 1/2] Implemented reverse proxy mode: -R upstreamhost:port makes the proxy accept a 'GET / HTTP/1.0' request and fill up the destination host and port from the ones given with -R (for example, "-R localhost:80"). --- libmproxy/cmdline.py | 5 +++++ libmproxy/proxy.py | 12 ++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/libmproxy/cmdline.py b/libmproxy/cmdline.py index 6d1ffa3db..e7ca1bcf9 100644 --- a/libmproxy/cmdline.py +++ b/libmproxy/cmdline.py @@ -64,6 +64,11 @@ def common_options(parser): action="store", type = "int", dest="port", default=8080, help = "Proxy service port." ) + parser.add_option( + "-R", + action="store", dest="reverse_upstream", default=None, + help="Reverse proxy: upstream server host:port" + ) parser.add_option( "-q", action="store_true", dest="quiet", diff --git a/libmproxy/proxy.py b/libmproxy/proxy.py index 1fce46d67..3b853e94e 100644 --- a/libmproxy/proxy.py +++ b/libmproxy/proxy.py @@ -22,13 +22,14 @@ class ProxyError(Exception): class ProxyConfig: - def __init__(self, certfile = None, ciphers = None, cacert = None, cert_wait_time=0, body_size_limit = None): + def __init__(self, certfile = None, ciphers = None, cacert = None, cert_wait_time=0, body_size_limit = None, reverse_upstream=None): self.certfile = certfile self.ciphers = ciphers self.cacert = cacert self.certdir = None self.cert_wait_time = cert_wait_time self.body_size_limit = body_size_limit + self.reverse_upstream = reverse_upstream def read_chunked(fp, limit): @@ -347,6 +348,12 @@ class ProxyHandler(SocketServer.StreamRequestHandler): self.rfile = FileLike(self.connection) self.wfile = FileLike(self.connection) method, scheme, host, port, path, httpminor = parse_request_line(self.rfile.readline()) + # if we're in reverse proxy mode, we only get the path and version in the request + # and need to fill up host and port from the configuration + if self.config.reverse_upstream: + scheme = 'http' + host, port = self.config.reverse_upstream.split(':') + port = int(port) if scheme is None: scheme = "https" headers = flow.Headers() @@ -488,7 +495,8 @@ def process_proxy_options(parser, options): cacert = cacert, ciphers = options.ciphers, cert_wait_time = options.cert_wait_time, - body_size_limit = body_size_limit + body_size_limit = body_size_limit, + reverse_upstream = options.reverse_upstream ) From a3509b7f229eafdcbdd545e49de8ad2ac728e034 Mon Sep 17 00:00:00 2001 From: Heikki Hannikainen Date: Thu, 16 Feb 2012 16:36:49 +0200 Subject: [PATCH 2/2] reverse proxy mode: small comment clarification --- libmproxy/proxy.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libmproxy/proxy.py b/libmproxy/proxy.py index 3b853e94e..9b22c5005 100644 --- a/libmproxy/proxy.py +++ b/libmproxy/proxy.py @@ -348,8 +348,11 @@ class ProxyHandler(SocketServer.StreamRequestHandler): self.rfile = FileLike(self.connection) self.wfile = FileLike(self.connection) method, scheme, host, port, path, httpminor = parse_request_line(self.rfile.readline()) - # if we're in reverse proxy mode, we only get the path and version in the request - # and need to fill up host and port from the configuration + # If we're in reverse proxy mode, we only get the path and + # version in the request and need to fill up host and port + # from the configuration. This still assumes that the client will + # provide the correct Host: header and we do not need to tamper + # with that (or will tamper using other means). if self.config.reverse_upstream: scheme = 'http' host, port = self.config.reverse_upstream.split(':')