commit d7f3e050630ce32a48cbee4bbfad223f3648aa23
parent 73e5916cc58f505aaa06fe5231f1823f34d793a2
Author: Daniel Barlow <dan@telent.net>
Date: Sun, 16 Jul 2023 16:55:50 +0100
turn nftables firewall into a service-providing module
Diffstat:
4 files changed, 114 insertions(+), 56 deletions(-)
diff --git a/examples/rotuer.nix b/examples/rotuer.nix
@@ -35,39 +35,13 @@ in rec {
../modules/standard.nix
../modules/ppp
../modules/dnsmasq
+ ../modules/firewall
];
rootfsType = "jffs2";
hostname = "rotuer";
kernel = {
config = {
BRIDGE = "y";
-
- NETFILTER_XT_MATCH_CONNTRACK = "y";
-
- IP6_NF_IPTABLES= "y"; # do we still need these
- IP_NF_IPTABLES= "y"; # if using nftables directly
-
- IP_NF_NAT = "y";
- IP_NF_TARGET_MASQUERADE = "y";
- NETFILTER = "y";
- NETFILTER_ADVANCED = "y";
- NETFILTER_XTABLES = "y";
-
- NFT_COMPAT = "y";
- NFT_CT = "y";
- NFT_LOG = "y";
- NFT_MASQ = "y";
- NFT_NAT = "y";
- NFT_REJECT = "y";
- NFT_REJECT_INET = "y";
-
- NF_CONNTRACK = "y";
- NF_NAT = "y";
- NF_NAT_MASQUERADE = "y";
- NF_TABLES= "y";
- NF_TABLES_INET = "y";
- NF_TABLES_IPV4 = "y";
- NF_TABLES_IPV6 = "y";
};
};
@@ -221,33 +195,9 @@ in rec {
};
services.firewall =
- let
- script= pkgs.firewallgen "firewall.nft" (import ./rotuer-firewall.nix);
- kmodules = pkgs.kernel-modules.override {
- kernelSrc = config.system.outputs.kernel.src;
- modulesupport = config.system.outputs.kernel.modulesupport;
- kconfig = {
- NFT_FIB_IPV4 = "m";
- NFT_FIB_IPV6 = "m";
- NF_TABLES = "m";
- NF_CT_PROTO_DCCP = "y";
- NF_CT_PROTO_SCTP = "y";
- NF_CT_PROTO_UDPLITE = "y";
- # NF_CONNTRACK_FTP = "m";
- NFT_CT = "m";
- };
- targets = [
- "nft_fib_ipv4"
- "nft_fib_ipv6"
- ];
- };
- in oneshot {
- name = "firewall";
- up = ''
- sh ${kmodules}/load.sh
- ${script};
- '';
- down = "${pkgs.nftables}/bin/nft flush ruleset";
+ let ruleset = import ./rotuer-firewall.nix;
+ in config.system.service.firewall {
+ inherit ruleset;
};
services.packet_forwarding =
diff --git a/modules/base.nix b/modules/base.nix
@@ -26,6 +26,11 @@ in {
};
kernel = {
src = mkOption { type = types.package; } ;
+ modular = mkOption {
+ type = types.boolean;
+ default = true;
+ description = "support loadable kernel modules";
+ };
extraPatchPhase = mkOption {
default = "true";
type = types.lines;
@@ -67,14 +72,15 @@ in {
};
kernel = rec {
+ modular = true; # disabling this is not yet supported
config = {
IKCONFIG = "y";
IKCONFIG_PROC = "y";
PROC_FS = "y";
KEXEC = "y";
- MODULES = "y";
- MODULE_SIG = "y";
+ MODULES = if modular then "y" else "n";
+ MODULE_SIG = if modular then "y" else "n";
DEBUG_FS = "y";
MIPS_BOOTLOADER_CMDLINE_REQUIRE_COOKIE = "y";
diff --git a/modules/firewall/default.nix b/modules/firewall/default.nix
@@ -0,0 +1,76 @@
+{ lib, pkgs, config, ...}:
+let
+ inherit (lib) mkOption types;
+ inherit (pkgs.liminix.services) oneshot;
+
+ kconf = isModule :
+ # setting isModule false is utterly untested and mostly
+ # unimplemented: I say this to preempt any "how on earth is this
+ # even supposed to work?" questions
+ let yes = if isModule then "m" else "y";
+ in {
+ NFT_FIB_IPV4 = yes;
+ NFT_FIB_IPV6 = yes;
+ NF_TABLES = yes;
+ NF_CT_PROTO_DCCP = "y";
+ NF_CT_PROTO_SCTP = "y";
+ NF_CT_PROTO_UDPLITE = "y";
+ # NF_CONNTRACK_FTP = yes;
+ NFT_CT = yes;
+ };
+ kmodules = pkgs.kernel-modules.override {
+ kernelSrc = config.system.outputs.kernel.src;
+ modulesupport = config.system.outputs.kernel.modulesupport;
+ targets = [
+ "nft_fib_ipv4"
+ "nft_fib_ipv6"
+ ];
+ kconfig = kconf true;
+ };
+ loadModules = oneshot {
+ name = "firewall-modules";
+ up = "sh ${kmodules}/load.sh";
+ down = "sh ${kmodules}/unload.sh";
+ };
+in
+{
+ options = {
+ system.service.firewall = mkOption {
+ type = types.anything; # types.functionTo pkgs.liminix.lib.types.service;
+ };
+ };
+ config = {
+ system.service.firewall = params :
+ let svc = (pkgs.callPackage ./service.nix {}) params;
+ in svc // { dependencies = svc.dependencies ++ [loadModules]; };
+
+ kernel.config = {
+ NETFILTER_XT_MATCH_CONNTRACK = "y";
+
+ IP6_NF_IPTABLES= "y"; # do we still need these
+ IP_NF_IPTABLES= "y"; # if using nftables directly
+
+ IP_NF_NAT = "y";
+ IP_NF_TARGET_MASQUERADE = "y";
+ NETFILTER = "y";
+ NETFILTER_ADVANCED = "y";
+ NETFILTER_XTABLES = "y";
+
+ NFT_COMPAT = "y";
+ NFT_CT = "y";
+ NFT_LOG = "y";
+ NFT_MASQ = "y";
+ NFT_NAT = "y";
+ NFT_REJECT = "y";
+ NFT_REJECT_INET = "y";
+
+ NF_CONNTRACK = "y";
+ NF_NAT = "y";
+ NF_NAT_MASQUERADE = "y";
+ NF_TABLES= "y";
+ NF_TABLES_INET = "y";
+ NF_TABLES_IPV4 = "y";
+ NF_TABLES_IPV6 = "y";
+ };
+ };
+}
diff --git a/modules/firewall/service.nix b/modules/firewall/service.nix
@@ -0,0 +1,26 @@
+{
+ liminix
+, lib
+, firewallgen
+, nftables
+}:
+let
+ inherit (liminix.services) oneshot;
+ inherit (liminix.lib) typeChecked;
+ inherit (lib) mkOption types;
+ t = {
+ ruleset = mkOption {
+ type = types.anything; # we could usefully define this more tightly
+ description = "firewall ruleset";
+ };
+ };
+in
+params:
+let
+ inherit (typeChecked "firewall" t params) ruleset;
+ script = firewallgen "firewall.nft" ruleset;
+in oneshot {
+ name = "firewall";
+ up = script;
+ down = "${nftables}/bin/nft flush ruleset";
+}