Documentation
¶
Overview ¶
Package egressproxy implements the transparent sandbox egress filter: a userspace proxy that all sandbox TCP is iptables-REDIRECT'd through, plus the redirect installer and the on-disk policy contract the control plane writes.
The enforcement model mirrors e2b-dev/infra's tcpfirewall, adapted for a Kubernetes Pod (init container installs the redirect, a sidecar runs the proxy) and hardened for the eval anti-cheat use case: the default action is deny (allowlist), not allow.
Index ¶
Constants ¶
const ( // DefaultProxyUID is the uid the sidecar runs as; the redirect exempts it so // the proxy's own upstream connections are not looped back. DefaultProxyUID = 1337 DefaultHTTPPort = 15001 DefaultTLSPort = 15002 DefaultOtherPort = 15003 // DefaultPolicyPath is the emptyDir file the control plane writes (exec) and // the proxy reads (fsnotify). Mounted only in the sidecar. DefaultPolicyPath = "/var/run/egress/policy.json" )
Fixed wiring shared by the redirect installer, the proxy, and the control plane. These are container-internal (the sidecar owns the whole netns view), so constants rather than config keep init and sidecar in lockstep.
Variables ¶
This section is empty.
Functions ¶
func InstallRedirect ¶
func InstallRedirect(cfg RedirectConfig) error
InstallRedirect programs nat OUTPUT so all sandbox TCP is transparently redirected to the local proxy, while the proxy's own traffic, DNS, and loopback are exempted. Idempotent: the chain is flushed and rebuilt, and the OUTPUT jump is added only if absent.
Runs in the Pod netns (shared by all containers); requires CAP_NET_ADMIN.
func WritePolicy ¶
WritePolicy atomically writes the policy to path (write temp + rename) so a reader (fsnotify reload) never observes a half-written file.
Types ¶
type MatchType ¶
type MatchType string
MatchType records why a connection was allowed/denied, for metrics and logs.
type Policy ¶
type Policy struct {
// SandboxID records which sandbox this policy was pushed for. Informational
// (surfaced in logs/metrics); the proxy enforces whatever is present.
SandboxID string `json:"sandboxId,omitempty"`
// Enforce gates the whole filter. When false the policy is treated as
// fail-closed (deny all). The control plane sets it true only after a
// concrete ruleset has been resolved for a claimed sandbox.
Enforce bool `json:"enforce"`
// DisableEgress blocks all outbound traffic regardless of the allow lists
// (DNS is still permitted so name resolution does not hang). Equivalent to
// an empty allowlist.
DisableEgress bool `json:"disableEgress,omitempty"`
// AllowedDomains permits egress to matching hostnames (exact, "*", or
// "*.example.com"). Domains only ever allow; there is no domain deny.
AllowedDomains []string `json:"allowedDomains,omitempty"`
// AllowedCIDRs / DeniedCIDRs are IP/CIDR allow/deny for traffic without a
// usable hostname (non-80/443 TCP, or bare-IP connections).
AllowedCIDRs []string `json:"allowedCIDRs,omitempty"`
DeniedCIDRs []string `json:"deniedCIDRs,omitempty"`
// AllowPrivateNetworks disables the built-in anti-SSRF deny of private /
// link-local / cloud-metadata ranges. Default false (baseline stays on).
AllowPrivateNetworks bool `json:"allowPrivateNetworks,omitempty"`
}
Policy is the on-disk egress ruleset the control plane pushes to the proxy. It is the single source of truth read by the sidecar; an absent, empty, or unparseable file means fail-closed (deny all egress except DNS).
func FailClosed ¶
func FailClosed() Policy
FailClosed is the policy applied when no valid policy file is present: deny everything. DNS egress is permitted separately by the iptables rules, not by this policy, so resolution keeps working even while fail-closed.
func LoadPolicy ¶
LoadPolicy reads and parses the policy file. A missing file yields FailClosed with no error (that is the expected steady state before the first push). A present-but-corrupt file yields FailClosed WITH an error so the caller can log it — but enforcement still fails closed.
func (Policy) Evaluate ¶
Evaluate applies the policy to a connection. hostname is the peeked HTTP Host or TLS SNI ("" when unavailable); ip is the original destination IP.
Semantics (allowlist / default-deny, hardened vs e2b's default-allow):
- Not enforcing -> allow (feature effectively off).
- Anti-SSRF baseline -> deny private ranges unless AllowPrivateNetworks.
- DisableEgress -> deny (allowlist empty by construction).
- Allowed domain match -> allow.
- Allowed CIDR match -> allow.
- Denied CIDR match -> deny.
- Default -> DENY (this is the key hardening).
type Proxy ¶
type Proxy struct {
// contains filtered or unexported fields
}
Proxy is the running egress filter.
func NewProxy ¶
func NewProxy(cfg ServeConfig) *Proxy
NewProxy builds a Proxy, loading the initial policy (fail-closed if absent).