{ secret, inputs', pkgs, lib, ... }: { networking.notnft.postStop = '' if systemctl status podman ; then ${lib.getExe' pkgs.podman "podman"} network reload -a fi ''; networking.notnft.postStart = '' if systemctl status podman ; then ${lib.getExe' pkgs.podman "podman"} network reload -a fi ''; networking.notnft.rules = let notnft = inputs'.notnft.lib.${pkgs.stdenv.system}; logRule = with notnft.dsl; with payload; prefix: [ (log { prefix = "${prefix} dropped: "; flags = f: [f.all]; }) ]; traceChain = with notnft.dsl; with payload; add chain [(is.eq th.dport 53) (mangle meta.nftrace 1)] [(is.eq th.dport 53) (mangle meta.nftrace 1)] [(is.eq th.dport 22) (mangle meta.nftrace 1)] [(is.eq th.sport 22) (mangle meta.nftrace 1)] [(is.eq meta.oifname "uk3s0") (mangle meta.nftrace 1)] [(is.eq meta.iifname "uk3s0") (mangle meta.nftrace 1)]; in with notnft.dsl; with payload; ruleset { filter = add table {family = f: f.inet;} { trace = traceChain; ### lo input-lo = add chain [accept]; output-lo = add chain [accept]; ### ### mvm input-mvm = add chain; output-mvm = add chain [(is.eq ip.protocol (f: f.icmp)) (is.eq ip.saddr "10.80.1.1") (is.eq ip.daddr "10.80.1.2") accept] [(is.eq ip.protocol (f: f.icmp)) (is.eq ip.saddr "10.80.1.2") (is.eq ip.daddr "10.80.1.1") accept] [(is.eq ip.protocol (f: with f; set [tcp])) (is.eq th.dport 22) (is.eq ip.saddr "10.80.1.1") (is.eq ip.daddr "10.80.1.2") accept] [(is.eq ip.protocol (f: with f; set [tcp])) (is.eq th.dport 80) (is.eq ip.saddr "10.80.1.1") (is.eq ip.daddr "10.80.1.2") accept]; ### ### input-uk3s = add chain; output-uk3s = add chain [(is.eq ip.daddr (cidr "10.50.0.0/22")) accept]; ### wlan0 input-wlan0 = add chain [(is.eq ip.protocol (f: f.tcp)) (is.eq th.dport "8080") accept] [(is.eq ip.protocol (f: f.udp)) (is.eq th.dport "20111") accept] [(is.eq ip.protocol (f: f.tcp)) (is.eq th.dport "27036") accept] [(is.eq ip.protocol (f: f.udp)) (is.eq th.dport (set [27031 27032 27033 27034 27035 27036])) accept]; output-wlan0 = add chain [(is.ne ip.daddr (secret.network.ips.blowhole.ip or "")) (is.eq ip.protocol (f: with f; set [tcp udp])) (is.eq th.dport 53) drop] [accept]; ### ### wlan0 input-eth0 = add chain; output-eth0 = add chain [(is.ne ip.daddr (secret.network.ips.blowhole.ip or "")) (is.eq ip.protocol (f: with f; set [tcp udp])) (is.eq th.dport 53) drop] [accept]; ### ### wg0 input-wg0 = add chain # accept syncthing sharing [(is.eq ip.protocol (f: f.udp)) (is.eq th.sport "22000") (is.eq th.dport "22000") accept] [(is.eq ip.protocol (f: f.tcp)) (is.eq th.dport "22000") accept] [(is.eq ip.protocol (f: f.icmp)) accept]; output-wg0 = add chain # TCP, UDP 53 to blowhole [(is.eq ip.protocol (f: with f; set [udp tcp])) (is.eq th.dport 53) (is.eq ip.saddr (secret.network.ips.omen.vpn or "")) (is.eq ip.daddr (secret.network.ips.blowhole.ip or "")) accept] # TCP 22, 80, 4646, 8200, 8500, 2049 to blowhole [(is.eq ip.protocol (f: with f; set [tcp])) (is.eq th.dport (set [22 80 4646 8200 8500 2049])) (is.eq ip.saddr (secret.network.ips.omen.vpn or "")) (is.eq ip.daddr (secret.network.ips.blowhole.ip or "")) accept] # NFS services to blowhole [(is.eq ip.protocol (f: with f; set [tcp udp])) (is.eq th.dport (set [111 2049 4000 4002 20048])) (is.eq ip.saddr (secret.network.ips.omen.vpn or "")) (is.eq ip.daddr (secret.network.ips.blowhole.ip or "")) accept] # TCP 22, 4646, 8200 toothpick [(is.eq ip.protocol (f: with f; set [tcp])) (is.eq th.dport (set [22 4646 8200])) (is.eq ip.saddr (secret.network.ips.omen.vpn or "")) (is.eq ip.daddr (secret.network.ips.toothpick or "")) accept] # TCP 22 altra [(is.eq ip.protocol (f: with f; set [tcp])) (is.eq th.dport (set [22])) (is.eq ip.saddr (secret.network.ips.omen.vpn or "")) (is.eq ip.daddr (secret.network.ips.altra.ip or "")) accept] # ICMP to blowhole, toothpick, altra [(is.eq ip.protocol (f: f.icmp)) (is.eq ip.saddr (secret.network.ips.omen.vpn or "")) (is.eq ip.daddr (set [(secret.network.ips.toothpick or "") (secret.network.ips.altra.ip or "") (secret.network.ips.blowhole.ip or "")])) accept] [(is.eq ip.protocol (f: f.tcp)) (is.eq th.dport 8883) (is.eq ip.saddr (secret.network.ips.omen.vpn or "")) (is.eq ip.daddr (secret.network.ips.altra.ip or "")) accept] # accept syncthing sharing [(is.eq ip.protocol (f: f.tcp)) (is.eq th.dport 554) (is.eq ip.saddr (secret.network.ips.omen.vpn or "")) (is.eq ip.daddr "10.64.2.128") accept] [(is.eq ip.protocol (f: f.udp)) (is.eq th.sport "22000") (is.eq th.dport "22000") accept] [(is.eq ip.protocol (f: f.tcp)) (is.eq th.dport "22000") accept]; ### input = add chain { type = f: f.filter; hook = f: f.input; prio = -300; policy = f: f.drop; } # accept related, established and drop invalid [ (vmap ct.state { established = accept; related = accept; invalid = drop; }) ] # # accept icmp between the same IP # [ (is.eq ip.protocol (f: f.icmp)) (is.eq ip.daddr ip.saddr) accept ] [(jump "trace")] [(is.eq meta.iifname "wlan0") (jump "input-wlan0")] [(is.eq meta.iifname "eth0") (jump "input-eth0")] [(is.eq meta.iifname "mvm0") (jump "input-mvm")] [(is.eq meta.iifname "lo") (jump "input-lo")] [(is.eq meta.iifname "wg0") (jump "input-wg0")] [(is.eq meta.iifname "uk3s0") (jump "input-uk3s")] [(is.eq ip.protocol (f: f.icmp)) accept] (logRule "Input"); output = add chain { type = f: f.filter; hook = f: f.output; prio = -300; policy = f: f.drop; } [(jump "trace")] [(is.eq meta.oifname "wlan0") (jump "output-wlan0")] [(is.eq meta.oifname "eth0") (jump "output-eth0")] [(is.eq meta.oifname "lo") (jump "output-lo")] [(is.eq meta.oifname "mvm0") (jump "output-mvm")] [(is.eq meta.oifname "wg0") (jump "output-wg0")] [(is.eq meta.oifname "uk3s0") (jump "output-uk3s")] (logRule "Output"); forward = add chain { type = f: f.filter; hook = f: f.forward; prio = -300; policy = f: f.drop; } [(jump "trace")] # accept masquaraded packets incoming from wg0 [ (is.eq meta.iifname (set ["wg0" "wlan0" "eth0"])) (vmap ct.state { established = accept; related = accept; }) ] # accept TCP, UDP 53 from 10.80.1.2 to blowhole [(is.eq meta.iifname "mvm0") (is.eq meta.oifname "wg0") (is.eq ip.protocol (f: with f; set [tcp udp])) (is.eq th.dport 53) (is.eq ip.saddr "10.80.1.2") (is.eq ip.daddr (secret.network.ips.blowhole.ip or "")) accept] # accept TCP, UDP 53 from 10.80.1.2 to blowhole [(is.eq meta.iifname "podman0") (is.eq meta.oifname "wg0") (is.eq ip.protocol (f: with f; set [tcp udp])) (is.eq th.dport 53) (is.eq ip.daddr (secret.network.ips.blowhole.ip or "")) accept] [(is.eq meta.iifname "uk3s0") (is.eq meta.oifname "wg0") (is.eq ip.protocol (f: with f; set [tcp udp])) (is.eq th.dport 53) (is.eq ip.daddr (secret.network.ips.blowhole.ip or "")) accept] [(is.eq meta.iifname "uk3s0") (is.eq meta.oifname (set ["wlan0" "eth0"])) accept] (logRule "Forward"); prerouting = add chain { type = f: f.nat; hook = f: f.prerouting; prio = -199; policy = f: f.accept; } [(jump "trace")]; postrouting = add chain { type = f: f.nat; hook = f: f.postrouting; prio = -199; policy = f: f.accept; } [(jump "trace")] # masquarade from 10.80.1.2 heading to wg0 [(is.eq meta.iifname "mvm0") (is.eq meta.oifname "wg0") (is.eq ip.saddr (set ["10.80.1.2"])) masquerade] [(is.eq meta.iifname "uk3s0") (is.eq meta.oifname "wg0") (is.eq ip.saddr (cidr "10.50.0.0/22")) masquerade] [(is.eq meta.iifname "uk3s0") (is.eq meta.oifname (set ["wlan0" "eth0"])) (is.eq ip.saddr (cidr "10.50.0.0/22")) masquerade]; }; bridge-t = add table {family = f: f.bridge;} { trace = traceChain; input-body = add chain; input = add chain { type = f: f.filter; hook = f: f.input; prio = f: f.filter; policy = f: f.drop; } [(jump "trace")] [ (vmap ct.state { established = accept; related = accept; invalid = drop; }) ] [(is.eq meta.protocol (f: f.arp)) accept] [(is.eq meta.iifname "veth0") (is.eq ip.daddr (secret.network.ips.blowhole.ip or "")) (is.eq ip.protocol (f: with f; set [tcp udp])) (is.eq th.dport 53) accept] [(jump "input-body")] (logRule "Bridge input"); output-body = add chain; output = add chain { type = f: f.filter; hook = f: f.output; prio = f: f.out; policy = f: f.drop; } [(jump "trace")] [(is.eq ether.type (f: f.arp)) accept] [(jump "output-body")] [(is.eq ip.daddr (cidr "10.88.0.0" 16)) (is.eq ip.saddr (cidr "10.88.0.0" 16)) accept] (logRule "Bridge output"); forward-body = add chain; forward = add chain { type = f: f.filter; hook = f: f.forward; prio = f: f.filter; policy = f: f.drop; } [(jump "trace")] [(jump "forward-body")] (logRule "Bridge forward"); prerouting = add chain { type = f: f.filter; hook = f: f.prerouting; prio = f: f.dstnat; policy = f: f.accept; }; postrouting = add chain { type = f: f.filter; hook = f: f.postrouting; prio = f: f.srcnat; policy = f: f.accept; }; }; }; }