aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mitmproxy/connections.py16
-rw-r--r--mitmproxy/io_compat.py2
-rw-r--r--mitmproxy/proxy/protocol/http.py3
-rw-r--r--mitmproxy/proxy/protocol/http2.py7
-rw-r--r--mitmproxy/proxy/protocol/http_replay.py6
-rw-r--r--mitmproxy/proxy/server.py3
-rw-r--r--mitmproxy/test/tflow.py4
-rw-r--r--mitmproxy/tools/console/flowdetailview.py4
-rw-r--r--setup.py2
9 files changed, 30 insertions, 17 deletions
diff --git a/mitmproxy/connections.py b/mitmproxy/connections.py
index c7941ad9..fc637420 100644
--- a/mitmproxy/connections.py
+++ b/mitmproxy/connections.py
@@ -22,6 +22,7 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject):
timestamp_end: Connection end timestamp
sni: Server Name Indication sent by client during the TLS handshake
cipher_name: The current used cipher
+ alpn_proto_negotiated: The negotiated application protocol
tls_version: TLS version
"""
@@ -44,14 +45,16 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject):
self.timestamp_ssl_setup = None
self.sni = None
self.cipher_name = None
+ self.alpn_proto_negotiated = None
self.tls_version = None
def connected(self):
return bool(self.connection) and not self.finished
def __repr__(self):
- return "<ClientConnection: {ssl}{address}>".format(
+ return "<ClientConnection: {ssl}{alpn}{address}>".format(
ssl="[ssl] " if self.ssl_established else "",
+ alpn="[ALPN: {}] ".format(self.alpn_proto_negotiated) if self.alpn_proto_negotiated else "",
address=repr(self.address)
)
@@ -68,6 +71,7 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject):
timestamp_end=float,
sni=str,
cipher_name=str,
+ alpn_proto_negotiated=str,
tls_version=str,
)
@@ -97,6 +101,7 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject):
timestamp_ssl_setup=None,
sni=None,
cipher_name=None,
+ alpn_proto_negotiated=None,
tls_version=None,
))
@@ -109,6 +114,7 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject):
else:
self.sni = None
self.cipher_name = self.connection.get_cipher_name()
+ self.alpn_proto_negotiated = self.get_alpn_proto_negotiated()
self.tls_version = self.connection.get_protocol_version_name()
def finish(self):
@@ -128,6 +134,7 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject):
ssl_established: True if TLS is established, False otherwise
cert: The certificate presented by the remote during the TLS handshake
sni: Server Name Indication sent by the proxy during the TLS handshake
+ alpn_proto_negotiated: The negotiated application protocol
via: The underlying server connection (e.g. the connection to the upstream proxy in upstream proxy mode)
timestamp_start: Connection start timestamp
timestamp_tcp_setup: TCP ACK received timestamp
@@ -138,6 +145,7 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject):
def __init__(self, address, source_address=None, spoof_source_address=None):
tcp.TCPClient.__init__(self, address, source_address, spoof_source_address)
+ self.alpn_proto_negotiated = None
self.via = None
self.timestamp_start = None
self.timestamp_end = None
@@ -154,8 +162,9 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject):
ssl = "[ssl] "
else:
ssl = ""
- return "<ServerConnection: {ssl}{address}>".format(
+ return "<ServerConnection: {ssl}{alpn}{address}>".format(
ssl=ssl,
+ alpn="[ALPN: {}] ".format(self.alpn_proto_negotiated) if self.alpn_proto_negotiated else "",
address=repr(self.address)
)
@@ -170,6 +179,7 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject):
ssl_established=bool,
cert=certs.SSLCert,
sni=str,
+ alpn_proto_negotiated=str,
timestamp_start=float,
timestamp_tcp_setup=float,
timestamp_ssl_setup=float,
@@ -189,6 +199,7 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject):
ip_address=dict(address=address, use_ipv6=False),
cert=None,
sni=None,
+ alpn_proto_negotiated=None,
source_address=dict(address=('', 0), use_ipv6=False),
ssl_established=False,
timestamp_start=None,
@@ -228,6 +239,7 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject):
self.convert_to_ssl(cert=clientcert, sni=sni, **kwargs)
self.sni = sni
+ self.alpn_proto_negotiated = self.get_alpn_proto_negotiated()
self.timestamp_ssl_setup = time.time()
def finish(self):
diff --git a/mitmproxy/io_compat.py b/mitmproxy/io_compat.py
index 20ee8824..14f4928c 100644
--- a/mitmproxy/io_compat.py
+++ b/mitmproxy/io_compat.py
@@ -67,8 +67,10 @@ def convert_017_018(data):
def convert_018_019(data):
data["version"] = (0, 19)
data["client_conn"]["sni"] = None
+ data["client_conn"]["alpn_proto_negotiated"] = None
data["client_conn"]["cipher_name"] = None
data["client_conn"]["tls_version"] = None
+ data["server_conn"]["alpn_proto_negotiated"] = None
data["mode"] = "regular"
data["metadata"] = dict()
return data
diff --git a/mitmproxy/proxy/protocol/http.py b/mitmproxy/proxy/protocol/http.py
index 50d64e17..59de070f 100644
--- a/mitmproxy/proxy/protocol/http.py
+++ b/mitmproxy/proxy/protocol/http.py
@@ -1,6 +1,5 @@
import h2.exceptions
import time
-import traceback
import enum
from mitmproxy import connections # noqa
@@ -431,7 +430,7 @@ class HttpLayer(base.Layer):
response = http.make_error_response(code, message, headers)
self.send_response(response)
except (exceptions.NetlibException, h2.exceptions.H2Error, exceptions.Http2ProtocolException):
- self.log(traceback.format_exc(), "debug")
+ self.log("Failed to send error response to client: {}".format(message), "debug")
def change_upstream_proxy_server(self, address) -> None:
# Make set_upstream_proxy_server always available,
diff --git a/mitmproxy/proxy/protocol/http2.py b/mitmproxy/proxy/protocol/http2.py
index 41707096..b7548221 100644
--- a/mitmproxy/proxy/protocol/http2.py
+++ b/mitmproxy/proxy/protocol/http2.py
@@ -1,6 +1,5 @@
import threading
import time
-import traceback
import functools
from typing import Dict, Callable, Any, List # noqa
@@ -328,7 +327,7 @@ class Http2Layer(base.Layer):
try:
while True:
- r = tcp.ssl_read_select(conns, 1)
+ r = tcp.ssl_read_select(conns, 0.1)
for conn in r:
source_conn = self.client_conn if conn == self.client_conn.connection else self.server_conn
other_conn = self.server_conn if conn == self.client_conn.connection else self.client_conn
@@ -358,7 +357,6 @@ class Http2Layer(base.Layer):
self._cleanup_streams()
except Exception as e: # pragma: no cover
self.log(repr(e), "info")
- self.log(traceback.format_exc(), "debug")
self._kill_all_streams()
@@ -580,7 +578,7 @@ class Http2SingleStreamLayer(httpbase._HttpTransmissionLayer, basethread.BaseThr
def read_response_body(self, request, response):
while True:
try:
- yield self.response_data_queue.get(timeout=1)
+ yield self.response_data_queue.get(timeout=0.1)
except queue.Empty: # pragma: no cover
pass
if self.response_data_finished.is_set():
@@ -624,7 +622,6 @@ class Http2SingleStreamLayer(httpbase._HttpTransmissionLayer, basethread.BaseThr
pass
except exceptions.ProtocolException as e: # pragma: no cover
self.log(repr(e), "info")
- self.log(traceback.format_exc(), "debug")
except exceptions.SetServerNotAllowedException as e: # pragma: no cover
self.log("Changing the Host server for HTTP/2 connections not allowed: {}".format(e), "info")
except exceptions.Kill:
diff --git a/mitmproxy/proxy/protocol/http_replay.py b/mitmproxy/proxy/protocol/http_replay.py
index 2e4c91b0..38f511c4 100644
--- a/mitmproxy/proxy/protocol/http_replay.py
+++ b/mitmproxy/proxy/protocol/http_replay.py
@@ -1,5 +1,3 @@
-import traceback
-
from mitmproxy import log
from mitmproxy import controller
from mitmproxy import exceptions
@@ -107,10 +105,10 @@ class RequestReplayThread(basethread.BaseThread):
"log",
log.LogEntry("Connection killed", "info")
)
- except Exception:
+ except Exception as e:
self.channel.tell(
"log",
- log.LogEntry(traceback.format_exc(), "error")
+ log.LogEntry(repr(e), "error")
)
finally:
r.first_line_format = first_line_format_backup
diff --git a/mitmproxy/proxy/server.py b/mitmproxy/proxy/server.py
index fc00a633..97018dad 100644
--- a/mitmproxy/proxy/server.py
+++ b/mitmproxy/proxy/server.py
@@ -120,7 +120,6 @@ class ConnectionHandler:
except exceptions.Kill:
self.log("Connection killed", "info")
except exceptions.ProtocolException as e:
-
if isinstance(e, exceptions.ClientHandshakeException):
self.log(
"Client Handshake failed. "
@@ -134,7 +133,7 @@ class ConnectionHandler:
else:
self.log(str(e), "warn")
- self.log(traceback.format_exc(), "debug")
+ self.log(repr(e), "debug")
# If an error propagates to the topmost level,
# we send an HTTP error response, which is both
# understandable by HTTP clients and humans.
diff --git a/mitmproxy/test/tflow.py b/mitmproxy/test/tflow.py
index 281047f5..f100f62e 100644
--- a/mitmproxy/test/tflow.py
+++ b/mitmproxy/test/tflow.py
@@ -72,6 +72,7 @@ def tclient_conn():
timestamp_end=3,
sni="address",
cipher_name="cipher",
+ alpn_proto_negotiated=None,
tls_version="TLSv1.2",
))
c.reply = controller.DummyReply()
@@ -93,7 +94,8 @@ def tserver_conn():
timestamp_end=4,
ssl_established=False,
sni="address",
- via=None
+ alpn_proto_negotiated=None,
+ via=None,
))
c.reply = controller.DummyReply()
return c
diff --git a/mitmproxy/tools/console/flowdetailview.py b/mitmproxy/tools/console/flowdetailview.py
index 7677efe4..8c08d6ee 100644
--- a/mitmproxy/tools/console/flowdetailview.py
+++ b/mitmproxy/tools/console/flowdetailview.py
@@ -31,6 +31,8 @@ def flowdetails(state, flow):
["Address", repr(sc.address)],
["Resolved Address", repr(sc.ip_address)],
]
+ if sc.alpn_proto_negotiated:
+ parts.append(["ALPN", sc.alpn_proto_negotiated])
text.extend(
common.format_keyvals(parts, key="key", val="text", indent=4)
@@ -94,6 +96,8 @@ def flowdetails(state, flow):
parts.append(["Server Name Indication", cc.sni])
if cc.cipher_name:
parts.append(["Cipher Name", cc.cipher_name])
+ if cc.alpn_proto_negotiated:
+ parts.append(["ALPN", cc.alpn_proto_negotiated])
text.extend(
common.format_keyvals(parts, key="key", val="text", indent=4)
diff --git a/setup.py b/setup.py
index 2f05eddc..08708b31 100644
--- a/setup.py
+++ b/setup.py
@@ -67,7 +67,7 @@ setup(
"cryptography>=1.3, <1.8",
"cssutils>=1.0.1, <1.1",
"Flask>=0.10.1, <0.12",
- "h2>=2.5.0, <3",
+ "h2>=2.5.1, <3",
"html2text>=2016.1.8, <=2016.9.19",
"hyperframe>=4.0.1, <5",
"jsbeautifier>=1.6.3, <1.7",