diff --git a/mitmproxy/connections.py b/mitmproxy/connections.py index fc6374204..9c4bca2f0 100644 --- a/mitmproxy/connections.py +++ b/mitmproxy/connections.py @@ -6,6 +6,7 @@ import os from mitmproxy import stateobject from mitmproxy import certs from mitmproxy.net import tcp +from mitmproxy.utils import strutils class ClientConnection(tcp.BaseHandler, stateobject.StateObject): @@ -52,9 +53,15 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject): return bool(self.connection) and not self.finished def __repr__(self): + if self.alpn_proto_negotiated: + alpn = "[ALPN: {}] ".format( + strutils.bytes_to_escaped_str(self.alpn_proto_negotiated) + ) + else: + alpn = "" return "".format( ssl="[ssl] " if self.ssl_established else "", - alpn="[ALPN: {}] ".format(self.alpn_proto_negotiated) if self.alpn_proto_negotiated else "", + alpn=alpn, address=repr(self.address) ) @@ -71,7 +78,7 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject): timestamp_end=float, sni=str, cipher_name=str, - alpn_proto_negotiated=str, + alpn_proto_negotiated=bytes, tls_version=str, ) @@ -162,9 +169,15 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject): ssl = "[ssl] " else: ssl = "" + if self.alpn_proto_negotiated: + alpn = "[ALPN: {}] ".format( + strutils.bytes_to_escaped_str(self.alpn_proto_negotiated) + ) + else: + alpn = "" return "".format( ssl=ssl, - alpn="[ALPN: {}] ".format(self.alpn_proto_negotiated) if self.alpn_proto_negotiated else "", + alpn=alpn, address=repr(self.address) ) @@ -179,7 +192,7 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject): ssl_established=bool, cert=certs.SSLCert, sni=str, - alpn_proto_negotiated=str, + alpn_proto_negotiated=bytes, timestamp_start=float, timestamp_tcp_setup=float, timestamp_ssl_setup=float, diff --git a/mitmproxy/test/tflow.py b/mitmproxy/test/tflow.py index f100f62ed..959c9a2c3 100644 --- a/mitmproxy/test/tflow.py +++ b/mitmproxy/test/tflow.py @@ -72,7 +72,7 @@ def tclient_conn(): timestamp_end=3, sni="address", cipher_name="cipher", - alpn_proto_negotiated=None, + alpn_proto_negotiated=b"http/1.1", tls_version="TLSv1.2", )) c.reply = controller.DummyReply() diff --git a/mitmproxy/tools/console/flowdetailview.py b/mitmproxy/tools/console/flowdetailview.py index 8c08d6eef..571a5e1b6 100644 --- a/mitmproxy/tools/console/flowdetailview.py +++ b/mitmproxy/tools/console/flowdetailview.py @@ -2,6 +2,7 @@ import urwid from mitmproxy.tools.console import common, searchable from mitmproxy.utils import human +from mitmproxy.utils import strutils def maybe_timestamp(base, attr): @@ -77,7 +78,7 @@ def flowdetails(state, flow): parts.append( [ "Alt names", - ", ".join(str(x) for x in c.altnames) + ", ".join(strutils.bytes_to_escaped_str(x) for x in c.altnames) ] ) text.extend( diff --git a/mitmproxy/tools/web/app.py b/mitmproxy/tools/web/app.py index ce18c6f06..c0de4c1f4 100644 --- a/mitmproxy/tools/web/app.py +++ b/mitmproxy/tools/web/app.py @@ -34,6 +34,12 @@ def flow_to_json(flow: mitmproxy.flow.Flow) -> dict: "type": flow.type, "modified": flow.modified(), } + # .alpn_proto_negotiated is bytes, we need to decode that. + for conn in "client_conn", "server_conn": + if f[conn]["alpn_proto_negotiated"] is None: + continue + f[conn]["alpn_proto_negotiated"] = \ + f[conn]["alpn_proto_negotiated"].decode(errors="backslashreplace") if flow.error: f["error"] = flow.error.get_state()