egress

package
v0.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 8, 2026 License: Apache-2.0 Imports: 20 Imported by: 0

Documentation

Overview

Package egress implements the forward proxy that constrains sandbox network traffic. Sandboxes are pointed at it via HTTP(S)_PROXY, and it only permits connections allowed by a Policy. Stdlib only.

Index

Constants

View Source
const (
	// StrictProxyUID is the uid the transparent proxy runs as; iptables
	// exempts it so the proxy's upstream traffic isn't redirected back to
	// itself. The sandbox must run as a different uid to be intercepted.
	StrictProxyUID = 1337

	// StrictRedirectPort is the proxy's listen port and the iptables REDIRECT target.
	StrictRedirectPort = 15001
)

Constants shared between the Kubernetes backend and the runeward-egress binary for strict (L3) enforcement.

Variables

This section is empty.

Functions

func ExtractSNI

func ExtractSNI(data []byte) (string, bool)

ExtractSNI parses the SNI host from a TLS ClientHello, returning "" and false if data isn't a ClientHello or has no SNI extension. The transparent proxy uses it to recover the hostname when only the destination IP is known.

func RecordDecision

func RecordDecision(sandboxID, host, ip string, allow bool, reason string)

RecordDecision appends one decision to the per-sandbox bounded in-memory log.

func SetupRedirect

func SetupRedirect(proxyUID, redirectPort int) error

SetupRedirect installs iptables rules that redirect outbound TCP to the transparent proxy on redirectPort, exempting the proxy's own uid, loopback, and DNS. Runs once from a privileged init container before the sandbox starts. Enforcement happens in the kernel, so an app can't opt out by ignoring HTTP(S)_PROXY.

Beyond TCP redirect it also closes two bypass paths the proxy can't see:

  • non-DNS UDP is dropped, so QUIC/HTTP3 (443/udp) can't tunnel around the TCP-only proxy — clients fall back to TCP, which is proxied.
  • IPv6 egress is dropped (except loopback and DNS), since the proxy is IPv4-only; this forces traffic onto the proxied IPv4 path.

Types

type Decision

type Decision struct {
	Timestamp time.Time `json:"timestamp"`
	Host      string    `json:"host"`
	IP        string    `json:"ip"`
	Allow     bool      `json:"allow"`
	Reason    string    `json:"reason"`
}

Decision is one recorded egress allow/deny outcome for dashboard inspection.

func ListDecisions

func ListDecisions(sandboxID string) []Decision

ListDecisions returns the current per-sandbox decision log, oldest to newest.

type PinnedTransport

type PinnedTransport struct {
	Base *http.Transport
}

PinnedTransport wraps base and forces dials to outReq.URL.Host (already pinned). It keeps TLS ServerName from request context when provided.

func (*PinnedTransport) RoundTrip

func (t *PinnedTransport) RoundTrip(r *http.Request) (*http.Response, error)

type Policy

type Policy struct {
	// Default is "allow" or "deny"; empty means "allow".
	Default string `json:"default"`
	Rules   []Rule `json:"rules"`
}

Policy is an ordered list of [Rule]s; the first match wins, otherwise Default applies.

func LoadPolicy

func LoadPolicy(path string) (Policy, error)

LoadPolicy reads and decodes a JSON Policy from the file at path.

func (Policy) Allow

func (p Policy) Allow(host string) bool

Allow reports whether host is permitted. Only Hostname rules are considered; first match decides, otherwise Default applies.

func (Policy) AllowAddr

func (p Policy) AllowAddr(hostport string) bool

AllowAddr reports whether the destination "host:port" is permitted. The host is checked against Hostname rules, and against CIDR rules when it parses as an IP; first match decides, otherwise Default applies.

func (Policy) AllowListedHostname

func (p Policy) AllowListedHostname(host string) bool

AllowListedHostname reports whether host matches an explicit hostname rule whose first matching verdict is allow. Unlike [Allow], it does not fall back to the policy default.

type Proxy

type Proxy struct {
	Policy Policy
	// SandboxID associates decisions with a sandbox for dashboard egress logs.
	SandboxID string
	// Logger receives allow/deny decisions; nil discards them.
	Logger *log.Logger
	// AuthUser/AuthPass, when both set, require Proxy-Authorization (HTTP Basic)
	// on every request. This keeps a proxy bound on a shared interface (e.g. the
	// host proxy reachable via host.docker.internal) from being used by other
	// local/LAN processes.
	AuthUser string
	AuthPass string
	// contains filtered or unexported fields
}

Proxy is a forward proxy that enforces Policy on CONNECT tunnels (HTTPS) and plain absolute-URI HTTP requests.

func (*Proxy) Handler

func (p *Proxy) Handler() http.Handler

Handler returns an http.Handler implementing the forward proxy.

func (*Proxy) ListenAndServe

func (p *Proxy) ListenAndServe(addr string) error

ListenAndServe serves the proxy handler on addr until an error occurs.

type Rule

type Rule struct {
	// Verdict is "allow" or "deny"; anything but "allow" denies.
	Verdict string `json:"verdict"`
	// Hostname matches exactly or by a leading "*." wildcard.
	Hostname string `json:"hostname"`
	// CIDR matches a destination IP (e.g. "10.0.0.0/8").
	CIDR string `json:"cidr"`
}

Rule is a single allow/deny entry in a Policy. Set exactly one of Hostname or CIDR.

type TransparentProxy

type TransparentProxy struct {
	Policy Policy
	// SandboxID associates decisions with a sandbox for dashboard egress logs.
	SandboxID string
	// Logger receives allow/deny decisions; nil discards them.
	Logger *log.Logger
}

TransparentProxy enforces a Policy on connections redirected to it by iptables. Unlike Proxy it needs no HTTP(S)_PROXY cooperation: the original destination comes from SO_ORIGINAL_DST and the hostname is sniffed from TLS SNI or the HTTP Host header. Linux-only.

func (*TransparentProxy) Serve

func (t *TransparentProxy) Serve(addr string) error

Serve handles redirected connections on addr until an accept error occurs.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL