# How to Configure the MITM TPROXY Proxy to Capture Traffic from CLI Tools that Ignore Proxy Environment Variables in OmniRoute

> Learn to configure MITM TPROXY proxy in OmniRoute to capture CLI tool traffic bypassing proxy environment variables. Intercept TCP traffic at the kernel level with iptables.

- Repository: [Diego Rodrigues de Sa e Souza/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- Tags: how-to-guide
- Published: 2026-07-10

---

**Use OmniRoute's kernel-level TPROXY capture mode to intercept outbound TCP traffic via iptables rules, bypassing the need for proxy environment variables entirely.**

OmniRoute's MITM subsystem provides a **TPROXY capture mode** that operates at the kernel level to intercept traffic from command-line tools that hard-code direct connections or ignore standard `http_proxy` and `https_proxy` settings. Unlike traditional proxy configurations that rely on environment variables, this transparent proxy implementation uses Linux netfilter rules to redirect packets before they leave the system, making it effective for capturing traffic from `curl`, `git`, and proprietary CLIs.

## How TPROXY Interception Works in OmniRoute

The TPROXY implementation in `diegosouzapw/OmniRoute` bypasses the application layer entirely by intercepting packets at the kernel level. When you **configure the MITM proxy TPROXY** mode, OmniRoute applies iptables rules to the `PREROUTING` mangle chain, redirecting outbound TCP connections to a local transparent listener without modifying the destination IP headers.

Key components handle the lifecycle:
- **[`src/mitm/tproxy/setup.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/mitm/tproxy/setup.ts)** contains the transactional builder `applyTproxy()` and `revertTproxy()` that manage iptables rule insertion and rollback
- **[`src/mitm/tproxy/captureMode.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/mitm/tproxy/captureMode.ts)** implements the transparent listener that reads the original destination via `socket.localAddress`
- **[`src/mitm/tproxy/caTrust.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/mitm/tproxy/caTrust.ts)** handles dynamic per-SNI CA generation and OS trust-store installation

## Configuring TPROXY Capture Step-by-Step

### Starting the TPROXY Capture Session

Initiate capture by sending a POST request to the local-only API endpoint `POST /api/tools/agent-bridge/tproxy`. This endpoint, defined in [`src/app/api/tools/agent-bridge/tproxy/route.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/tools/agent-bridge/tproxy/route.ts), orchestrates the startup sequence:

1. Transactionally applies iptables TPROXY rules (`applyTproxy` in [`src/mitm/tproxy/setup.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/mitm/tproxy/setup.ts))
2. Opens a transparent listener on the specified port
3. Installs a per-SNI dynamic CA into the OS trust store

```typescript
// Client-side helper to start capture
import { startCapture } from '@/lib/inspector/tproxyCaptureApi';

await startCapture({
  onPort: 8443,          // listener port
  mark: 9011,            // iptables MARK value
  sudoPassword: '••••',  // required on non-root desktop builds
});

```

### Preventing Capture Loops with Socket Marking

To avoid OmniRoute intercepting its own outbound connections, the system uses the `setSocketMark` primitive from the native addon. In [`src/mitm/tproxy/transparentSocket.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/mitm/tproxy/transparentSocket.ts), this function tags egress sockets with a specific mark value that the iptables OUTPUT chain excludes.

```typescript
import { setSocketMark } from '@/mitm/tproxy/transparentSocket';
import net from 'net';

const socket = net.createConnection({ host, port });
await setSocketMark(socket);   // ensures OUTPUT rule skips this socket

```

The iptables configuration applies separate rules: TPROXY redirection for general traffic and an exclusion for packets bearing the process-specific mark.

### Configuring Capture Parameters

The request body schema, defined in [`src/lib/inspector/tproxyCaptureApi.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/inspector/tproxyCaptureApi.ts), accepts:
- **`onPort`**: The local port where the transparent listener binds (default: 8443)
- **`mark`**: The iptables MARK value used for loop prevention (default: 9011)
- **`sudoPassword`**: Authentication for iptables manipulation on desktop builds

### Stopping the Session

Terminate capture by sending a `DELETE` request to the same endpoint. This triggers `stopTproxy()` in [`src/mitm/tproxy/captureManager.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/mitm/tproxy/captureManager.ts), which calls `revertTproxy()` to safely rollback iptables rules, close the listener, and remove the CA from the trust store.

```typescript
// Server-side entry point for stop operations
import { stopTproxy } from '@/mitm/tproxy/captureManager';

export async function DELETE(req: Request) {
  await stopTproxy();  // exact inverse of start, safe-idempotent rollback
  return Response.json({ success: true });
}

```

## Implementation Examples

### Transactional iptables Rule Application

The [`src/mitm/tproxy/setup.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/mitm/tproxy/setup.ts) module provides atomic rule management:

```typescript
import { applyTproxy, revertTproxy } from '@/mitm/tproxy/setup';

export async function startTproxy(cfg: TproxyConfig) {
  await applyTproxy(cfg);   // runs PREROUTING mangle TPROXY + OUTPUT mark commands
}

export async function stopTproxy(cfg: TproxyConfig) {
  await revertTproxy(cfg);  // exact inverse, safe-idempotent rollback
}

```

### Server-Side API Route Handler

The complete request handler in [`src/app/api/tools/agent-bridge/tproxy/route.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/tools/agent-bridge/tproxy/route.ts):

```typescript
import { startTproxy, stopTproxy } from '@/mitm/tproxy/captureManager';

export async function POST(req: Request) {
  const cfg = await req.json();               // validates via StartTproxyBodySchema
  await startTproxy(cfg);                     // applies rules, opens listener, installs CA
  return Response.json({ success: true });
}

```

## Summary

- **Configure the MITM proxy TPROXY** in OmniRoute by posting to `/api/tools/agent-bridge/tproxy`, which triggers kernel-level packet interception via iptables rules in [`src/mitm/tproxy/setup.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/mitm/tproxy/setup.ts)
- The transparent listener in [`src/mitm/tproxy/captureMode.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/mitm/tproxy/captureMode.ts) receives original destination information through `socket.localAddress`, eliminating the need for proxy environment variables
- Use `setSocketMark` from [`src/mitm/tproxy/transparentSocket.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/mitm/tproxy/transparentSocket.ts) to mark OmniRoute's own sockets and prevent capture loops via iptables mark exclusions
- Dynamic CA installation via [`src/mitm/tproxy/caTrust.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/mitm/tproxy/caTrust.ts) enables TLS decryption without requiring application-level proxy configuration
- The entire flow is reversible through the `DELETE` endpoint, which safely rolls back all system modifications

## Frequently Asked Questions

### What is TPROXY and why does it capture traffic that ignores proxy settings?

TPROXY is a Linux netfilter target that intercepts TCP packets at the kernel level before they reach the network interface. Because it operates below the application layer, it does not rely on applications checking `http_proxy` environment variables. According to the OmniRoute source code in [`src/mitm/tproxy/captureMode.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/mitm/tproxy/captureMode.ts), the transparent listener receives the original destination IP through socket options, allowing interception of hard-coded connections from CLIs like `curl` or `git` that bypass standard proxy configurations.

### How does OmniRoute prevent infinite loops when capturing its own traffic?

The implementation uses socket marking via the native addon exposed in [`src/mitm/tproxy/transparentSocket.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/mitm/tproxy/transparentSocket.ts). The `setSocketMark` function tags egress sockets with a specific mark value (default: 9011). The iptables OUTPUT chain includes a rule that excludes packets bearing this mark from TPROXY redirection, ensuring that OmniRoute's own outbound connections—such as API calls or CA updates—do not get recursively intercepted.

### Is root access required to configure TPROXY in OmniRoute?

Yes, manipulating iptables rules and binding transparent sockets requires elevated privileges. The `startCapture` helper in [`src/lib/inspector/tproxyCaptureApi.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/inspector/tproxyCaptureApi.ts) accepts an optional `sudoPassword` parameter for non-root desktop builds. On production deployments, OmniRoute should run with appropriate capabilities or as root to execute the `applyTproxy` commands in [`src/mitm/tproxy/setup.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/mitm/tproxy/setup.ts).

### Can TPROXY capture mode decrypt HTTPS traffic from CLI tools?

Yes, because TPROXY intercepts the TCP connection before TLS handshakes occur, OmniRoute can perform TLS termination. The [`src/mitm/tproxy/caTrust.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/mitm/tproxy/caTrust.ts) module dynamically generates a per-SNI CA certificate and installs it into the system trust store. This allows the transparent proxy in [`src/mitm/tproxy/captureMode.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/mitm/tproxy/captureMode.ts) to present valid certificates to the client while establishing a separate TLS connection to the target server, enabling full traffic inspection in the Traffic Inspector UI.