How OmniRoute Captures CLI Traffic Using MITM/TPROXY: A Technical Deep Dive

OmniRoute captures command-line interface (CLI) network traffic by leveraging Linux TPROXY rules to redirect packets, terminating TLS with dynamically generated certificates, and recording decrypted requests before securely forwarding them to upstream services.

OmniRoute is an open-source traffic inspection platform that enables developers to monitor HTTPS calls from local CLI tools without modifying application code. By implementing a layered MITM/TPROXY (Man-in-the-Middle/Transparent Proxy) architecture, the system intercepts encrypted traffic at the kernel level while preserving end-to-end behavior for the originating process.

The Three-Stage MITM/TPROXY Architecture

OmniRoute’s capture mechanism operates through three distinct stages: traffic redirection, TLS decryption, and request recording.

Stage 1: Kernel-Level Traffic Redirection via iptables

When TPROXY mode is enabled, OmniRoute constructs an iptables rule in the mangle table that intercepts outgoing TCP packets—typically targeting port 443 for HTTPS traffic. The rule generation logic resides in src/mitm/tproxy/commands.ts, which produces a command similar to:

iptables -t mangle -A PREROUTING -p tcp --dport <port> \
  -m mark --mark <mark> -j TPROXY \
  --on-port <local-proxy-port> --tproxy-mark <mark>

The applyTproxy function in src/mitm/tproxy/setup.ts executes this rule, marking packets and redirecting them to OmniRoute’s local proxy listener. To prevent remote exploitation, src/server/authz/routeGuard.ts enforces that these rules can only be applied on the local host where OmniRoute is running.

Stage 2: TLS Termination and Dynamic Certificate Generation

Once redirected, traffic reaches the TLS capture engine defined in src/mitm/tproxy/tlsCapture.ts. Here, OmniRoute performs a full TLS handshake with the CLI client using dynamically generated certificates. For each intercepted domain, src/mitm/tproxy/dynamicCert.ts issues a leaf certificate signed by the MITM root CA located at src/mitm/cert/rootCa.ts.

The dedicated trust store implementation in src/mitm/tproxy/caTrust.ts manages these temporary credentials, ensuring the CLI tool receives a certificate it trusts (once the root CA is installed) while allowing OmniRoute to decrypt the payload.

Stage 3: Recording and Re-encryption

After decryption, the request is structured as an InterceptedRequest object with source: "tproxy", as defined in src/shared/schemas/inspector.ts. The capture API in src/lib/inspector/tproxyCaptureApi.ts records the sanitized headers and masked request bodies according to configured guardrails.

Crucially, OmniRoute re-encrypts the request before forwarding it to the real upstream service. This maintains the original CLI’s expected behavior while providing full visibility into the plaintext request/response cycle. The native addon in src/mitm/tproxy/transparentSocket.ts enables efficient transparent socket handling during this process.

Capture Lifecycle Management and Cleanup

The src/mitm/tproxy/captureManager.ts module tracks active capture sessions, monitoring their status and associated process IDs. When a CLI process terminates or the user disables capture, the revertTproxy function in src/mitm/tproxy/setup.ts removes the iptables rules and deletes temporary certificate files, restoring the host’s original network configuration.

Programmatic control is exposed through the REST endpoint at src/app/api/tools/agent-bridge/tproxy/route.ts, which handles the complete lifecycle:

  • POST: Creates iptables rules, installs the dedicated CA, and starts the TLS capture engine
  • GET: Returns the current CaptureManagerStatus and active configuration
  • DELETE: Triggers cleanup via revertTproxy, removing rules and CA files

Implementing TPROXY Capture in Practice

To enable MITM/TPROXY capture for a local CLI tool, interact with the agent-bridge API:

// Enable TPROXY capture on port 8443 with mark 9011
await fetch('/api/tools/agent-bridge/tproxy', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ onPort: 8443, mark: 9011 })
});

Monitor active captures by querying the status endpoint:

// Retrieve current capture status
const status = await fetch('/api/tools/agent-bridge/tproxy')
  .then(r => r.json()) as CaptureManagerStatus;

When finished, clean up the environment:

// Disable capture and restore network state
await fetch('/api/tools/agent-bridge/tproxy', { method: 'DELETE' });

Summary

Frequently Asked Questions

What is TPROXY and why does OmniRoute use it for CLI traffic?

TPROXY is a Linux netfilter target that enables transparent proxying of TCP traffic without requiring the client application to configure a proxy explicitly. OmniRoute leverages TPROXY in src/mitm/tproxy/setup.ts because CLI tools often lack built-in proxy support; TPROXY intercepts packets at the kernel level before they leave the network stack, allowing OmniRoute to capture traffic from hardcoded HTTPS clients without code modifications.

How does OmniRoute handle TLS certificates for HTTPS CLI tools?

OmniRoute maintains a dedicated MITM root CA in src/mitm/cert/rootCa.ts. When a TLS connection is intercepted by src/mitm/tproxy/tlsCapture.ts, the src/mitm/tproxy/dynamicCert.ts module generates a domain-specific leaf certificate signed by this root. The CLI tool trusts this certificate once the root CA is installed in the system trust store, while OmniRoute maintains separate encrypted channels to the upstream service.

Is the TPROXY capture mode secure for production environments?

According to the source code in src/server/authz/routeGuard.ts, the TPROXY implementation is strictly local-only and guarded by route-level authorization. The architecture requires local host execution permissions to apply iptables rules, and cleanup routines in src/mitm/tproxy/setup.ts remove all network modifications and temporary certificates when captures end. However, as with any MITM tool, it should only be used in controlled development or testing environments with proper access controls.

How do I programmatically start and stop TPROXY captures?

Send HTTP requests to the Next.js API route at /api/tools/agent-bridge/tproxy defined in src/app/api/tools/agent-bridge/tproxy/route.ts. Use a POST request with JSON body {"onPort": <port>, "mark": <mark>} to initiate capture, a GET request to check CaptureManagerStatus, and a DELETE request to trigger the revertTproxy cleanup function and restore original network settings.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →