Overview
Obscura requires a MitM (Man-in-the-Middle) proxy to intercept and modify HTTPS traffic. This document evaluates the available options.
Approaches
Approach 1: Go mitmproxy Library
Library: github.com/elazarl/goproxy
Pros:
- Mature, well-tested
- Handles CONNECT tunnels automatically
- Supports response modification
- MITM with on-the-fly certificate generation
Cons:
- HTTP/2 support is limited
- Large dependency tree
- Not designed for transparent proxy
Approach 2: Custom Rust Proxy with tokio + rustls
Pros:
- Full control over TLS stack
- Performance (zero-cost abstractions)
tokio-rustlsfor TLS termination- Hyper for HTTP/1 and HTTP/2
- Can integrate
utlsfor TLS fingerprint spoofing
Cons:
- More development effort
- Must handle certificate generation manually
- HTTP/2 frame-level parsing required
Approach 3: Squid + External Modification
Pros:
- Battle-tested proxy
- SSL Bump for MITM
- ICAP/eCAP for content modification
Cons:
- Complex configuration
- EOL versions still in use
- Not designed for JS injection
- Heavy container image
Approach 4: Envoy Proxy with Wasm Filter
Pros:
- High performance
- L4/L7 proxy
- WebAssembly (Wasm) filters for modification
- Native HTTP/2 and HTTP/3
Cons:
- Complex configuration
- Wasm filter development overhead
- Not designed for client-side JS injection
- Overkill for small-scale deployment
Approach 5: Custom TCP-Level Interception
Raw socket interception + TLS termination:
- Use iptables
TPROXYto redirect traffic - Raw TCP socket read
- Manual TLS handshake (via rustls/crypto/tls)
- HTTP/1.1 or HTTP/2 parsing
- Header modification + JS injection
- Forward to upstream
Pros:
- Maximum control
- No dependency on proxy frameworks
- Can handle all edge cases
Cons:
- Maximum development effort
- Must implement HTTP/2 and HTTP/3 handling
- Must handle connection pooling correctly
Recommendation
For Obscura, a custom Rust implementation (Approach 2) is the best trade-off:
- Go's goproxy lacks HTTP/2 and TLS spoofing
- Rust gives fine-grained control over TLS (utls integration)
- Performance matters for a network gateway
- Rust's safety guarantees reduce proxy bugs
Certificate Generation
For MITM, the proxy must generate TLS certificates on-the-fly:
- A CA certificate is generated at first startup
- For each new domain, a leaf certificate is signed by the CA
- The client must trust the CA certificate
Obscura CA (private key)
*.example.com (leaf, generated on first request)
*.anotherexample.com (leaf, generated on first request)
Certificate Storage
/var/lib/obscura/certs/
ca.pem # CA certificate (public)
ca-key.pem # CA private key
cache/ # Generated leaf certs
example.com.pem
...
serial # Certificate serial counter
Limitations
- HPKP (HTTP Public Key Pinning): Now deprecated in Chrome, but some sites still use it
- HSTS preloading: Sites in the HSTS preload list (e.g., google.com, stripe.com) will reject MITM certificates. Must be intercepted at DNS/network level first.
- Certificate Transparency: Some sites require CT logs. The proxy must embed SCTs.
- HTTP/3 (QUIC): Runs over UDP and is encrypted end-to-end. Must be blocked at the network level.
Conclusions
- Rust with
tokio-rustls+hyperis the recommended proxy stack - TLS fingerprint spoofing requires
utlsintegration - HSTS preloaded sites must be handled at DNS/network level
- HTTP/3 must be blocked (QUIC bypasses the proxy)