egressfwd

package
v0.21.0 Latest Latest
Warning

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

Go to latest
Published: Jul 30, 2026 License: AGPL-3.0 Imports: 27 Imported by: 0

Documentation

Overview

Package egressfwd installs the in-Sentry egress forwarders for compute-worker sandboxes — the APO-713 data path that makes a worker fetch() actually leave the box. The core sentrystack wires lo+eth0 and then, if an embedder set the ForwarderInstaller hook, hands the stack to us. We register two forwarders, each gated on its own InitStr field:

  • TCP (InitStr.EgressHostAddr): a catch-all TCP forwarder. Every outbound SYN the worker issues loops back through eth0 (promiscuous+spoofing), matches no bound listener, and is stolen by the forwarder, which bridges it to the host egress endpoint.
  • DNS (InitStr.DNSResolvers): a UDP:53 forwarder. The worker's getaddrinfo query (sent to the sandbox resolv.conf's gateway IP) loops back the same way; the forwarder rewrites the destination to a configured resolver and dials it from the host netns. Its responses feed a per-sandbox IP→name cache the TCP forwarder reads to attribute a later connect() to the hostname the worker resolved it from. Non-DNS UDP fails closed.

With neither field set the same SYN / datagram is RST in the stack (fail-closed) — see the core's egress_demux_test.go.

The forwarder is armed ONLY in a binary that blank-imports this package (init() sets sentrystack.ForwarderInstaller). Production wiring (cmd/workerd-manager) and the Stage-0 spike each opt in explicitly; a standalone core consumer leaves the hook nil and gets a no-egress sandbox. The pure wire framing the forwarder and the host bridge share lives in the side-effect-free sibling package egresswire, so a consumer that only needs to read/write the preamble (the host bridge) does not transitively arm the forwarder by importing this package.

This file carries no build tag so the package always has a buildable Go source on every platform; the forwarder itself is linux-only (forwarder_linux.go, install_linux.go).

Index

Constants

This section is empty.

Variables

View Source
var ErrNonDNSUDPDenied = errors.New("non-DNS UDP egress denied (no UDP policy plumbing yet)")

ErrNonDNSUDPDenied is returned by routedUDPDialer.DialUDP when a worker attempts UDP egress to anything other than :53. Worker-side UDP policy is not wired yet; until it is, non-DNS UDP fails closed so a worker can't bypass the egress policy / SSRF backstop (which only see the TCP bridge) by switching protocols. Stable error value — tests rely on it.

Functions

func InstallEgress

func InstallEgress(s *sentrystack.Stack, init *sentrystack.InitStr)

InstallEgress is the sentrystack.ForwarderInstaller: after the core wires lo+eth0, it registers the outbound forwarders. It arms two independent data paths, each gated on its own InitStr field so a resident can enable either without the other:

  • TCP egress (init.EgressHostAddr): a catch-all TCP forwarder that bridges every outbound stream to the host egress endpoint. The Sentry stays policy-dumb; the host bridge owns policy + gateway-vs-direct selection.
  • DNS (init.DNSResolvers): a UDP:53 forwarder that rewrites the worker's query to a configured resolver and dials it from the host netns. Its responses feed a per-sandbox IP→name cache the TCP dialer reads to attribute a flow to the hostname the worker resolved it from (dstName).

With neither field set, outbound stays fail-closed: the core RSTs the unhandled SYN / UDP datagram rather than silently direct-dialing through the host netns.

Types

This section is empty.

Jump to

Keyboard shortcuts

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