diff --git a/nix/host-modules/hive-egress.nix b/nix/host-modules/hive-egress.nix index a82b82145..fc04c0ab2 100644 --- a/nix/host-modules/hive-egress.nix +++ b/nix/host-modules/hive-egress.nix @@ -473,6 +473,17 @@ in the low 17 bits of the agent's address. ''; } + { + assertion = cfg.egress.forward != "reject" || cfg.egress.intercept.enable; + message = '' + services.hyperhive.network.egress.forward = "reject" needs + services.hyperhive.network.egress.intercept.enable = true: + without the intercept nothing redirects the agents' web traffic into + squid, and the reject would refuse all of it. + Enable the intercept (hive-squid.nix does on a hive controller host), + or keep forward = "log". + ''; + } { assertion = !(lib.any (k: isOn (config.boot.kernel.sysctl.${k} or 0)) routeLocalnetKeys); message = '' diff --git a/nix/module-eval/core-toggle.nix b/nix/module-eval/core-toggle.nix index 1cb51c8c9..eb14b0b91 100644 --- a/nix/module-eval/core-toggle.nix +++ b/nix/module-eval/core-toggle.nix @@ -80,7 +80,10 @@ let network.egress.forward = "accept"; network.egress.antiSpoof = "log"; }; - egressForwardReject = hive { + egressForwardReject = hiveWithController { + network.egress.forward = "reject"; + }; + egressRejectNoIntercept = hive { network.enable = true; network.egress.forward = "reject"; }; @@ -1699,7 +1702,9 @@ let logged = lib.filter (lib.hasInfix "log prefix") rules; bareText = bare.services.hyperhive.network.egress.ruleset; in - !(lib.any (a: !a.assertion) egressForwardReject.assertions) + !(lib.any ( + a: !a.assertion && lib.hasInfix "network.egress" a.message + ) egressForwardReject.assertions) && lib.hasInfix "type filter hook forward priority filter - 10; policy accept;" chain && lib.hasInfix "chain input" text && idx ''oifname "wg-hive" accept'' < idx "ether saddr @direct_mac accept" @@ -1722,6 +1727,28 @@ let && !(lib.hasInfix "reject with" bareText) && lib.hasInfix "would-drop" bareText; } + { + # `reject` without the intercept is refused by an assertion that names + # the option and both ways out; the controller host with `reject` (the + # intercept on) and `bare` (`log`) are the controls that the lookup + # finds nothing for them. + name = "egress.forward reject without the intercept is refused"; + ok = + let + refused = + m: + lib.filter ( + a: + !a.assertion + && lib.hasInfix "services.hyperhive.network.egress.forward = \"reject\" needs" a.message + ) m.assertions; + in + lib.length (refused egressRejectNoIntercept) == 1 + && lib.hasInfix "intercept.enable = true" (lib.head (refused egressRejectNoIntercept)).message + && lib.hasInfix "keep forward = \"log\"" (lib.head (refused egressRejectNoIntercept)).message + && refused egressForwardReject == [ ] + && refused bare == [ ]; + } { # The redirect of the agents' web traffic: IPv4 TCP 80 and 443 from the # bridge go to squid's two intercept ports, after the rules that leave