Rust intercepting proxy workspace for SOTH, built for deterministic policy enforcement, transport normalization, and production hardening.
- At A Glance
- Core Capabilities
- Public API Contract
- Configuration Surface
- Quick Start
- Build And Validation
- Docker Tooling
- CI Matrix
- Benchmark Snapshot
- Documentation Index
- Repository Rules
- Community
- License
| Area | Summary |
|---|---|
| What it is | Reusable Rust MITM proxy core (soth-mitm) with stable handler/config/runtime contracts. |
| Runtime stack | mitm-* engine crates for HTTP(S) interception, tunnel control, protocol normalization, and eventing. |
| Quality model | Acceptance, chaos, differential, performance, and compliance gate suites. |
| What it is not | Provider-specific AI logic, product rule bundles, or app-specific semantics. |
| Ownership boundary | Product behavior belongs in downstream adapters (see docs/consumer/soth-proxy-adapter-contract.md). |
- HTTP
CONNECTtunnel handling withintercept | tunnel | blockoutcomes. - TLS MITM path with process-aware interception hooks:
should_intercept_tls(host, process_info)on_tls_failure(host, error)
- HTTP/1.1 and HTTP/2 forwarding/interception.
- WebSocket upgrade handling and stream frame events.
- Stream normalization for SSE, NDJSON, and gRPC framing.
- HTTP/3 passthrough hint support.
- Eager connection metadata with socket family and optional process attribution.
- Runtime controls for hot reload, graceful shutdown, and metrics snapshots.
| Contract | Shape |
|---|---|
RawRequest |
method, path, headers, body, connection_meta |
RawResponse |
status, headers, body, connection_meta |
StreamChunk |
connection_id, payload, sequence, frame_kind |
ConnectionMeta |
connection_id, socket_family, process_info, tls_info |
should_intercept_tls(&self, host, process_info) -> boolon_tls_failure(&self, host, error)on_request(&self, &RawRequest) -> Future<Output = HandlerDecision>on_stream_chunk(&self, &StreamChunk) -> Future<Output = ()>on_stream_end(&self, connection_id) -> Future<Output = ()>on_response(&self, &RawResponse) -> Future<Output = ()>on_connection_open(&self, &ConnectionMeta)on_connection_close(&self, connection_id)
HandlerDecision::AllowHandlerDecision::Block { status, body }
MitmProxyBuilder::new(config, handler).build()MitmProxy::run()MitmProxy::start() -> MitmProxyHandleMitmProxyHandle::reload(config)MitmProxyHandle::current_config()MitmProxyHandle::metrics()MitmProxyHandle::shutdown(timeout)
Top-level type: MitmConfig
| Section | Fields |
|---|---|
| bind | bind, unix_socket_path |
| interception | destinations, passthrough_unlisted |
| process attribution | enabled, lookup_timeout_ms |
| tls | ca_cert_path, ca_key_path, min_version, capture_fingerprint |
| upstream | timeout_ms, connect_timeout_ms, retry_on_failure, retry_delay_ms, verify_upstream_tls |
| connection pool | max_connections_per_host, idle_timeout_ms, max_idle_per_host |
| body | max_size_bytes, buffer_request_bodies |
| handler | request_timeout_ms, response_timeout_ms, recover_from_panics |
[dependencies]
soth-mitm = "0.1.0"
tokio = { version = "1", features = ["macros", "rt-multi-thread", "time"] }
bytes = "1"use std::time::Duration;
use bytes::Bytes;
use soth_mitm::{
HandlerDecision, InterceptHandler, MitmConfig, MitmProxyBuilder, ProcessInfo, RawRequest,
};
struct Gate;
impl InterceptHandler for Gate {
fn should_intercept_tls(&self, host: &str, process_info: Option<&ProcessInfo>) -> bool {
let _ = host;
process_info.and_then(|p| p.exe_name.as_deref()) != Some("trusted-local-agent")
}
async fn on_request(&self, request: &RawRequest) -> HandlerDecision {
if request.path.contains("/blocked") {
return HandlerDecision::Block {
status: 403,
body: Bytes::from_static(b"blocked by policy"),
};
}
HandlerDecision::Allow
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut config = MitmConfig::default();
config
.interception
.destinations
.push("api.example.com:443".to_string());
let proxy = MitmProxyBuilder::new(config, Gate).build()?;
let handle = proxy.start().await?;
let _metrics = handle.metrics();
handle.shutdown(Duration::from_secs(2)).await?;
Ok(())
}Compilable integration example:
crates/soth-mitm/examples/soth_proxy_integration.rs
Workspace crate:
crates/soth-mitm
cargo check --workspace
cargo fmt --all --check
cargo clippy --workspace --all-targets -- -W clippy::all
cargo test --workspace
./scripts/phase_a_smoke.sh
./scripts/tls_failure_fixtures.sh
./scripts/p1_reliability.sh./scripts/p2_protocol_matrix.sh
./scripts/p4_differential_validation.sh
./scripts/p4_performance_gates.sh
./scripts/p4_failure_injection.sh
./scripts/p4_chaos_network_faults.sh
./scripts/p4_chaos_adversarial.sh
./scripts/p5_reliability_contract.sh
./scripts/p5_event_log_contract.sh
./scripts/p5_runtime_soak.sh --duration-seconds 300
./scripts/p6_perf_gate.sh
./scripts/p6_acceptance_matrix.sh --report-dir artifacts/p6-acceptance./scripts/p6_release_readiness.sh --report-dir artifacts/p6-release-readiness./scripts/docker_build_tools.sh
./scripts/docker_run_testing.sh --profile stress
./scripts/docker_run_testing.sh --profile parity --profile benchmark --strict-tools
SOTH_MITM_SOAK_DURATION_SECONDS=300 ./scripts/docker_run_testing.sh --profile soak
./scripts/docker_run_testing.sh --list-lanesLane registry and defaults:
testing/lanes/registry.tsvtesting/test-plan.envscripts/run_testing_plan.sh
GitHub Actions (.github/workflows/ci.yml) runs:
- Linux + macOS + Windows feature checks/tests/smoke/reliability.
- Compliance gates (
cargo deny,cargo audit,cargo machete). - Protocol matrix lanes and triage.
- Differential, performance, failure-injection, and chaos lanes.
- Phase-6 performance and acceptance matrices.
Latest TLS-relevant side-by-side run versus mitmproxy (3 runs per case, all runs had 0 failed requests):
| Case | soth-mitm RPS | mitmproxy RPS | Delta (soth vs mitm) | soth p95 (ms) | mitm p95 (ms) |
|---|---|---|---|---|---|
| 1KiB response | 1993.420 | 1959.733 | +1.72% | 23.463 | 22.928 |
| 64KiB response | 1470.978 | 1408.606 | +4.43% | 27.887 | 28.039 |
| Case | soth-mitm RPS | mitmproxy RPS | Delta (soth vs mitm) | soth p95 (ms) | mitm p95 (ms) |
|---|---|---|---|---|---|
| 1KiB response | 1900.936 | 631.214 | +201.16% | 23.950 | 43.384 |
| 64KiB response | 1341.737 | 522.238 | +156.92% | 29.115 | 53.466 |
| Case | soth-mitm RPS | mitmproxy RPS | Delta (soth vs mitm) | soth p95 (ms) | mitm p95 (ms) |
|---|---|---|---|---|---|
| SSE first chunk | 356.699 | 51.727 | +589.58% | 127.862 | 533.329 |
Method:
- Client benchmark engine: Python
requests+ thread pool. - Upstream: local HTTPS server with cert signed by local benchmark CA.
- Proxy target
soth-mitm:crates/soth-mitm/examples/bench_proxy.rson127.0.0.1:28080. - Proxy target
mitmdump 11.0.2:127.0.0.1:28081with--quiet --set flow_detail=0 --set termlog_verbosity=error --set ssl_insecure=true. - HTTP workload
1KiB:n=2400,c=24. - HTTP workload
64KiB:n=900,c=24. - SSE workload
sse_first_chunk:n=240,c=24.
Reproduce:
./scripts/benchmark_tls_vs_mitmproxy.sh
./scripts/benchmark_vs_mitmproxy.shRun artifacts:
- TLS benchmark report:
artifacts/bench-tls-vs-mitmproxy/20260225T211452Z/summary.md - HTTP loopback dataplane report:
artifacts/bench-vs-mitmproxy/20260225T210145Z/summary.md
Notes:
- TLS benchmark covers production-relevant paths: CONNECT passthrough, full MITM, SSE over MITM.
- HTTP loopback dataplane benchmark is retained as baseline reference.
- Re-run on target hardware/network before using as production SLO claims.
- Aggregated implementation/hardening plan:
docs/SOTH_MITM_AGGREGATED_PLAN_AND_HARDENING.md - CI gate definitions:
docs/testing/ci-gates.md - Acceptance matrix:
docs/testing/p6-acceptance.md - Reliability invariants:
docs/testing/reliability-invariants.md - Protocol matrix:
docs/testing/protocol-matrix.md - Hardening plan:
docs/testing/hardening-plan.md - Differential validation contract:
docs/testing/differential-validation.md - Differential replay runbook:
docs/testing/differential-vs-mitmproxy.md - TLS taxonomy:
docs/testing/tls-taxonomy.md - Performance baselines:
docs/testing/perf-baselines.md - Artifact triage:
docs/testing/artifact-triage.md - Consumer adapter contract:
docs/consumer/soth-proxy-adapter-contract.md - Cutover playbook:
docs/migration/soth-cutover.md - Versioning/MSRV policy:
docs/policies/versioning-and-msrv.md
- Max file length is
500lines for core Rust source files undercrates/*/src/**/*.rs. - Oversized core Rust files must be split before merge.
- Guard command:
./scripts/check_max_file_lines.sh - Prohibition policy guard:
./scripts/check_prohibitions.sh - Install local pre-push enforcement:
./scripts/install_git_hooks.sh
- Contributing:
CONTRIBUTING.md - Code of conduct:
CODE_OF_CONDUCT.md - Security policy:
SECURITY.md - Support guide:
SUPPORT.md - Pull request template:
.github/pull_request_template.md - Issue templates:
.github/ISSUE_TEMPLATE/
Mozilla Public License 2.0 (LICENSE).