Repository: mitmproxy/mitmproxy

Issue:
View used SSL/TLS Version and Cipher Suite
Hey,

is it possible to view the Cipher Suite used to encrypt the traffic? I think this could be interesting while testing some application without the need to set specific ciphers. E.g. this information could be saved as an attribute in the HTTPMessage class. Moreover this could be helpful to check if the something was really encrypted, e.g. by setting the attribute to None (or is this information already provided by the scheme attribute?).  



Discussion:
> (or is this information already provided by the scheme attribute?)

yes. We also have the flow detail view (`X` in 0.11.3, more prominently on the current github master) to view the certificate.
Displaying the current cipher suite is useful, but we should keep in mind that the cipher suite may change at any point in time of the TLS connection, which makes displaying/storing it not entirely trivial.

It would be nice to have a first PR that just displays the cipher suite that is currently in use.

From #1589: It would also be very useful to display the TLS version that has been used for the server and client connections. If anyone picks this up, let me know and I'm happy to help!


Resolving patch:
diff --git a/mitmproxy/connections.py b/mitmproxy/connections.py
--- a/mitmproxy/connections.py
+++ b/mitmproxy/connections.py
@@ -21,6 +21,8 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject):
         timestamp_ssl_setup: TLS established timestamp
         timestamp_end: Connection end timestamp
         sni: Server Name Indication sent by client during the TLS handshake
+        cipher_name: The current used cipher
+        tls_version: TLS version
     """
 
     def __init__(self, client_connection, address, server):
@@ -42,6 +44,8 @@ def __init__(self, client_connection, address, server):
         self.timestamp_ssl_setup = None
         self.protocol = None
         self.sni = None
+        self.cipher_name = None
+        self.tls_version = None
 
     def __bool__(self):
         return bool(self.connection) and not self.finished
@@ -64,6 +68,8 @@ def tls_established(self):
         timestamp_ssl_setup=float,
         timestamp_end=float,
         sni=str,
+        cipher_name=str,
+        tls_version=str,
     )
 
     def copy(self):
@@ -90,13 +96,17 @@ def make_dummy(cls, address):
             timestamp_start=None,
             timestamp_end=None,
             timestamp_ssl_setup=None,
-            sni=None
+            sni=None,
+            cipher_name=None,
+            tls_version=None,
         ))
 
     def convert_to_ssl(self, *args, **kwargs):
         super().convert_to_ssl(*args, **kwargs)
         self.timestamp_ssl_setup = time.time()
         self.sni = self.connection.get_servername()
+        self.cipher_name = self.connection.get_cipher_name()
+        self.tls_version = self.connection.get_protocol_version_name()
 
     def finish(self):
         super().finish()
diff --git a/mitmproxy/io_compat.py b/mitmproxy/io_compat.py
--- a/mitmproxy/io_compat.py
+++ b/mitmproxy/io_compat.py
@@ -67,6 +67,8 @@ def convert_017_018(data):
 def convert_018_019(data):
     data["version"] = (0, 19)
     data["client_conn"]["sni"] = None
+    data["client_conn"]["cipher_name"] = None
+    data["client_conn"]["tls_version"] = None
     return data
 
 
diff --git a/mitmproxy/tools/console/flowdetailview.py b/mitmproxy/tools/console/flowdetailview.py
--- a/mitmproxy/tools/console/flowdetailview.py
+++ b/mitmproxy/tools/console/flowdetailview.py
@@ -82,8 +82,12 @@ def flowdetails(state, flow):
         parts = [
             ["Address", repr(cc.address)],
         ]
+        if cc.tls_version:
+            parts.append(["TLS Version", cc.tls_version])
         if cc.sni:
             parts.append(["Server Name Indication", cc.sni])
+        if cc.cipher_name:
+            parts.append(["Cipher Name", cc.cipher_name])
 
         text.extend(
             common.format_keyvals(parts, key="key", val="text", indent=4)


Test patch:
diff --git a/test/mitmproxy/tutils.py b/test/mitmproxy/tutils.py
--- a/test/mitmproxy/tutils.py
+++ b/test/mitmproxy/tutils.py
@@ -133,6 +133,8 @@ def tclient_conn():
         timestamp_ssl_setup=2,
         timestamp_end=3,
         sni="address",
+        cipher_name="cipher",
+        tls_version="TLSv1.2",
     ))
     c.reply = controller.DummyReply()
     return c