Zone-based firewall page, per-sensor temperatures, 15 minute default
The firewall page now manages zones (assign each LAN or tunnel, add and remove zones) and rules with zone, address and port on both sides plus the protocol. router.firewall.zones declares zones without members and rules take sourcePorts. The temperature chart draws every thermal zone and hwmon sensor; the overview defaults to 15 minutes, 1h stays an option. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AeFqV9dZrK6nipHkPfyM4F
This commit is contained in:
@@ -310,6 +310,56 @@ let
|
||||
};
|
||||
expect = [ "ports are only valid with protocol tcp or udp" ];
|
||||
};
|
||||
ruleSourcePortsWithoutProtocol = {
|
||||
router = {
|
||||
lans = {
|
||||
main = lan { };
|
||||
iot = lan2 { };
|
||||
};
|
||||
firewall.rules = [
|
||||
{
|
||||
from = "iot";
|
||||
to = "main";
|
||||
sourcePorts = [ 53 ];
|
||||
}
|
||||
];
|
||||
};
|
||||
expect = [ "sourcePorts are only valid with protocol tcp or udp" ];
|
||||
};
|
||||
ruleSourcePortOutOfRange = {
|
||||
router = {
|
||||
lans = {
|
||||
main = lan { };
|
||||
iot = lan2 { };
|
||||
};
|
||||
firewall.rules = [
|
||||
{
|
||||
from = "iot";
|
||||
to = "main";
|
||||
protocol = "udp";
|
||||
sourcePorts = [ "2000-1000" ];
|
||||
}
|
||||
];
|
||||
};
|
||||
expect = [ "out of range" ];
|
||||
};
|
||||
ruleToDeclaredEmptyZone = {
|
||||
router = {
|
||||
lans.main = lan { };
|
||||
firewall = {
|
||||
zones = [ "guests" ];
|
||||
rules = [
|
||||
{
|
||||
from = "main";
|
||||
to = "guests";
|
||||
protocol = "tcp";
|
||||
sourcePorts = [ 1024 ];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
expect = [ ];
|
||||
};
|
||||
ruleDestinationInvalid = {
|
||||
router = {
|
||||
lans = {
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#
|
||||
# rules: trusted -> iot (anything)
|
||||
# iot -> trusted, tcp 8080, only to 192.168.10.100
|
||||
# iot -> trusted, tcp 9090, only from source ports 40000-40010
|
||||
# "lab" (no interface yet) -> trusted: matches nothing
|
||||
#
|
||||
# upstream (ISP) -- vlan 1 -- router -- vlan 2 (trunk) -- main / iot / cams
|
||||
{ self, pkgs }:
|
||||
@@ -148,7 +150,20 @@ pkgs.testers.runNixOSTest {
|
||||
ports = [ 8080 ];
|
||||
destination = "192.168.10.100";
|
||||
}
|
||||
{
|
||||
from = "iot";
|
||||
to = "trusted";
|
||||
protocol = "tcp";
|
||||
ports = [ 9090 ];
|
||||
sourcePorts = [ "40000-40010" ];
|
||||
destination = "192.168.10.100";
|
||||
}
|
||||
{
|
||||
from = "lab";
|
||||
to = "trusted";
|
||||
}
|
||||
];
|
||||
firewall.zones = [ "lab" ];
|
||||
dns.forwarders = [ "203.0.113.1" ];
|
||||
};
|
||||
|
||||
@@ -247,5 +262,15 @@ pkgs.testers.runNixOSTest {
|
||||
host.succeed("nc -z -w 2 192.168.10.100 8080")
|
||||
host.fail("nc -z -w 2 192.168.10.100 9090")
|
||||
host.fail("nc -z -w 2 192.168.10.150 8080")
|
||||
|
||||
with subtest("a rule can match the source port too"):
|
||||
for host in (iot, cams):
|
||||
host.succeed("nc -z -w 2 -p 40005 192.168.10.100 9090")
|
||||
host.fail("nc -z -w 2 -p 50000 192.168.10.100 9090")
|
||||
host.fail("nc -z -w 2 -p 40005 192.168.10.150 9090")
|
||||
|
||||
with subtest("a zone without interfaces does not break the ruleset"):
|
||||
router.succeed("nft list ruleset | grep -q 'sport 40000-40010'")
|
||||
router.succeed("systemctl is-active nftables.service")
|
||||
'';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user