networking

package
v0.2.7 Latest Latest
Warning

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

Go to latest
Published: Aug 26, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Index

Constants

View Source
const DefaultSubnet = "10.88.0.0/16"

DefaultSubnet is the preferred IP range for containers.

Variables

View Source
var DefaultPublicDNS = []string{"1.1.1.1", "8.8.8.8"}

DefaultPublicDNS is the resolver set handed to containers that resolve names over NAT egress. There is NO resolver running on the bridge gateway (the gateway IP is just the bridge address); containers reach these public resolvers through the firewall's egress path. This matches what job containers get via withDNSMount (pkg/runtime) and what dind provisions for sibling containers (pkg/dind) — build containers must use the same, or they point at a resolver that does not exist. See issue #180.

Functions

func CNIConfListPath added in v0.2.5

func CNIConfListPath(dataDir string) string

CNIConfListPath returns the path to the CNI conflist for the given data dir.

Exposed so the embedded BuildKit worker can point its network provider at the SAME bridge/subnet this package configures, ensuring build `RUN` steps land on the firewalled container network instead of the host netns. The file is only written on Linux (network_linux.go); on other platforms the path is meaningful only as a lookup key and nothing consumes it.

func CleanStaleBridge

func CleanStaleBridge(log *slog.Logger)

CleanStaleBridge deletes the ephemerd0 bridge if it exists. Used on startup in the WSL containerd-only worker to remove bridges left over from a previous boot (all WSL2 distros share one kernel so bridges persist across instances).

Types

type Config

type Config struct {
	DataDir   string
	Subnet    string // container subnet (auto-selected if empty)
	MTU       int    // bridge MTU (auto-detected from host if 0)
	CNIBinDir string // path to CNI plugin binaries (Linux only, ignored elsewhere)

	// GatewayPorts are the extra TCP ports on the host/gateway address that a
	// container may reach (e.g. the Go module proxy). On Linux this is a true
	// allow-list: EPHEMERD-INPUT default-denies container→host traffic and
	// admits only DNS plus these ports. Anything listed here is exposed to
	// hostile job code, so list only services meant for jobs. Ports that are
	// also ControlPorts are ignored rather than opened.
	GatewayPorts []int

	// ControlPorts are TCP ports the ephemerd control plane binds on the
	// gateway (bridge) address that MUST NOT be reachable from inside
	// containers: the in-VM containerd (default 10000), the unauthenticated
	// dispatch gRPC server (containerd+1), and the debug exec server
	// (containerd+2). The firewall adds targeted INPUT DROP rules from the
	// container subnet to the gateway on these ports. Empty = no INPUT
	// control-plane rules (e.g. a bare-metal Linux host with no in-VM
	// dispatch server listening on the bridge).
	ControlPorts []int

	// The fields below configure the Windows L2Bridge egress path (see
	// network_windows.go and l2bridge.go). They are ignored on Linux/macOS.
	// When L2BridgeEgress is false (the default), Windows uses the HNS NAT
	// network and none of them are consulted.
	//
	// L2BridgeEgress is the opt-in. HostNIC (the host adapter to bridge onto)
	// and IPPool (the reserved LAN range container addresses come from) are
	// REQUIRED when it is set; Subnet and Gateway are derived from HostNIC when
	// empty. PublicDNS defaults to public resolvers so container DNS never needs
	// the blocked LAN router. ExtraAllowedCIDRs carves destinations out above
	// the RFC1918 block.
	L2BridgeEgress    bool
	HostNIC           string
	IPPool            string
	Gateway           string
	PublicDNS         []string
	ExtraAllowedCIDRs []string

	// AllowHostAccess permits job containers to address the ephemerd host
	// itself on the L2Bridge path. Required by anything ephemerd serves TO
	// containers over the network — the per-job dind Docker API and the Go
	// module proxy both listen on the host address — because the egress ACLs
	// otherwise block the host along with the rest of RFC1918.
	//
	// It is an address-scoped /32 allow, so it opens every port the host has
	// listening, not just ephemerd's. The control-plane ports are blocked back
	// off at the host firewall (see l2BridgeControlPlaneRules), which CAN match
	// on the container source here because L2Bridge does not NAT. Left false
	// when nothing needs to be reachable, which is the strictest posture.
	AllowHostAccess bool

	Log *slog.Logger
}

Config for container networking.

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

Manager handles platform-specific container networking. On Linux, this uses CNI with a bridge and iptables firewall. On Windows, this uses HCN with a NAT network and ACL policies.

func New

func New(cfg Config) (*Manager, error)

New creates and initializes the networking manager for the current platform.

func (*Manager) Cleanup

func (m *Manager) Cleanup()

Cleanup removes all networking state: firewall rules, bridge interface, CNI config, IP allocations, and DNS files. Called on shutdown.

func (*Manager) CloseHostPort added in v0.2.0

func (m *Manager) CloseHostPort(port int, containerIP string)

CloseHostPort removes an allow previously added by OpenHostPort. containerIP must match the one it was opened with.

func (*Manager) GatewayIP

func (m *Manager) GatewayIP() string

GatewayIP returns the host address that services ephemerd runs for jobs must bind to in order to be reachable from inside containers — the Go module proxy and, on Windows, the per-job dind Docker API listener.

Normally that is the bridge gateway (e.g. "10.88.0.1"), the first usable address of the container subnet. On the Windows L2Bridge path there is no such bridge gateway: containers are peers on the host's LAN, so the platform reports the host's own adapter address instead. Binding to the old hard-coded 10.88.0.1 there would fail outright — no interface holds that address once the NAT network is out of the picture — and take dind provisioning down with it.

func (*Manager) InstallFirewallRules

func (m *Manager) InstallFirewallRules() error

InstallFirewallRules blocks container traffic to private network ranges.

func (*Manager) JoinJobNetwork added in v0.2.6

func (m *Manager) JoinJobNetwork(cniID, jobID, containerIP string) error

JoinJobNetwork registers the container attached under cniID as belonging to jobID at containerIP and opens intra-job container-to-container reachability for it, while the bridge's default posture keeps it from reaching any other job's containers. Call it after Setup has returned the container's IP and before the container starts doing work. Pair with LeaveJobNetwork, passing the same cniID. No-op when no platform is initialized.

func (*Manager) LeaveJobNetwork added in v0.2.6

func (m *Manager) LeaveJobNetwork(cniID string)

LeaveJobNetwork reverses JoinJobNetwork for the container attached under cniID, removing the intra-job allows it held. Best-effort and safe to call for an id that never joined. Call it on teardown, alongside Teardown.

func (*Manager) OpenHostPort added in v0.2.0

func (m *Manager) OpenHostPort(port int, containerIP string) error

OpenHostPort opens a scoped host-firewall inbound allow for one TCP port from the single container at containerIP to the host, so a per-job service ephemerd binds on the host (dind's Docker API) is reachable from THAT job's container and no other. Both Windows paths (L2Bridge and the default NAT network) and the Linux VM-isolated path install a rule; macOS is a no-op. Pair with CloseHostPort on teardown, passing the same containerIP.

Returns an error rather than opening anything when containerIP is empty or unparseable — see the platformNetworking doc for why widening is not a permissible fallback.

func (*Manager) Setup

func (m *Manager) Setup(ctx context.Context, id string, netns string) (*SetupResult, error)

Setup attaches a container to the network.

func (*Manager) Teardown

func (m *Manager) Teardown(ctx context.Context, id string, netns string) error

Teardown detaches a container from the network.

type SetupResult

type SetupResult struct {
	// NetNS is the network namespace identifier (Linux: path, Windows: namespace ID).
	NetNS string
	// EndpointID is the HCN endpoint ID (Windows only). Used to attach
	// the network to the container via the OCI spec.
	EndpointID string
	// IP is the container's IP address on the container network. Populated on
	// Linux from the CNI result, and on Windows from the HCN endpoint — the
	// address ephemerd pinned on the L2Bridge path, the one HNS allocated on
	// the NAT path. Empty on macOS.
	//
	// Not informational: it is the scope of the per-job dind host-firewall
	// allow (see OpenHostPort). An empty IP on a platform that needs one costs
	// the job its Docker access, by design.
	IP string
}

SetupResult contains the network configuration applied to a container.

Jump to

Keyboard shortcuts

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