diff options
author | Aldo Cortesi <aldo@nullcube.com> | 2016-09-01 12:32:09 +1200 |
---|---|---|
committer | Aldo Cortesi <aldo@nullcube.com> | 2016-09-01 12:32:09 +1200 |
commit | afe34e8b28988bdff91123862194606152c03c33 (patch) | |
tree | 891a543646fb6764a3c670e84103ce4936bd3bab | |
parent | 9306e80e65bfa7e0945f4163536e2059e302e710 (diff) | |
download | mitmproxy-afe34e8b28988bdff91123862194606152c03c33.tar.gz mitmproxy-afe34e8b28988bdff91123862194606152c03c33.tar.bz2 mitmproxy-afe34e8b28988bdff91123862194606152c03c33.zip |
Improve the way we handle upstream errors
- Don't log a traceback for either HTTP or HTTPS DNS resolution or TCP
connection errors. These are "ordinary" errors, not mitmproxy issues.
- Ensure that the error handler is correctly called for SSL-related protocol
errors.
-rwxr-xr-x | examples/flowbasic | 4 | ||||
-rw-r--r-- | mitmproxy/protocol/http.py | 62 |
2 files changed, 39 insertions, 27 deletions
diff --git a/examples/flowbasic b/examples/flowbasic index 2e3458b1..67c6f596 100755 --- a/examples/flowbasic +++ b/examples/flowbasic @@ -32,8 +32,8 @@ class MyMaster(flow.FlowMaster): print("error", f) @controller.handler - def log(self, f): - print("log", f) + def log(self, l): + print("log", l.msg) opts = options.Options(cadir="~/.mitmproxy/") config = ProxyConfig(opts) diff --git a/mitmproxy/protocol/http.py b/mitmproxy/protocol/http.py index a765d97c..d81fc8ca 100644 --- a/mitmproxy/protocol/http.py +++ b/mitmproxy/protocol/http.py @@ -142,39 +142,53 @@ class HttpLayer(base.Layer): while True: try: request = self.get_request_from_client() - self.log("request", "debug", [repr(request)]) - - # Handle Proxy Authentication - # Proxy Authentication conceptually does not work in transparent mode. - # We catch this misconfiguration on startup. Here, we sort out requests - # after a successful CONNECT request (which do not need to be validated anymore) - if not (self.http_authenticated or self.authenticate(request)): - return - # Make sure that the incoming request matches our expectations self.validate_request(request) - - # Regular Proxy Mode: Handle CONNECT - if self.mode == "regular" and request.first_line_format == "authority": - self.handle_regular_mode_connect(request) - return except netlib.exceptions.HttpReadDisconnect: # don't throw an error for disconnects that happen before/between requests. return - except netlib.exceptions.NetlibException as e: + except netlib.exceptions.HttpException as e: + # We optimistically guess there might be an HTTP client on the + # other end self.send_error_response(400, repr(e)) - six.reraise(exceptions.ProtocolException, exceptions.ProtocolException( - "Error in HTTP connection: %s" % repr(e)), sys.exc_info()[2]) + self.log( + "request", + "warn", + "HTTP protocol error in client request: %s" % e + ) + return + + self.log("request", "debug", [repr(request)]) + + # Handle Proxy Authentication + # Proxy Authentication conceptually does not work in transparent mode. + # We catch this misconfiguration on startup. Here, we sort out requests + # after a successful CONNECT request (which do not need to be validated anymore) + if not (self.http_authenticated or self.authenticate(request)): + return + + flow = models.HTTPFlow(self.client_conn, self.server_conn, live=self) + flow.request = request try: - flow = models.HTTPFlow(self.client_conn, self.server_conn, live=self) - flow.request = request + # Regular Proxy Mode: Handle CONNECT + if self.mode == "regular" and request.first_line_format == "authority": + self.handle_regular_mode_connect(request) + return + except (exceptions.ProtocolException, netlib.exceptions.NetlibException) as e: + # HTTPS tasting means that ordinary errors like resolution and + # connection errors can happen here. + self.send_error_response(502, repr(e)) + flow.error = models.Error(str(e)) + self.channel.ask("error", flow) + return - # set upstream auth - if self.mode == "upstream" and self.config.upstream_auth is not None: - flow.request.headers["Proxy-Authorization"] = self.config.upstream_auth - self.process_request_hook(flow) + # set upstream auth + if self.mode == "upstream" and self.config.upstream_auth is not None: + flow.request.headers["Proxy-Authorization"] = self.config.upstream_auth + self.process_request_hook(flow) + try: if not flow.response: self.establish_server_connection( flow.request.host, @@ -209,11 +223,9 @@ class HttpLayer(base.Layer): except (exceptions.ProtocolException, netlib.exceptions.NetlibException) as e: self.send_error_response(502, repr(e)) - if not flow.response: flow.error = models.Error(str(e)) self.channel.ask("error", flow) - self.log(traceback.format_exc(), "debug") return else: six.reraise(exceptions.ProtocolException, exceptions.ProtocolException( |