Detect Conversion of Existing Connection to TLS

I’m using the docker image mitmproxy/mitmproxy:2.0.2 to sniff traffic between a Postgres client (psql) and server. The server uses TLS, but the client and server each send a single message before deciding to do the TLS handshake - these message appear to confuse mitmdump, so that it doesn’t know to intercept/decrypt the subsequent TLS traffic:

I monitor the connection using this inline script for mitdump:

def tcp_message(tcp_flow):
    client_addr = tcp_flow.client_conn.address
    server_addr = tcp_flow.server_conn.address
    latest_msg = tcp_flow.messages[-1]
    content = latest_msg.content
    timestamp = latest_msg.timestamp
    from_client = latest_msg.from_client
    output = """
client addr: {}
server addr: {}
from_client: {}
timestamp: {}
""".format(client_addr, server_addr, from_client, timestamp, content)

This script shows me the messages that precede the TLS handshake:

client addr:
server addr:
from_client: True
timestamp: 1504758794.6508732

client addr:
server addr:
from_client: False
timestamp: 1504758794.6517434

Subsequently, mitmdump does not recognize the conversion of the connection to use TLS, so all I can see is the encrypted messages. Does anyone have any advice about how to catch the handshake when it happens (since it does not happen right at the initial connect) and force mitmdump to intercept it? Any suggested modifications to my script appreciated!

This is quite tricky unfortunately. The easiest way to do this is probably writing your own Layer, and then hooking next_layer (as e.g. here). In that layer, you’d read both pre-TLS messages before opening up a TLS layer. You can read through modes/ to get a rough idea on how to write your own layer, but it’s still a fairly nontrivial thing to do.

Thank you for your reply! I will try out writing my own layer as you suggested.