From 4c50c36345761f2b012c52bff230bdc5347f3d66 Mon Sep 17 00:00:00 2001 From: Terry Long Date: Sat, 28 Mar 2015 00:10:24 -0700 Subject: [PATCH] Prevent unecessary upstream server connects Selectively connect to upstream server based on no_upstream_cert option. When no_upstream_cert is used during server replay, prevent connecting to the upstream server unless absolutely necessary. --- libmproxy/flow.py | 6 +++++- libmproxy/protocol/http.py | 6 ++++-- libmproxy/protocol/primitives.py | 2 +- test/test_server.py | 11 +++++++++++ 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/libmproxy/flow.py b/libmproxy/flow.py index 1a052f51d..59312cebf 100644 --- a/libmproxy/flow.py +++ b/libmproxy/flow.py @@ -240,9 +240,13 @@ class ServerPlaybackState: _, _, path, _, query, _ = urlparse.urlparse(r.url) queriesArray = urlparse.parse_qsl(query, keep_blank_values=True) + # scheme should match the client connection to be able to replay + # although r.scheme may have been changed to http to connect to upstream server + scheme = "https" if flow.client_conn and flow.client_conn.ssl_established else "http" + key = [ str(r.port), - str(r.scheme), + str(scheme), str(r.method), str(path), ] diff --git a/libmproxy/protocol/http.py b/libmproxy/protocol/http.py index da15066bf..2bb1f5287 100644 --- a/libmproxy/protocol/http.py +++ b/libmproxy/protocol/http.py @@ -1297,7 +1297,6 @@ class HTTPHandler(ProtocolHandler): self.c.set_server_address((request.host, request.port)) # Update server_conn attribute on the flow flow.server_conn = self.c.server_conn - self.c.establish_server_connection() self.c.client_conn.send( ('HTTP/%s.%s 200 ' % (request.httpversion[0], request.httpversion[1])) + 'Connection established\r\n' + @@ -1498,7 +1497,10 @@ class HTTPHandler(ProtocolHandler): "Received CONNECT request to SSL port. " "Upgrading to SSL...", "debug" ) - self.c.establish_ssl(server=True, client=True) + server_ssl = not self.c.config.no_upstream_cert + if server_ssl: + self.c.establish_server_connection() + self.c.establish_ssl(server=server_ssl, client=True) self.c.log("Upgrade to SSL completed.", "debug") if self.c.config.check_tcp(address): diff --git a/libmproxy/protocol/primitives.py b/libmproxy/protocol/primitives.py index 2f8ea3e05..a9193c5f4 100644 --- a/libmproxy/protocol/primitives.py +++ b/libmproxy/protocol/primitives.py @@ -236,7 +236,7 @@ class LiveConnection(object): ssl_mismatch = ( ssl is not None and ( - ssl != self.c.server_conn.ssl_established + (self.c.server_conn.connection and ssl != self.c.server_conn.ssl_established) or (sni is not None and sni != self.c.server_conn.sni) ) diff --git a/test/test_server.py b/test/test_server.py index 2805e936c..9df4ef824 100644 --- a/test/test_server.py +++ b/test/test_server.py @@ -800,6 +800,17 @@ class TestFakeResponse(tservers.HTTPProxTest): assert "header_response" in f.headers.keys() +class TestServerConnect(tservers.HTTPProxTest): + masterclass = MasterFakeResponse + no_upstream_cert = True + ssl = True + def test_unnecessary_serverconnect(self): + """A replayed/fake response with no_upstream_cert should not connect to an upstream server""" + assert self.pathod("200").status_code == 200 + for msg in self.proxy.tmaster.log: + assert "serverconnect" not in msg + + class MasterKillRequest(tservers.TestMaster): def handle_request(self, f): f.reply(KILL)