Inspecting non-HTTPS TLS traffic

Posted on Feb 27, 2021

Inspecting TLS traffic from a browser or any application that works with an HTTPS proxy is straight-forward in most cases. Browser support for SSLKEYLOGFILE or mitmproxy (if you control the trusted CA list the application uses and it doesn’t use certificate pinning) address these scenarios respectively. I ran into a scenario recently where I wanted to inspect non-HTTP TLS traffic from a .NET library.

The default .NET HTTP client respects the standard HTTP_PROXY environment variables, but that didn’t help in this case. Internally the library is using DotNetty which in turn is using SslStream. At this time, SslStream doesn’t support exporting the secrets required to decrypt TLS traffic.

I came across this post from Peter Wu. He links to a .c file for building a library that can wrap the OpenSSL context initialization function calls and adds SSLKEYLOGFILE file support to any application (that dynamically links OpenSSL). Unfortunately it didn’t work with .NET executables. It turns out that the .NET runtime dlopens the OpenSSL .so directly and then passes the object handle to dlsym. dlsym will only search that object and its dependencies for symbols, so it won’t find the SSL_new wrapper symbol that was loaded via LD_PRELOAD.

In order to solve this problem, we can also intercept dlsym itself and ensure it always returns the wrapped SSL_new from our library and not the real one from the object handle passed in. I’ve done that and published the result as openssl-keylog. There is a convenience wrapper script called dumpcapssl that greatly simplifies making capture files + SSL secrets.

$ dumpcapssl eth0 ./SimulatedDevice
*** SSL keys: /tmp/dumpcapssl-BsybG1mk.keys ***
*** Capture : /tmp/dumpcapssl-BsybG1mk.pcapng from interface: eth0 ***
*** Starting Capture ***
Capturing on 'eth0'
File: /tmp/dumpcapssl-BsybG1mk.pcapng
*** Starting Command ***
IoT Hub - Simulated Mqtt device.
Press control-C to exit.
...
^C
Exiting...
Device simulator finished.
*** Command Stopped ***
*** Stopping Capture ***
Packets captured: 556
Packets received/dropped on interface 'eth0': 556/0 (pcap:0/dumpcap:0/flushed:0/ps_ifdrop:0) (100.0%)
*** Stopped Capture : /tmp/dumpcapssl-BsybG1mk.pcapng Keys: /tmp/dumpcapssl-BsybG1mk.keys ***

The .keys file can be used in the Wireshark TLS preferences to decrypt the capture.

decrypted packets in wireshark