Repository: mitmproxy/mitmproxy

Issue:
Display Server Name Indication in the UI
##### Steps to reproduce the problem:
1. `mitmproxy`
2. `curl -x localhost:8080 https://example.com/`
3. View Details Tab
##### What is the expected behavior?

The Server Name Indication sent by the client should be displayed in the UI.
##### What went wrong?

The SNI is not displayed in the "Client Connection" section.
##### Any other comments? What have you tried so far?

The first step here is to make a `.sni` attribute in ClientConnection which also gets serialized. I'm happy to help if anyone wants to pick this issue up! :smiley:

---

Mitmproxy Version: master
Operating System: Win10 x64

<!-- Please use the mitmproxy forums (https://discourse.mitmproxy.org/) for support/how-to questions. Thanks! :) -->



Discussion:
refs #582


Resolving patch:
diff --git a/mitmproxy/connections.py b/mitmproxy/connections.py
--- a/mitmproxy/connections.py
+++ b/mitmproxy/connections.py
@@ -20,6 +20,7 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject):
         timestamp_start: Connection start timestamp
         timestamp_ssl_setup: TLS established timestamp
         timestamp_end: Connection end timestamp
+        sni: Server Name Indication sent by client during the TLS handshake
     """
 
     def __init__(self, client_connection, address, server):
@@ -40,6 +41,7 @@ def __init__(self, client_connection, address, server):
         self.timestamp_end = None
         self.timestamp_ssl_setup = None
         self.protocol = None
+        self.sni = None
 
     def __bool__(self):
         return bool(self.connection) and not self.finished
@@ -61,6 +63,7 @@ def tls_established(self):
         timestamp_start=float,
         timestamp_ssl_setup=float,
         timestamp_end=float,
+        sni=str,
     )
 
     def copy(self):
@@ -86,12 +89,14 @@ def make_dummy(cls, address):
             ssl_established=False,
             timestamp_start=None,
             timestamp_end=None,
-            timestamp_ssl_setup=None
+            timestamp_ssl_setup=None,
+            sni=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()
 
     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
@@ -66,6 +66,7 @@ def convert_017_018(data):
 
 def convert_018_019(data):
     data["version"] = (0, 19)
+    data["client_conn"]["sni"] = 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,6 +82,8 @@ def flowdetails(state, flow):
         parts = [
             ["Address", repr(cc.address)],
         ]
+        if cc.sni:
+            parts.append(["Server Name Indication", cc.sni])
 
         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
@@ -132,6 +132,7 @@ def tclient_conn():
         timestamp_start=1,
         timestamp_ssl_setup=2,
         timestamp_end=3,
+        sni="address",
     ))
     c.reply = controller.DummyReply()
     return c