Personal Nix setup
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add common blocklist to nftables

+134 -3
+6 -3
machines/ramune/configuration.nix
··· 39 39 { macAddress = "c4:f1:74:51:4c:f2"; ipAddress = "10.0.0.124"; } # eero router 40 40 { macAddress = "1c:1d:d3:de:4b:06"; ipAddress = "10.0.0.35"; } # irnbru 41 41 ]; 42 - nftables.blockForward = [ 43 - "ec:e5:12:1d:23:40" # tado 44 - ]; 42 + nftables = { 43 + blocklist.enable = true; 44 + blockForward = [ 45 + "ec:e5:12:1d:23:40" # tado 46 + ]; 47 + }; 45 48 }; 46 49 automation = { 47 50 enable = true;
+1
modules/router/default.nix
··· 18 18 ./network.nix 19 19 ./timeserver.nix 20 20 ./nftables.nix 21 + ./nftables-blocklist.nix 21 22 ./upnp.nix 22 23 ./kernel.nix 23 24 ];
+103
modules/router/nftables-blocklist.nix
··· 1 + { config, lib, pkgs, ... }: 2 + 3 + with lib; 4 + let 5 + cfg = config.modules.router; 6 + blcfg = cfg.nftables.blocklist; 7 + setV4 = "blocklist_v4"; 8 + setV6 = "blocklist_v6"; 9 + 10 + updateScript = let 11 + v4Urls = concatStringsSep " " (map escapeShellArg blcfg.urls); 12 + v6Urls = concatStringsSep " " (map escapeShellArg blcfg.urlsV6); 13 + in pkgs.writeShellApplication { 14 + name = "nftables-blocklist-update"; 15 + runtimeInputs = with pkgs; [ curl nftables gawk coreutils ]; 16 + text = '' 17 + dir="$STATE_DIRECTORY" 18 + 19 + nft list tables || exit 0 20 + 21 + fetch() { 22 + local out="$1"; shift 23 + local tmp="$dir/.tmp" ok=false 24 + : > "$tmp" 25 + for url in "$@"; do 26 + if curl -sfL --max-time 30 --retry 2 "$url" >> "$tmp"; then 27 + ok=true 28 + fi 29 + done 30 + if "$ok"; then mv "$tmp" "$out"; else rm -f "$tmp"; fi 31 + } 32 + 33 + fetch "$dir/v4.json" ${v4Urls} 34 + fetch "$dir/v6.json" ${v6Urls} 35 + 36 + touch "$dir/v4.json" "$dir/v6.json" 37 + awk -F'"' ' 38 + BEGINFILE { elems = ""; sep = ""; n = 0 } 39 + $2 == "cidr" { elems = elems sep $4; sep = ", "; n++ } 40 + ENDFILE { 41 + print "flush set inet filter " SET 42 + if (n) print "add element inet filter " SET " { " elems " }" 43 + printf "%d %s entries\n", n, SET > "/dev/stderr" 44 + } 45 + ' SET=${setV4} "$dir/v4.json" SET=${setV6} "$dir/v6.json" \ 46 + | nft -f - 47 + ''; 48 + }; 49 + in { 50 + options.modules.router.nftables.blocklist = { 51 + enable = mkOption { 52 + default = false; 53 + description = "Whether to enable IP blocklist using Spamhaus DROP"; 54 + type = types.bool; 55 + }; 56 + 57 + urls = mkOption { 58 + default = [ 59 + "https://www.spamhaus.org/drop/drop_v4.json" 60 + ]; 61 + description = "URLs to fetch IPv4 blocklists from (NDJSON with cidr field)"; 62 + type = types.listOf types.str; 63 + }; 64 + 65 + urlsV6 = mkOption { 66 + default = [ 67 + "https://www.spamhaus.org/drop/drop_v6.json" 68 + ]; 69 + description = "URLs to fetch IPv6 blocklists from (NDJSON with cidr field)"; 70 + type = types.listOf types.str; 71 + }; 72 + }; 73 + 74 + config = mkIf (cfg.nftables.enable && blcfg.enable) { 75 + systemd.services.nftables-blocklist = { 76 + description = "Update nftables IP blocklist"; 77 + after = [ "nftables.service" "network-online.target" ]; 78 + wants = [ "network-online.target" ]; 79 + serviceConfig = { 80 + Type = "oneshot"; 81 + StateDirectory = "nftables-blocklist"; 82 + ExecStart = getExe updateScript; 83 + }; 84 + }; 85 + 86 + systemd.timers.nftables-blocklist = { 87 + wantedBy = [ "timers.target" ]; 88 + timerConfig = { 89 + OnCalendar = "*-*-* 00/12:00:00"; 90 + RandomizedDelaySec = "1h"; 91 + Persistent = true; 92 + }; 93 + }; 94 + 95 + # Re-populate blocklist sets after nftables starts or reloads (flushRuleset clears them) 96 + systemd.services.nftables.serviceConfig = let 97 + trigger = "${pkgs.systemd}/bin/systemctl start --no-block nftables-blocklist.service"; 98 + in { 99 + ExecStartPost = [ trigger ]; 100 + ExecReload = [ trigger ]; 101 + }; 102 + }; 103 + }
+24
modules/router/nftables.nix
··· 3 3 with lib; 4 4 let 5 5 cfg = config.modules.router; 6 + blcfg = cfg.nftables.blocklist; 7 + blSetV4 = "blocklist_v4"; 8 + blSetV6 = "blocklist_v6"; 6 9 7 10 extern = cfg.interfaces.external; 8 11 intern = cfg.interfaces.internal; ··· 75 78 udp dport {${udpPorts}} ct state new meter udp6-conncount { ip6 saddr . udp dport ct count over 150 } counter drop 76 79 udp dport {${udpPorts}} ct state new accept 77 80 ''; 81 + blocklistSets = optionalString blcfg.enable '' 82 + set ${blSetV4} { 83 + type ipv4_addr 84 + flags interval 85 + auto-merge 86 + } 87 + set ${blSetV6} { 88 + type ipv6_addr 89 + flags interval 90 + auto-merge 91 + } 92 + ''; 93 + blocklistRules = optionalString blcfg.enable '' 94 + ip saddr @${blSetV4} counter drop 95 + ip6 saddr @${blSetV6} counter drop 96 + ''; 78 97 in '' 98 + ${blocklistSets} 99 + 79 100 chain prerouting { 80 101 type nat hook prerouting priority dstnat; policy accept; 81 102 ${capturePortsRules} ··· 92 113 ct state invalid drop 93 114 94 115 iifname { ${concatIfnames trustedInterfaces} } accept 116 + 117 + ${blocklistRules} 95 118 96 119 tcp flags & (fin|syn|rst|ack) != syn ct state new counter drop 97 120 tcp flags & (fin|syn|rst|psh|ack|urg) == fin|syn|rst|psh|ack|urg counter drop ··· 195 218 ''; 196 219 }; 197 220 }; 221 + 198 222 }; 199 223 }