diff --git a/docs/network.md b/docs/network.md index 7a14be0d..6cb56c07 100644 --- a/docs/network.md +++ b/docs/network.md @@ -66,12 +66,16 @@ agent containers. ## Firewall posture -`networking.firewall.interfaces..allowedUDPPorts = [ 53 ]` +`networking.firewall.interfaces..allowedUDPPorts = [ 53 67 ]` `networking.firewall.interfaces..allowedTCPPorts = [ 53 80 443 ]` - Port 53 opens the resolver on the bridge interface only. Other interfaces stay closed. The hive resolver isn't an external-facing service. +- Port 67 (UDP) admits DHCP requests to the dnsmasq pool. dnsmasq + receives DHCP via a regular UDP socket (it does not use a + netfilter-bypassing raw socket), so the hole is mandatory — without + it containers never get a lease and fall back to 169.254.x.x. - Ports 80 and 443 let isolated agents reach nginx (gateway container, shared host netns) for the forge sub-domain, per-agent UI proxies, and any other HTTP services. diff --git a/nix/modules/hive-network.nix b/nix/modules/hive-network.nix index e2c23cf6..50bd9a6f 100644 --- a/nix/modules/hive-network.nix +++ b/nix/modules/hive-network.nix @@ -163,9 +163,16 @@ in } ]; - # DNS only on the bridge interface — no external amplification surface. + # DNS + DHCP on the bridge interface only — no external amplification + # surface. UDP 67 is required for the dnsmasq DHCP pool: dnsmasq + # receives DHCPDISCOVER via a regular UDP socket (no netfilter-bypassing + # raw socket like ISC dhcpd), so without this hole the host INPUT chain + # drops the broadcasts and every container falls back to IPv4LL. networking.firewall.interfaces.${cfg.bridgeName} = { - allowedUDPPorts = [ 53 ]; + allowedUDPPorts = [ + 53 + 67 + ]; allowedTCPPorts = [ 53 ]; }; })