This repository has no description
0

Configure Feed

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

configs: replace krebs.iptables with the nftables firewall

Every machine now uses networking.firewall on networking.nftables with
the same defaults krebs.iptables had: input and forward drop, all ICMP
accepted, no reverse path filter. Open ports and trusted interfaces are
unchanged on all machines.

- interface port rules become firewall.interfaces.<if>.allowed*Ports,
interface-wide accepts trustedInterfaces
- forwarding goes through extraForwardRules; yellow keeps forward
unfiltered for the transmission namespace
- NAT rules become per-module networking.nftables.tables
- ssh-redirect: 45621 redirects to 22, new connections to 22 are reset
unless they come from lo, retiolum or wiregrill
- xerxes: the JOOL xtables target is added by jool-iptables through
ip6tables-nft, with XTABLES_LIBDIR pointing at jool's extension
- flushRuleset = false so libvirt/podman/jool tables survive reloads;
extraDeletions drops the iptables-nft tables krebs.iptables left

Rules that were silently ignored while networking.firewall was disabled,
such as clan's yggdrasil filter, now take effect.

+188 -332
+15 -38
configs/consul.nix
··· 190 190 }; 191 191 }; 192 192 193 - krebs.iptables.tables.filter.INPUT.rules = [ 194 - { 195 - predicate = "-i retiolum -p tcp --dport 8300"; 196 - target = "ACCEPT"; 197 - } 198 - { 199 - predicate = "-i retiolum -p tcp --dport 8301"; 200 - target = "ACCEPT"; 201 - } 202 - { 203 - predicate = "-i retiolum -p udp --dport 8301"; 204 - target = "ACCEPT"; 205 - } 206 - { 207 - predicate = "-i retiolum -p tcp --dport 8302"; 208 - target = "ACCEPT"; 209 - } 210 - { 211 - predicate = "-i retiolum -p udp --dport 8302"; 212 - target = "ACCEPT"; 213 - } 214 - { 215 - predicate = "-i retiolum -p tcp --dport 8400"; 216 - target = "ACCEPT"; 217 - } 218 - { 219 - predicate = "-i retiolum -p tcp --dport 8500"; 220 - target = "ACCEPT"; 221 - } 222 - { 223 - predicate = "-i retiolum -p tcp --dport 8600"; 224 - target = "ACCEPT"; 225 - } 226 - { 227 - predicate = "-i retiolum -p udp --dport 8500"; 228 - target = "ACCEPT"; 229 - } 230 - ]; 193 + networking.firewall.interfaces.retiolum = { 194 + allowedTCPPorts = [ 195 + 8300 196 + 8301 197 + 8302 198 + 8400 199 + 8500 200 + 8600 201 + ]; 202 + allowedUDPPorts = [ 203 + 8301 204 + 8302 205 + 8500 206 + ]; 207 + }; 231 208 }
+42 -60
configs/container-bridge.nix
··· 129 129 ''; 130 130 }; 131 131 132 - # Firewall rules for container bridge 133 - krebs.iptables.tables.filter.FORWARD.rules = [ 134 - # IPv6 forwarding for containers 135 - { 136 - v4 = false; 137 - v6 = true; 138 - predicate = "-i ctr0"; 139 - target = "ACCEPT"; 140 - } 141 - { 142 - v4 = false; 143 - v6 = true; 144 - predicate = "-o ctr0 -m conntrack --ctstate RELATED,ESTABLISHED"; 145 - target = "ACCEPT"; 146 - } 147 - # IPv4 forwarding for NAT64 translated packets 148 - { 149 - v4 = true; 150 - v6 = false; 151 - predicate = "-m conntrack --ctstate RELATED,ESTABLISHED"; 152 - target = "ACCEPT"; 153 - } 154 - { 155 - v4 = true; 156 - v6 = false; 157 - predicate = ""; 158 - target = "ACCEPT"; 159 - } 160 - ]; 132 + # Firewall rules for container bridge: IPv6 from the containers, and the 133 + # IPv4 side of NAT64 (packets Jool translated). 134 + networking.firewall.extraForwardRules = '' 135 + iifname "ctr0" meta nfproto ipv6 accept 136 + meta nfproto ipv4 accept 137 + ''; 138 + 139 + # Allow containers to reach host's DNS64 resolver (IPv6 only) 140 + networking.firewall.extraInputRules = '' 141 + ip6 saddr fd00:c700::/64 meta l4proto { tcp, udp } th dport 53 accept 142 + ''; 161 143 162 144 # NAT66 - masquerade container IPv6 to reach public IPv6 (when host has IPv6) 163 145 # Note: No IPv4 MASQUERADE needed - jool does SNAT with pool4 address for NAT64 traffic 164 - krebs.iptables.tables.nat.POSTROUTING.rules = [ 165 - { 166 - v4 = false; 167 - v6 = true; 168 - predicate = "-s fd00:c700::/64 ! -d fd00:c700::/64"; 169 - target = "MASQUERADE"; 170 - } 171 - ]; 172 - 173 - # Allow containers to reach host's DNS64 resolver (IPv6 only) 174 - krebs.iptables.tables.filter.INPUT.rules = [ 175 - { 176 - v4 = false; 177 - v6 = true; 178 - predicate = "-s fd00:c700::/64 -p udp --dport 53"; 179 - target = "ACCEPT"; 180 - } 181 - { 182 - v4 = false; 183 - v6 = true; 184 - predicate = "-s fd00:c700::/64 -p tcp --dport 53"; 185 - target = "ACCEPT"; 186 - } 187 - ]; 146 + networking.nftables.tables.container-bridge = { 147 + family = "ip6"; 148 + content = '' 149 + chain postrouting { 150 + type nat hook postrouting priority srcnat; policy accept; 151 + ip6 saddr fd00:c700::/64 ip6 daddr != fd00:c700::/64 masquerade 152 + } 153 + ''; 154 + }; 188 155 189 156 # Send only container traffic to Jool NAT64 (--iptables mode) 190 157 # Host traffic to 64:ff9b::/96 passes through to upstream NAT64 (e.g., Android hotspot) 191 - krebs.iptables.tables.mangle.PREROUTING.rules = [ 158 + # JOOL is an xtables target, nftables has no equivalent; ip6tables (the 159 + # nft backend) loads it through nft_compat into the ip6 mangle table. 160 + systemd.services.jool-iptables = 161 + let 162 + rule = "PREROUTING -i ctr0 -d 64:ff9b::/96 -j JOOL"; 163 + in 192 164 { 193 - v4 = false; 194 - v6 = true; 195 - predicate = "-i ctr0 -d 64:ff9b::/96"; 196 - target = "JOOL"; 197 - } 198 - ]; 165 + description = "Send container traffic to Jool NAT64"; 166 + after = [ 167 + "jool.service" 168 + "nftables.service" 169 + ]; 170 + requires = [ "jool.service" ]; 171 + wantedBy = [ "multi-user.target" ]; 172 + path = [ pkgs.iptables ]; 173 + environment.XTABLES_LIBDIR = "${pkgs.jool-cli}/lib/xtables"; 174 + serviceConfig = { 175 + Type = "oneshot"; 176 + RemainAfterExit = true; 177 + }; 178 + script = "ip6tables -t mangle -C ${rule} 2>/dev/null || ip6tables -t mangle -A ${rule}"; 179 + preStop = "ip6tables -t mangle -D ${rule} || true"; 180 + }; 199 181 }
+28 -27
configs/default.nix
··· 30 30 31 31 # Import stockholm modules 32 32 ./kartei.nix 33 - self.inputs.stockholm.nixosModules.iptables 34 33 self.inputs.stockholm.nixosModules.sitemap 35 34 self.inputs.stockholm.nixosModules.ssl 36 35 { ··· 263 262 Storage = "persistent"; 264 263 }; 265 264 266 - krebs.iptables = { 265 + # nftables based NixOS firewall. Input and forward drop by default, as 266 + # krebs.iptables did; no reverse path filter either, the routers, 267 + # container hosts and NAT64 boxes route asymmetrically. 268 + networking.nftables = { 267 269 enable = true; 268 - tables = { 269 - filter.INPUT.policy = "DROP"; 270 - filter.FORWARD.policy = lib.mkDefault "DROP"; 271 - filter.INPUT.rules = lib.mkMerge [ 272 - (lib.mkBefore [ 273 - { 274 - predicate = "-m conntrack --ctstate RELATED,ESTABLISHED"; 275 - target = "ACCEPT"; 276 - } 277 - { 278 - predicate = "-p icmp"; 279 - target = "ACCEPT"; 280 - } 281 - { 282 - predicate = "-p ipv6-icmp"; 283 - target = "ACCEPT"; 284 - v4 = false; 285 - } 286 - { 287 - predicate = "-i lo"; 288 - target = "ACCEPT"; 289 - } 290 - ]) 291 - ]; 292 - }; 270 + # Defaults to true on machines older than 23.11, which would also wipe 271 + # the tables libvirt, podman and jool keep on every reload. 272 + flushRuleset = false; 273 + # krebs.iptables loaded its rules through iptables-nft into these 274 + # tables; nothing removes them when it goes away. Drop once every 275 + # machine has switched to nftables. 276 + extraDeletions = '' 277 + table ip filter 278 + delete table ip filter 279 + table ip6 filter 280 + delete table ip6 filter 281 + table ip nat 282 + delete table ip nat 283 + table ip6 nat 284 + delete table ip6 nat 285 + ''; 286 + }; 287 + networking.firewall = { 288 + filterForward = lib.mkDefault true; 289 + checkReversePath = false; 290 + # all of ICMP, not just echo-request, like krebs.iptables 291 + extraInputRules = '' 292 + meta l4proto icmp accept 293 + ''; 293 294 }; 294 295 295 296 networking.firewall.allowedTCPPorts = [ 22 ]; # ssh
+17 -41
configs/gg23.nix
··· 1 - { lib, pkgs, ... }: 1 + { pkgs, ... }: 2 2 { 3 3 # vodafone router drifts out of time 4 4 services.timesyncd.servers = [ ··· 90 90 ]; 91 91 }; 92 92 networking.networkmanager.unmanaged = [ "int0" ]; 93 - krebs.iptables.tables.filter.INPUT.rules = [ 94 - { 95 - predicate = "-i int0"; 96 - target = "ACCEPT"; 97 - } 98 - ]; 99 - krebs.iptables.tables.filter.FORWARD.rules = [ 100 - { 101 - predicate = "-i int0"; 102 - target = "ACCEPT"; 103 - } 104 - { 105 - predicate = "-o int0"; 106 - target = "ACCEPT"; 107 - } 108 - { 109 - predicate = "-p ipv6-icmp"; 110 - target = "ACCEPT"; 111 - v4 = false; 112 - } 113 - ]; 114 - krebs.iptables.tables.nat.PREROUTING.rules = lib.mkBefore [ 115 - { 116 - v6 = false; 117 - predicate = "-s 10.42.0.0/24"; 118 - target = "ACCEPT"; 119 - } 120 - ]; 121 - krebs.iptables.tables.nat.POSTROUTING.rules = [ 122 - { 123 - v6 = false; 124 - predicate = "-s 10.42.0.0/24"; 125 - target = "MASQUERADE"; 126 - } 127 - { 128 - v4 = false; 129 - predicate = "-s fd42:7d6a::/64"; 130 - target = "MASQUERADE"; 131 - } 132 - ]; 93 + networking.firewall.trustedInterfaces = [ "int0" ]; 94 + # ICMPv6 is forwarded by nixos-fw's forward chain already. 95 + networking.firewall.extraForwardRules = '' 96 + iifname "int0" accept 97 + oifname "int0" accept 98 + ''; 99 + networking.nftables.tables.gg23 = { 100 + family = "inet"; 101 + content = '' 102 + chain postrouting { 103 + type nat hook postrouting priority srcnat; policy accept; 104 + ip saddr 10.42.0.0/24 masquerade 105 + ip6 saddr fd42:7d6a::/64 masquerade 106 + } 107 + ''; 108 + }; 133 109 134 110 networking.domain = "gg23"; 135 111
+2 -10
configs/n8n.nix
··· 8 8 environment.N8N_SECURE_COOKIE = "false"; 9 9 }; 10 10 11 - krebs.iptables.tables.filter.INPUT.rules = [ 12 - { 13 - predicate = "-i retiolum -p tcp --dport 5678"; 14 - target = "ACCEPT"; 15 - } 16 - { 17 - predicate = "-i wiregrill -p tcp --dport 5678"; 18 - target = "ACCEPT"; 19 - } 20 - ]; 11 + networking.firewall.interfaces.retiolum.allowedTCPPorts = [ 5678 ]; 12 + networking.firewall.interfaces.wiregrill.allowedTCPPorts = [ 5678 ]; 21 13 }
+1 -6
configs/paste.nix
··· 189 189 (. ${stockholmPkgs.htgen-cyberlocker}/bin/htgen-cyberlocker) 190 190 ''; 191 191 }; 192 - krebs.iptables.tables.filter.INPUT.rules = [ 193 - { 194 - predicate = "-i retiolum -p tcp --dport 80"; 195 - target = "ACCEPT"; 196 - } 197 - ]; 192 + networking.firewall.interfaces.retiolum.allowedTCPPorts = [ 80 ]; 198 193 }
+18 -26
configs/riot.nix
··· 63 63 64 64 boot.kernel.sysctl."net.ipv4.ip_forward" = lib.mkDefault 1; 65 65 66 - krebs.iptables.tables.nat.POSTROUTING.rules = [ 67 - { 68 - v6 = false; 69 - predicate = "-s ${config.containers.riot.localAddress}"; 70 - target = "MASQUERADE"; 71 - } 72 - ]; 73 - 74 - # networking.nat can be used instead of this 75 - krebs.iptables.tables.nat.PREROUTING.rules = [ 76 - { 77 - predicate = "-p tcp --dport 45622"; 78 - target = "DNAT --to-destination ${config.containers.riot.localAddress}:22"; 79 - v6 = false; 80 - } 81 - ]; 82 - krebs.iptables.tables.filter.FORWARD.rules = [ 83 - { 84 - predicate = "-i ve-riot"; 85 - target = "ACCEPT"; 86 - } 87 - { 88 - predicate = "-o ve-riot"; 89 - target = "ACCEPT"; 90 - } 91 - ]; 66 + networking.firewall.extraForwardRules = '' 67 + iifname "ve-riot" accept 68 + oifname "ve-riot" accept 69 + ''; 70 + # ssh into the container on 45622 71 + networking.nftables.tables.riot = { 72 + family = "ip"; 73 + content = '' 74 + chain prerouting { 75 + type nat hook prerouting priority dstnat; policy accept; 76 + tcp dport 45622 dnat to ${config.containers.riot.localAddress}:22 77 + } 78 + chain postrouting { 79 + type nat hook postrouting priority srcnat; policy accept; 80 + ip saddr ${config.containers.riot.localAddress} masquerade 81 + } 82 + ''; 83 + }; 92 84 93 85 # non container stuff 94 86
+20 -28
configs/ssh-redirect.nix
··· 1 + # Public ssh is on 45621; port 22 itself only answers on the VPNs (and lo). 1 2 { 2 - krebs.iptables = { 3 - enable = true; 4 - tables = { 5 - nat.PREROUTING.rules = [ 6 - { 7 - predicate = "-i retiolum -p tcp -m tcp --dport 22"; 8 - target = "ACCEPT"; 9 - } 10 - { 11 - predicate = "-i wiregrill -p tcp -m tcp --dport 22"; 12 - target = "ACCEPT"; 13 - } 14 - { 15 - predicate = "-p tcp -m tcp --dport 22"; 16 - target = "REDIRECT --to-ports 0"; 17 - } 18 - { 19 - predicate = "-p tcp -m tcp --dport 45621"; 20 - target = "REDIRECT --to-ports 22"; 21 - } 22 - ]; 23 - nat.OUTPUT.rules = [ 24 - { 25 - predicate = "-o lo -p tcp -m tcp --dport 45621"; 26 - target = "REDIRECT --to-ports 22"; 27 - } 28 - ]; 29 - }; 3 + networking.nftables.tables.ssh-redirect = { 4 + family = "inet"; 5 + content = '' 6 + chain prerouting { 7 + type nat hook prerouting priority dstnat; policy accept; 8 + tcp dport 45621 redirect to :22 9 + } 10 + chain output { 11 + type nat hook output priority dstnat; policy accept; 12 + oifname "lo" tcp dport 45621 redirect to :22 13 + } 14 + # Runs before nixos-fw, which accepts 22 everywhere. Connections that 15 + # came in on 45621 have been redirected to 22 already, so match the 16 + # port the client asked for. 17 + chain input { 18 + type filter hook input priority filter - 1; policy accept; 19 + ct state new meta l4proto tcp ct original proto-dst 22 iifname != { "lo", "retiolum", "wiregrill" } reject with tcp reset 20 + } 21 + ''; 30 22 }; 31 23 }
+14 -23
modules/sync-containers3.nix
··· 303 303 Name = "ctr0"; 304 304 }; 305 305 networking.networkmanager.unmanaged = [ "ctr0" ]; 306 - krebs.iptables.tables.filter.INPUT.rules = [ 307 - { 308 - predicate = "-i ctr0"; 309 - target = "ACCEPT"; 310 - } 311 - ]; 312 - krebs.iptables.tables.filter.FORWARD.rules = [ 313 - { 314 - predicate = "-i ctr0"; 315 - target = "ACCEPT"; 316 - } 317 - { 318 - predicate = "-o ctr0"; 319 - target = "ACCEPT"; 320 - } 321 - ]; 322 - krebs.iptables.tables.nat.POSTROUTING.rules = [ 323 - { 324 - v6 = false; 325 - predicate = "-s 10.233.0.0/24"; 326 - target = "MASQUERADE"; 327 - } 328 - ]; 306 + networking.firewall.trustedInterfaces = [ "ctr0" ]; 307 + networking.firewall.extraForwardRules = '' 308 + iifname "ctr0" accept 309 + oifname "ctr0" accept 310 + ''; 311 + networking.nftables.tables.sync-containers3 = { 312 + family = "ip"; 313 + content = '' 314 + chain postrouting { 315 + type nat hook postrouting priority srcnat; policy accept; 316 + ip saddr 10.233.0.0/24 masquerade 317 + } 318 + ''; 319 + }; 329 320 }) 330 321 (lib.mkIf cfg.inContainer.enable { 331 322 users.groups.container_sync = { };
+14 -34
configs/hass/default.nix
··· 4 4 ./zigbee.nix 5 5 ]; 6 6 7 - krebs.iptables.tables.filter.INPUT.rules = [ 8 - { 9 - predicate = "-i et0 -p tcp --dport 1883"; 10 - target = "ACCEPT"; 11 - } # mosquitto 12 - { 13 - predicate = "-i docker0 -p tcp --dport 1883"; 14 - target = "ACCEPT"; 15 - } # mosquitto 16 - { 17 - predicate = "-i et0 -p tcp --dport 8123"; 18 - target = "ACCEPT"; 19 - } # hass 20 - { 21 - predicate = "-i et0 -p tcp --dport 1337"; 22 - target = "ACCEPT"; 23 - } # zigbee2mqtt frontend 24 - { 25 - predicate = "-i retiolum -p tcp --dport 8123"; 26 - target = "ACCEPT"; 27 - } # hass 28 - { 29 - predicate = "-i retiolum -p tcp --dport 1337"; 30 - target = "ACCEPT"; 31 - } # zigbee2mqtt frontend 32 - { 33 - predicate = "-i wiregrill -p tcp --dport 8123"; 34 - target = "ACCEPT"; 35 - } # hass 36 - { 37 - predicate = "-i zttzibeakb -p tcp --dport 8123"; 38 - target = "ACCEPT"; 39 - } # hass 40 - ]; 7 + networking.firewall.interfaces = { 8 + et0.allowedTCPPorts = [ 9 + 1883 # mosquitto 10 + 8123 # hass 11 + 1337 # zigbee2mqtt frontend 12 + ]; 13 + docker0.allowedTCPPorts = [ 1883 ]; # mosquitto 14 + retiolum.allowedTCPPorts = [ 15 + 8123 # hass 16 + 1337 # zigbee2mqtt frontend 17 + ]; 18 + wiregrill.allowedTCPPorts = [ 8123 ]; # hass 19 + zttzibeakb.allowedTCPPorts = [ 8123 ]; # hass 20 + }; 41 21 42 22 systemd.services.hass-update = { 43 23 startAt = "daily";
+1 -6
machines/daedalus/config.nix
··· 91 91 x11vnc 92 92 # torbrowser 93 93 ]; 94 - krebs.iptables.tables.filter.INPUT.rules = [ 95 - { 96 - predicate = "-p tcp -i retiolum --dport 5900"; 97 - target = "ACCEPT"; 98 - } 99 - ]; 94 + networking.firewall.interfaces.retiolum.allowedTCPPorts = [ 5900 ]; 100 95 } 101 96 ]; 102 97
-7
machines/green/config.nix
··· 60 60 "L+ /var/lib/zerotier-one - - - - ../../var/state/zerotier-one" 61 61 ]; 62 62 63 - krebs.iptables.tables.nat.PREROUTING.rules = [ 64 - { 65 - predicate = "-i eth0 -p tcp -m tcp --dport 22"; 66 - target = "ACCEPT"; 67 - } 68 - ]; 69 - 70 63 # workaround for ssh access from yubikey via android 71 64 services.openssh.extraConfig = '' 72 65 HostKeyAlgorithms +ssh-rsa
+1 -3
machines/icarus/config.nix
··· 20 20 # enable = true; 21 21 # defaultWindowManager = "xmonad"; 22 22 # }; 23 - # krebs.iptables.tables.filter.INPUT.rules = [ 24 - # { predicate = "-p tcp --dport 3389"; target = "ACCEPT"; } # xrdp 25 - # ]; 23 + # networking.firewall.allowedTCPPorts = [ 3389 ]; # xrdp 26 24 27 25 environment.systemPackages = [ pkgs.chromium ]; 28 26
+5 -13
machines/neoprism/config.nix
··· 159 159 160 160 # riot VM (HFOS): fresh libvirt guest on a dedicated bridged public IP. 161 161 # Bridged onto ext-br with its own Hetzner MAC, so libvirt manages no 162 - # iptables for it -> no nat-chain race, no restart-iptables hack (cf. hfos.nix). 162 + # firewall rules for it -> no nat-chain race, no restart-iptables hack (cf. hfos.nix). 163 163 virtualisation.libvirtd.enable = true; 164 164 security.polkit.enable = true; 165 165 users.users.riot = { ··· 170 170 ]; 171 171 }; 172 172 # the only forwarding the VM needs: accept traffic to/from its public IP. 173 - krebs.iptables.tables.filter.FORWARD.rules = lib.mkBefore [ 174 - { 175 - v6 = false; 176 - predicate = "--destination 95.217.192.52"; 177 - target = "ACCEPT"; 178 - } 179 - { 180 - v6 = false; 181 - predicate = "--source 95.217.192.52"; 182 - target = "ACCEPT"; 183 - } 184 - ]; 173 + networking.firewall.extraForwardRules = '' 174 + ip daddr 95.217.192.52 accept 175 + ip saddr 95.217.192.52 accept 176 + ''; 185 177 186 178 # tank/radicle (radicle seed storage) is created by disko at install; on an 187 179 # already-provisioned host it must be created before deploying:
+10 -10
configs/services/flix/default.nix
··· 367 367 4001 # smbd 368 368 4002 # smbd 369 369 ]; 370 - krebs.iptables = { 371 - enable = true; 372 - tables.nat.PREROUTING.rules = [ 373 - # transmission rpc port 374 - { 375 - predicate = "-i retiolum -p tcp --dport 9091"; 376 - target = "DNAT --to-destination fdb4:3310:947::2"; 377 - v4 = false; 370 + # we need this so we can forward into the the transmission network namespace 371 + networking.firewall.filterForward = false; 372 + # transmission rpc port 373 + networking.nftables.tables.flix = { 374 + family = "ip6"; 375 + content = '' 376 + chain prerouting { 377 + type nat hook prerouting priority dstnat; policy accept; 378 + iifname "retiolum" tcp dport 9091 dnat to fdb4:3310:947::2 378 379 } 379 - ]; 380 - tables.filter.FORWARD.policy = "ACCEPT"; # we need this so we can forward into the the transmission network namespace 380 + ''; 381 381 }; 382 382 383 383 systemd.services.flix-index = {