aboutsummaryrefslogtreecommitdiffstats
path: root/mitmproxy/proxy/protocol
diff options
context:
space:
mode:
authorMaximilian Hils <git@maximilianhils.com>2020-04-08 20:21:12 +0200
committerMaximilian Hils <git@maximilianhils.com>2020-04-08 20:21:12 +0200
commit9d5305301a8e073cbb64bb6574e66bb34373935a (patch)
tree7f30b0412a9974751846c757d44889694d00dc7b /mitmproxy/proxy/protocol
parent40925181e9d64c727f75e89acf0205bb4b87bb3a (diff)
parent4d6886a0f4ebbf6bc66b74fa548ff724ba2ad660 (diff)
downloadmitmproxy-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.py4
-rw-r--r--mitmproxy/proxy/protocol/http.py6
-rw-r--r--mitmproxy/proxy/protocol/http2.py46
-rw-r--r--mitmproxy/proxy/protocol/rawtcp.py11
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