feat(egress): chain transparent mitmproxy egress through an upstream CONNECT proxy

Author: hpliStartAgainCreated Sep 11, 2026Updated Sep 11, 2026

Motivation

Sandboxed workloads in organizations typically must send outbound traffic through a managed forward proxy (corporate egress gateway, DLP boundary, or an audit point) rather than dialing the internet directly. Today the egress sidecar's transparent mitmproxy always dials the original destination itself, so there is no built-in way to chain it to an upstream CONNECT proxy.

OPENSANDBOX_EGRESS_MITMPROXY_SCRIPT can technically load a custom addon that sets server_conn.via, but scripting the security boundary ad hoc means every deployment re-implements (and re-audits) the same mechanism — including the fail-closed details that are easy to get wrong (pass-through flows silently bypassing the proxy, credentials in URLs, incompatible ignore_hosts combinations).

Proposal

Ship a bundled, opt-in upstream-proxy addon in the egress image:

  • OPENSANDBOX_EGRESS_UPSTREAM_PROXY=http(s)://host[:port] — when set, every mitmproxy-handled connection is chained via CONNECT <request.host>:<port>. For intercepted TLS the authority is the SNI/Host-derived FQDN, keeping the CONNECT authority consistent with SNI and Host rather than the intercepted IP.
  • OPENSANDBOX_EGRESS_UPSTREAM_PROXY_AUTH — optional complete Proxy-Authorization header value injected only on the upstream CONNECT (never logged).
  • https:// endpoints get TLS to the proxy with SNI + hostname verification through the existing ssl_verify_upstream_trusted_confdir / _trusted_ca options (default /etc/ssl/certs, overridable via OPENSANDBOX_EGRESS_MITMPROXY_UPSTREAM_TRUST_DIR).

Fail-closed semantics:

  • Flows that cannot be chained (TLS pass-through from no-SNI or ignore_hosts/tcp_hosts/udp_hosts, UDP/QUIC dials) are refused — no silent direct egress.
  • Malformed URLs, userinfo credentials, ..._AUTH without ..._PROXY, non-lazy connection_strategy, and non-empty pass-through lists fail at startup, not at runtime.
  • Default off: no behavior change when the env is unset; system.py, networkPolicy and Credential Vault semantics are unchanged.

This is intentionally component-level only: the server-side typed upstreamProxy config (with admin-controlled CA/identity file mounts for the egress container) is a follow-up change, so request-level env remains unable to set or override these variables.

I have an implementation ready and will link a PR.

Source: opensandbox-group/OpenSandbox