1
0

firewall: update zones with interface names as they appear

This commit is contained in:
Daniel Barlow 2025-02-10 00:42:27 +00:00
parent 4bb081ffcf
commit 7f17125039
2 changed files with 78 additions and 4 deletions

View File

@ -0,0 +1,63 @@
(local { : system : join } (require :anoia))
(local svc (require :anoia.svc))
(local ll (require :lualinux))
;; ifwatch.fnl wan:/nix/store/eee/.outputs/ifname wan:/nix/store/ffff/.outputs/ifname lan:/nix/store/abc123/.outputs/ifname
(fn parse-options [cmdline]
(let [interfaces {}]
(each [_ s (ipairs cmdline)]
(let [(zone service) (string.match s "(.-):(.+)")]
(tset interfaces (svc.open service) zone)))
interfaces))
(local POLLIN 1)
(local POLLHUP 16)
(fn zone-contents [interfaces]
(accumulate [zones {}
intf zone (pairs interfaces)]
(let [ifs (or (. zones zone) [])]
(table.insert ifs (intf:output "ifname"))
(tset zones zone ifs)
zones)))
(fn wait-for-change [interfaces]
(let [pollfds (icollect [k _ (pairs interfaces)]
(bor (lshift (k:fileno) 32)
(lshift (bor POLLIN POLLHUP) 16)))]
(ll.poll pollfds)))
(fn fail [msg]
(io.stderr:write (.. "ERROR: " msg "\n")))
(macro with-popen [[handle command mode] & body]
`(let [,handle (assert (io.popen ,command ,mode))
val# (do ,(unpack body))]
(case (: ,handle :close)
ok# val#
(nil :exit code#) (fail (.. ,command " exited " code#))
(nil :signal sig#) (fail (.. ,command " killed by " sig#)))))
(fn update-zone-str [zone ifnames]
(if (> (# ifnames) 0)
(..
"flush set ip table-ip " zone " ; add element ip table-ip " zone " { " (table.concat ifnames ", ") " };\n"
"flush set ip6 table-ip6 " zone " ; add element ip6 table-ip6 " zone " { " (table.concat ifnames ", ") " };\n"
)
(..
"flush set ip table-ip " zone "; \n"
"flush set ip6 table-ip6 " zone "; \n"
)))
(fn run []
(while true
(let [interfaces (parse-options arg)]
(with-popen [nft "nft -f -" :w]
(each [zone ifnames (pairs (zone-contents interfaces))]
(nft:write (update-zone-str zone ifnames))))
(wait-for-change interfaces)
(each [k _ (pairs interfaces)]
(k:close)))))
{ : run }

View File

@ -3,11 +3,17 @@
, lib
, firewallgen
, nftables
, writeFennel
, anoia
, lualinux
, linotify
}:
{ rules, extraRules, zones }:
let
inherit (liminix.services) longrun ; # oneshot;
inherit (lib.attrsets) mapAttrs' nameValuePair;
inherit (liminix.services) longrun;
inherit (lib.attrsets) mapAttrs' nameValuePair mapAttrsToList;
inherit (lib.strings) concatStringsSep;
inherit (lib.lists) flatten;
mkSet = family : name :
nameValuePair
"${name}-set-${family}"
@ -20,12 +26,17 @@ let
(mapAttrs' (n : _ : mkSet "ip6" n) zones);
allRules = lib.recursiveUpdate extraRules (lib.recursiveUpdate (builtins.trace sets sets) rules);
script = firewallgen "firewall1.nft" allRules;
ifwatch = writeFennel "ifwatch" {
packages = [anoia lualinux linotify];
mainFunction = "run";
} ./ifwatch.fnl ;
watchArg = z : intfs : map (i: "${z}:${i}/.outputs") intfs;
in longrun {
name = "firewall";
run = ''
${script}
while : ; do sleep 86400 ; done
PATH=${nftables}/bin:$PATH
${ifwatch} ${concatStringsSep " " (flatten (mapAttrsToList watchArg zones))}
'';
finish = "${nftables}/bin/nft flush ruleset";
}