tinspect is a transparent HTTP/HTTPS/WebSocket inspector and MITM proxy written in Rust.
It is designed to sit behind a TPROXY rule on Linux and receive redirected traffic destined for arbitrary remote hosts, terminate application-layer protocols, optionally inspect or transform them, and then forward traffic to the intended upstream server.
The project already supports HTTP/1.1, HTTPS MITM, WebSocket (ws:// and wss://), and transparent forwarding.
The only major missing protocol is HTTP/2.
This crate is not yet production ready, but the core pipeline works end-to-end.
- Receives TCP connections redirected using
TPROXY. - Recovers the original destination address and port.
- Opens a new outbound connection to the correct origin server.
- Forwards bytes bidirectionally.
- Uses Hyper 1.x to parse HTTP/1 requests and responses.
- Logging example shows full request/response forwarding.
- Supports body buffering (100MiB max).
- Enables inspection and transformation at many points.
- Terminates TLS using rustls.
- Extracts SNI from the client handshake.
- Dynamically generates per-hostname leaf certificates using rcgen.
- Signs those certificates with a company CA loaded from PEM.
- Caches generated certificates in an LRU cache for fast lookup.
- Creates a second TLS client session to the upstream server.
Effectively: full HTTPS MITM is already working.
- Detects HTTP Upgrade requests (
Connection: upgrade,Upgrade: websocket). - Responds with
101 Switching Protocolsvia Hyper. - Uses
hyper::upgrade::on(req)to obtain the raw TCP stream. - Wraps the stream in
tokio-tungstenite::WebSocketStream. - For
wss://, this happens after TLS MITM → you receive decrypted frames. - Handles Ping/Pong automatically (tungstenite handles this internally).
- HTTP/2 (h2) support ALPN + rustls + Hyper integration for h2 still needs to be implemented.
- HTTP/3 / QUIC (out of scope for now)
- Raw TCP forwarding fallback (not planned)
- Advanced inspection plugins
- Policy engine & configuration layer
- Corporate / lab networks that want central HTTPS/WSS inspection using a private CA.
- Diagnostic and debugging tools to observe and modify HTTP/TLS/WebSocket flows.
- A programmable, embeddable Rust-native MITM engine.
- Research environments needing deterministic control over traffic.
This crate is not intended for covert MITM. It assumes a network where clients trust your internal CA.
-
src/– core library- TPROXY listener
- HTTP/1 handling (client and upstream)
- TLS MITM (rustls + rcgen)
- WebSocket upgrade + framing (tokio-tungstenite)
- Forwarding utilities
-
examples/– runnable binaries demonstrating usage- Logging-only example (currently provided): forwards traffic unmodified and logs metadata
Clone and build:
git clone https://github.com/metastable-void/tinspect
cd tinspect
cargo build
Run the logging example (check actual example names):
cargo run --example tinspect-logging-proxy
This is only a starting point. Adapt to your network (interfaces, marks, routing tables) and test on a safe machine:
# send TCP/80 + TCP/443 traffic from lan0 to our transparent proxy
iptables -t mangle -A PREROUTING -i lan0 -p tcp --dport 80 -j TPROXY --on-port 80 --tproxy-mark 0x1/0x1
iptables -t mangle -A PREROUTING -i lan0 -p tcp --dport 443 -j TPROXY --on-port 443 --tproxy-mark 0x1/0x1
# route marked packets back to the local machine so the proxy can accept them
ip rule add fwmark 0x1 lookup 100
ip route add local 0.0.0.0/0 dev lo table 100
ip6tables -t mangle -A PREROUTING -i lan0 -p tcp --dport 80 -j TPROXY --on-port 80 --tproxy-mark 0x1/0x1
ip6tables -t mangle -A PREROUTING -i lan0 -p tcp --dport 443 -j TPROXY --on-port 443 --tproxy-mark 0x1/0x1
ip -6 rule add fwmark 0x1 lookup 100
ip -6 route add local ::/0 dev lo table 100
The listeners bind to [::]:80 and [::]:443 with IPV6_V6ONLY disabled, so a single socket handles both IPv4 and IPv6 once the NAT rules feed the traffic back to the host.
-
systemd service – create a oneshot unit (e.g.
/etc/systemd/system/tinspect-tproxy.service) that runs the iptables/ip rule commands inExecStart, and add matchingExecStoplines that delete them.WantedBy=multi-user.targetkeeps them applied during normal boots. -
systemd-networkd – if your host uses
systemd-networkd, you can keep everything in declarative files:-
*.network– apply the fwmark routing when the interface comes up:[Match] Name=lan0 [RoutingPolicyRule] Priority=100 FwMark=0x1 Table=100 [Route] Table=100 Gateway=0.0.0.0 PreferredSource=0.0.0.0 Type=localAdd a second
[RoutingPolicyRule]/[Route]block for IPv6 (Table=100,Type=local,Gateway=::). -
*.netdev– attach atcqdisc or IP rule helper if you prefer invokingiptablesviaExecStart=; otherwise use a companion*.servicewithWantedBy=sys-subsystem-net-devices-lan0.deviceso the firewall rules track the interface state.
-
-
iptables-persistent – store the mangle table in
/etc/iptables/rules.v4and/etc/iptables/rules.v6(iptables-save > /etc/iptables/rules.v4). The routing policy entries can be added fromsystemd-networkdas above or via/etc/network/if-pre-up.d/scripts. -
Always pair persistence with a rollback plan (console access or a watchdog timer) so you do not lock yourself out of the machine.
-
At startup you provide:
- a CA private key PEM
- a CA certificate PEM
-
These are loaded into a
rcgen::Issuer. -
When a client starts TLS:
- rustls extracts SNI
- the proxy looks up that hostname in a
DashMap - if missing, it generates a leaf keypair + certificate for that host
- signs it with your CA
- hands it to rustls as the server certificate
-
From that point onward, the proxy can inspect decrypted data.
This matches what corporate TLS inspection gateways typically do.
-
All WebSockets start as HTTP/1.1 requests.
-
The proxy:
- parses the request via Hyper,
- detects Upgrade,
- builds a 101 response,
- calls
hyper::upgrade::on(req), - wraps the resulting stream with
tokio_tungstenite.
-
Because tungstenite automatically responds to pings, the proxy only needs to read/write frames or forward them upstream.
Works for:
ws://host/pathwss://host/path(after TLS termination)
- Clients must trust your internal CA.
- Certificate pinning may break for some applications (expected).
- QUIC and HTTP/3 cannot be MITM’d with this architecture.
- Use only in networks where MITM is authorized.
- HTTP/2 parsing & forwarding
- Extensible inspection rule engine
- Streaming body inspection
- Performance tuning (zero-copy, buffer pools)
- Configuration loader (TOML/YAML)
- Better metrics and tracing
Dual-licensed:
- Apache License 2.0
- Mozilla Public License 2.0
See the LICENSE.APACHE and LICENSE.MPL files for details.
PRs, issues, and discussion are very welcome — especially around:
- correct and efficient TPROXY usage,
- rustls MITM details,
- Hyper 1.x integration,
- HTTP/2 handling strategies,
- WebSocket inspection examples.