Rustler is a man-in-the-middle TCP proxy with TLS termination and HTTPS interception, written in Rust.
I had that project idea during some Network Engineering lectures, the purpose was to enforce my network knowledge with a real world example. The main idea was to work over TCP and TLS and allow the user to implement any kind of protocol over TCP. Another important point was to handle TLS and Certificates to allow the proxy to display/modify the intercepted traffic
flowchart LR
C[Client] -->|request| P[Proxy] -->|forward| S[Server]
P -->|hostname| X{target: match?}
S -->|response| P -->|response| C
X -->|no| CF[1.1.1.1]
CF -->|real record| P
X -->|yes| D[Fake DNS]
D -->|proxy ip| P
-
HTTP: term1:
cargo run -- --tcp-listen 0.0.0.0:8080 --target-hostname example.com --udp-port 31313 --ca-dir /tmp/rustlerterm2:curl -x http://localhost:8080 http://example.com -
HTTPS: term1:
cargo run -- --tcp-listen 0.0.0.0:8080 --target-hostname example.com --udp-port 31313 --ca-dir /tmp/rustlerterm2:curl --cacert /tmp/rustler/cert.pem -v -x http://localhost:8080 https://example.com -
DNS: term1:
cargo run -- --tcp-listen 0.0.0.0:8080 --target-hostname example.com --udp-port 31313 --ca-dir /tmp/rustlerterm2:dig @127.0.0.1 -p 31313 example.com
Protocol handling is currently hardcoded for HTTP/HTTPS. Supporting arbitrary user-defined protocols would require a protocol handler registry (trait-based dispatch) that is not implemented yet. SNI parsing for transparent (non-CONNECT) proxying is also not yet implemented; the proxy currently relies on the CONNECT hostname About the fake DNS server, the strategy is to forward the traffic that is no targeted and send a fake DNS record to the client with the proxy IP for the targeted traffic. Other strategies could have been implemented and are still considered for a v2+ like a Transparent/full intercept. DNS-based interception assumes the client uses plain DNS (UDP port 53). Clients with DNS-over-HTTPS enabled (default in some browsers) bypass the fake DNS server entirely and resolve directly against a remote resolver, so the proxy is never engaged for those clients. A v2 could address this with gateway-level traffic redirection (e.g. iptables/pf rules forcing all outbound port 443 traffic through the proxy) instead of relying on DNS spoofing, which is the standard approach used by transparent MITM appliances.
RFC 1035: STD 13: Domain names - implementation and specification
RFC 8446: The Transport Layer Security (TLS) Protocol Version 1.3
RFC 9110: STD 97: HTTP Semantics
Beej's Guide to Network Programming
