nixos/keepalived: support nftables for openFirewall

This commit is contained in:
Justinas Stankevicius 2025-11-01 13:38:08 +02:00
commit 2cadaefb71
4 changed files with 80 additions and 58 deletions

View file

@ -325,18 +325,28 @@ in
assertions = flatten (map vrrpInstanceAssertions vrrpInstances);
networking.firewall = lib.mkIf cfg.openFirewall {
extraCommands = ''
# Allow VRRP and AH packets
ip46tables -A nixos-fw -p vrrp -m comment --comment "services.keepalived.openFirewall" -j ACCEPT
ip46tables -A nixos-fw -p ah -m comment --comment "services.keepalived.openFirewall" -j ACCEPT
'';
networking.firewall = lib.mkIf cfg.openFirewall (
if config.networking.nftables.enable then
{
extraInputRules = ''
meta l4proto vrrp counter accept comment "services.keepalived.openFirewall"
meta l4proto ah counter accept comment "services.keepalived.openFirewall"
'';
}
else
{
extraCommands = ''
# Allow VRRP and AH packets
ip46tables -A nixos-fw -p vrrp -m comment --comment "services.keepalived.openFirewall" -j ACCEPT
ip46tables -A nixos-fw -p ah -m comment --comment "services.keepalived.openFirewall" -j ACCEPT
'';
extraStopCommands = ''
ip46tables -D nixos-fw -p vrrp -m comment --comment "services.keepalived.openFirewall" -j ACCEPT
ip46tables -D nixos-fw -p ah -m comment --comment "services.keepalived.openFirewall" -j ACCEPT
'';
};
extraStopCommands = ''
ip46tables -D nixos-fw -p vrrp -m comment --comment "services.keepalived.openFirewall" -j ACCEPT
ip46tables -D nixos-fw -p ah -m comment --comment "services.keepalived.openFirewall" -j ACCEPT
'';
}
);
systemd.timers.keepalived-boot-delay = {
description = "Keepalive Daemon delay to avoid instant transition to MASTER state";

View file

@ -793,7 +793,7 @@ in
kbd-setfont-decompress = runTest ./kbd-setfont-decompress.nix;
kbd-update-search-paths-patch = runTest ./kbd-update-search-paths-patch.nix;
kea = runTest ./kea.nix;
keepalived = runTest ./keepalived.nix;
keepalived = discoverTests (import ./keepalived.nix);
keepassxc = runTest ./keepassxc.nix;
kerberos = handleTest ./kerberos/default.nix { };
kernel-generic = handleTest ./kernel-generic { };

View file

@ -1,48 +1,60 @@
{ pkgs, lib, ... }:
let
mkTest =
{ useNftables }:
import ./make-test-python.nix (
{ pkgs, lib, ... }:
{
name = "keepalived-${if useNftables then "nftables" else "iptables"}";
meta.maintainers = [ lib.maintainers.raitobezarius ];
nodes = {
node1 =
{ pkgs, ... }:
{
networking.nftables.enable = useNftables;
services.keepalived.enable = true;
services.keepalived.openFirewall = true;
services.keepalived.vrrpInstances.test = {
interface = "eth1";
state = "MASTER";
priority = 50;
virtualIps = [ { addr = "192.168.1.200"; } ];
virtualRouterId = 1;
};
environment.systemPackages = [ pkgs.tcpdump ];
};
node2 =
{ pkgs, ... }:
{
networking.nftables.enable = useNftables;
services.keepalived.enable = true;
services.keepalived.openFirewall = true;
services.keepalived.vrrpInstances.test = {
interface = "eth1";
state = "MASTER";
priority = 100;
virtualIps = [ { addr = "192.168.1.200"; } ];
virtualRouterId = 1;
};
environment.systemPackages = [ pkgs.tcpdump ];
};
};
testScript = ''
# wait for boot time delay to pass
for node in [node1, node2]:
node.wait_until_succeeds(
"systemctl show -p LastTriggerUSecMonotonic keepalived-boot-delay.timer | grep -vq 'LastTriggerUSecMonotonic=0'"
)
node.wait_for_unit("keepalived")
node2.wait_until_succeeds("ip addr show dev eth1 | grep -q 192.168.1.200")
node1.fail("ip addr show dev eth1 | grep -q 192.168.1.200")
node1.succeed("ping -c1 192.168.1.200")
'';
}
);
in
{
name = "keepalived";
meta.maintainers = [ lib.maintainers.raitobezarius ];
nodes = {
node1 =
{ pkgs, ... }:
{
services.keepalived.enable = true;
services.keepalived.openFirewall = true;
services.keepalived.vrrpInstances.test = {
interface = "eth1";
state = "MASTER";
priority = 50;
virtualIps = [ { addr = "192.168.1.200"; } ];
virtualRouterId = 1;
};
environment.systemPackages = [ pkgs.tcpdump ];
};
node2 =
{ pkgs, ... }:
{
services.keepalived.enable = true;
services.keepalived.openFirewall = true;
services.keepalived.vrrpInstances.test = {
interface = "eth1";
state = "MASTER";
priority = 100;
virtualIps = [ { addr = "192.168.1.200"; } ];
virtualRouterId = 1;
};
environment.systemPackages = [ pkgs.tcpdump ];
};
};
testScript = ''
# wait for boot time delay to pass
for node in [node1, node2]:
node.wait_until_succeeds(
"systemctl show -p LastTriggerUSecMonotonic keepalived-boot-delay.timer | grep -vq 'LastTriggerUSecMonotonic=0'"
)
node.wait_for_unit("keepalived")
node2.wait_until_succeeds("ip addr show dev eth1 | grep -q 192.168.1.200")
node1.fail("ip addr show dev eth1 | grep -q 192.168.1.200")
node1.succeed("ping -c1 192.168.1.200")
'';
nftables = mkTest { useNftables = true; };
iptables = mkTest { useNftables = false; };
}

View file

@ -38,7 +38,7 @@ stdenv.mkDerivation rec {
enableParallelBuilding = true;
passthru.tests.keepalived = nixosTests.keepalived;
passthru.tests = nixosTests.keepalived;
nativeBuildInputs = [
pkg-config