From fe68bfbadcdf9657c9af36ce1aacb3e5f4447de2 Mon Sep 17 00:00:00 2001 From: damocles Date: Wed, 24 Jun 2026 19:28:29 +0200 Subject: [PATCH] fix(network): co-locate exposeHostPorts firewall opening with the proxies (argus review on #1972) --- nix/modules/hive-network.nix | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/nix/modules/hive-network.nix b/nix/modules/hive-network.nix index 0d02d5e1..4737b7d5 100644 --- a/nix/modules/hive-network.nix +++ b/nix/modules/hive-network.nix @@ -229,12 +229,12 @@ in # Allow isolated agents to reach the gateway (nginx on the host, shared # netns). Port 80 covers `http://forge.`, per-agent UI proxies, # and any other HTTP services the gateway fronts. Port 443 for HTTPS. - # `exposeHostPorts` adds any operator-declared host-loopback proxies. + # (`exposeHostPorts` opens its own ports in its dedicated block below, + # co-located with the proxies so the firewall hole + listener can't drift.) networking.firewall.interfaces.${cfg.bridgeName}.allowedTCPPorts = [ 80 443 - ] - ++ cfg.exposeHostPorts; + ]; # Tells hive-c0re to pass PRIVATE_NETWORK + bridge settings to each # container. HIVE_NETWORK_SUBNET is host-bridge IP/prefix, not canonical @@ -253,6 +253,14 @@ in # DROP rule above — agents connect to the bridge IP, and the host's own # proxy process is what dials 127.0.0.1. See docs/network.md. (lib.mkIf (config.services.hyperhive.enable && cfg.exposeHostPorts != [ ]) { + # Open the proxied ports on the bridge firewall HERE — same block + same + # gate as the proxies — so the firewall hole and the listener are always + # created together (never one without the other). Merges with the + # [ 80 443 ] gateway ports defined above. Independent of the deprecated + # isolateContainers toggle: isolation is unconditional, so this works + # under network isolation (the only mode). + networking.firewall.interfaces.${cfg.bridgeName}.allowedTCPPorts = cfg.exposeHostPorts; + systemd.sockets = lib.listToAttrs ( map ( p: @@ -274,8 +282,10 @@ in serviceConfig = { ExecStart = "${config.systemd.package}/lib/systemd/systemd-socket-proxyd 127.0.0.1:${toString p}"; SyslogIdentifier = "hive-hostport-${toString p}"; - # Pure userspace TCP proxy: no filesystem, no privileges, no extra - # address families beyond inet/unix. DynamicUser keeps it unprivileged. + # Hardened userspace TCP relay. AF_INET/AF_INET6 for the upstream + # loopback dial; AF_UNIX only for systemd-socket-proxyd's sd_notify + # (the listen fd itself is inherited via LISTEN_FDS, so the relay + # never socket()s its own listener). DynamicUser keeps it unprivileged. DynamicUser = true; NoNewPrivileges = true; ProtectSystem = "strict";