firewall: use extraText for zone set contents
* the lua necessary is quite wordy, but it's less of a hack than post-processing the rules file with pseudo-sed to get rid of `elements = { }` lines * also switch from stop/starting the firewall service to using a signal, so that we don't go briefly offline every time a new interface appears
This commit is contained in:
parent
d4e46dbe28
commit
c6918fec00
@ -21,7 +21,7 @@ let
|
|||||||
inherit (lib.attrsets) mapAttrs' nameValuePair mapAttrsToList;
|
inherit (lib.attrsets) mapAttrs' nameValuePair mapAttrsToList;
|
||||||
inherit (lib.strings) concatStringsSep;
|
inherit (lib.strings) concatStringsSep;
|
||||||
inherit (lib.lists) flatten;
|
inherit (lib.lists) flatten;
|
||||||
inherit (builtins) concatLists attrValues;
|
inherit (builtins) concatLists toJSON attrValues;
|
||||||
inherit (liminix) outputRef;
|
inherit (liminix) outputRef;
|
||||||
mkSet =
|
mkSet =
|
||||||
family: name:
|
family: name:
|
||||||
@ -29,11 +29,25 @@ let
|
|||||||
kind = "set";
|
kind = "set";
|
||||||
inherit name family;
|
inherit name family;
|
||||||
type = "ifname";
|
type = "ifname";
|
||||||
elements = map (s: "{{ output(${builtins.toJSON s}, \"ifname\", \"\") }}") zones.${name};
|
extraText = ''
|
||||||
};
|
{{;
|
||||||
|
local services = { ${concatStringsSep ", " (map toJSON zones.${name})} }
|
||||||
|
local ifnames = {}
|
||||||
|
for _, v in ipairs(services) do
|
||||||
|
local o = output(v, "ifname")
|
||||||
|
if o then table.insert(ifnames, o) end
|
||||||
|
end
|
||||||
|
if (#ifnames > 0) then
|
||||||
|
return "elements = { " .. table.concat(ifnames, ", ") .. " }\n"
|
||||||
|
else
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
}}
|
||||||
|
'';
|
||||||
|
};
|
||||||
sets = (mapAttrs' (n: _: mkSet "ip" n) zones) //
|
sets = (mapAttrs' (n: _: mkSet "ip" n) zones) //
|
||||||
(mapAttrs' (n: _: mkSet "ip6" n) zones);
|
(mapAttrs' (n: _: mkSet "ip6" n) zones);
|
||||||
allRules = lib.recursiveUpdate extraRules (lib.recursiveUpdate (builtins.trace sets sets) rules);
|
allRules = lib.recursiveUpdate extraRules (lib.recursiveUpdate sets rules);
|
||||||
script = firewallgen "firewall1.nft" allRules;
|
script = firewallgen "firewall1.nft" allRules;
|
||||||
ifwatch = writeFennel "ifwatch" {
|
ifwatch = writeFennel "ifwatch" {
|
||||||
packages = [
|
packages = [
|
||||||
@ -48,19 +62,25 @@ let
|
|||||||
service = longrun {
|
service = longrun {
|
||||||
inherit name;
|
inherit name;
|
||||||
run = ''
|
run = ''
|
||||||
mkdir -p /run/${name}; in_outputs ${name}
|
|
||||||
# exec > /dev/console 2>&1
|
|
||||||
echo RESTARTING FIREWALL >/dev/console
|
|
||||||
PATH=${nftables}/bin:${lua}/bin:$PATH
|
PATH=${nftables}/bin:${lua}/bin:$PATH
|
||||||
${output-template}/bin/output-template '{{' '}}' < ${script} | lua -e 'for x in io.lines() do if not string.match(x, "elements = {%s+}") then print(x) end; end' > /run/${name}/fw.nft
|
reload() {
|
||||||
# cat /run/${name}/fw.nft > /dev/console
|
echo reloading firewall
|
||||||
nft -f /run/${name}/fw.nft
|
${output-template}/bin/output-template '{{' '}}' < ${script} > /run/${name}/fw.nft;
|
||||||
while sleep 86400 ; do : ; done
|
nft -f /run/${name}/fw.nft ;
|
||||||
|
}
|
||||||
|
trap reload SIGUSR1
|
||||||
|
mkdir -p /run/${name}; in_outputs ${name}
|
||||||
|
reload
|
||||||
|
while :; do
|
||||||
|
# signals sent to ash won't interrupt sleep, but will interrupt wait
|
||||||
|
sleep 86400 & wait
|
||||||
|
done
|
||||||
'';
|
'';
|
||||||
finish = "${nftables}/bin/nft flush ruleset";
|
finish = "${nftables}/bin/nft flush ruleset";
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
svc.secrets.subscriber.build {
|
svc.secrets.subscriber.build {
|
||||||
|
action = "usr1";
|
||||||
watch =
|
watch =
|
||||||
concatLists
|
concatLists
|
||||||
(mapAttrsToList (_zone : services : map (s: outputRef s "ifname") services) zones);
|
(mapAttrsToList (_zone : services : map (s: outputRef s "ifname") services) zones);
|
||||||
|
@ -8,29 +8,39 @@ send "PS1=\$(echo 'I1JFQURZIyA=' | base64 -d); stty -echo\n"
|
|||||||
expect "#READY#"
|
expect "#READY#"
|
||||||
set FINISHED 0
|
set FINISHED 0
|
||||||
set EXIT "1"
|
set EXIT "1"
|
||||||
while { $FINISHED < 10 } {
|
while { $FINISHED < 20 } {
|
||||||
send "ip address show dev ppp0 | grep ppp0\n"
|
send "ip address show dev ppp0 | grep ppp0\n"
|
||||||
expect {
|
expect {
|
||||||
"192.168.100.1" { set FINISHED 20; set EXIT 0; }
|
"192.168.100.1" { set FINISHED 200; set EXIT 0; }
|
||||||
"can't find device" { send_user "waiting ..." ; sleep 3 }
|
"can't find device" { send_user "waiting ..." ; sleep 3 }
|
||||||
"DOWN" { send_user "waiting ..." ; sleep 3 }
|
"DOWN" { send_user "waiting ..." ; sleep 3 }
|
||||||
}
|
}
|
||||||
set FINISHED [ expr $FINISHED + 1 ]
|
set FINISHED [ expr $FINISHED + 1 ]
|
||||||
}
|
}
|
||||||
expect "#READY#"
|
expect "#READY#"
|
||||||
send "nft list set ip table-ip wan || touch /non/existent\n"
|
send "s6-svwait -U /run/service/wan.link.pppoe\n"
|
||||||
expect {
|
|
||||||
"ppp0" { puts "ppp0 found " }
|
|
||||||
"{ }" { puts "missing ifname"; exit 1 }
|
|
||||||
"No such file or directory" { exit 1 }
|
|
||||||
}
|
|
||||||
expect "#READY#"
|
expect "#READY#"
|
||||||
|
|
||||||
|
set timeout 30
|
||||||
send "nft list set ip table-ip lan || touch /non/existent\n"
|
send "nft list set ip table-ip lan || touch /non/existent\n"
|
||||||
expect {
|
expect {
|
||||||
"lan" { puts "lan found" }
|
"lan" { puts "lan found" }
|
||||||
"{ }" { puts "missing ifname"; exit 1 }
|
"{ }" { puts "missing ifname"; exit 1 }
|
||||||
"No such file or directory" { exit 1 }
|
"No such file or directory" { exit 1 }
|
||||||
}
|
}
|
||||||
|
|
||||||
expect "#READY#"
|
expect "#READY#"
|
||||||
|
|
||||||
|
# if the test fails for no apparent reason, it is quite likely because
|
||||||
|
# the firewall hasn't had time to reload after the new interface
|
||||||
|
# appears and you just have to make this sleep longer. Ew, yes
|
||||||
|
send "sleep 10; nft list set ip table-ip wan || touch /non/existent\n"
|
||||||
|
expect {
|
||||||
|
"ppp0" { puts "ppp0 found " }
|
||||||
|
"{ }" { puts "missing ifname"; exit 1 }
|
||||||
|
"No such file or directory" { exit 1 }
|
||||||
|
timeout { exit 1 }
|
||||||
|
}
|
||||||
|
expect "#READY#"
|
||||||
|
|
||||||
exit $EXIT
|
exit $EXIT
|
||||||
|
Loading…
Reference in New Issue
Block a user