MITM TLS session started in middle of TCP flow


#1

I’m trying to decrypt a connection that goes like this:

client -> server: plain tcp message
server -> client: plain tcp message
client -> server: TLS client hello
server -> client: TLS server hello
      <->         encrypted application data I want to see 

I can read the plain tcp messages just fine, but the TLS handshake is interpreted as raw data too, and the desired behavior is to have it mitm’d, terminating TLS.

I’ve tried a few things in scripts with my limited knowledge of mitmproxy internals. The most promising seeming was calling convert_to_tls() on flow.client_conn or flow.client_conn in the tcp_message event, but I don’t know exactly what it does or what arguments to pass.

To help with testing, I wrote a simple POC.

client:

import socket
import ssl

c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c.connect(('SERVER_HERE', 12345))
c.send(b"hi I'm about to start SSL")
print(c.recv(4096))
c_ssl = ssl.wrap_socket(c)
c_ssl.send(b"I'm connecting over ssl now")
print(c_ssl.recv(4096))
c_ssl.close()

server:

from socket import AF_INET, SOCK_STREAM, SO_REUSEADDR, SOL_SOCKET                                                  
import ssl                                                                                                         
                                                                                                                   
                                                                                                                   
KEYFILE = 'key.pem'                                                                                                
CERTFILE = 'certificate.pem'                                                                                       
                                                                                                                   
s = socket.socket(AF_INET, SOCK_STREAM)                                                                            
s.bind(('SERVER_HERE', 12345))                                                                                   
s.listen(1)                                                                                                        
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)                                                                          
                                                                                                                   
c, a = s.accept()                                                                                                  
print(c.recv(4096))                                                                                                
c.send(b"ok I'm switching to ssl too")                                                                             
c_ssl = ssl.wrap_socket(c, keyfile=KEYFILE, certfile=CERTFILE, server_side=True)                                   
print(c_ssl.recv(4096))                                                                                            
c_ssl.send(b'welcome to ssl')                                                                                      
c_ssl.close()

tl;dr how can I write a script to tell mitmproxy that a tls session starts at packet n in a tcp stream?