Documentation
¶
Index ¶
- Constants
- Variables
- func CNIConfListPath(dataDir string) string
- func CleanStaleBridge(log *slog.Logger)
- type Config
- type Manager
- func (m *Manager) Cleanup()
- func (m *Manager) CloseHostPort(port int, containerIP string)
- func (m *Manager) GatewayIP() string
- func (m *Manager) InstallFirewallRules() error
- func (m *Manager) JoinJobNetwork(cniID, jobID, containerIP string) error
- func (m *Manager) LeaveJobNetwork(cniID string)
- func (m *Manager) OpenHostPort(port int, containerIP string) error
- func (m *Manager) Setup(ctx context.Context, id string, netns string) (*SetupResult, error)
- func (m *Manager) Teardown(ctx context.Context, id string, netns string) error
- type SetupResult
Constants ¶
const DefaultSubnet = "10.88.0.0/16"
DefaultSubnet is the preferred IP range for containers.
Variables ¶
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
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 ¶
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 (*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
CloseHostPort removes an allow previously added by OpenHostPort. containerIP must match the one it was opened with.
func (*Manager) GatewayIP ¶
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 ¶
InstallFirewallRules blocks container traffic to private network ranges.
func (*Manager) JoinJobNetwork ¶ added in v0.2.6
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
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
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.
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.