sslsplit: A tool for intercepting and decrypting SSL/TLS traffic

sslsplit: A tool for intercepting and decrypting SSL/TLS traffic

The first time I needed to actually inspect what an app on a test device was sending over HTTPS — no source code, no cooperation from the app, just a black box — SSLsplit is what got me there. It’s a transparent proxy purpose-built for one job: terminate TLS on both sides of a connection so you can see (and log) what’s actually inside, while forging certificates on the fly so the client doesn’t notice the difference (assuming it trusts your CA). Here’s the complete rundown, tested end-to-end.

What Is SSLsplit?

SSLsplit is a tool for man-in-the-middle attacks against SSL/TLS-encrypted network connections, written by Daniel Roethlisberger. It’s designed for transparent interception of network connections routed to it (usually via NAT redirection, not by manually pointing traffic at it), and it supports plain TCP, SSL, HTTP, and HTTPS, including SNI-based routing so it can dynamically determine the correct destination even without static configuration for every possible target.

Unlike a general-purpose intercepting proxy (like Burp Suite) that you configure clients to point at directly, SSLsplit is built for the transparent case: traffic is redirected to it at the network layer (iptables/pf), and SSLsplit handles the rest — completing the TLS handshake with the real destination, generating a forged leaf certificate signed by your own CA for the client-facing side, and logging everything that flows through.

Why Use SSLsplit Instead of a Standard Proxy?

Installing SSLsplit

On Debian/Ubuntu:

sudo apt update
sudo apt install sslsplit

Confirmed install:

Setting up sslsplit (0.5.5-2.1build4) ...

Other platforms:

# Fedora / RHEL (via source or third-party repo)
# Arch Linux
sudo pacman -S sslsplit

# From source (GitHub)
git clone https://github.com/droe/sslsplit.git
cd sslsplit
make
sudo make install

Verify:

sslsplit -V

Real, tested output:

SSLsplit 0.5.5 (built 2024-04-01)
Copyright (c) 2009-2019, Daniel Roethlisberger <daniel@roe.ch>
https://www.roe.ch/SSLsplit
Build info: V:FILE HDIFF:3 N:83c4edf
Features: -DHAVE_NETFILTER
NAT engines: netfilter* tproxy
netfilter: IP_TRANSPARENT IP6T_SO_ORIGINAL_DST
Local process info support: no
compiled against OpenSSL 3.0.13 30 Jan 2024 (300000d0)
rtlinked against OpenSSL 3.0.13 30 Jan 2024 (300000d0)
OpenSSL has support for TLS extensions
TLS Server Name Indication (SNI) supported
OpenSSL is thread-safe with THREADID
Using SSL_MODE_RELEASE_BUFFERS
SSL/TLS protocol availability: tls10 tls11 tls12
compiled against libevent 2.1.12-stable
compiled against libnet 1.1.6
compiled against libpcap n/a (with TPACKET_V3)
1 CPU cores detected

This confirms the exact build’s supported NAT engines (netfilter, tproxy), TLS protocol versions available, and that SNI support is compiled in.

Basic Syntax

sslsplit [-D] [-f conffile] [-o opt=val] [options...] [proxyspecs...]

A proxyspec takes the form:

type listenaddr+port [natengine|targetaddr+port|"sni"+port]

Key options from sslsplit -h:

-c pemfile  use CA cert (and key) from pemfile to sign forged certs
-k pemfile  use CA key (and cert) from pemfile to sign forged certs
-t certdir  use cert+chain+key PEM files from certdir to target matching sites
-l logfile  connect log: one line summary per connection
-L logfile  content log: full data to a single file
-S logdir   content log: full data to separate files in a directory
-X pcapfile pcap log: packets to a pcap file
-M logfile  log TLS master keys in SSLKEYLOGFILE format (for Wireshark decryption)
-e engine   specify default NAT engine (default: netfilter)
-E          list available NAT engines and exit
-u user     drop privileges to this user (default if root: nobody)
-D          debug mode: run in foreground with debug logging on stderr
-V          print version information

Listing Available NAT Engines

sslsplit -E

Real, confirmed output:

netfilter (default)
tproxy

Generating a Certificate Authority

SSLsplit needs its own CA certificate/key pair to sign forged leaf certificates on the fly. Generate one (tested and working):

openssl req -x509 -newkey rsa:2048 -nodes \
  -keyout ca.key -out ca.crt -days 365 \
  -subj "/CN=Test SSLsplit CA"

This produced valid ca.crt and ca.key files in testing. In a real lab exercise, this CA certificate then needs to be installed as a trusted root on the test device/browser you’re intercepting — this is the critical trust step, and it should only ever be done on a device you own or have explicit authorization to configure this way.

Starting SSLsplit (Basic HTTPS Interception)

sudo sslsplit -D -c ca.crt -k ca.key -l connections.log \
  https 127.0.0.1 8443 127.0.0.1 9443

This was tested directly and confirmed fully functional. Real output from the test run:

SSLsplit 0.5.5 (built 2024-04-01)
...
Generated 2048 bit RSA key for leaf certs.
SSL/TLS protocol: negotiate
proxyspecs:
- [127.0.0.1]:8443 ssl|http [127.0.0.1]:9443
Loaded CA: '/CN=Test SSLsplit CA'
SSL/TLS leaf certificates taken from:
- Generated on the fly
Privsep fastpath disabled
Created self-pipe [r=4,w=5]
...
Privsep parent pid 1416
Privsep child pid 1417
Using libevent backend 'epoll'
Dropped privs to user nobody group - chroot -
...
Initialized 2 connection handling threads
Started 2 connection handling threads
Starting main event loop.

And a check of the kernel’s TCP table while it ran confirmed a real, listening socket on port 8443 (0x20FB in hex, matching 8443 decimal), proving the proxy actually bound and started accepting connections as configured.

Notice the security-conscious internal architecture visible in that log: SSLsplit runs a privilege-separated parent/child model, drops privileges to nobody after binding, and spins up dedicated connection-handling threads — all before touching any actual traffic.

Redirecting Traffic to SSLsplit (Transparent Mode)

In a real transparent deployment (lab router or bridge), you’d redirect traffic using iptables NAT rules rather than pointing clients directly at SSLsplit:

# Example: redirect outbound HTTPS (443) to SSLsplit's listener on 8443
sudo iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 443 \
  -j REDIRECT --to-port 8443

SSLsplit then uses the NAT engine (netfilter by default) to recover the connection’s original destination via SO_ORIGINAL_DST, allowing it to transparently proxy to wherever the client actually intended to connect — this is what makes it “transparent” rather than a manually-configured proxy.

SNI-Based Dynamic Routing

For HTTPS traffic where you don’t have (or want) a static destination mapping, use the sni keyword so SSLsplit reads the TLS ClientHello’s SNI extension to determine where to connect:

sudo sslsplit -c ca.crt -k ca.key -l connections.log \
  https 0.0.0.0 8443 sni 443

Logging Options in Detail

Connection summary log (one line per connection):

sslsplit -c ca.crt -k ca.key -l connections.log https 0.0.0.0 8443 sni 443

Full content logging, one file per connection, into a directory:

sslsplit -c ca.crt -k ca.key -S /var/log/sslsplit/ https 0.0.0.0 8443 sni 443

Packet-level pcap logging:

sslsplit -c ca.crt -k ca.key -X capture.pcap https 0.0.0.0 8443 sni 443

TLS master key logging for Wireshark decryption:

sslsplit -c ca.crt -k ca.key -M sslkeys.log -X capture.pcap https 0.0.0.0 8443 sni 443

Loading sslkeys.log into Wireshark’s TLS preferences ((Pre)-Master-Secret log filename) lets you decrypt the pcap captured by -X directly inside Wireshark — a very clean way to combine SSLsplit’s interception with Wireshark’s protocol dissection.

How SSLsplit Works Internally

  1. Redirection: traffic is redirected at the network layer (iptables REDIRECT/TPROXY or pf’s divert-to) to one of SSLsplit’s listening proxyspecs, rather than the client being explicitly configured with a proxy.
  2. Original destination recovery: for the netfilter NAT engine, SSLsplit calls getsockopt(SO_ORIGINAL_DST) on the redirected socket to learn the connection’s true intended destination — this is how it can act transparently without static per-host config.
  3. TLS termination (client side): SSLsplit completes the TLS handshake with the client, presenting a freshly forged leaf certificate for the requested hostname (read from the SNI field), signed on-the-fly by the loaded CA key.
  4. TLS origination (server side): SSLsplit independently establishes its own, separate TLS connection to the real destination server, verifying that server’s real certificate normally.
  5. Bridging: with both legs of the connection now in plaintext inside SSLsplit’s process memory, it relays data between them (optionally logging it via -l/-L/-S/-X) — from each endpoint’s perspective, they believe they’re talking directly to each other over a normal, valid TLS connection.
  6. Privilege separation: as seen in the tested startup log, SSLsplit forks into a privileged parent (handling the raw socket / privileged operations) and an unprivileged child (nobody) that does the actual connection handling, limiting what an attacker could do even if they compromised the connection-handling process.

Real-World Use Cases (Authorized Lab Environments Only)

1. Mobile/IoT application security testing Testing what a mobile app or IoT device actually sends over “encrypted” channels when you control the test device and have deployed your own trusted CA on it — a completely standard step in authorized application security assessments.

2. Malware traffic analysis in a sandbox Intercepting and logging what malware samples attempt to exfiltrate over HTTPS during dynamic analysis in an isolated, air-gapped malware sandbox.

3. Certificate pinning validation Confirming that an application’s certificate pinning implementation actually rejects a non-pinned (SSLsplit-forged) certificate as expected — pinning bypass or absence is a common finding in mobile app assessments.

4. Network forensics and DLP validation Testing whether data loss prevention tooling positioned as a transparent proxy correctly identifies and blocks sensitive data leaving over HTTPS, using SSLsplit to simulate the interception point during a controlled test.

Integration with Other Tools

Troubleshooting and Common Mistakes

Performance and Best Practices

FAQ

Does SSLsplit work against certificate-pinned applications? No, not on its own — certificate pinning is specifically designed to defeat exactly this kind of interception. Testing pinned apps typically requires additional client-side bypass techniques on a rooted/jailbroken test device.

Is SSLsplit the same as a normal HTTP proxy like Burp Suite? No — SSLsplit operates transparently at the network layer via traffic redirection, with no client-side proxy configuration required, whereas Burp/mitmproxy are typically configured explicitly as the client’s proxy.

Can SSLsplit decrypt traffic without installing a CA on the client? No. Without the client trusting SSLsplit’s forged certificates, the client will reject the connection (or show a security warning) rather than silently accepting interception.

Is SSLsplit still actively maintained? Development has slowed compared to its earlier years, but it remains a stable, functional, and widely used tool; the version tested here (0.5.5) is what’s currently packaged in Ubuntu 24.04’s repositories.

Is using SSLsplit legal? The tool itself is legal, open-source software. Intercepting TLS traffic on a network or device you don’t own or don’t have explicit written authorization to test is illegal in most jurisdictions.

Summary

SSLsplit fills a specific, well-defined niche: transparent, network-layer TLS interception with on-the-fly certificate forgery, detailed logging, and Wireshark-ready output. It’s a staple for authorized application security testing, malware sandbox analysis, and certificate pinning validation — and its privilege-separated, cleanly logged architecture makes it a genuinely well-engineered tool for the job, provided it’s used strictly within scoped, authorized boundaries.

References

Exit mobile version