From 19fabe369c24d72a8ccddd1188bbe45fd5f94cb4 Mon Sep 17 00:00:00 2001 From: mkl Date: Tue, 18 Nov 2025 20:07:10 -0500 Subject: [PATCH 01/23] added default ipv6 gateway --- hosts/zerocool/configuration.nix | 1 + hosts/zerocool/router.nix | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/hosts/zerocool/configuration.nix b/hosts/zerocool/configuration.nix index 9bb16c2..d57b823 100644 --- a/hosts/zerocool/configuration.nix +++ b/hosts/zerocool/configuration.nix @@ -19,6 +19,7 @@ in (import ./router.nix { inherit wan_iface lan_iface lan_addr lan_cidr wg_iface; wan_gateway = "198.82.185.129"; + wan_gateway6 = "2001:468:c80:6119::1"; wan_addr = "198.82.185.170"; wan_cidr = 22; wan_addr6 = "2001:468:c80:6119:82c1:6eff:fe21:2b88"; diff --git a/hosts/zerocool/router.nix b/hosts/zerocool/router.nix index 3164bfc..3adbef7 100644 --- a/hosts/zerocool/router.nix +++ b/hosts/zerocool/router.nix @@ -1,4 +1,4 @@ -{ wan_gateway, wan_iface, wan_addr, wan_cidr, wan_addr6, wan_cidr6, lan_iface, lan_addr, lan_cidr, wg_iface, ... }: +{ wan_gateway, wan_gateway6, wan_iface, wan_addr, wan_cidr, wan_addr6, wan_cidr6, lan_iface, lan_addr, lan_cidr, wg_iface, ... }: { boot.kernel.sysctl = { "net.ipv4.conf.all.forwarding" = true; @@ -12,6 +12,10 @@ networking.useDHCP = false; networking.defaultGateway = wan_gateway; + networking.defaultGateway6 = { + address = wan_gateway6; + interface = wan_iface; + }; networking.interfaces = { "${wan_iface}" = { ipv4.addresses = [ From 52df1021ab8a67f169ab570e6f9939415fa18aba Mon Sep 17 00:00:00 2001 From: mkl Date: Fri, 5 Dec 2025 00:23:16 -0500 Subject: [PATCH 02/23] hosts/zerocool: changed zerocool networking configuration to use a pretty nix attrset --- hosts/zerocool/configuration.nix | 78 ++++++++++++++++++++++++++++---- hosts/zerocool/lan.nix | 39 ++++++++++++++++ hosts/zerocool/router.nix | 34 +------------- hosts/zerocool/wan.nix | 26 +++++++++++ 4 files changed, 135 insertions(+), 42 deletions(-) create mode 100644 hosts/zerocool/lan.nix create mode 100644 hosts/zerocool/wan.nix diff --git a/hosts/zerocool/configuration.nix b/hosts/zerocool/configuration.nix index d57b823..1ab73e6 100644 --- a/hosts/zerocool/configuration.nix +++ b/hosts/zerocool/configuration.nix @@ -1,10 +1,68 @@ { config, lib, pkgs, ... }: let wan_iface = "enp3s0f0"; - lan_iface = "enp3s0f1"; + wan = { + ipv4 = { + gateway = "198.82.185.129"; + address = "198.82.185.170"; + cidr = 22; + }; + ipv6 = { + gateway = "2001:468:c80:6119::1"; + address = "2001:468:c80:6119:82c1:6eff:fe21:2b88"; + cidr = 60; + }; + }; + wg_iface = "wg0"; - lan_addr = "10.98.4.1"; - lan_cidr = 22; + + lan_iface = "enp3s0f1"; + lan = { + # Static hosts + "10" = { + ipv4 = { + address = "10.98.4.1"; + cidr = 24; + }; + ipv6 = { + address = "2607:b400:c:ce80::1"; + cidr = 64; + }; + }; + # Dynamic host + "20" = { + ipv4 = { + address = "10.98.5.1"; + cidr = 24; + }; + ipv6 = { + address = "2607:b400:c:ce81::1"; + cidr = 64; + }; + }; + # Co-location stuff + "30" = { + ipv4 = { + address = "10.98.6.1"; + cidr = 24; + }; + ipv6 = { + address = "2607:b400:c:ce82::1"; + cidr = 64; + }; + }; + # Management + "40" = { + ipv4 = { + address = "10.98.7.1"; + cidr = 24; + }; + ipv6 = { + address = "2607:b400:c:ce83::1"; + cidr = 64; + }; + }; + }; in { imports = @@ -17,13 +75,13 @@ in ./dns.nix (import ./router.nix { - inherit wan_iface lan_iface lan_addr lan_cidr wg_iface; - wan_gateway = "198.82.185.129"; - wan_gateway6 = "2001:468:c80:6119::1"; - wan_addr = "198.82.185.170"; - wan_cidr = 22; - wan_addr6 = "2001:468:c80:6119:82c1:6eff:fe21:2b88"; - wan_cidr6 = 64; + inherit wan_iface lan_iface wg_iface; + }) + (import ./lan.nix { + inherit lib lan_iface lan; + }) + (import ./wan.nix { + inherit wan_iface wan; }) (import ./firewall.nix { inherit lan_iface; diff --git a/hosts/zerocool/lan.nix b/hosts/zerocool/lan.nix new file mode 100644 index 0000000..753a5cd --- /dev/null +++ b/hosts/zerocool/lan.nix @@ -0,0 +1,39 @@ +{ + lib, + lan_iface, + lan, + ... +}: +{ + networking.vlans = builtins.listToAttrs ( + builtins.map (vlanid: { + name = "vlan${vlanid}"; + value = { + id = builtins.fromJSON vlanid; + interface = lan_iface; + }; + }) (builtins.attrNames lan) + ); + + # recursiveUpdate appends generated interface attrset with existing one to avoid overwriting existing configuration + networking.interfaces = builtins.listToAttrs ( + builtins.map (e: { + name = "vlan${e.fst}"; + value = { + useDHCP = false; + ipv4.addresses = [ + { + address = e.snd.ipv4.address; + prefixLength = e.snd.ipv4.cidr; + } + ]; + ipv6.addresses = [ + { + address = e.snd.ipv6.address; + prefixLength = e.snd.ipv6.cidr; + } + ]; + }; + }) (lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan)) + ); +} diff --git a/hosts/zerocool/router.nix b/hosts/zerocool/router.nix index 3adbef7..5b7e2ec 100644 --- a/hosts/zerocool/router.nix +++ b/hosts/zerocool/router.nix @@ -1,43 +1,13 @@ -{ wan_gateway, wan_gateway6, wan_iface, wan_addr, wan_cidr, wan_addr6, wan_cidr6, lan_iface, lan_addr, lan_cidr, wg_iface, ... }: +{ wan_iface, lan_iface, wg_iface, ... }: { boot.kernel.sysctl = { "net.ipv4.conf.all.forwarding" = true; "net.ipv6.conf.all.forwarding" = true; }; + networking.nat = { enable = true; externalInterface = wan_iface; internalInterfaces = [ lan_iface wg_iface ]; }; - - networking.useDHCP = false; - networking.defaultGateway = wan_gateway; - networking.defaultGateway6 = { - address = wan_gateway6; - interface = wan_iface; - }; - networking.interfaces = { - "${wan_iface}" = { - ipv4.addresses = [ - { - address = wan_addr; - prefixLength = wan_cidr; - } - ]; - ipv6.addresses = [ - { - address = wan_addr6; - prefixLength = wan_cidr6; - } - ]; - }; - "${lan_iface}" = { - ipv4.addresses = [ - { - address = lan_addr; - prefixLength = lan_cidr; - } - ]; - }; - }; } diff --git a/hosts/zerocool/wan.nix b/hosts/zerocool/wan.nix new file mode 100644 index 0000000..69ae4d1 --- /dev/null +++ b/hosts/zerocool/wan.nix @@ -0,0 +1,26 @@ +{ wan_iface, wan, ... }: +{ + networking.defaultGateway = wan.ipv4.gateway; + networking.defaultGateway6 = { + address = wan.ipv6.gateway; + interface = wan_iface; + }; + + networking.interfaces = { + "${wan_iface}" = { + useDHCP = false; + ipv4.addresses = [ + { + address = wan.ipv4.address; + prefixLength = wan.ipv4.cidr; + } + ]; + ipv6.addresses = [ + { + address = wan.ipv6.address; + prefixLength = wan.ipv6.cidr; + } + ]; + }; + }; +} From 8b418f69e1ad4e534bc35cff799fa318de4eb4d8 Mon Sep 17 00:00:00 2001 From: mkl Date: Fri, 5 Dec 2025 00:24:42 -0500 Subject: [PATCH 03/23] hosts/zerocool: removed outdated comment in lan declaration --- hosts/zerocool/lan.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/hosts/zerocool/lan.nix b/hosts/zerocool/lan.nix index 753a5cd..b4c0bfc 100644 --- a/hosts/zerocool/lan.nix +++ b/hosts/zerocool/lan.nix @@ -15,7 +15,6 @@ }) (builtins.attrNames lan) ); - # recursiveUpdate appends generated interface attrset with existing one to avoid overwriting existing configuration networking.interfaces = builtins.listToAttrs ( builtins.map (e: { name = "vlan${e.fst}"; From 4d0f8428f89fd2f5bb90959470a67db0cd803fdf Mon Sep 17 00:00:00 2001 From: mkl Date: Mon, 15 Dec 2025 14:19:30 -0500 Subject: [PATCH 04/23] hosts/zerocool: correct IPv6 prefix and added vlans to IPv4 NAT --- hosts/zerocool/configuration.nix | 10 +++++----- hosts/zerocool/router.nix | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/hosts/zerocool/configuration.nix b/hosts/zerocool/configuration.nix index 1ab73e6..681c390 100644 --- a/hosts/zerocool/configuration.nix +++ b/hosts/zerocool/configuration.nix @@ -25,7 +25,7 @@ let cidr = 24; }; ipv6 = { - address = "2607:b400:c:ce80::1"; + address = "2607:b400:6:ce80::1"; cidr = 64; }; }; @@ -36,7 +36,7 @@ let cidr = 24; }; ipv6 = { - address = "2607:b400:c:ce81::1"; + address = "2607:b400:6:ce81::1"; cidr = 64; }; }; @@ -47,7 +47,7 @@ let cidr = 24; }; ipv6 = { - address = "2607:b400:c:ce82::1"; + address = "2607:b400:6:ce82::1"; cidr = 64; }; }; @@ -58,7 +58,7 @@ let cidr = 24; }; ipv6 = { - address = "2607:b400:c:ce83::1"; + address = "2607:b400:6:ce83::1"; cidr = 64; }; }; @@ -75,7 +75,7 @@ in ./dns.nix (import ./router.nix { - inherit wan_iface lan_iface wg_iface; + inherit wan_iface wg_iface lan_iface lan; }) (import ./lan.nix { inherit lib lan_iface lan; diff --git a/hosts/zerocool/router.nix b/hosts/zerocool/router.nix index 5b7e2ec..7d2e0d2 100644 --- a/hosts/zerocool/router.nix +++ b/hosts/zerocool/router.nix @@ -1,4 +1,4 @@ -{ wan_iface, lan_iface, wg_iface, ... }: +{ wan_iface, wg_iface, lan_iface, lan, ... }: { boot.kernel.sysctl = { "net.ipv4.conf.all.forwarding" = true; @@ -8,6 +8,6 @@ networking.nat = { enable = true; externalInterface = wan_iface; - internalInterfaces = [ lan_iface wg_iface ]; + internalInterfaces = [ lan_iface wg_iface ] ++ builtins.map (vlanid: "vlan${vlanid}" ) (builtins.attrNames lan); }; } From e3a66d21c2fb5e80f8833ec577df8a1845fe7a7a Mon Sep 17 00:00:00 2001 From: Ralakus Date: Thu, 5 Mar 2026 02:20:59 -0500 Subject: [PATCH 05/23] hosts/zerocool: added firewall, untagged vlan, and dhcp configuration --- hosts/zerocool/configuration.nix | 99 ++++++++++------- hosts/zerocool/dhcp.nix | 42 ++++++-- hosts/zerocool/firewall.nix | 180 ++++++++++++++++++++++++++++++- hosts/zerocool/lan.nix | 91 +++++++++++----- hosts/zerocool/router.nix | 10 +- 5 files changed, 341 insertions(+), 81 deletions(-) diff --git a/hosts/zerocool/configuration.nix b/hosts/zerocool/configuration.nix index 681c390..7ecf5e6 100644 --- a/hosts/zerocool/configuration.nix +++ b/hosts/zerocool/configuration.nix @@ -1,4 +1,9 @@ -{ config, lib, pkgs, ... }: +{ + config, + lib, + pkgs, + ... +}: let wan_iface = "enp3s0f0"; wan = { @@ -14,11 +19,11 @@ let }; }; - wg_iface = "wg0"; + wg_iface = "wg0"; lan_iface = "enp3s0f1"; lan = { - # Static hosts + # Management "10" = { ipv4 = { address = "10.98.4.1"; @@ -28,8 +33,11 @@ let address = "2607:b400:6:ce80::1"; cidr = 64; }; + allow_router_access = true; + dhcpv4 = "10.98.4.128,10.98.4.254,12h"; + dhcpv6 = "ra-stateless,ra-names,12h"; }; - # Dynamic host + # Untagged (native) VLAN Internal Traffic "20" = { ipv4 = { address = "10.98.5.1"; @@ -39,8 +47,12 @@ let address = "2607:b400:6:ce81::1"; cidr = 64; }; + allow_router_access = true; + untagged = true; + dhcpv4 = "10.98.5.128,10.98.5.254,12h"; + dhcpv6 = "ra-stateless,ra-names,12h"; }; - # Co-location stuff + # General Hosts "30" = { ipv4 = { address = "10.98.6.1"; @@ -50,8 +62,11 @@ let address = "2607:b400:6:ce82::1"; cidr = 64; }; + allow_router_access = true; + dhcpv4 = "10.98.6.128,10.98.6.254,12h"; + dhcpv6 = "ra-stateless,ra-names,12h"; }; - # Management + # Co-location "40" = { ipv4 = { address = "10.98.7.1"; @@ -61,42 +76,54 @@ let address = "2607:b400:6:ce83::1"; cidr = 64; }; + allow_router_access = false; + dhcpv4 = "10.98.7.128,10.98.7.254,12h"; + dhcpv6 = "ra-stateless,ra-names,12h"; }; }; + + check_untagged = lib.asserts.assertMsg ( + builtins.length ( + builtins.filter (e: builtins.hasAttr "untagged" e.snd) ( + lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan) + ) + ) == 1 + ) "There must be exactly one untagged VLAN for LAN" lan; in { - imports = - [ - ./hardware-configuration.nix - ../common/nix.nix - ../common/sshd.nix - ../common/users-local.nix - ../common/tz-locale.nix + imports = [ + ./hardware-configuration.nix + ../common/nix.nix + ../common/sshd.nix + ../common/users-local.nix + ../common/tz-locale.nix - ./dns.nix - (import ./router.nix { - inherit wan_iface wg_iface lan_iface lan; - }) - (import ./lan.nix { - inherit lib lan_iface lan; - }) - (import ./wan.nix { - inherit wan_iface wan; - }) - (import ./firewall.nix { - inherit lan_iface; - }) - (import ./dhcp.nix { - inherit lan_iface; - dhcp_start = "10.98.5.1"; - dhcp_end = "10.98.5.127"; - }) - (import ./wireguard.nix { - inherit config wg_iface; - }) - ]; + ./dns.nix + ./router.nix + (import ./lan.nix { + inherit lib lan_iface lan; + }) + (import ./dhcp.nix { + inherit lib lan_iface lan; + }) + (import ./wan.nix { + inherit wan_iface wan; + }) + (import ./firewall.nix { + inherit + lib + lan_iface + lan + wan_iface + wan + wg_iface + ; + }) + (import ./wireguard.nix { + inherit config wg_iface; + }) + ]; networking.hostName = "zerocool"; system.stateVersion = "25.05"; } - diff --git a/hosts/zerocool/dhcp.nix b/hosts/zerocool/dhcp.nix index bab2f1a..efcc635 100644 --- a/hosts/zerocool/dhcp.nix +++ b/hosts/zerocool/dhcp.nix @@ -1,20 +1,40 @@ -{ lan_iface, dhcp_start, dhcp_end }: +{ + lib, + lan_iface, + lan, + ... +}: let hosts = import ./static-hosts.nix; - dnsmasq-hosts = builtins.map (host: - "${host.mac},${host.ipv4},${host.name}" - ) hosts; + dnsmasq-hosts = builtins.map (host: "${host.mac},${host.ipv4},${host.name}") hosts; + + tagged_vlans = ( + builtins.filter (e: !builtins.hasAttr "untagged" e.snd) ( + lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan) + ) + ); + untagged_vlan = lib.lists.findFirst ( + e: builtins.hasAttr "untagged" e + ) (throw "Must have untagged VLAN") (builtins.attrValues lan); in { services.dnsmasq = { enable = true; settings = { - interface = lan_iface; - dhcp-range = [ - "${dhcp_start},${dhcp_end},12h" - "10.98.4.2,static,255.255.255.0" - ]; - "dhcp-host" = dnsmasq-hosts; + interface = [ + lan_iface + ] + ++ builtins.map (e: "vlan${e.fst}") tagged_vlans; + dhcp-range = + (lib.lists.optional (builtins.hasAttr "dhcpv4" untagged_vlan) "interface:${lan_iface},${untagged_vlan.dhcpv4}") + ++ (lib.lists.optional (builtins.hasAttr "dhcpv6" untagged_vlan) "interface:${lan_iface},::,constructor:${lan_iface},${untagged_vlan.dhcpv6}") + ++ (builtins.map (e: "interface:vlan${e.fst},${e.snd.dhcpv4}") ( + builtins.filter (e: builtins.hasAttr "dhcpv4" e.snd) tagged_vlans + )) + ++ (builtins.map (e: "interface:vlan${e.fst},::,constructor:vlan${e.fst},${e.snd.dhcpv6}") ( + builtins.filter (e: builtins.hasAttr "dhcpv6" e.snd) tagged_vlans + )); + dhcp-host = dnsmasq-hosts; }; }; -} \ No newline at end of file +} diff --git a/hosts/zerocool/firewall.nix b/hosts/zerocool/firewall.nix index 090667d..ab393d4 100644 --- a/hosts/zerocool/firewall.nix +++ b/hosts/zerocool/firewall.nix @@ -1,9 +1,185 @@ -{ lan_iface }: { - networking.nftables.enable = true; + lib, + lan_iface, + lan, + wan_iface, + wg_iface, + ... +}: +let + generateInterVlanBlockPairings = + list: + builtins.concatLists ( + map ( + x: + map ( + y: + ''iifname "vlan${x.fst}" oifname "vlan${y.fst}" drop comment "Drop vlan${x.fst} to vlan${y.fst} traffic"'' + ) (builtins.filter (y: x.fst != y.fst) list) + ) list + ); + + intervlan_forward_block = lib.strings.concatStringsSep "\n" ( + generateInterVlanBlockPairings ( + builtins.filter (e: !builtins.hasAttr "untagged" e.snd) ( + lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan) + ) + ) + ); + + untagged_intervlan_block = lib.strings.concatStringsSep "\n" ( + builtins.map + (e: '' + iifname "vlan${e.fst}" oifname "${lan_iface}" drop comment "Drop vlan${e.fst} to ${lan_iface} traffic" + iifname "${lan_iface}" oifname "vlan${e.fst}" drop comment "Drop ${lan_iface} to vlan${e.fst} traffic" + '') + ( + builtins.filter (e: !builtins.hasAttr "untagged" e.snd) ( + lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan) + ) + ) + ); + + router_access = lib.strings.concatStringsSep "\n" ( + builtins.map + (e: ''iifname { "vlan${e.fst}" } accept comment "Allow vlan${e.fst} to access the router"'') + ( + builtins.filter (e: e.snd.allow_router_access && !builtins.hasAttr "untagged" e.snd) ( + lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan) + ) + ) + ); + + router_forward = lib.strings.concatStringsSep "\n" ( + builtins.map + (e: '' + iifname { "vlan${e.fst}" } oifname { "${wan_iface}" } accept comment "Allow vlan${e.fst} to WAN" + iifname { "${wan_iface}" } oifname { "vlan${e.fst}" } ct state established, related accept comment "Allow established back to vlan${e.fst}" + '') + ( + builtins.filter (e: !builtins.hasAttr "untagged" e.snd) ( + lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan) + ) + ) + ); + + router_ipv6_icmp_access = lib.strings.concatStringsSep "\n" ( + builtins.map + (e: '' + iifname "vlan${e.fst}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } counter accept comment "Allow SLAAC and DHCPv6 on vlan${e.fst}" + '') + ( + builtins.filter (e: !builtins.hasAttr "untagged" e.snd) ( + lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan) + ) + ) + ); + + router_ipv6_nd_forward = lib.strings.concatStringsSep "\n" ( + builtins.map + (e: '' + iifname "vlan${e.fst}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept comment "Allow essential ND in FORWARD on vlan${e.fst}" + '') + ( + builtins.filter (e: !builtins.hasAttr "untagged" e.snd) ( + lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan) + ) + ) + ); + +in +{ networking.firewall = { enable = true; allowPing = true; trustedInterfaces = [ lan_iface ]; }; + + networking.nftables = { + enable = true; + ruleset = '' + table ip filter { + chain input { + type filter hook input priority 0; policy drop; + + iifname { "${lan_iface}" } accept comment "Allow local network to access the router" + iifname { "${wg_iface}" } accept comment "Allow wireguard network to access the router" + + ${router_access} + + iifname "${wan_iface}" ct state { established, related } accept comment "Allow established traffic" + iifname "${wan_iface}" icmp type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP" + iifname "${wan_iface}" tcp dport 2222 accept comment "SSH allow from outside" + iifname "${wan_iface}" tcp dport 22 accept comment "SSH allow from outside" + iifname "${wan_iface}" udp dport 51820 accept comment "Wireguard allow from outside" + iifname "${wan_iface}" counter drop comment "Drop all other unsolicited traffic from wan" + + iif lo accept comment "Allow all loopback traffic" + } + + chain forward { + type filter hook forward priority 0; policy drop; + + ${intervlan_forward_block} + ${untagged_intervlan_block} + + iifname { "${lan_iface}" } oifname { "${wan_iface}" } accept comment "Allow trusted LAN to WAN" + iifname { "${wan_iface}" } oifname { "${lan_iface}" } ct state established, related accept comment "Allow established back to LANs" + + ${router_forward} + + iifname { "${lan_iface}" } oifname { "${wg_iface}" } accept comment "Allow LAN to wireguard" + iifname { "${wg_iface}" } oifname { "${lan_iface}" } accept comment "Allow wireguard back to LANs" + } + } + + table ip nat { + chain postrouting { + type nat hook postrouting priority 100; policy accept; + oifname "${wan_iface}" masquerade comment "NAT IPv4 traffic to WAN" + } + } + + table ip6 filter { + chain input { + type filter hook input priority 0; policy drop; + + iifname { "${lan_iface}" } accept comment "Allow local network to access the router" + iifname { "${wg_iface}" } accept comment "Allow wireguard to access the router" + + ${router_access} + + iifname "${wan_iface}" ct state { established, related } accept comment "Allow established traffic" + iifname "${wan_iface}" icmpv6 type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP" + iifname "${wan_iface}" tcp dport 2222 accept comment "SSH allow from outside" + iifname "${wan_iface}" tcp dport 22 accept comment "SSH allow from outside" + iifname "${wan_iface}" udp dport 51820 accept comment "Wireguard allow from outside" + iifname "${wan_iface}" counter drop comment "Drop all other unsolicited traffic from WAN" + + iif lo accept comment "Allow all loopback traffic" + + iifname "${lan_iface}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } counter accept comment "Allow SLAAC and DHCPv6" + ${router_ipv6_icmp_access} + } + + chain forward { + type filter hook forward priority 0; policy drop; + + ${intervlan_forward_block} + ${untagged_intervlan_block} + + iifname { "${lan_iface}" } oifname { "${wan_iface}" } accept comment "Allow trusted LAN to WAN" + iifname { "${wan_iface}" } oifname { "${lan_iface}" } ct state established, related accept comment "Allow established back to LANs" + + ${router_forward} + + iifname { "${lan_iface}" } oifname { "${wg_iface}" } accept comment "Allow LAN to Tailscale" + iifname { "${wg_iface}" } oifname { "${lan_iface}" } accept comment "Allow tailscale back to LANs" + + iifname "${lan_iface}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept comment "Allow essential ND in FORWARD" + ${router_ipv6_nd_forward} + } + } + ''; + }; } diff --git a/hosts/zerocool/lan.nix b/hosts/zerocool/lan.nix index b4c0bfc..1b92f1b 100644 --- a/hosts/zerocool/lan.nix +++ b/hosts/zerocool/lan.nix @@ -4,35 +4,76 @@ lan, ... }: +let + # First element in LAN is always the untagged VLAN + untagged_lan_attrs = lib.lists.findFirst ( + e: builtins.hasAttr "untagged" e + ) (throw "Must have untagged VLAN") (builtins.attrValues lan); +in { networking.vlans = builtins.listToAttrs ( - builtins.map (vlanid: { - name = "vlan${vlanid}"; - value = { - id = builtins.fromJSON vlanid; - interface = lan_iface; - }; - }) (builtins.attrNames lan) + builtins.map + (e: { + name = "vlan${e.fst}"; + value = { + id = builtins.fromJSON e.fst; + interface = lan_iface; + }; + }) + ( + builtins.filter (e: !builtins.hasAttr "untagged" e.snd) ( + lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan) + ) + ) ); networking.interfaces = builtins.listToAttrs ( - builtins.map (e: { - name = "vlan${e.fst}"; - value = { - useDHCP = false; - ipv4.addresses = [ - { - address = e.snd.ipv4.address; - prefixLength = e.snd.ipv4.cidr; - } - ]; - ipv6.addresses = [ - { - address = e.snd.ipv6.address; - prefixLength = e.snd.ipv6.cidr; - } - ]; - }; - }) (lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan)) + # Tagged VLANs + (builtins.map + (e: { + name = "vlan${e.fst}"; + value = { + useDHCP = false; + ipv4.addresses = [ + { + address = e.snd.ipv4.address; + prefixLength = e.snd.ipv4.cidr; + } + ]; + ipv6.addresses = [ + { + address = e.snd.ipv6.address; + prefixLength = e.snd.ipv6.cidr; + } + ]; + }; + }) + ( + builtins.filter (e: !builtins.hasAttr "untagged" e.snd) ( + lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan) + ) + ) + ) + ++ [ + # Untagged (native) VLAN + { + name = lan_iface; + value = { + useDHCP = false; + ipv4.addresses = [ + { + address = untagged_lan_attrs.ipv4.address; + prefixLength = untagged_lan_attrs.ipv4.cidr; + } + ]; + ipv6.addresses = [ + { + address = untagged_lan_attrs.ipv6.address; + prefixLength = untagged_lan_attrs.ipv6.cidr; + } + ]; + }; + } + ] ); } diff --git a/hosts/zerocool/router.nix b/hosts/zerocool/router.nix index 7d2e0d2..e789f7c 100644 --- a/hosts/zerocool/router.nix +++ b/hosts/zerocool/router.nix @@ -1,13 +1,9 @@ -{ wan_iface, wg_iface, lan_iface, lan, ... }: +{ + ... +}: { boot.kernel.sysctl = { "net.ipv4.conf.all.forwarding" = true; "net.ipv6.conf.all.forwarding" = true; }; - - networking.nat = { - enable = true; - externalInterface = wan_iface; - internalInterfaces = [ lan_iface wg_iface ] ++ builtins.map (vlanid: "vlan${vlanid}" ) (builtins.attrNames lan); - }; } From e47076db2c848c41af0c338376ac215b4fd84276 Mon Sep 17 00:00:00 2001 From: Ralakus Date: Thu, 5 Mar 2026 02:31:07 -0500 Subject: [PATCH 06/23] hosts/zerocool: update variables to camelCase --- hosts/zerocool/configuration.nix | 30 ++++----- hosts/zerocool/dhcp.nix | 22 +++---- hosts/zerocool/firewall.nix | 104 +++++++++++++++---------------- hosts/zerocool/lan.nix | 17 +++-- hosts/zerocool/wan.nix | 6 +- hosts/zerocool/wireguard.nix | 4 +- 6 files changed, 91 insertions(+), 92 deletions(-) diff --git a/hosts/zerocool/configuration.nix b/hosts/zerocool/configuration.nix index 7ecf5e6..473b82f 100644 --- a/hosts/zerocool/configuration.nix +++ b/hosts/zerocool/configuration.nix @@ -5,7 +5,7 @@ ... }: let - wan_iface = "enp3s0f0"; + wanIface = "enp3s0f0"; wan = { ipv4 = { gateway = "198.82.185.129"; @@ -19,9 +19,9 @@ let }; }; - wg_iface = "wg0"; + wgIface = "wg0"; - lan_iface = "enp3s0f1"; + lanIface = "enp3s0f1"; lan = { # Management "10" = { @@ -33,7 +33,7 @@ let address = "2607:b400:6:ce80::1"; cidr = 64; }; - allow_router_access = true; + allowRouterAccess = true; dhcpv4 = "10.98.4.128,10.98.4.254,12h"; dhcpv6 = "ra-stateless,ra-names,12h"; }; @@ -47,7 +47,7 @@ let address = "2607:b400:6:ce81::1"; cidr = 64; }; - allow_router_access = true; + allowRouterAccess = true; untagged = true; dhcpv4 = "10.98.5.128,10.98.5.254,12h"; dhcpv6 = "ra-stateless,ra-names,12h"; @@ -62,7 +62,7 @@ let address = "2607:b400:6:ce82::1"; cidr = 64; }; - allow_router_access = true; + allowRouterAccess = true; dhcpv4 = "10.98.6.128,10.98.6.254,12h"; dhcpv6 = "ra-stateless,ra-names,12h"; }; @@ -76,13 +76,13 @@ let address = "2607:b400:6:ce83::1"; cidr = 64; }; - allow_router_access = false; + allowRouterAccess = false; dhcpv4 = "10.98.7.128,10.98.7.254,12h"; dhcpv6 = "ra-stateless,ra-names,12h"; }; }; - check_untagged = lib.asserts.assertMsg ( + checkUntagged = lib.asserts.assertMsg ( builtins.length ( builtins.filter (e: builtins.hasAttr "untagged" e.snd) ( lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan) @@ -101,26 +101,26 @@ in ./dns.nix ./router.nix (import ./lan.nix { - inherit lib lan_iface lan; + inherit lib lanIface lan; }) (import ./dhcp.nix { - inherit lib lan_iface lan; + inherit lib lanIface lan; }) (import ./wan.nix { - inherit wan_iface wan; + inherit wanIface wan; }) (import ./firewall.nix { inherit lib - lan_iface + lanIface lan - wan_iface + wanIface wan - wg_iface + wgIface ; }) (import ./wireguard.nix { - inherit config wg_iface; + inherit config wgIface; }) ]; diff --git a/hosts/zerocool/dhcp.nix b/hosts/zerocool/dhcp.nix index efcc635..6c4ff4c 100644 --- a/hosts/zerocool/dhcp.nix +++ b/hosts/zerocool/dhcp.nix @@ -1,19 +1,19 @@ { lib, - lan_iface, + lanIface, lan, ... }: let hosts = import ./static-hosts.nix; - dnsmasq-hosts = builtins.map (host: "${host.mac},${host.ipv4},${host.name}") hosts; + dnsmasqHosts = builtins.map (host: "${host.mac},${host.ipv4},${host.name}") hosts; - tagged_vlans = ( + taggedVlans = ( builtins.filter (e: !builtins.hasAttr "untagged" e.snd) ( lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan) ) ); - untagged_vlan = lib.lists.findFirst ( + untaggedVlan = lib.lists.findFirst ( e: builtins.hasAttr "untagged" e ) (throw "Must have untagged VLAN") (builtins.attrValues lan); in @@ -22,19 +22,19 @@ in enable = true; settings = { interface = [ - lan_iface + lanIface ] - ++ builtins.map (e: "vlan${e.fst}") tagged_vlans; + ++ builtins.map (e: "vlan${e.fst}") taggedVlans; dhcp-range = - (lib.lists.optional (builtins.hasAttr "dhcpv4" untagged_vlan) "interface:${lan_iface},${untagged_vlan.dhcpv4}") - ++ (lib.lists.optional (builtins.hasAttr "dhcpv6" untagged_vlan) "interface:${lan_iface},::,constructor:${lan_iface},${untagged_vlan.dhcpv6}") + (lib.lists.optional (builtins.hasAttr "dhcpv4" untaggedVlan) "interface:${lanIface},${untaggedVlan.dhcpv4}") + ++ (lib.lists.optional (builtins.hasAttr "dhcpv6" untaggedVlan) "interface:${lanIface},::,constructor:${lanIface},${untaggedVlan.dhcpv6}") ++ (builtins.map (e: "interface:vlan${e.fst},${e.snd.dhcpv4}") ( - builtins.filter (e: builtins.hasAttr "dhcpv4" e.snd) tagged_vlans + builtins.filter (e: builtins.hasAttr "dhcpv4" e.snd) taggedVlans )) ++ (builtins.map (e: "interface:vlan${e.fst},::,constructor:vlan${e.fst},${e.snd.dhcpv6}") ( - builtins.filter (e: builtins.hasAttr "dhcpv6" e.snd) tagged_vlans + builtins.filter (e: builtins.hasAttr "dhcpv6" e.snd) taggedVlans )); - dhcp-host = dnsmasq-hosts; + dhcp-host = dnsmasqHosts; }; }; } diff --git a/hosts/zerocool/firewall.nix b/hosts/zerocool/firewall.nix index ab393d4..e15fd6c 100644 --- a/hosts/zerocool/firewall.nix +++ b/hosts/zerocool/firewall.nix @@ -1,9 +1,9 @@ { lib, - lan_iface, + lanIface, lan, - wan_iface, - wg_iface, + wanIface, + wgIface, ... }: let @@ -19,7 +19,7 @@ let ) list ); - intervlan_forward_block = lib.strings.concatStringsSep "\n" ( + interVlanRoutingBlock = lib.strings.concatStringsSep "\n" ( generateInterVlanBlockPairings ( builtins.filter (e: !builtins.hasAttr "untagged" e.snd) ( lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan) @@ -27,11 +27,11 @@ let ) ); - untagged_intervlan_block = lib.strings.concatStringsSep "\n" ( + untaggedInterVlanBlock = lib.strings.concatStringsSep "\n" ( builtins.map (e: '' - iifname "vlan${e.fst}" oifname "${lan_iface}" drop comment "Drop vlan${e.fst} to ${lan_iface} traffic" - iifname "${lan_iface}" oifname "vlan${e.fst}" drop comment "Drop ${lan_iface} to vlan${e.fst} traffic" + iifname "vlan${e.fst}" oifname "${lanIface}" drop comment "Drop vlan${e.fst} to ${lanIface} traffic" + iifname "${lanIface}" oifname "vlan${e.fst}" drop comment "Drop ${lanIface} to vlan${e.fst} traffic" '') ( builtins.filter (e: !builtins.hasAttr "untagged" e.snd) ( @@ -40,21 +40,21 @@ let ) ); - router_access = lib.strings.concatStringsSep "\n" ( + routerAccess = lib.strings.concatStringsSep "\n" ( builtins.map (e: ''iifname { "vlan${e.fst}" } accept comment "Allow vlan${e.fst} to access the router"'') ( - builtins.filter (e: e.snd.allow_router_access && !builtins.hasAttr "untagged" e.snd) ( + builtins.filter (e: e.snd.allowRouterAccess && !builtins.hasAttr "untagged" e.snd) ( lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan) ) ) ); - router_forward = lib.strings.concatStringsSep "\n" ( + routerForward = lib.strings.concatStringsSep "\n" ( builtins.map (e: '' - iifname { "vlan${e.fst}" } oifname { "${wan_iface}" } accept comment "Allow vlan${e.fst} to WAN" - iifname { "${wan_iface}" } oifname { "vlan${e.fst}" } ct state established, related accept comment "Allow established back to vlan${e.fst}" + iifname { "vlan${e.fst}" } oifname { "${wanIface}" } accept comment "Allow vlan${e.fst} to WAN" + iifname { "${wanIface}" } oifname { "vlan${e.fst}" } ct state established, related accept comment "Allow established back to vlan${e.fst}" '') ( builtins.filter (e: !builtins.hasAttr "untagged" e.snd) ( @@ -63,7 +63,7 @@ let ) ); - router_ipv6_icmp_access = lib.strings.concatStringsSep "\n" ( + routerIpv6IcmpAccess = lib.strings.concatStringsSep "\n" ( builtins.map (e: '' iifname "vlan${e.fst}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } counter accept comment "Allow SLAAC and DHCPv6 on vlan${e.fst}" @@ -75,7 +75,7 @@ let ) ); - router_ipv6_nd_forward = lib.strings.concatStringsSep "\n" ( + routerIpv6NdForward = lib.strings.concatStringsSep "\n" ( builtins.map (e: '' iifname "vlan${e.fst}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept comment "Allow essential ND in FORWARD on vlan${e.fst}" @@ -92,7 +92,7 @@ in networking.firewall = { enable = true; allowPing = true; - trustedInterfaces = [ lan_iface ]; + trustedInterfaces = [ lanIface ]; }; networking.nftables = { @@ -102,17 +102,17 @@ in chain input { type filter hook input priority 0; policy drop; - iifname { "${lan_iface}" } accept comment "Allow local network to access the router" - iifname { "${wg_iface}" } accept comment "Allow wireguard network to access the router" + iifname { "${lanIface}" } accept comment "Allow local network to access the router" + iifname { "${wgIface}" } accept comment "Allow wireguard network to access the router" - ${router_access} + ${routerAccess} - iifname "${wan_iface}" ct state { established, related } accept comment "Allow established traffic" - iifname "${wan_iface}" icmp type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP" - iifname "${wan_iface}" tcp dport 2222 accept comment "SSH allow from outside" - iifname "${wan_iface}" tcp dport 22 accept comment "SSH allow from outside" - iifname "${wan_iface}" udp dport 51820 accept comment "Wireguard allow from outside" - iifname "${wan_iface}" counter drop comment "Drop all other unsolicited traffic from wan" + iifname "${wanIface}" ct state { established, related } accept comment "Allow established traffic" + iifname "${wanIface}" icmp type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP" + iifname "${wanIface}" tcp dport 2222 accept comment "SSH allow from outside" + iifname "${wanIface}" tcp dport 22 accept comment "SSH allow from outside" + iifname "${wanIface}" udp dport 51820 accept comment "Wireguard allow from outside" + iifname "${wanIface}" counter drop comment "Drop all other unsolicited traffic from wan" iif lo accept comment "Allow all loopback traffic" } @@ -120,23 +120,23 @@ in chain forward { type filter hook forward priority 0; policy drop; - ${intervlan_forward_block} - ${untagged_intervlan_block} + ${interVlanRoutingBlock} + ${untaggedInterVlanBlock} - iifname { "${lan_iface}" } oifname { "${wan_iface}" } accept comment "Allow trusted LAN to WAN" - iifname { "${wan_iface}" } oifname { "${lan_iface}" } ct state established, related accept comment "Allow established back to LANs" + iifname { "${lanIface}" } oifname { "${wanIface}" } accept comment "Allow trusted LAN to WAN" + iifname { "${wanIface}" } oifname { "${lanIface}" } ct state established, related accept comment "Allow established back to LANs" - ${router_forward} + ${routerForward} - iifname { "${lan_iface}" } oifname { "${wg_iface}" } accept comment "Allow LAN to wireguard" - iifname { "${wg_iface}" } oifname { "${lan_iface}" } accept comment "Allow wireguard back to LANs" + iifname { "${lanIface}" } oifname { "${wgIface}" } accept comment "Allow LAN to wireguard" + iifname { "${wgIface}" } oifname { "${lanIface}" } accept comment "Allow wireguard back to LANs" } } table ip nat { chain postrouting { type nat hook postrouting priority 100; policy accept; - oifname "${wan_iface}" masquerade comment "NAT IPv4 traffic to WAN" + oifname "${wanIface}" masquerade comment "NAT IPv4 traffic to WAN" } } @@ -144,40 +144,40 @@ in chain input { type filter hook input priority 0; policy drop; - iifname { "${lan_iface}" } accept comment "Allow local network to access the router" - iifname { "${wg_iface}" } accept comment "Allow wireguard to access the router" + iifname { "${lanIface}" } accept comment "Allow local network to access the router" + iifname { "${wgIface}" } accept comment "Allow wireguard to access the router" - ${router_access} + ${routerAccess} - iifname "${wan_iface}" ct state { established, related } accept comment "Allow established traffic" - iifname "${wan_iface}" icmpv6 type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP" - iifname "${wan_iface}" tcp dport 2222 accept comment "SSH allow from outside" - iifname "${wan_iface}" tcp dport 22 accept comment "SSH allow from outside" - iifname "${wan_iface}" udp dport 51820 accept comment "Wireguard allow from outside" - iifname "${wan_iface}" counter drop comment "Drop all other unsolicited traffic from WAN" + iifname "${wanIface}" ct state { established, related } accept comment "Allow established traffic" + iifname "${wanIface}" icmpv6 type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP" + iifname "${wanIface}" tcp dport 2222 accept comment "SSH allow from outside" + iifname "${wanIface}" tcp dport 22 accept comment "SSH allow from outside" + iifname "${wanIface}" udp dport 51820 accept comment "Wireguard allow from outside" + iifname "${wanIface}" counter drop comment "Drop all other unsolicited traffic from WAN" iif lo accept comment "Allow all loopback traffic" - iifname "${lan_iface}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } counter accept comment "Allow SLAAC and DHCPv6" - ${router_ipv6_icmp_access} + iifname "${lanIface}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } counter accept comment "Allow SLAAC and DHCPv6" + ${routerIpv6IcmpAccess} } chain forward { type filter hook forward priority 0; policy drop; - ${intervlan_forward_block} - ${untagged_intervlan_block} + ${interVlanRoutingBlock} + ${untaggedInterVlanBlock} - iifname { "${lan_iface}" } oifname { "${wan_iface}" } accept comment "Allow trusted LAN to WAN" - iifname { "${wan_iface}" } oifname { "${lan_iface}" } ct state established, related accept comment "Allow established back to LANs" + iifname { "${lanIface}" } oifname { "${wanIface}" } accept comment "Allow trusted LAN to WAN" + iifname { "${wanIface}" } oifname { "${lanIface}" } ct state established, related accept comment "Allow established back to LANs" - ${router_forward} + ${routerForward} - iifname { "${lan_iface}" } oifname { "${wg_iface}" } accept comment "Allow LAN to Tailscale" - iifname { "${wg_iface}" } oifname { "${lan_iface}" } accept comment "Allow tailscale back to LANs" + iifname { "${lanIface}" } oifname { "${wgIface}" } accept comment "Allow LAN to Tailscale" + iifname { "${wgIface}" } oifname { "${lanIface}" } accept comment "Allow tailscale back to LANs" - iifname "${lan_iface}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept comment "Allow essential ND in FORWARD" - ${router_ipv6_nd_forward} + iifname "${lanIface}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept comment "Allow essential ND in FORWARD" + ${routerIpv6NdForward} } } ''; diff --git a/hosts/zerocool/lan.nix b/hosts/zerocool/lan.nix index 1b92f1b..1db7793 100644 --- a/hosts/zerocool/lan.nix +++ b/hosts/zerocool/lan.nix @@ -1,12 +1,11 @@ { lib, - lan_iface, + lanIface, lan, ... }: let - # First element in LAN is always the untagged VLAN - untagged_lan_attrs = lib.lists.findFirst ( + untaggedVlan = lib.lists.findFirst ( e: builtins.hasAttr "untagged" e ) (throw "Must have untagged VLAN") (builtins.attrValues lan); in @@ -17,7 +16,7 @@ in name = "vlan${e.fst}"; value = { id = builtins.fromJSON e.fst; - interface = lan_iface; + interface = lanIface; }; }) ( @@ -57,19 +56,19 @@ in ++ [ # Untagged (native) VLAN { - name = lan_iface; + name = lanIface; value = { useDHCP = false; ipv4.addresses = [ { - address = untagged_lan_attrs.ipv4.address; - prefixLength = untagged_lan_attrs.ipv4.cidr; + address = untaggedVlan.ipv4.address; + prefixLength = untaggedVlan.ipv4.cidr; } ]; ipv6.addresses = [ { - address = untagged_lan_attrs.ipv6.address; - prefixLength = untagged_lan_attrs.ipv6.cidr; + address = untaggedVlan.ipv6.address; + prefixLength = untaggedVlan.ipv6.cidr; } ]; }; diff --git a/hosts/zerocool/wan.nix b/hosts/zerocool/wan.nix index 69ae4d1..8b0edd4 100644 --- a/hosts/zerocool/wan.nix +++ b/hosts/zerocool/wan.nix @@ -1,13 +1,13 @@ -{ wan_iface, wan, ... }: +{ wanIface, wan, ... }: { networking.defaultGateway = wan.ipv4.gateway; networking.defaultGateway6 = { address = wan.ipv6.gateway; - interface = wan_iface; + interface = wanIface; }; networking.interfaces = { - "${wan_iface}" = { + "${wanIface}" = { useDHCP = false; ipv4.addresses = [ { diff --git a/hosts/zerocool/wireguard.nix b/hosts/zerocool/wireguard.nix index b9c42f4..0cb3ed0 100644 --- a/hosts/zerocool/wireguard.nix +++ b/hosts/zerocool/wireguard.nix @@ -1,8 +1,8 @@ -{ config, wg_iface }: +{ config, wgIface }: { age.secrets."wg.priv".file = ../../secrets/zerocool/wg.priv.age; networking.wireguard.interfaces = { - "${wg_iface}" = { + "${wgIface}" = { ips = [ "10.98.255.2/32" ]; listenPort = 51820; From ac5a998396e03ac6a09e3f2a1adee7ecd5be7fb4 Mon Sep 17 00:00:00 2001 From: Ralakus Date: Thu, 5 Mar 2026 02:33:44 -0500 Subject: [PATCH 07/23] hosts/zerocool: changed static hosts to general host vlan --- hosts/zerocool/static-hosts.nix | 36 ++++++++++++++++----------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/hosts/zerocool/static-hosts.nix b/hosts/zerocool/static-hosts.nix index ce679d2..52da2b8 100644 --- a/hosts/zerocool/static-hosts.nix +++ b/hosts/zerocool/static-hosts.nix @@ -2,86 +2,86 @@ { name = "switch"; mac = "00:12:a9:d5:d4:20"; - ipv4 = "10.98.4.2"; + ipv4 = "10.98.6.2"; } { name = "meltdown"; mac = "02:00:0a:62:00:03"; - ipv4 = "10.98.4.3"; + ipv4 = "10.98.6.3"; } { name = "spectre"; mac = "02:00:0a:62:00:04"; - ipv4 = "10.98.4.4"; + ipv4 = "10.98.6.4"; } { name = "cyberdelia"; mac = "00:1e:4f:20:50:d6"; - ipv4 = "10.98.4.6"; + ipv4 = "10.98.6.6"; } { name = "dirtycow"; mac = "00:1e:c9:ef:13:f8"; - ipv4 = "10.98.4.7"; + ipv4 = "10.98.6.7"; } { name = "gibson"; mac = "48:4d:7e:f9:8b:e5"; - ipv4 = "10.98.4.8"; + ipv4 = "10.98.6.8"; } { name = "prospit"; mac = "d8:9e:f3:3e:f9:41"; - ipv4 = "10.98.4.9"; + ipv4 = "10.98.6.9"; } { name = "chimera"; mac = "02:00:0a:62:00:0a"; - ipv4 = "10.98.4.10"; + ipv4 = "10.98.6.10"; } { name = "sczi"; mac = "02:00:0a:62:00:0b"; - ipv4 = "10.98.4.11"; + ipv4 = "10.98.6.11"; } { name = "acidburn"; mac = "02:00:0a:62:00:0c"; - ipv4 = "10.98.4.12"; + ipv4 = "10.98.6.12"; } { name = "mirror"; mac = "02:00:0a:62:00:10"; - ipv4 = "10.98.4.16"; + ipv4 = "10.98.6.16"; } { name = "crashoverride"; mac = "02:00:0a:62:00:12"; - ipv4 = "10.98.4.18"; + ipv4 = "10.98.6.18"; } { name = "wargame"; mac = "02:00:0a:62:00:13"; - ipv4 = "10.98.4.19"; + ipv4 = "10.98.6.19"; } { name = "sphinx"; mac = "02:00:0a:62:00:0d"; - ipv4 = "10.98.4.20"; + ipv4 = "10.98.6.20"; } { name = "nikonwormhole"; mac = "02:00:0a:62:00:0e"; - ipv4 = "10.98.4.21"; + ipv4 = "10.98.6.21"; } { name = "scaryterry"; mac = "02:00:0a:62:00:0f"; - ipv4 = "10.98.4.22"; + ipv4 = "10.98.6.22"; } { name = "lora"; mac = "60:81:f9:3e:c9:06"; - ipv4 = "10.98.4.253"; + ipv4 = "10.98.6.127"; } -] \ No newline at end of file +] From 7d19892150afa58040836db501b761d8a02ef248 Mon Sep 17 00:00:00 2001 From: Ralakus Date: Thu, 5 Mar 2026 03:05:14 -0500 Subject: [PATCH 08/23] hosts/zerocool: cleaned up duplicate code --- hosts/zerocool/firewall.nix | 85 +++++++++++++------------------------ 1 file changed, 29 insertions(+), 56 deletions(-) diff --git a/hosts/zerocool/firewall.nix b/hosts/zerocool/firewall.nix index e15fd6c..d517e88 100644 --- a/hosts/zerocool/firewall.nix +++ b/hosts/zerocool/firewall.nix @@ -7,6 +7,12 @@ ... }: let + taggedVlans = ( + builtins.filter (e: !builtins.hasAttr "untagged" e.snd) ( + lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan) + ) + ); + generateInterVlanBlockPairings = list: builtins.concatLists ( @@ -20,80 +26,43 @@ let ); interVlanRoutingBlock = lib.strings.concatStringsSep "\n" ( - generateInterVlanBlockPairings ( - builtins.filter (e: !builtins.hasAttr "untagged" e.snd) ( - lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan) - ) - ) + generateInterVlanBlockPairings taggedVlans ); untaggedInterVlanBlock = lib.strings.concatStringsSep "\n" ( - builtins.map - (e: '' - iifname "vlan${e.fst}" oifname "${lanIface}" drop comment "Drop vlan${e.fst} to ${lanIface} traffic" - iifname "${lanIface}" oifname "vlan${e.fst}" drop comment "Drop ${lanIface} to vlan${e.fst} traffic" - '') - ( - builtins.filter (e: !builtins.hasAttr "untagged" e.snd) ( - lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan) - ) - ) + builtins.map (e: '' + iifname "vlan${e.fst}" oifname "${lanIface}" drop comment "Drop vlan${e.fst} to ${lanIface} traffic" + iifname "${lanIface}" oifname "vlan${e.fst}" drop comment "Drop ${lanIface} to vlan${e.fst} traffic" + '') taggedVlans ); routerAccess = lib.strings.concatStringsSep "\n" ( - builtins.map - (e: ''iifname { "vlan${e.fst}" } accept comment "Allow vlan${e.fst} to access the router"'') - ( - builtins.filter (e: e.snd.allowRouterAccess && !builtins.hasAttr "untagged" e.snd) ( - lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan) - ) - ) + builtins.map ( + e: ''iifname { "vlan${e.fst}" } accept comment "Allow vlan${e.fst} to access the router"'' + ) taggedVlans ); routerForward = lib.strings.concatStringsSep "\n" ( - builtins.map - (e: '' - iifname { "vlan${e.fst}" } oifname { "${wanIface}" } accept comment "Allow vlan${e.fst} to WAN" - iifname { "${wanIface}" } oifname { "vlan${e.fst}" } ct state established, related accept comment "Allow established back to vlan${e.fst}" - '') - ( - builtins.filter (e: !builtins.hasAttr "untagged" e.snd) ( - lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan) - ) - ) + builtins.map (e: '' + iifname { "vlan${e.fst}" } oifname { "${wanIface}" } accept comment "Allow vlan${e.fst} to WAN" + iifname { "${wanIface}" } oifname { "vlan${e.fst}" } ct state established, related accept comment "Allow established back to vlan${e.fst}" + '') taggedVlans ); routerIpv6IcmpAccess = lib.strings.concatStringsSep "\n" ( - builtins.map - (e: '' - iifname "vlan${e.fst}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } counter accept comment "Allow SLAAC and DHCPv6 on vlan${e.fst}" - '') - ( - builtins.filter (e: !builtins.hasAttr "untagged" e.snd) ( - lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan) - ) - ) + builtins.map (e: '' + iifname "vlan${e.fst}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } counter accept comment "Allow SLAAC and DHCPv6 on vlan${e.fst}" + '') taggedVlans ); routerIpv6NdForward = lib.strings.concatStringsSep "\n" ( - builtins.map - (e: '' - iifname "vlan${e.fst}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept comment "Allow essential ND in FORWARD on vlan${e.fst}" - '') - ( - builtins.filter (e: !builtins.hasAttr "untagged" e.snd) ( - lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan) - ) - ) + builtins.map (e: '' + iifname "vlan${e.fst}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept comment "Allow essential ND in FORWARD on vlan${e.fst}" + '') taggedVlans ); - in { - networking.firewall = { - enable = true; - allowPing = true; - trustedInterfaces = [ lanIface ]; - }; + networking.firewall.enable = true; networking.nftables = { enable = true; @@ -109,9 +78,11 @@ in iifname "${wanIface}" ct state { established, related } accept comment "Allow established traffic" iifname "${wanIface}" icmp type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP" + iifname "${wanIface}" tcp dport 2222 accept comment "SSH allow from outside" iifname "${wanIface}" tcp dport 22 accept comment "SSH allow from outside" iifname "${wanIface}" udp dport 51820 accept comment "Wireguard allow from outside" + iifname "${wanIface}" counter drop comment "Drop all other unsolicited traffic from wan" iif lo accept comment "Allow all loopback traffic" @@ -151,9 +122,11 @@ in iifname "${wanIface}" ct state { established, related } accept comment "Allow established traffic" iifname "${wanIface}" icmpv6 type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP" + iifname "${wanIface}" tcp dport 2222 accept comment "SSH allow from outside" iifname "${wanIface}" tcp dport 22 accept comment "SSH allow from outside" iifname "${wanIface}" udp dport 51820 accept comment "Wireguard allow from outside" + iifname "${wanIface}" counter drop comment "Drop all other unsolicited traffic from WAN" iif lo accept comment "Allow all loopback traffic" From 579beade7768b3064b0df88802564d30f201dbc2 Mon Sep 17 00:00:00 2001 From: Ralakus Date: Thu, 5 Mar 2026 03:15:11 -0500 Subject: [PATCH 09/23] hosts/zerocool: fixed typo in firewall --- hosts/zerocool/firewall.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hosts/zerocool/firewall.nix b/hosts/zerocool/firewall.nix index d517e88..e7245ba 100644 --- a/hosts/zerocool/firewall.nix +++ b/hosts/zerocool/firewall.nix @@ -146,8 +146,8 @@ in ${routerForward} - iifname { "${lanIface}" } oifname { "${wgIface}" } accept comment "Allow LAN to Tailscale" - iifname { "${wgIface}" } oifname { "${lanIface}" } accept comment "Allow tailscale back to LANs" + iifname { "${lanIface}" } oifname { "${wgIface}" } accept comment "Allow LAN to wireguard" + iifname { "${wgIface}" } oifname { "${lanIface}" } accept comment "Allow wireguard back to LANs" iifname "${lanIface}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept comment "Allow essential ND in FORWARD" ${routerIpv6NdForward} From a1e819d8f81e785b4f94f5971301a8619f4831f0 Mon Sep 17 00:00:00 2001 From: Ralakus Date: Thu, 5 Mar 2026 04:10:09 -0500 Subject: [PATCH 10/23] hosts/zerocool: added WAN port opening, host forwarding, and fixed denied VLANs having access to router --- hosts/zerocool/configuration.nix | 6 +++ hosts/zerocool/dhcp.nix | 15 +++++-- hosts/zerocool/firewall.nix | 73 ++++++++++++++++++++++++++------ 3 files changed, 78 insertions(+), 16 deletions(-) diff --git a/hosts/zerocool/configuration.nix b/hosts/zerocool/configuration.nix index 473b82f..8313dd5 100644 --- a/hosts/zerocool/configuration.nix +++ b/hosts/zerocool/configuration.nix @@ -17,6 +17,12 @@ let address = "2001:468:c80:6119:82c1:6eff:fe21:2b88"; cidr = 60; }; + tcpPorts = [ 22 2222 ]; + udpPorts = [ 51820 ]; + # Publicly routable IPv4 addresses only + exposeIpv4Hosts = []; + # Publicly routable IPv6 addresses only + exposeIpv6Hosts = []; }; wgIface = "wg0"; diff --git a/hosts/zerocool/dhcp.nix b/hosts/zerocool/dhcp.nix index 6c4ff4c..0db8ff2 100644 --- a/hosts/zerocool/dhcp.nix +++ b/hosts/zerocool/dhcp.nix @@ -16,15 +16,22 @@ let untaggedVlan = lib.lists.findFirst ( e: builtins.hasAttr "untagged" e ) (throw "Must have untagged VLAN") (builtins.attrValues lan); + + interfaces = builtins.map (e: "vlan${e.fst}") ( + builtins.filter ( + e: (builtins.hasAttr "dhcpv4" e.snd) || (builtins.hasAttr "dhcpv6" e.snd) + ) taggedVlans + ); in { services.dnsmasq = { enable = true; settings = { - interface = [ - lanIface - ] - ++ builtins.map (e: "vlan${e.fst}") taggedVlans; + interface = + (lib.lists.optional ( + (builtins.hasAttr "dhcpv4" untaggedVlan) || (builtins.hasAttr "dhcpv6" untaggedVlan) + ) lanIface) + ++ interfaces; dhcp-range = (lib.lists.optional (builtins.hasAttr "dhcpv4" untaggedVlan) "interface:${lanIface},${untaggedVlan.dhcpv4}") ++ (lib.lists.optional (builtins.hasAttr "dhcpv6" untaggedVlan) "interface:${lanIface},::,constructor:${lanIface},${untaggedVlan.dhcpv6}") diff --git a/hosts/zerocool/firewall.nix b/hosts/zerocool/firewall.nix index e7245ba..cc33fdc 100644 --- a/hosts/zerocool/firewall.nix +++ b/hosts/zerocool/firewall.nix @@ -3,6 +3,7 @@ lanIface, lan, wanIface, + wan, wgIface, ... }: @@ -39,7 +40,27 @@ let routerAccess = lib.strings.concatStringsSep "\n" ( builtins.map ( e: ''iifname { "vlan${e.fst}" } accept comment "Allow vlan${e.fst} to access the router"'' - ) taggedVlans + ) (builtins.filter (e: e.snd.allowRouterAccess) taggedVlans) + ); + + routerDenyAccess = lib.strings.concatStringsSep "\n" ( + builtins.map ( + e: ''iifname { "vlan${e.fst}" } drop comment "Deny vlan${e.fst} to access the router"'' + ) (builtins.filter (e: !e.snd.allowRouterAccess) taggedVlans) + ); + + deniedVlanDhcpAccess = lib.strings.concatStringsSep "\n" ( + builtins.map + (e: '' + iifname { "vlan${e.fst}" } udp dport { 53, 67 } accept comment "Allow vlan${e.fst} DHCP and DNS access the router" + iifname { "vlan${e.fst}" } tcp dport 53 accept comment "Allow vlan${e.fst} TCP DNS access the router" + '') + ( + builtins.filter ( + e: + !e.snd.allowRouterAccess && ((builtins.hasAttr "dhcpv4" e.snd) || (builtins.hasAttr "dhcpv6" e.snd)) + ) taggedVlans + ) ); routerForward = lib.strings.concatStringsSep "\n" ( @@ -60,6 +81,30 @@ let iifname "vlan${e.fst}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept comment "Allow essential ND in FORWARD on vlan${e.fst}" '') taggedVlans ); + + exposedUdpPorts = lib.strings.concatStringsSep "\n" ( + builtins.map (port: '' + iifname { "${wanIface}" } udp dport ${toString port} accept comment "Allow UDP port ${toString port} from WAN" + '') wan.udpPorts + ); + + exposedTcpPorts = lib.strings.concatStringsSep "\n" ( + builtins.map (port: '' + iifname { "${wanIface}" } tcp dport ${toString port} accept comment "Allow TCP port ${toString port} from WAN" + '') wan.tcpPorts + ); + + exposedIpv4Hosts = lib.strings.concatStringsSep "\n" ( + builtins.map (daddr: '' + iifname { "${wanIface}" } daddr ${daddr} accept comment "Expose ${daddr} to WAN" + '') wan.exposeIpv4Hosts + ); + + exposedIpv6Hosts = lib.strings.concatStringsSep "\n" ( + builtins.map (daddr: '' + iifname { "${wanIface}" } daddr ${daddr} accept comment "Expose ${daddr} to WAN" + '') wan.exposeIpv6Hosts + ); in { networking.firewall.enable = true; @@ -74,14 +119,15 @@ in iifname { "${lanIface}" } accept comment "Allow local network to access the router" iifname { "${wgIface}" } accept comment "Allow wireguard network to access the router" + ${deniedVlanDhcpAccess} + ${routerDenyAccess} ${routerAccess} iifname "${wanIface}" ct state { established, related } accept comment "Allow established traffic" iifname "${wanIface}" icmp type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP" - iifname "${wanIface}" tcp dport 2222 accept comment "SSH allow from outside" - iifname "${wanIface}" tcp dport 22 accept comment "SSH allow from outside" - iifname "${wanIface}" udp dport 51820 accept comment "Wireguard allow from outside" + ${exposedUdpPorts} + ${exposedTcpPorts} iifname "${wanIface}" counter drop comment "Drop all other unsolicited traffic from wan" @@ -96,11 +142,12 @@ in iifname { "${lanIface}" } oifname { "${wanIface}" } accept comment "Allow trusted LAN to WAN" iifname { "${wanIface}" } oifname { "${lanIface}" } ct state established, related accept comment "Allow established back to LANs" + iifname { "${lanIface}" } oifname { "${wgIface}" } accept comment "Allow LAN to wireguard" + iifname { "${wgIface}" } oifname { "${lanIface}" } accept comment "Allow wireguard back to LANs" ${routerForward} - iifname { "${lanIface}" } oifname { "${wgIface}" } accept comment "Allow LAN to wireguard" - iifname { "${wgIface}" } oifname { "${lanIface}" } accept comment "Allow wireguard back to LANs" + ${exposedIpv4Hosts} } } @@ -118,14 +165,15 @@ in iifname { "${lanIface}" } accept comment "Allow local network to access the router" iifname { "${wgIface}" } accept comment "Allow wireguard to access the router" + ${deniedVlanDhcpAccess} + ${routerDenyAccess} ${routerAccess} iifname "${wanIface}" ct state { established, related } accept comment "Allow established traffic" iifname "${wanIface}" icmpv6 type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP" - iifname "${wanIface}" tcp dport 2222 accept comment "SSH allow from outside" - iifname "${wanIface}" tcp dport 22 accept comment "SSH allow from outside" - iifname "${wanIface}" udp dport 51820 accept comment "Wireguard allow from outside" + ${exposedUdpPorts} + ${exposedTcpPorts} iifname "${wanIface}" counter drop comment "Drop all other unsolicited traffic from WAN" @@ -143,14 +191,15 @@ in iifname { "${lanIface}" } oifname { "${wanIface}" } accept comment "Allow trusted LAN to WAN" iifname { "${wanIface}" } oifname { "${lanIface}" } ct state established, related accept comment "Allow established back to LANs" - - ${routerForward} - iifname { "${lanIface}" } oifname { "${wgIface}" } accept comment "Allow LAN to wireguard" iifname { "${wgIface}" } oifname { "${lanIface}" } accept comment "Allow wireguard back to LANs" + ${routerForward} + iifname "${lanIface}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept comment "Allow essential ND in FORWARD" ${routerIpv6NdForward} + + ${exposedIpv6Hosts} } } ''; From 418f1985024fb7bda26cdd1858b00298caeae7d2 Mon Sep 17 00:00:00 2001 From: Ralakus Date: Thu, 5 Mar 2026 04:26:25 -0500 Subject: [PATCH 11/23] hosts/zerocool: fixed dhcpv6 access to router on denied vlans --- hosts/zerocool/firewall.nix | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/hosts/zerocool/firewall.nix b/hosts/zerocool/firewall.nix index cc33fdc..499c40f 100644 --- a/hosts/zerocool/firewall.nix +++ b/hosts/zerocool/firewall.nix @@ -49,7 +49,7 @@ let ) (builtins.filter (e: !e.snd.allowRouterAccess) taggedVlans) ); - deniedVlanDhcpAccess = lib.strings.concatStringsSep "\n" ( + deniedVlanDhcpv4Access = lib.strings.concatStringsSep "\n" ( builtins.map (e: '' iifname { "vlan${e.fst}" } udp dport { 53, 67 } accept comment "Allow vlan${e.fst} DHCP and DNS access the router" @@ -58,11 +58,26 @@ let ( builtins.filter ( e: - !e.snd.allowRouterAccess && ((builtins.hasAttr "dhcpv4" e.snd) || (builtins.hasAttr "dhcpv6" e.snd)) + !e.snd.allowRouterAccess && (builtins.hasAttr "dhcpv4" e.snd) ) taggedVlans ) ); + deniedVlanDhcpv6Access = lib.strings.concatStringsSep "\n" ( + builtins.map + (e: '' + iifname { "vlan${e.fst}" } udp dport { 53, 547 } accept comment "Allow vlan${e.fst} DHCP and DNS access the router" + iifname { "vlan${e.fst}" } tcp dport 53 accept comment "Allow vlan${e.fst} TCP DNS access the router" + '') + ( + builtins.filter ( + e: + !e.snd.allowRouterAccess && (builtins.hasAttr "dhcpv6" e.snd) + ) taggedVlans + ) + ); + + routerForward = lib.strings.concatStringsSep "\n" ( builtins.map (e: '' iifname { "vlan${e.fst}" } oifname { "${wanIface}" } accept comment "Allow vlan${e.fst} to WAN" @@ -119,8 +134,7 @@ in iifname { "${lanIface}" } accept comment "Allow local network to access the router" iifname { "${wgIface}" } accept comment "Allow wireguard network to access the router" - ${deniedVlanDhcpAccess} - ${routerDenyAccess} + ${deniedVlanDhcpv4Access} ${routerAccess} iifname "${wanIface}" ct state { established, related } accept comment "Allow established traffic" @@ -131,6 +145,8 @@ in iifname "${wanIface}" counter drop comment "Drop all other unsolicited traffic from wan" + ${routerDenyAccess} + iif lo accept comment "Allow all loopback traffic" } @@ -165,8 +181,7 @@ in iifname { "${lanIface}" } accept comment "Allow local network to access the router" iifname { "${wgIface}" } accept comment "Allow wireguard to access the router" - ${deniedVlanDhcpAccess} - ${routerDenyAccess} + ${deniedVlanDhcpv6Access} ${routerAccess} iifname "${wanIface}" ct state { established, related } accept comment "Allow established traffic" @@ -177,10 +192,12 @@ in iifname "${wanIface}" counter drop comment "Drop all other unsolicited traffic from WAN" - iif lo accept comment "Allow all loopback traffic" - iifname "${lanIface}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } counter accept comment "Allow SLAAC and DHCPv6" ${routerIpv6IcmpAccess} + + ${routerDenyAccess} + + iif lo accept comment "Allow all loopback traffic" } chain forward { From 292b2c25616ca05085ae77443b166f357e56fc7c Mon Sep 17 00:00:00 2001 From: mkl Date: Thu, 5 Mar 2026 12:09:04 -0500 Subject: [PATCH 12/23] hosts/zerocool: added different dhcp domains for every vlan --- hosts/zerocool/configuration.nix | 4 ++++ hosts/zerocool/dhcp.nix | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/hosts/zerocool/configuration.nix b/hosts/zerocool/configuration.nix index 8313dd5..a0a3761 100644 --- a/hosts/zerocool/configuration.nix +++ b/hosts/zerocool/configuration.nix @@ -40,6 +40,7 @@ let cidr = 64; }; allowRouterAccess = true; + domain = "mgmt"; dhcpv4 = "10.98.4.128,10.98.4.254,12h"; dhcpv6 = "ra-stateless,ra-names,12h"; }; @@ -55,6 +56,7 @@ let }; allowRouterAccess = true; untagged = true; + domain = "internal"; dhcpv4 = "10.98.5.128,10.98.5.254,12h"; dhcpv6 = "ra-stateless,ra-names,12h"; }; @@ -69,6 +71,7 @@ let cidr = 64; }; allowRouterAccess = true; + domain = "g"; dhcpv4 = "10.98.6.128,10.98.6.254,12h"; dhcpv6 = "ra-stateless,ra-names,12h"; }; @@ -83,6 +86,7 @@ let cidr = 64; }; allowRouterAccess = false; + domain = "colo"; dhcpv4 = "10.98.7.128,10.98.7.254,12h"; dhcpv6 = "ra-stateless,ra-names,12h"; }; diff --git a/hosts/zerocool/dhcp.nix b/hosts/zerocool/dhcp.nix index 0db8ff2..768777e 100644 --- a/hosts/zerocool/dhcp.nix +++ b/hosts/zerocool/dhcp.nix @@ -7,6 +7,7 @@ let hosts = import ./static-hosts.nix; dnsmasqHosts = builtins.map (host: "${host.mac},${host.ipv4},${host.name}") hosts; + globalDomain = "mcb.vtluug.org"; taggedVlans = ( builtins.filter (e: !builtins.hasAttr "untagged" e.snd) ( @@ -27,6 +28,11 @@ in services.dnsmasq = { enable = true; settings = { + domain = + (lib.lists.optional (builtins.hasAttr "domain" untaggedVlan) "${untaggedVlan.domain}.${globalDomain},${untaggedVlan.ipv4.address}/${toString untaggedVlan.ipv4.cidr}") + ++ (builtins.map (e: "${e.snd.domain}.${globalDomain},${e.snd.ipv4.address}/${toString e.snd.ipv4.cidr}") ( + builtins.filter (e: builtins.hasAttr "domain" e.snd) taggedVlans + )); interface = (lib.lists.optional ( (builtins.hasAttr "dhcpv4" untaggedVlan) || (builtins.hasAttr "dhcpv6" untaggedVlan) From 1ce047f470660652e8b856fa5d521f19c9a3de82 Mon Sep 17 00:00:00 2001 From: mkl Date: Thu, 5 Mar 2026 12:19:31 -0500 Subject: [PATCH 13/23] hosts/zerocool: added proxy forwarding for WAN --- hosts/zerocool/wan.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/hosts/zerocool/wan.nix b/hosts/zerocool/wan.nix index 8b0edd4..a58166e 100644 --- a/hosts/zerocool/wan.nix +++ b/hosts/zerocool/wan.nix @@ -9,6 +9,7 @@ networking.interfaces = { "${wanIface}" = { useDHCP = false; + proxyARP = true; ipv4.addresses = [ { address = wan.ipv4.address; From fd639e42abf8bf002c97a052876fda13c5273ee6 Mon Sep 17 00:00:00 2001 From: mkl Date: Fri, 6 Mar 2026 17:05:23 -0500 Subject: [PATCH 14/23] hosts/zerocool: exposed dhcp and dns ports --- hosts/zerocool/dhcp.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hosts/zerocool/dhcp.nix b/hosts/zerocool/dhcp.nix index 768777e..ef57bbb 100644 --- a/hosts/zerocool/dhcp.nix +++ b/hosts/zerocool/dhcp.nix @@ -25,6 +25,8 @@ let ); in { + # DNS, DHCPv4, DHCPv6 + networking.firewall.allowedUDPPorts = [ 53 67 547 ]; services.dnsmasq = { enable = true; settings = { From 4b5fb849e7daad9e5ef1f23bebfbe643e24b40a3 Mon Sep 17 00:00:00 2001 From: mkl Date: Fri, 6 Mar 2026 17:06:57 -0500 Subject: [PATCH 15/23] hosts/zerocool: added proxy arp hosts and disabled ipv4 nat for public hosts --- hosts/zerocool/configuration.nix | 18 ++++++++++++++++-- hosts/zerocool/firewall.nix | 22 +++++++++++++++------- hosts/zerocool/lan.nix | 14 ++++++++++++++ 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/hosts/zerocool/configuration.nix b/hosts/zerocool/configuration.nix index a0a3761..d5f263d 100644 --- a/hosts/zerocool/configuration.nix +++ b/hosts/zerocool/configuration.nix @@ -20,9 +20,15 @@ let tcpPorts = [ 22 2222 ]; udpPorts = [ 51820 ]; # Publicly routable IPv4 addresses only - exposeIpv4Hosts = []; + exposeIpv4Hosts = [ + "198.82.185.171" + "198.82.185.174" + ]; # Publicly routable IPv6 addresses only - exposeIpv6Hosts = []; + exposeIpv6Hosts = [ + "2607:b400:6:ce82:0:aff:fe62:f" + "2607:b400:6:ce83:225:90ff:fe9b:ed30" + ]; }; wgIface = "wg0"; @@ -65,6 +71,10 @@ let ipv4 = { address = "10.98.6.1"; cidr = 24; + # IPv4 hosts for ARP proxy + publicHosts = [ + "198.82.185.171" + ]; }; ipv6 = { address = "2607:b400:6:ce82::1"; @@ -80,6 +90,10 @@ let ipv4 = { address = "10.98.7.1"; cidr = 24; + # IPv4 hosts for ARP proxy + publicHosts = [ + "198.82.185.174" + ]; }; ipv6 = { address = "2607:b400:6:ce83::1"; diff --git a/hosts/zerocool/firewall.nix b/hosts/zerocool/firewall.nix index 499c40f..c1324be 100644 --- a/hosts/zerocool/firewall.nix +++ b/hosts/zerocool/firewall.nix @@ -111,13 +111,21 @@ let exposedIpv4Hosts = lib.strings.concatStringsSep "\n" ( builtins.map (daddr: '' - iifname { "${wanIface}" } daddr ${daddr} accept comment "Expose ${daddr} to WAN" + iifname { "${wanIface}" } ip daddr ${daddr} accept comment "Expose ${daddr} to WAN" + oifname { "${wanIface}" } ip saddr ${daddr} accept comment "Expose ${daddr} to WAN" + '') wan.exposeIpv4Hosts ); + exposedIpv4HostsNatDisable = lib.strings.concatStringsSep "," ( + builtins.map (toString) wan.exposeIpv4Hosts + ); + + exposedIpv6Hosts = lib.strings.concatStringsSep "\n" ( builtins.map (daddr: '' - iifname { "${wanIface}" } daddr ${daddr} accept comment "Expose ${daddr} to WAN" + iifname { "${wanIface}" } ip6 daddr ${daddr} accept comment "Expose ${daddr} to WAN" + oifname { "${wanIface}" } ip6 saddr ${daddr} accept comment "Expose ${daddr} to WAN" '') wan.exposeIpv6Hosts ); in @@ -153,6 +161,8 @@ in chain forward { type filter hook forward priority 0; policy drop; + ${exposedIpv4Hosts} + ${interVlanRoutingBlock} ${untaggedInterVlanBlock} @@ -162,15 +172,13 @@ in iifname { "${wgIface}" } oifname { "${lanIface}" } accept comment "Allow wireguard back to LANs" ${routerForward} - - ${exposedIpv4Hosts} } } table ip nat { chain postrouting { type nat hook postrouting priority 100; policy accept; - oifname "${wanIface}" masquerade comment "NAT IPv4 traffic to WAN" + oifname "${wanIface}" ip saddr != { ${exposedIpv4HostsNatDisable} } masquerade comment "NAT IPv4 traffic to WAN" } } @@ -203,6 +211,8 @@ in chain forward { type filter hook forward priority 0; policy drop; + ${exposedIpv6Hosts} + ${interVlanRoutingBlock} ${untaggedInterVlanBlock} @@ -215,8 +225,6 @@ in iifname "${lanIface}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept comment "Allow essential ND in FORWARD" ${routerIpv6NdForward} - - ${exposedIpv6Hosts} } } ''; diff --git a/hosts/zerocool/lan.nix b/hosts/zerocool/lan.nix index 1db7793..c6a26be 100644 --- a/hosts/zerocool/lan.nix +++ b/hosts/zerocool/lan.nix @@ -45,6 +45,13 @@ in prefixLength = e.snd.ipv6.cidr; } ]; + ipv4.routes = lib.optionals (builtins.hasAttr "publicHosts" e.snd.ipv4) ( + builtins.map (host: { + address = host; + prefixLength = 32; + }) e.snd.ipv4.publicHosts + ); + proxyARP = builtins.hasAttr "publicHosts" e.snd.ipv4; }; }) ( @@ -71,6 +78,13 @@ in prefixLength = untaggedVlan.ipv6.cidr; } ]; + ipv4.routes = lib.optionals (builtins.hasAttr "publicHosts" untaggedVlan.ipv4) ( + builtins.map (host: { + address = host; + prefixLength = 32; + }) untaggedVlan.ipv4.publicHosts + ); + proxyARP = builtins.hasAttr "publicHosts" untaggedVlan.ipv4; }; } ] From e63977d53f9092ea6eb019d4a4b52ebef6a53a9f Mon Sep 17 00:00:00 2001 From: mkl Date: Fri, 6 Mar 2026 17:41:10 -0500 Subject: [PATCH 16/23] hosts/zerocool: fixed wan cidr --- hosts/zerocool/configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hosts/zerocool/configuration.nix b/hosts/zerocool/configuration.nix index d5f263d..468816c 100644 --- a/hosts/zerocool/configuration.nix +++ b/hosts/zerocool/configuration.nix @@ -15,7 +15,7 @@ let ipv6 = { gateway = "2001:468:c80:6119::1"; address = "2001:468:c80:6119:82c1:6eff:fe21:2b88"; - cidr = 60; + cidr = 64; }; tcpPorts = [ 22 2222 ]; udpPorts = [ 51820 ]; From 902140361f9b6c83ca70dce2b0e2d1fb23e4051d Mon Sep 17 00:00:00 2001 From: mkl Date: Fri, 6 Mar 2026 18:22:19 -0500 Subject: [PATCH 17/23] hosts/zerocool: cleaned up firewall --- hosts/zerocool/firewall.nix | 131 ++++++++++-------------------------- 1 file changed, 36 insertions(+), 95 deletions(-) diff --git a/hosts/zerocool/firewall.nix b/hosts/zerocool/firewall.nix index c1324be..8a138d1 100644 --- a/hosts/zerocool/firewall.nix +++ b/hosts/zerocool/firewall.nix @@ -14,29 +14,6 @@ let ) ); - generateInterVlanBlockPairings = - list: - builtins.concatLists ( - map ( - x: - map ( - y: - ''iifname "vlan${x.fst}" oifname "vlan${y.fst}" drop comment "Drop vlan${x.fst} to vlan${y.fst} traffic"'' - ) (builtins.filter (y: x.fst != y.fst) list) - ) list - ); - - interVlanRoutingBlock = lib.strings.concatStringsSep "\n" ( - generateInterVlanBlockPairings taggedVlans - ); - - untaggedInterVlanBlock = lib.strings.concatStringsSep "\n" ( - builtins.map (e: '' - iifname "vlan${e.fst}" oifname "${lanIface}" drop comment "Drop vlan${e.fst} to ${lanIface} traffic" - iifname "${lanIface}" oifname "vlan${e.fst}" drop comment "Drop ${lanIface} to vlan${e.fst} traffic" - '') taggedVlans - ); - routerAccess = lib.strings.concatStringsSep "\n" ( builtins.map ( e: ''iifname { "vlan${e.fst}" } accept comment "Allow vlan${e.fst} to access the router"'' @@ -50,51 +27,17 @@ let ); deniedVlanDhcpv4Access = lib.strings.concatStringsSep "\n" ( - builtins.map - (e: '' - iifname { "vlan${e.fst}" } udp dport { 53, 67 } accept comment "Allow vlan${e.fst} DHCP and DNS access the router" - iifname { "vlan${e.fst}" } tcp dport 53 accept comment "Allow vlan${e.fst} TCP DNS access the router" - '') - ( - builtins.filter ( - e: - !e.snd.allowRouterAccess && (builtins.hasAttr "dhcpv4" e.snd) - ) taggedVlans - ) - ); - - deniedVlanDhcpv6Access = lib.strings.concatStringsSep "\n" ( - builtins.map - (e: '' - iifname { "vlan${e.fst}" } udp dport { 53, 547 } accept comment "Allow vlan${e.fst} DHCP and DNS access the router" - iifname { "vlan${e.fst}" } tcp dport 53 accept comment "Allow vlan${e.fst} TCP DNS access the router" - '') - ( - builtins.filter ( - e: - !e.snd.allowRouterAccess && (builtins.hasAttr "dhcpv6" e.snd) - ) taggedVlans - ) - ); - - - routerForward = lib.strings.concatStringsSep "\n" ( builtins.map (e: '' - iifname { "vlan${e.fst}" } oifname { "${wanIface}" } accept comment "Allow vlan${e.fst} to WAN" - iifname { "${wanIface}" } oifname { "vlan${e.fst}" } ct state established, related accept comment "Allow established back to vlan${e.fst}" - '') taggedVlans + iifname { "vlan${e.fst}" } udp dport { 53, 67 } accept comment "Allow vlan${e.fst} DHCP and DNS access the router" + iifname { "vlan${e.fst}" } tcp dport 53 accept comment "Allow vlan${e.fst} TCP DNS access the router" + '') (builtins.filter (e: !e.snd.allowRouterAccess && (builtins.hasAttr "dhcpv4" e.snd)) taggedVlans) ); - routerIpv6IcmpAccess = lib.strings.concatStringsSep "\n" ( - builtins.map (e: '' - iifname "vlan${e.fst}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } counter accept comment "Allow SLAAC and DHCPv6 on vlan${e.fst}" - '') taggedVlans - ); - - routerIpv6NdForward = lib.strings.concatStringsSep "\n" ( + deniedVlanDhcpv6Access = lib.strings.concatStringsSep "\n" ( builtins.map (e: '' - iifname "vlan${e.fst}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept comment "Allow essential ND in FORWARD on vlan${e.fst}" - '') taggedVlans + iifname { "vlan${e.fst}" } udp dport { 53, 547 } accept comment "Allow vlan${e.fst} DHCP and DNS access the router" + iifname { "vlan${e.fst}" } tcp dport 53 accept comment "Allow vlan${e.fst} TCP DNS access the router" + '') (builtins.filter (e: !e.snd.allowRouterAccess && (builtins.hasAttr "dhcpv6" e.snd)) taggedVlans) ); exposedUdpPorts = lib.strings.concatStringsSep "\n" ( @@ -121,7 +64,6 @@ let builtins.map (toString) wan.exposeIpv4Hosts ); - exposedIpv6Hosts = lib.strings.concatStringsSep "\n" ( builtins.map (daddr: '' iifname { "${wanIface}" } ip6 daddr ${daddr} accept comment "Expose ${daddr} to WAN" @@ -139,21 +81,20 @@ in chain input { type filter hook input priority 0; policy drop; + ct state { established, related } accept comment "Allow all established traffic" iifname { "${lanIface}" } accept comment "Allow local network to access the router" - iifname { "${wgIface}" } accept comment "Allow wireguard network to access the router" + iifname { "${wgIface}" } accept comment "Allow wireguard to access the router" - ${deniedVlanDhcpv4Access} ${routerAccess} + ${deniedVlanDhcpv4Access} - iifname "${wanIface}" ct state { established, related } accept comment "Allow established traffic" iifname "${wanIface}" icmp type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP" ${exposedUdpPorts} ${exposedTcpPorts} - iifname "${wanIface}" counter drop comment "Drop all other unsolicited traffic from wan" - ${routerDenyAccess} + iifname "${wanIface}" counter drop comment "Drop all other unsolicited traffic from wan" iif lo accept comment "Allow all loopback traffic" } @@ -161,17 +102,17 @@ in chain forward { type filter hook forward priority 0; policy drop; - ${exposedIpv4Hosts} - - ${interVlanRoutingBlock} - ${untaggedInterVlanBlock} + ct state { established, related } accept comment "Allow all established traffic" + iifname { "${lanIface}", "vlan*" } oifname { "${wanIface}" } accept comment "Allow all traffic going out" - iifname { "${lanIface}" } oifname { "${wanIface}" } accept comment "Allow trusted LAN to WAN" - iifname { "${wanIface}" } oifname { "${lanIface}" } ct state established, related accept comment "Allow established back to LANs" iifname { "${lanIface}" } oifname { "${wgIface}" } accept comment "Allow LAN to wireguard" iifname { "${wgIface}" } oifname { "${lanIface}" } accept comment "Allow wireguard back to LANs" - ${routerForward} + iifname "vlan*" oifname "vlan*" drop comment "Drop inter-VLAN traffic" + iifname "${lanIface}*" oifname "vlan*" drop comment "Drop LAN to VLAN traffic" + iifname "vlan*" oifname "${lanIface}*" drop comment "Drop VLAN to LAN traffic" + + ${exposedIpv4Hosts} } } @@ -186,45 +127,45 @@ in chain input { type filter hook input priority 0; policy drop; + ct state { established, related } accept comment "Allow all established traffic" iifname { "${lanIface}" } accept comment "Allow local network to access the router" iifname { "${wgIface}" } accept comment "Allow wireguard to access the router" - - ${deniedVlanDhcpv6Access} ${routerAccess} + ${deniedVlanDhcpv6Access} - iifname "${wanIface}" ct state { established, related } accept comment "Allow established traffic" - iifname "${wanIface}" icmpv6 type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP" + iifname { "${wanIface}", "${lanIface}", "vlan*" } icmpv6 type { + destination-unreachable, packet-too-big, time-exceeded, + parameter-problem, echo-request, echo-reply, + nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert + } accept comment "Allow essential ICMPv6" ${exposedUdpPorts} ${exposedTcpPorts} - iifname "${wanIface}" counter drop comment "Drop all other unsolicited traffic from WAN" - - iifname "${lanIface}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } counter accept comment "Allow SLAAC and DHCPv6" - ${routerIpv6IcmpAccess} - ${routerDenyAccess} + iifname "${wanIface}" counter drop comment "Drop all other unsolicited traffic from WAN" iif lo accept comment "Allow all loopback traffic" } + chain output { + type filter hook output priority 0; policy accept; + } + chain forward { type filter hook forward priority 0; policy drop; - ${exposedIpv6Hosts} - - ${interVlanRoutingBlock} - ${untaggedInterVlanBlock} + ct state { established, related } accept comment "Allow all established traffic" + iifname { "${lanIface}", "vlan*" } oifname { "${wanIface}" } accept comment "Allow all traffic going out" - iifname { "${lanIface}" } oifname { "${wanIface}" } accept comment "Allow trusted LAN to WAN" - iifname { "${wanIface}" } oifname { "${lanIface}" } ct state established, related accept comment "Allow established back to LANs" iifname { "${lanIface}" } oifname { "${wgIface}" } accept comment "Allow LAN to wireguard" iifname { "${wgIface}" } oifname { "${lanIface}" } accept comment "Allow wireguard back to LANs" - ${routerForward} + iifname "vlan*" oifname "vlan*" drop comment "Drop inter-VLAN traffic" + iifname "${lanIface}*" oifname "vlan*" drop comment "Drop LAN to VLAN traffic" + iifname "vlan*" oifname "${lanIface}*" drop comment "Drop VLAN to LAN traffic" - iifname "${lanIface}" ip6 nexthdr icmpv6 icmpv6 type { nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept comment "Allow essential ND in FORWARD" - ${routerIpv6NdForward} + ${exposedIpv6Hosts} } } ''; From c200ddcb6a3f7d2564d9d11ad11f161909f7dd58 Mon Sep 17 00:00:00 2001 From: mkl Date: Fri, 6 Mar 2026 18:22:36 -0500 Subject: [PATCH 18/23] hosts/zerocool: added essential networking packages --- hosts/zerocool/configuration.nix | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hosts/zerocool/configuration.nix b/hosts/zerocool/configuration.nix index 468816c..0dfb5aa 100644 --- a/hosts/zerocool/configuration.nix +++ b/hosts/zerocool/configuration.nix @@ -148,6 +148,16 @@ in }) ]; + environment.systemPackages = with pkgs; [ + neovim + helix + mtr + dig + tcpdump + ndisc6 + inetutils + ]; + networking.hostName = "zerocool"; system.stateVersion = "25.05"; } From 08cca101d5d585b7b80b37d34cb2e9a2f8ffdbeb Mon Sep 17 00:00:00 2001 From: mkl Date: Fri, 6 Mar 2026 18:26:53 -0500 Subject: [PATCH 19/23] hosts/zerocool: autoformat files --- hosts/zerocool/configuration.nix | 11 +++++++- hosts/zerocool/dhcp.nix | 12 ++++++--- hosts/zerocool/firewall.nix | 5 ---- hosts/zerocool/hardware-configuration.nix | 33 ++++++++++++++++------- hosts/zerocool/static-hosts.nix | 2 +- hosts/zerocool/wan.nix | 4 +-- hosts/zerocool/wireguard.nix | 5 ++-- 7 files changed, 48 insertions(+), 24 deletions(-) diff --git a/hosts/zerocool/configuration.nix b/hosts/zerocool/configuration.nix index 0dfb5aa..27cb83c 100644 --- a/hosts/zerocool/configuration.nix +++ b/hosts/zerocool/configuration.nix @@ -17,16 +17,23 @@ let address = "2001:468:c80:6119:82c1:6eff:fe21:2b88"; cidr = 64; }; - tcpPorts = [ 22 2222 ]; + tcpPorts = [ + 22 + 2222 + ]; udpPorts = [ 51820 ]; # Publicly routable IPv4 addresses only exposeIpv4Hosts = [ + # Scaryterry "198.82.185.171" + # Alex's box "198.82.185.174" ]; # Publicly routable IPv6 addresses only exposeIpv6Hosts = [ + # Scaryterry "2607:b400:6:ce82:0:aff:fe62:f" + # Alex's box "2607:b400:6:ce83:225:90ff:fe9b:ed30" ]; }; @@ -73,6 +80,7 @@ let cidr = 24; # IPv4 hosts for ARP proxy publicHosts = [ + # Scaryterry "198.82.185.171" ]; }; @@ -92,6 +100,7 @@ let cidr = 24; # IPv4 hosts for ARP proxy publicHosts = [ + # Alex's box "198.82.185.174" ]; }; diff --git a/hosts/zerocool/dhcp.nix b/hosts/zerocool/dhcp.nix index ef57bbb..d7dd8a2 100644 --- a/hosts/zerocool/dhcp.nix +++ b/hosts/zerocool/dhcp.nix @@ -26,15 +26,19 @@ let in { # DNS, DHCPv4, DHCPv6 - networking.firewall.allowedUDPPorts = [ 53 67 547 ]; + networking.firewall.allowedUDPPorts = [ + 53 + 67 + 547 + ]; services.dnsmasq = { enable = true; settings = { domain = (lib.lists.optional (builtins.hasAttr "domain" untaggedVlan) "${untaggedVlan.domain}.${globalDomain},${untaggedVlan.ipv4.address}/${toString untaggedVlan.ipv4.cidr}") - ++ (builtins.map (e: "${e.snd.domain}.${globalDomain},${e.snd.ipv4.address}/${toString e.snd.ipv4.cidr}") ( - builtins.filter (e: builtins.hasAttr "domain" e.snd) taggedVlans - )); + ++ (builtins.map ( + e: "${e.snd.domain}.${globalDomain},${e.snd.ipv4.address}/${toString e.snd.ipv4.cidr}" + ) (builtins.filter (e: builtins.hasAttr "domain" e.snd) taggedVlans)); interface = (lib.lists.optional ( (builtins.hasAttr "dhcpv4" untaggedVlan) || (builtins.hasAttr "dhcpv6" untaggedVlan) diff --git a/hosts/zerocool/firewall.nix b/hosts/zerocool/firewall.nix index 8a138d1..32be66e 100644 --- a/hosts/zerocool/firewall.nix +++ b/hosts/zerocool/firewall.nix @@ -56,7 +56,6 @@ let builtins.map (daddr: '' iifname { "${wanIface}" } ip daddr ${daddr} accept comment "Expose ${daddr} to WAN" oifname { "${wanIface}" } ip saddr ${daddr} accept comment "Expose ${daddr} to WAN" - '') wan.exposeIpv4Hosts ); @@ -148,10 +147,6 @@ in iif lo accept comment "Allow all loopback traffic" } - chain output { - type filter hook output priority 0; policy accept; - } - chain forward { type filter hook forward priority 0; policy drop; diff --git a/hosts/zerocool/hardware-configuration.nix b/hosts/zerocool/hardware-configuration.nix index fdebaf2..1e3ff38 100644 --- a/hosts/zerocool/hardware-configuration.nix +++ b/hosts/zerocool/hardware-configuration.nix @@ -1,14 +1,29 @@ # Do not modify this file! It was generated by ‘nixos-generate-config’ # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, modulesPath, ... }: +{ + config, + lib, + pkgs, + modulesPath, + ... +}: { - imports = - [ (modulesPath + "/installer/scan/not-detected.nix") - ]; + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; - boot.initrd.availableKernelModules = [ "uhci_hcd" "ehci_pci" "ata_piix" "hpsa" "usb_storage" "usbhid" "sd_mod" "sr_mod" ]; + boot.initrd.availableKernelModules = [ + "uhci_hcd" + "ehci_pci" + "ata_piix" + "hpsa" + "usb_storage" + "usbhid" + "sd_mod" + "sr_mod" + ]; boot.initrd.kernelModules = [ ]; boot.kernelModules = [ "kvm-intel" ]; boot.extraModulePackages = [ ]; @@ -16,10 +31,10 @@ boot.loader.grub.enable = true; boot.loader.grub.device = "/dev/sda"; - fileSystems."/" = - { device = "/dev/disk/by-uuid/d8144b9a-85d4-4ea3-938a-f21f2795d967"; - fsType = "ext4"; - }; + fileSystems."/" = { + device = "/dev/disk/by-uuid/d8144b9a-85d4-4ea3-938a-f21f2795d967"; + fsType = "ext4"; + }; swapDevices = [ ]; diff --git a/hosts/zerocool/static-hosts.nix b/hosts/zerocool/static-hosts.nix index 52da2b8..44ac731 100644 --- a/hosts/zerocool/static-hosts.nix +++ b/hosts/zerocool/static-hosts.nix @@ -1,4 +1,4 @@ - [ +[ { name = "switch"; mac = "00:12:a9:d5:d4:20"; diff --git a/hosts/zerocool/wan.nix b/hosts/zerocool/wan.nix index a58166e..0a23a7e 100644 --- a/hosts/zerocool/wan.nix +++ b/hosts/zerocool/wan.nix @@ -18,8 +18,8 @@ ]; ipv6.addresses = [ { - address = wan.ipv6.address; - prefixLength = wan.ipv6.cidr; + address = wan.ipv6.address; + prefixLength = wan.ipv6.cidr; } ]; }; diff --git a/hosts/zerocool/wireguard.nix b/hosts/zerocool/wireguard.nix index 0cb3ed0..5e15a13 100644 --- a/hosts/zerocool/wireguard.nix +++ b/hosts/zerocool/wireguard.nix @@ -11,10 +11,11 @@ allowedIPsAsRoutes = true; peers = [ - { # shellshock + { + # shellshock publicKey = "gEk7+YfwkxM89v+nqlGZTcaxMlhAN5vCCE8U+w+Vy2g="; endpoint = "128.173.88.191:51820"; - allowedIPs = [ + allowedIPs = [ "10.98.255.1/32" # wg fabric "10.98.0.0/22" # whit ]; From a61fc6c4bb78e8e667aea9bae4e9fcb5b2e83991 Mon Sep 17 00:00:00 2001 From: mkl Date: Fri, 6 Mar 2026 18:42:50 -0500 Subject: [PATCH 20/23] hosts/zerocool: updated dns to use local dnsmasq --- hosts/zerocool/configuration.nix | 1 - hosts/zerocool/dhcp.nix | 14 ++++++++++++++ hosts/zerocool/dns.nix | 7 ------- hosts/zerocool/wireguard.nix | 7 +++++-- 4 files changed, 19 insertions(+), 10 deletions(-) delete mode 100644 hosts/zerocool/dns.nix diff --git a/hosts/zerocool/configuration.nix b/hosts/zerocool/configuration.nix index 27cb83c..9ae3e69 100644 --- a/hosts/zerocool/configuration.nix +++ b/hosts/zerocool/configuration.nix @@ -131,7 +131,6 @@ in ../common/users-local.nix ../common/tz-locale.nix - ./dns.nix ./router.nix (import ./lan.nix { inherit lib lanIface lan; diff --git a/hosts/zerocool/dhcp.nix b/hosts/zerocool/dhcp.nix index d7dd8a2..3ec7133 100644 --- a/hosts/zerocool/dhcp.nix +++ b/hosts/zerocool/dhcp.nix @@ -25,12 +25,18 @@ let ); in { + networking.nameservers = [ + "::" + "127.0.0.1" + ]; + # DNS, DHCPv4, DHCPv6 networking.firewall.allowedUDPPorts = [ 53 67 547 ]; + services.dnsmasq = { enable = true; settings = { @@ -39,6 +45,14 @@ in ++ (builtins.map ( e: "${e.snd.domain}.${globalDomain},${e.snd.ipv4.address}/${toString e.snd.ipv4.cidr}" ) (builtins.filter (e: builtins.hasAttr "domain" e.snd) taggedVlans)); + server = [ + "9.9.9.9" + "2620:fe::fe" + "1.1.1.1" + "2606:4700:4700::1111" + "/whit.vtluug.org/10.98.3.2" + "/bastille.vtluug.org/10.98.3.2" + ]; interface = (lib.lists.optional ( (builtins.hasAttr "dhcpv4" untaggedVlan) || (builtins.hasAttr "dhcpv6" untaggedVlan) diff --git a/hosts/zerocool/dns.nix b/hosts/zerocool/dns.nix deleted file mode 100644 index 86be9cb..0000000 --- a/hosts/zerocool/dns.nix +++ /dev/null @@ -1,7 +0,0 @@ -{ config, pkgs, ... }: -{ - networking.nameservers = [ - "1.1.1.1" - "9.9.9.9" - ]; -} diff --git a/hosts/zerocool/wireguard.nix b/hosts/zerocool/wireguard.nix index 5e15a13..42916a1 100644 --- a/hosts/zerocool/wireguard.nix +++ b/hosts/zerocool/wireguard.nix @@ -16,8 +16,11 @@ publicKey = "gEk7+YfwkxM89v+nqlGZTcaxMlhAN5vCCE8U+w+Vy2g="; endpoint = "128.173.88.191:51820"; allowedIPs = [ - "10.98.255.1/32" # wg fabric - "10.98.0.0/22" # whit + # Wireguard fabric + "10.98.255.1/32" + + # Whittemore + "10.98.0.0/22" ]; persistentKeepalive = 25; } From 2ab191b3d0604cf26e88407153c1187bb3b69560 Mon Sep 17 00:00:00 2001 From: mkl Date: Sat, 7 Mar 2026 07:03:11 -0500 Subject: [PATCH 21/23] hosts/zerocool: cleaned up firewall rules and added selective vlan isolation rather than global isolation --- hosts/zerocool/configuration.nix | 4 ++ hosts/zerocool/dhcp.nix | 12 +++--- hosts/zerocool/firewall.nix | 69 +++++++++++++++++++++++--------- 3 files changed, 61 insertions(+), 24 deletions(-) diff --git a/hosts/zerocool/configuration.nix b/hosts/zerocool/configuration.nix index 9ae3e69..ed7b9ce 100644 --- a/hosts/zerocool/configuration.nix +++ b/hosts/zerocool/configuration.nix @@ -52,6 +52,7 @@ let address = "2607:b400:6:ce80::1"; cidr = 64; }; + isolate = true; allowRouterAccess = true; domain = "mgmt"; dhcpv4 = "10.98.4.128,10.98.4.254,12h"; @@ -67,6 +68,7 @@ let address = "2607:b400:6:ce81::1"; cidr = 64; }; + isolate = false; allowRouterAccess = true; untagged = true; domain = "internal"; @@ -88,6 +90,7 @@ let address = "2607:b400:6:ce82::1"; cidr = 64; }; + isolate = false; allowRouterAccess = true; domain = "g"; dhcpv4 = "10.98.6.128,10.98.6.254,12h"; @@ -108,6 +111,7 @@ let address = "2607:b400:6:ce83::1"; cidr = 64; }; + isolate = true; allowRouterAccess = false; domain = "colo"; dhcpv4 = "10.98.7.128,10.98.7.254,12h"; diff --git a/hosts/zerocool/dhcp.nix b/hosts/zerocool/dhcp.nix index 3ec7133..89e2319 100644 --- a/hosts/zerocool/dhcp.nix +++ b/hosts/zerocool/dhcp.nix @@ -46,12 +46,12 @@ in e: "${e.snd.domain}.${globalDomain},${e.snd.ipv4.address}/${toString e.snd.ipv4.cidr}" ) (builtins.filter (e: builtins.hasAttr "domain" e.snd) taggedVlans)); server = [ - "9.9.9.9" - "2620:fe::fe" - "1.1.1.1" - "2606:4700:4700::1111" - "/whit.vtluug.org/10.98.3.2" - "/bastille.vtluug.org/10.98.3.2" + "9.9.9.9" + "2620:fe::fe" + "1.1.1.1" + "2606:4700:4700::1111" + "/whit.vtluug.org/10.98.3.2" + "/bastille.vtluug.org/10.98.3.2" ]; interface = (lib.lists.optional ( diff --git a/hosts/zerocool/firewall.nix b/hosts/zerocool/firewall.nix index 32be66e..10c3187 100644 --- a/hosts/zerocool/firewall.nix +++ b/hosts/zerocool/firewall.nix @@ -8,6 +8,10 @@ ... }: let + untaggedVlan = lib.lists.findFirst ( + e: builtins.hasAttr "untagged" e + ) (throw "Must have untagged VLAN") (builtins.attrValues lan); + taggedVlans = ( builtins.filter (e: !builtins.hasAttr "untagged" e.snd) ( lib.lists.zipLists (builtins.attrNames lan) (builtins.attrValues lan) @@ -18,12 +22,38 @@ let builtins.map ( e: ''iifname { "vlan${e.fst}" } accept comment "Allow vlan${e.fst} to access the router"'' ) (builtins.filter (e: e.snd.allowRouterAccess) taggedVlans) + ++ (lib.lists.optional (untaggedVlan.allowRouterAccess) ''iifname { "${lanIface}" } accept comment "Allow ${lanIface} to access the router"'') ); routerDenyAccess = lib.strings.concatStringsSep "\n" ( builtins.map ( e: ''iifname { "vlan${e.fst}" } drop comment "Deny vlan${e.fst} to access the router"'' ) (builtins.filter (e: !e.snd.allowRouterAccess) taggedVlans) + ++ (lib.lists.optional ( + !untaggedVlan.allowRouterAccess + ) ''iifname { "${lanIface}" } drop comment "Deny ${lanIface} to access the router"'') + ); + + isolateVlans = lib.strings.concatStringsSep "\n" ( + builtins.map (e: '' + iifname { "vlan${e.fst}" } oifname { "${lanIface}", "${wgIface}", "vlan*" } drop comment "Isolate vlan${e.fst} from luug network" + iifname { "${lanIface}", "${wgIface}", "vlan*" } oifname { "vlan${e.fst}" } drop comment "Allow luug network from vlan${e.fst}" + '') (builtins.filter (e: e.snd.isolate) taggedVlans) + ++ (lib.lists.optional (untaggedVlan.isolate) '' + iifname { "${lanIface}" } oifname { "${wgIface}", "vlan*" } drop comment "Isolate ${lanIface} from luug network" + iifname { "${wgIface}", "vlan*" } oifname { "${lanIface}" } drop comment "Isolate luug network from ${lanIface}" + '') + ); + + luugNetworkForward = lib.strings.concatStringsSep "\n" ( + builtins.map (e: '' + iifname { "vlan${e.fst}" } oifname { "${lanIface}", "${wgIface}", "vlan*" } accept comment "Allow vlan${e.fst} to luug network" + iifname { "${lanIface}", "${wgIface}", "vlan*" } oifname { "vlan${e.fst}" } accept comment "Allow luug network to vlan${e.fst}" + '') (builtins.filter (e: !e.snd.isolate) taggedVlans) + ++ (lib.lists.optional (!untaggedVlan.isolate) '' + iifname { "${lanIface}" } oifname { "${wgIface}", "vlan*"} accept comment "Allow ${lanIface} to luug network" + iifname { "${wgIface}", "vlan*" } oifname { "${lanIface}" } accept comment "Allow luug network to ${lanIface}" + '') ); deniedVlanDhcpv4Access = lib.strings.concatStringsSep "\n" ( @@ -31,6 +61,12 @@ let iifname { "vlan${e.fst}" } udp dport { 53, 67 } accept comment "Allow vlan${e.fst} DHCP and DNS access the router" iifname { "vlan${e.fst}" } tcp dport 53 accept comment "Allow vlan${e.fst} TCP DNS access the router" '') (builtins.filter (e: !e.snd.allowRouterAccess && (builtins.hasAttr "dhcpv4" e.snd)) taggedVlans) + ++ (lib.lists.optional (!untaggedVlan.allowRouterAccess && (builtins.hasAttr "dhcpv4" untaggedVlan)) + '' + iifname { "${lanIface}" } udp dport { 53, 67 } accept comment "Allow ${lanIface} DHCP and DNS access the router" + iifname { "${lanIface}" } tcp dport 53 accept comment "Allow ${lanIface} TCP DNS access the router" + '' + ) ); deniedVlanDhcpv6Access = lib.strings.concatStringsSep "\n" ( @@ -38,6 +74,12 @@ let iifname { "vlan${e.fst}" } udp dport { 53, 547 } accept comment "Allow vlan${e.fst} DHCP and DNS access the router" iifname { "vlan${e.fst}" } tcp dport 53 accept comment "Allow vlan${e.fst} TCP DNS access the router" '') (builtins.filter (e: !e.snd.allowRouterAccess && (builtins.hasAttr "dhcpv6" e.snd)) taggedVlans) + ++ (lib.lists.optional (!untaggedVlan.allowRouterAccess && (builtins.hasAttr "dhcpv6" untaggedVlan)) + '' + iifname { "${lanIface}" } udp dport { 53, 547 } accept comment "Allow ${lanIface} DHCP and DNS access the router" + iifname { "${lanIface}" } tcp dport 53 accept comment "Allow ${lanIface} TCP DNS access the router" + '' + ) ); exposedUdpPorts = lib.strings.concatStringsSep "\n" ( @@ -81,14 +123,13 @@ in type filter hook input priority 0; policy drop; ct state { established, related } accept comment "Allow all established traffic" - iifname { "${lanIface}" } accept comment "Allow local network to access the router" iifname { "${wgIface}" } accept comment "Allow wireguard to access the router" + iifname { "${wanIface}", "${lanIface}", "vlan*" } icmp type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP" + ${routerAccess} ${deniedVlanDhcpv4Access} - iifname "${wanIface}" icmp type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP" - ${exposedUdpPorts} ${exposedTcpPorts} @@ -104,12 +145,8 @@ in ct state { established, related } accept comment "Allow all established traffic" iifname { "${lanIface}", "vlan*" } oifname { "${wanIface}" } accept comment "Allow all traffic going out" - iifname { "${lanIface}" } oifname { "${wgIface}" } accept comment "Allow LAN to wireguard" - iifname { "${wgIface}" } oifname { "${lanIface}" } accept comment "Allow wireguard back to LANs" - - iifname "vlan*" oifname "vlan*" drop comment "Drop inter-VLAN traffic" - iifname "${lanIface}*" oifname "vlan*" drop comment "Drop LAN to VLAN traffic" - iifname "vlan*" oifname "${lanIface}*" drop comment "Drop VLAN to LAN traffic" + ${isolateVlans} + ${luugNetworkForward} ${exposedIpv4Hosts} } @@ -127,10 +164,7 @@ in type filter hook input priority 0; policy drop; ct state { established, related } accept comment "Allow all established traffic" - iifname { "${lanIface}" } accept comment "Allow local network to access the router" iifname { "${wgIface}" } accept comment "Allow wireguard to access the router" - ${routerAccess} - ${deniedVlanDhcpv6Access} iifname { "${wanIface}", "${lanIface}", "vlan*" } icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, @@ -138,6 +172,9 @@ in nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept comment "Allow essential ICMPv6" + ${routerAccess} + ${deniedVlanDhcpv6Access} + ${exposedUdpPorts} ${exposedTcpPorts} @@ -153,12 +190,8 @@ in ct state { established, related } accept comment "Allow all established traffic" iifname { "${lanIface}", "vlan*" } oifname { "${wanIface}" } accept comment "Allow all traffic going out" - iifname { "${lanIface}" } oifname { "${wgIface}" } accept comment "Allow LAN to wireguard" - iifname { "${wgIface}" } oifname { "${lanIface}" } accept comment "Allow wireguard back to LANs" - - iifname "vlan*" oifname "vlan*" drop comment "Drop inter-VLAN traffic" - iifname "${lanIface}*" oifname "vlan*" drop comment "Drop LAN to VLAN traffic" - iifname "vlan*" oifname "${lanIface}*" drop comment "Drop VLAN to LAN traffic" + ${isolateVlans} + ${luugNetworkForward} ${exposedIpv6Hosts} } From 2926a70dff49cbd474f7a10d3ad00bde150dff5c Mon Sep 17 00:00:00 2001 From: mkl Date: Sat, 7 Mar 2026 07:10:30 -0500 Subject: [PATCH 22/23] hosts/zerocool: removed scaryterry --- hosts/zerocool/configuration.nix | 9 +-------- hosts/zerocool/lan.nix | 2 -- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/hosts/zerocool/configuration.nix b/hosts/zerocool/configuration.nix index ed7b9ce..a2cb45a 100644 --- a/hosts/zerocool/configuration.nix +++ b/hosts/zerocool/configuration.nix @@ -24,15 +24,11 @@ let udpPorts = [ 51820 ]; # Publicly routable IPv4 addresses only exposeIpv4Hosts = [ - # Scaryterry - "198.82.185.171" # Alex's box "198.82.185.174" ]; # Publicly routable IPv6 addresses only exposeIpv6Hosts = [ - # Scaryterry - "2607:b400:6:ce82:0:aff:fe62:f" # Alex's box "2607:b400:6:ce83:225:90ff:fe9b:ed30" ]; @@ -81,10 +77,7 @@ let address = "10.98.6.1"; cidr = 24; # IPv4 hosts for ARP proxy - publicHosts = [ - # Scaryterry - "198.82.185.171" - ]; + publicHosts = [ ]; }; ipv6 = { address = "2607:b400:6:ce82::1"; diff --git a/hosts/zerocool/lan.nix b/hosts/zerocool/lan.nix index c6a26be..9f6294a 100644 --- a/hosts/zerocool/lan.nix +++ b/hosts/zerocool/lan.nix @@ -51,7 +51,6 @@ in prefixLength = 32; }) e.snd.ipv4.publicHosts ); - proxyARP = builtins.hasAttr "publicHosts" e.snd.ipv4; }; }) ( @@ -84,7 +83,6 @@ in prefixLength = 32; }) untaggedVlan.ipv4.publicHosts ); - proxyARP = builtins.hasAttr "publicHosts" untaggedVlan.ipv4; }; } ] From d517005386952b4d1ce061cacf67f52d42939276 Mon Sep 17 00:00:00 2001 From: mkl Date: Sat, 7 Mar 2026 13:02:19 -0500 Subject: [PATCH 23/23] hosts/zerocool: fixed proxy arp --- hosts/zerocool/lan.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hosts/zerocool/lan.nix b/hosts/zerocool/lan.nix index 9f6294a..649f6bb 100644 --- a/hosts/zerocool/lan.nix +++ b/hosts/zerocool/lan.nix @@ -51,6 +51,7 @@ in prefixLength = 32; }) e.snd.ipv4.publicHosts ); + proxyARP = (builtins.hasAttr "publicHosts" e.snd.ipv4) && (builtins.length e.snd.ipv4.publicHosts > 0); }; }) ( @@ -83,6 +84,8 @@ in prefixLength = 32; }) untaggedVlan.ipv4.publicHosts ); + proxyARP = (builtins.hasAttr "publicHosts" untaggedVlan.ipv4) && (builtins.length untaggedVlan.ipv4.publicHosts > 0); + }; } ]