-
Notifications
You must be signed in to change notification settings - Fork 927
Refactor/egress mitmproxy yaml config #975
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
3a364a1
8f1e7ae
a90b629
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| # Static mitmproxy options that override mitm built-in defaults for the | ||
| # OpenSandbox egress sidecar. Loaded automatically by mitmdump from | ||
| # /var/lib/mitmproxy/.mitmproxy/config.yaml. | ||
| # | ||
| # Only deviations from mitm defaults are listed here. Options that | ||
| # happen to match the mitm default (connection_strategy=lazy, http2=true, | ||
| # etc.) are intentionally omitted — the file is meant to be the diff | ||
| # against upstream defaults, not a full enumeration. The one exception | ||
| # is ignore_hosts: even though [] matches the mitm default, it is kept | ||
| # as a discoverable extension point for operators who want to bypass | ||
| # decryption for specific hosts without hunting through the docs. | ||
| # | ||
| # Per-deployment overrides remain env-driven and applied as --set by | ||
| # launch.go. Precedence: command-line --set > this file > mitm defaults. | ||
|
|
||
| mode: | ||
| - transparent | ||
|
|
||
| # mitm default 0.0.0.0; transparent mode must only accept loopback inside | ||
| # the netns (iptables REDIRECT pushes outbound traffic here, and exposing | ||
| # mitm on the LAN would route any inbound connection through it). | ||
| listen_host: 127.0.0.1 | ||
|
|
||
| # mitm default None (whole body buffered in memory). 10m bounds RSS for | ||
| # the allow path; chunked / SSE responses are forced to stream regardless | ||
| # by the system addon's responseheaders hook. | ||
| stream_large_bodies: 10m | ||
|
|
||
| # mitm default None (Python certifi bundle). Match the OS trust store so | ||
| # private-CA additions land where mitm reads them. | ||
| ssl_verify_upstream_trusted_confdir: /etc/ssl/certs | ||
|
|
||
| # Hosts (Python regex) for TLS pass-through: mitm forwards bytes without | ||
| # decryption and addons do not see request/response content. Empty matches | ||
| # the mitm default; kept here as a discoverable extension point. Append | ||
| # entries here rather than passing --set on the command line, because | ||
| # --set on a list option REPLACES the entire list. | ||
| ignore_hosts: [] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,12 +36,13 @@ const ( | |
| EnvNameserverExempt = "OPENSANDBOX_EGRESS_NAMESERVER_EXEMPT" | ||
|
|
||
| // MITM: mitmdump transparent; Linux + CAP_NET_ADMIN, runs as a dedicated user. | ||
| // Static mitm options (mode, listen_host, connection_strategy, stream_large_bodies, | ||
| // http2, ignore_hosts, ssl_verify_upstream_trusted_confdir default) live in | ||
| // /var/lib/mitmproxy/.mitmproxy/config.yaml; only per-deployment overrides are env-driven. | ||
|
Comment on lines
+39
to
+41
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as the |
||
| EnvMitmproxyTransparent = "OPENSANDBOX_EGRESS_MITMPROXY_TRANSPARENT" | ||
| EnvMitmproxyPort = "OPENSANDBOX_EGRESS_MITMPROXY_PORT" | ||
| EnvMitmproxyConfDir = "OPENSANDBOX_EGRESS_MITMPROXY_CONFDIR" | ||
| EnvMitmproxyScript = "OPENSANDBOX_EGRESS_MITMPROXY_SCRIPT" | ||
| EnvMitmproxyUpstreamTrustDir = "OPENSANDBOX_EGRESS_MITMPROXY_UPSTREAM_TRUST_DIR" | ||
| EnvMitmproxyIgnoreHosts = "OPENSANDBOX_EGRESS_MITMPROXY_IGNORE_HOSTS" | ||
| EnvMitmproxySslInsecure = "OPENSANDBOX_EGRESS_MITMPROXY_SSL_INSECURE" | ||
|
|
||
| // Comma-separated upstream resolvers: literal IP only (optional :port) — no hostnames (see dnsproxy REDIRECT note). | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,17 +32,23 @@ import ( | |
| const RunAsUser = "mitmproxy" | ||
|
|
||
| // Loopback: transparent mode receives via REDIRECT; do not listen on 0.0.0.0 in the netns. | ||
| // Kept as a Go constant only for the startup log line; the actual listen_host is set in | ||
| // /var/lib/mitmproxy/.mitmproxy/config.yaml (shipped via the egress Dockerfile). | ||
| const listenHostLoopback = "127.0.0.1" | ||
|
|
||
| // systemScriptPath: bundled system addon shipped via the egress Dockerfile | ||
| // (COPY components/egress/mitmscripts /var/egress/mitmscripts). Always loaded. | ||
| const systemScriptPath = "/var/egress/mitmscripts/system.py" | ||
|
|
||
| // Config: mitmdump --mode transparent; UserName must match iptables ! --uid-owner, ConfDir is mitm state/CA. | ||
| // Config: mitmdump --mode transparent. Static options (mode, listen_host, | ||
| // connection_strategy, stream_large_bodies, http2, ignore_hosts, | ||
| // ssl_verify_upstream_trusted_confdir) live in | ||
| // /var/lib/mitmproxy/.mitmproxy/config.yaml and are auto-loaded by mitmdump. | ||
|
Comment on lines
+43
to
+46
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: this comment lists Same inaccuracy in |
||
| // This struct carries only per-launch dynamic values that override those | ||
| // defaults via `--set`. | ||
| type Config struct { | ||
| ListenPort int | ||
| UserName string | ||
| ConfDir string | ||
| // ScriptPath is an optional user-supplied addon, loaded after the system addon. | ||
| ScriptPath string | ||
| // OnExit is called (if non-nil) when mitmdump exits. Called from a background goroutine. | ||
|
|
@@ -92,24 +98,21 @@ func Launch(cfg Config) (*Running, error) { | |
| return nil, fmt.Errorf("mitmproxy: lookup user %q: %w", uname, err) | ||
| } | ||
|
|
||
| // Only per-launch dynamic values are passed on the command line. Static | ||
| // options (mode, listen_host, connection_strategy, stream_large_bodies, | ||
| // http2, ignore_hosts, ssl_verify_upstream_trusted_confdir) come from | ||
| // /var/lib/mitmproxy/.mitmproxy/config.yaml shipped in the egress image. | ||
| // `--set` overrides config.yaml, so the env-driven overrides below take | ||
| // precedence at runtime without rebuilding the image. | ||
| args := []string{ | ||
| "--mode", "transparent", | ||
| "--listen-host", listenHostLoopback, | ||
| "--listen-port", strconv.Itoa(cfg.ListenPort), | ||
| } | ||
|
|
||
| trustDir := strings.TrimSpace(os.Getenv(constants.EnvMitmproxyUpstreamTrustDir)) | ||
| if trustDir == "" { | ||
| trustDir = "/etc/ssl/certs" | ||
| // Upstream cert trust path override. Default in config.yaml is /etc/ssl/certs; | ||
| // override per-deployment when the upstream uses a private CA bundle. | ||
| if trustDir := strings.TrimSpace(os.Getenv(constants.EnvMitmproxyUpstreamTrustDir)); trustDir != "" { | ||
| args = append(args, "--set", "ssl_verify_upstream_trusted_confdir="+trustDir) | ||
| } | ||
| args = append(args, "--set", "ssl_verify_upstream_trusted_confdir="+trustDir) | ||
|
|
||
| // Stream large bodies instead of buffering them in memory (OOM prevention). | ||
| args = append(args, "--set", "stream_large_bodies=1m") | ||
|
|
||
| // Lazy connection strategy: defer upstream connection until the request is fully received, | ||
| // which avoids unnecessary connections for blocked/filtered requests. | ||
| args = append(args, "--set", "connection_strategy=lazy") | ||
|
|
||
| // Transparent mode redirects TCP to IP addresses. Clients connecting to IPs | ||
| // do not send SNI, so upstream TLS cert hostname verification fails with | ||
|
|
@@ -119,34 +122,21 @@ func Launch(cfg Config) (*Running, error) { | |
| args = append(args, "--set", "ssl_insecure=true") | ||
| } | ||
|
|
||
| homeEnv := home | ||
| if strings.TrimSpace(cfg.ConfDir) != "" { | ||
| cd := strings.TrimSpace(cfg.ConfDir) | ||
| args = append(args, "--set", "confdir="+cd) | ||
| homeEnv = cd | ||
| } | ||
| // Load the system addon first so user addons can observe / override its hooks. | ||
| args = append(args, "-s", systemScriptPath) | ||
| if user := strings.TrimSpace(cfg.ScriptPath); user != "" { | ||
| args = append(args, "-s", user) | ||
| } | ||
|
|
||
| // Upstream passthrough: each pattern becomes --set ignore_hosts= (regex; IP ranges are practical in transparent mode). | ||
| for _, p := range strings.Split(os.Getenv(constants.EnvMitmproxyIgnoreHosts), ";") { | ||
| p = strings.TrimSpace(p) | ||
| if p == "" { | ||
| continue | ||
| } | ||
| args = append(args, "--set", "ignore_hosts="+p) | ||
| } | ||
|
|
||
| cmd := exec.Command("mitmdump", args...) | ||
| cmd.Stdout = os.Stdout | ||
| cmd.Stderr = os.Stderr | ||
| cmd.SysProcAttr = &syscall.SysProcAttr{ | ||
| Credential: &syscall.Credential{Uid: uid, Gid: gid}, | ||
| } | ||
| cmd.Env = append(os.Environ(), "HOME="+homeEnv) | ||
| // HOME determines mitm's confdir (~/.mitmproxy) which holds both the CA | ||
| // and the baked-in config.yaml. | ||
| cmd.Env = append(os.Environ(), "HOME="+home) | ||
|
|
||
| if err := cmd.Start(); err != nil { | ||
| return nil, fmt.Errorf("mitmproxy: start mitmdump: %w", err) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential behavioral change:
connection_strategysilently switches from lazy to eager.The old
launch.goexplicitly passed--set connection_strategy=lazy. This PR removes that flag and does NOT addconnection_strategytoconfig.yaml, relying on the mitmproxy default. The comment here saysconnection_strategy=lazy"matches the mitm default" — but in mitmproxy 10+ (which the Dockerfile installs:'mitmproxy>=10,<11'), the default changed fromlazytoeager.With
eager, mitmproxy opens upstream connections immediately on TCP handshake rather than waiting for the full request. This changes behavior for blocked/filtered requests (the oldlazycode avoided unnecessary upstream connections for them).The commit message even notes: "connection_strategy (lazy — historical default preserved here)" — but it's NOT preserved anywhere. Either add
connection_strategy: lazyto config.yaml explicitly, or acknowledge the intentional switch toeagerin the PR description.