A remotely-callable mitmproxy control plane: start/stop proxy instances on demand, collect HTTPS request samples, and manage CA certificates.
⚠️ CA Certificate Security Warning Never install the downloaded CA certificate into your system trust store or daily-use browser. Install it only in a dedicated, isolated browser profile used exclusively for prepare-phase scraping. An installed CA allows full interception of all HTTPS traffic in that trust store.
mitm-api serves the prepare phase of a "prepare + lightweight replay" scraping workflow. A client points a browser through the managed proxy once; mitm-api intercepts the HTTPS traffic and records the exact header order, header values, and cookies as request templates for the scraper to reuse.
Browser → mitm-api proxy (HTTPS decrypted) → upstream proxy → target site
↓ capture
SQLite samples
↓ GET /session/{id}
Your scraper
The image is published automatically to Docker Hub on every push to master: rabbir/mitm-api
docker run -d --name mitm-api \
-p 9000:9000 \
-p 48000-48500:48000-48500 \
-v /srv/mitm-api/data:/data \
-e MITM_API_TOKEN=your-secret-token \
-e PROXY_AUTH=true \
rabbir/mitm-api:latest
Or with Docker Compose (copy .env.example to .env and fill in the values):
docker compose up -d
Build locally:
docker build -t rabbir/mitm-api:latest .
A smoke-test script is bundled inside the container. Copy it out, set the three variables at the top, and run it. Requires jq.
docker cp mitm-api:/test.sh ./test.sh && chmod +x test.sh
# edit API, TOKEN, UPSTREAM at the top of the file, then:
./test.sh
The script runs 8 steps: health check → create session → download CA → HTTP via proxy → HTTPS via proxy (with TLS issuer verification) → fetch samples → destroy session → verify destroyed.
All endpoints require Authorization: Bearer <MITM_API_TOKEN> when MITM_API_TOKEN is set.
Interactive docs are available at /docs (Swagger UI), /redoc, and /openapi.json.
POST /session — Create a session and return proxy connection details.
{ "upstream": "1.2.3.4:8000" }
upstream is optional. Omit it for a direct connection (no upstream proxy).
Upstream limitations
- SOCKS5 is not supported — convert to HTTP first (e.g. with gost).
- Upstream proxies that require HTTP Basic authentication are not supported. The mitmproxy mode spec uses
@as a separator, which conflicts with the@in an authenticated proxy URL (http://user:pass@host:port).
Response (PROXY_AUTH=true includes credentials):
{
"id": "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
"proxy": {
"host": "100.x.x.x",
"port": 48001,
"username": "3f2504e0-...",
"password": "a1b2c3d4..."
},
"expires_at": "2026-06-04T12:30:00Z",
"status": "ready"
}
GET /sessions — List all non-destroyed sessions (metadata only, no credentials).
GET /session/{id} — Get full session detail including captured samples. Also resets expires_at to now + SESSION_DEFAULT_TTL. Call periodically as a heartbeat to keep the session alive.
DELETE /session/{id} — Destroy the session, stop the proxy, release the port.
GET /ca.pem — Download the CA public certificate (mitmproxy-ca-cert.pem). The private key is never exposed.
GET /healthz — Health check. Returns {"status": "ok"}.
| Variable | Default | Description |
|---|---|---|
MITM_API_TOKEN | (empty) | Bearer token for the control API. Leave empty to disable auth (trusted network only). |
SESSION_DEFAULT_TTL | 3600 | Session TTL in seconds, reset on every GET /session/{id}. |
PROXY_AUTH | false | Require per-session credentials on the proxy port. true → credentials returned on create; false → open proxy. |
CA_DIR | /data/ca | mitmproxy CA directory, validated on startup. |
CA_ALLOW_REGENERATE | false | If CA is invalid/expired, back it up and regenerate. Default: refuse to start. |
PORT_RANGE_START | 48000 | Start of proxy port allocation range. |
PORT_RANGE_END | 48500 | End of proxy port allocation range. |
SESSION_MAX_RETENTION_DAYS | 7 | Hard-delete sessions and samples older than this many days. 0 = never purge. |
Fixed constants (not configurable): control API on 0.0.0.0:9000, SQLite at /data/mitm-api.db.
On startup mitm-api inspects CA_DIR:
| State | Action |
|---|---|
| Empty / no CA files | First run — mitmproxy auto-generates a new CA. Fingerprint and expiry are logged. |
| CA valid | Reused. Fingerprint and expiry logged. |
| CA invalid (corrupt / not a CA / expired) | CA_ALLOW_REGENERATE=false (default): refuse to start. CA_ALLOW_REGENERATE=true: back up old files and regenerate. |
| Directory not writable | Refuse to start with a permission error. |
The default is to refuse regeneration to prevent silently invalidating a CA already installed in browsers, and to surface mount misconfiguration early.
9000 and 48000–48500 only on a WireGuard/Tailscale interface.MITM_API_TOKEN and PROXY_AUTH in production. The control API can launch an arbitrary HTTPS-decrypting proxy — it is more sensitive than the proxy port itself.mitmproxy-ca.pem) is never exposed through the API.mitm-api/
├── Dockerfile
├── docker-compose.yml
├── pyproject.toml
├── test.sh
├── mitm_api/
│ ├── main.py # FastAPI app + mitmproxy lifespan
│ ├── config.py # Environment variable parsing
│ ├── api/
│ │ ├── session.py # Session CRUD endpoints
│ │ └── ca.py # CA download + healthz
│ ├── core/
│ │ ├── mode_manager.py # Runtime mode add/remove, port allocation
│ │ ├── session.py # SessionInfo dataclass
│ │ ├── ca.py # Startup CA validation
│ │ ├── deps.py # FastAPI dependency providers
│ │ └── reaper.py # TTL reaper + retention purge
│ ├── addon/
│ │ └── capture.py # mitmproxy addon: flow tagging, proxy auth, sample capture
│ ├── storage/
│ │ ├── db.py # aiosqlite helpers (WAL, single write-lock)
│ │ └── models.py # CREATE TABLE statements
│ └── security/
│ └── auth.py # Bearer token FastAPI dependency
└── tests/
Content type
Image
Digest
sha256:2966cdd34…
Size
87.9 MB
Last updated
4 months ago
docker pull rabbir/mitm-api