go-egress-mitm-proxy
A MITM HTTP/HTTPS proxy that implements split-brain DNS for egress traffic control in containerised environments. Decide per host where traffic goes, what gets through and which headers travel with it.
- v4.1.1 · latest
- MIT
- Go
- Kubernetes sidecar
- outbound HTTP/2
docker pull ghcr.io/datarocks-ag/go-egress-mitm-proxy:4.1.1What it does
- Split-brain DNS — via TCP dial interception, routing to target_ip or target_host
- Path-based routing — different paths on one domain to different backends
- ACL — whitelist, blacklist and passthrough with exact, wildcard and regex matching
- Header policies — inject headers, strip sensitive ones, automatic X-Request-ID
- Upstream TLS trust — custom PEM bundle or PKCS#12 truststore, per-target bypass
- Hot reload — apply config changes with SIGHUP, no restart
- Audit & tracing — JSON log of blocked requests, opt-in request traces with redaction
- Operable — Prometheus metrics, health endpoints, graceful shutdown
proxy:
port: "8080"
metrics_port: "9090"
default_policy: "BLOCK" # Options: ALLOW, BLOCK
outgoing_ca_bundle: "" # Optional: path to PEM CA bundle for upstream TLS verification
outgoing_ca: [] # Optional: list of individual CA cert files (can be combined with bundle)
# outgoing_ca:
# - "certs/internal-ca.crt"
# - "certs/partner-ca.crt"
# Optional: PKCS#12 truststore for upstream TLS verification (additive with outgoing_ca_bundle)
# outgoing_truststore_path: "certs/upstream-cas.p12"
# outgoing_truststore_password: "changeit"
# Disable upstream TLS certificate verification globally (for dev/test only!)
# insecure_skip_verify: false
# Ceiling on concurrent client connections (0 or unset = unlimited).
# A hijacked CONNECT tunnel carries no deadline at any layer, so a client that
# completes the CONNECT and then goes silent holds a file descriptor and a
# goroutine until the process dies. This is what bounds that. At the cap the
# proxy pauses accepting until a connection closes, warns, and increments
# proxy_listener_saturated_total.
# max_connections: 2048
# MITM CA certificate - provide either PEM cert+key or a PKCS#12 keystore (not both)
# Generate with: mitm-proxy gencert --type root --cn "My CA" --out-cert certs/ca.crt --out-key certs/ca.key
# Or for intermediate CA: mitm-proxy gencert --type intermediate --signing-cert root.crt --signing-key root.key --out-chain certs/chain.crt --out-key certs/ca.key
# Option A: PEM files (use --out-chain for intermediate CA setup)
mitm_cert_path: "certs/ca.crt"
mitm_key_path: "certs/ca.key"
# Option B: PKCS#12 keystore (generate with: mitm-proxy gencert --out-p12 certs/ca.p12 --p12-password changeit)
# mitm_keystore_path: "certs/ca.p12"
# mitm_keystore_password: "changeit"
# Optional: Organization on the MITM leaf certificates the proxy mints.
# Default is goproxy's built-in "GoProxy untrusted MITM proxy Inc". Captured at
# startup -- SIGHUP does not reload it.How a request flows
Your app keeps calling the real hostnames. The proxy decides at dial time — not in DNS — whether and where the connection goes.
Intercept
The app sends HTTP and HTTPS through the proxy. TLS is terminated with your own internal CA.
Check the ACL
Whitelist, blacklist or passthrough. Anything unmatched follows default_policy — BLOCK answers 403.
Rewrite
Route by domain and path to a target IP or host, change scheme or port, inject or drop headers.
Forward
Dial the real target over HTTP/1.1 or HTTP/2, verified against your upstream CA bundle.
Patterns that don't fail open
ACLs, rewrites and traces share one domain syntax. Matching is case-insensitive, trailing dots are stripped, and regex patterns are anchored — so a denylist entry can't be slipped past.
| Pattern | Matches | Does not match |
|---|---|---|
| example.com | example.com, EXAMPLE.com, example.com. | api.example.com |
| *.example.com | api.example.com, a.b.example.com | example.com (the apex) |
| * | every host | — |
| ~^(.+\.)?example\.com$ | the apex and any subdomain | example.com.evil.net |
Run it as a sidecar
Point your app at the proxy with the standard proxy variables. /healthz and /readyz plug into Kubernetes probes; on SIGTERM it fails readiness first, then drains in-flight requests.
env:
- name: HTTPS_PROXY
value: "http://localhost:8080"
- name: HTTP_PROXY
value: "http://localhost:8080"Full documentation, configuration reference and how-tos.
Read the docs →Data Rocks AG
[ONE OR TWO LINES ON WHAT DATA ROCKS DOES AND FOR WHOM]