diff options
author | Maximilian Hils <git@maximilianhils.com> | 2020-04-08 20:21:12 +0200 |
---|---|---|
committer | Maximilian Hils <git@maximilianhils.com> | 2020-04-08 20:21:12 +0200 |
commit | 9d5305301a8e073cbb64bb6574e66bb34373935a (patch) | |
tree | 7f30b0412a9974751846c757d44889694d00dc7b /mitmproxy/proxy/protocol | |
parent | 40925181e9d64c727f75e89acf0205bb4b87bb3a (diff) | |
parent | 4d6886a0f4ebbf6bc66b74fa548ff724ba2ad660 (diff) | |
download | mitmproxy-9d5305301a8e073cbb64bb6574e66bb34373935a.tar.gz mitmproxy-9d5305301a8e073cbb64bb6574e66bb34373935a.tar.bz2 mitmproxy-9d5305301a8e073cbb64bb6574e66bb34373935a.zip |
Merge remote-tracking branch 'origin/master' into fix-ci
Diffstat (limited to 'mitmproxy/proxy/protocol')
-rw-r--r-- | mitmproxy/proxy/protocol/base.py | 4 | ||||
-rw-r--r-- | mitmproxy/proxy/protocol/http.py | 6 | ||||
-rw-r--r-- | mitmproxy/proxy/protocol/http2.py | 46 | ||||
-rw-r--r-- | mitmproxy/proxy/protocol/rawtcp.py | 11 |
4 files changed, 46 insertions, 21 deletions
diff --git a/mitmproxy/proxy/protocol/base.py b/mitmproxy/proxy/protocol/base.py index 2063f901..3bf03521 100644 --- a/mitmproxy/proxy/protocol/base.py +++ b/mitmproxy/proxy/protocol/base.py @@ -160,10 +160,10 @@ class ServerConnectionMixin: """ if not self.server_conn.address: raise exceptions.ProtocolException("Cannot connect to server, no server address given.") - self.log("serverconnect", "debug", [repr(self.server_conn.address)]) - self.channel.ask("serverconnect", self.server_conn) try: self.server_conn.connect() + self.log("serverconnect", "debug", [repr(self.server_conn.address)]) + self.channel.ask("serverconnect", self.server_conn) except exceptions.TcpException as e: raise exceptions.ProtocolException( "Server connection to {} failed: {}".format( diff --git a/mitmproxy/proxy/protocol/http.py b/mitmproxy/proxy/protocol/http.py index 4c20617b..37e1669e 100644 --- a/mitmproxy/proxy/protocol/http.py +++ b/mitmproxy/proxy/protocol/http.py @@ -1,3 +1,5 @@ +import textwrap + import h2.exceptions import time import enum @@ -142,13 +144,13 @@ def validate_request_form(mode, request): allowed_request_forms = MODE_REQUEST_FORMS[mode] if request.first_line_format not in allowed_request_forms: if mode == HTTPMode.transparent: - err_message = ( + err_message = textwrap.dedent(( """ Mitmproxy received an {} request even though it is not running in regular mode. This usually indicates a misconfiguration, please see the mitmproxy mode documentation for details. """ - ).format("HTTP CONNECT" if request.first_line_format == "authority" else "absolute-form") + )).strip().format("HTTP CONNECT" if request.first_line_format == "authority" else "absolute-form") else: err_message = "Invalid HTTP request form (expected: %s, got: %s)" % ( " or ".join(allowed_request_forms), request.first_line_format diff --git a/mitmproxy/proxy/protocol/http2.py b/mitmproxy/proxy/protocol/http2.py index a5870e6c..f5e7b1c6 100644 --- a/mitmproxy/proxy/protocol/http2.py +++ b/mitmproxy/proxy/protocol/http2.py @@ -87,6 +87,18 @@ class Http2Layer(base.Layer): # mypy type hints client_conn: connections.ClientConnection = None + class H2ConnLogger: + def __init__(self, name, log): + self.name = name + self.log = log + + def debug(self, fmtstr, *args): + msg = "H2Conn {}: {}".format(self.name, fmtstr % args) + self.log(msg, "debug") + + def trace(self, fmtstr, *args): + pass + def __init__(self, ctx, mode: str) -> None: super().__init__(ctx) self.mode = mode @@ -98,7 +110,8 @@ class Http2Layer(base.Layer): client_side=False, header_encoding=False, validate_outbound_headers=False, - validate_inbound_headers=False) + validate_inbound_headers=False, + logger=self.H2ConnLogger("client", self.log)) self.connections[self.client_conn] = SafeH2Connection(self.client_conn, config=config) def _initiate_server_conn(self): @@ -107,7 +120,8 @@ class Http2Layer(base.Layer): client_side=True, header_encoding=False, validate_outbound_headers=False, - validate_inbound_headers=False) + validate_inbound_headers=False, + logger=self.H2ConnLogger("server", self.log)) self.connections[self.server_conn] = SafeH2Connection(self.server_conn, config=config) self.connections[self.server_conn].initiate_connection() self.server_conn.send(self.connections[self.server_conn].data_to_send()) @@ -195,10 +209,12 @@ class Http2Layer(base.Layer): else: self.streams[eid].data_queue.put(event.data) self.streams[eid].queued_data_length += len(event.data) - self.connections[source_conn].safe_acknowledge_received_data( - event.flow_controlled_length, - event.stream_id - ) + + # always acknowledge receved data with a WINDOW_UPDATE frame + self.connections[source_conn].safe_acknowledge_received_data( + event.flow_controlled_length, + event.stream_id + ) return True def _handle_stream_ended(self, eid): @@ -209,13 +225,12 @@ class Http2Layer(base.Layer): def _handle_stream_reset(self, eid, event, is_server, other_conn): if eid in self.streams: self.streams[eid].kill() - if event.error_code == h2.errors.ErrorCodes.CANCEL: - if is_server: - other_stream_id = self.streams[eid].client_stream_id - else: - other_stream_id = self.streams[eid].server_stream_id - if other_stream_id is not None: - self.connections[other_conn].safe_reset_stream(other_stream_id, event.error_code) + if is_server: + other_stream_id = self.streams[eid].client_stream_id + else: + other_stream_id = self.streams[eid].server_stream_id + if other_stream_id is not None: + self.connections[other_conn].safe_reset_stream(other_stream_id, event.error_code) return True def _handle_remote_settings_changed(self, event, other_conn): @@ -461,7 +476,7 @@ class Http2SingleStreamLayer(httpbase._HttpTransmissionLayer, basethread.BaseThr if self.zombie is not None or connection_closed: if pre_command is not None: pre_command() - raise exceptions.Http2ZombieException("Connection already dead") + raise exceptions.Http2ZombieException("Connection or stream already dead: {}, {}".format(self.zombie, connection_closed)) @detect_zombie_stream def read_request_headers(self, flow): @@ -643,7 +658,8 @@ class Http2SingleStreamLayer(httpbase._HttpTransmissionLayer, basethread.BaseThr try: layer() except exceptions.Http2ZombieException: # pragma: no cover - pass + # zombies can be safely terminated - no need to kill them twice + return except exceptions.ProtocolException as e: # pragma: no cover self.log(repr(e), "info") except exceptions.SetServerNotAllowedException as e: # pragma: no cover diff --git a/mitmproxy/proxy/protocol/rawtcp.py b/mitmproxy/proxy/protocol/rawtcp.py index 0ec50594..00bba04c 100644 --- a/mitmproxy/proxy/protocol/rawtcp.py +++ b/mitmproxy/proxy/protocol/rawtcp.py @@ -29,13 +29,20 @@ class RawTCPLayer(base.Layer): server = self.server_conn.connection conns = [client, server] + # https://github.com/openssl/openssl/issues/6234 + for conn in conns: + if isinstance(conn, SSL.Connection) and hasattr(SSL._lib, "SSL_clear_mode"): + SSL._lib.SSL_clear_mode(conn._ssl, SSL._lib.SSL_MODE_AUTO_RETRY) + try: while not self.channel.should_exit.is_set(): r = mitmproxy.net.tcp.ssl_read_select(conns, 10) for conn in r: dst = server if conn == client else client - - size = conn.recv_into(buf, self.chunk_size) + try: + size = conn.recv_into(buf, self.chunk_size) + except (SSL.WantReadError, SSL.WantWriteError): + continue if not size: conns.remove(conn) # Shutdown connection to the other peer |