{ hostName }: { pkgs, ... }: let wan = "end0"; lan = "enp1s0"; bridge = "br-lan"; devices = "devices-vlan"; wifi = "wifi-vlan"; in { boot.kernel = { sysctl = { "net.ipv6.conf.all.forwarding" = 1; "net.ipv6.conf.${bridge}.accept_ra" = 2; "net.ipv6.conf.${devices}.accept_ra" = 2; "net.ipv6.conf.${wifi}.accept_ra" = 2; "net.ipv4.conf.all.forwarding" = true; "net.ipv4.conf.default.rp_filter" = 1; "net.ipv4.conf.${wan}.rp_filter" = 1; "net.ipv4.conf.${bridge}.rp_filter" = 0; "net.ipv4.conf.${devices}.rp_filter" = 0; "net.ipv4.conf.${wifi}.rp_filter" = 0; }; }; environment.systemPackages = with pkgs; [ arp-scan ]; systemd.network = { wait-online.anyInterface = true; netdevs = { # Attempted hack for more ipv6 prefixes # I got the prefixes but networkd wasn't smart enough to use them # "00-vrrp-1" = { # netdevConfig = { # Name = "vrrp-1"; # Kind = "macvlan"; # MACAddress = "00:00:5e:00:01:05"; # }; # macvlanConfig.Mode = "bridge"; # }; # "00-vrrp-2" = { # netdevConfig = { # Name = "vrrp-2"; # Kind = "macvlan"; # MACAddress = "00:00:5e:00:02:05"; # }; # macvlanConfig.Mode = "bridge"; # }; # "00-vrrp-3" = { # netdevConfig = { # Name = "vrrp-3"; # Kind = "macvlan"; # MACAddress = "00:00:5e:00:03:05"; # }; # macvlanConfig.Mode = "bridge"; # }; "10-${devices}" = { netdevConfig = { Name = devices; Kind = "vlan"; }; vlanConfig.Id = 30; }; "10-${wifi}" = { netdevConfig = { Name = wifi; Kind = "vlan"; }; vlanConfig.Id = 40; }; "20-${bridge}" = { netdevConfig = { Kind = "bridge"; Name = bridge; }; }; }; networks = { # "05-vrrp" = { # matchConfig.Name = "vrrp-*"; # linkConfig.RequiredForOnline = "routable"; # networkConfig = { # DHCP = "ipv6"; # IPv6AcceptRA = true; # DNSOverTLS = true; # DNSSEC = true; # IPv6PrivacyExtensions = true; # IPForward = true; # LinkLocalAddressing = "ipv6"; # }; # dhcpV6Config.PrefixDelegationHint = "::/64"; # }; "06-${wan}" = { matchConfig.Name = wan; linkConfig.RequiredForOnline = "routable"; networkConfig = { DHCP = true; IPv6AcceptRA = true; DNSOverTLS = true; DNSSEC = true; IPv6PrivacyExtensions = true; IPForward = true; LinkLocalAddressing = "ipv6"; # MACVLAN = [ "vrrp-1" "vrrp-2" "vrrp-3" ]; }; }; "30-${lan}" = { matchConfig.Name = lan; linkConfig.RequiredForOnline = "enslaved"; networkConfig = { Bridge = bridge; ConfigureWithoutCarrier = true; VLAN = [ devices wifi ]; }; }; "40-${bridge}" = { matchConfig.Name = bridge; bridgeConfig = { }; address = [ "192.168.20.1/24" ]; networkConfig = { ConfigureWithoutCarrier = true; IPv6SendRA = true; DHCPPrefixDelegation = true; LinkLocalAddressing = "ipv6"; }; linkConfig.RequiredForOnline = "no"; }; "50-${devices}" = { matchConfig = { Name = devices; Type = "vlan"; }; address = [ "192.168.30.1/24" ]; networkConfig = { }; linkConfig.RequiredForOnline = "routable"; }; "50-${wifi}" = { matchConfig = { Name = wifi; Type = "vlan"; }; address = [ "192.168.40.1/24" ]; networkConfig = { }; linkConfig.RequiredForOnline = "routable"; }; }; }; networking = { inherit hostName; useNetworkd = true; useDHCP = false; nat.enable = false; firewall.enable = false; nftables = { enable = true; checkRuleset = false; ruleset = '' define WAN=${wan} define LAN=${lan} define BRIDGE=${bridge} define DEVICES=${devices} define WIFI=${wifi} define HTTP_HOST=192.168.20.200 define FORGEJO_HOST=192.168.20.201 define FORGEJO_SSH_PORT=2222 define DRAWPILE_HOST=192.168.20.202 define DRAWPILE_TCP_PORT=27750 table inet filter { set hosted_services_tcp { type inet_service; flags interval; elements = { 22, 80, 443, $DRAWPILE_TCP_PORT } } set internal_access_tcp { type inet_service; flags interval; elements = { 22, 3128 } } set internal_access_udp { type inet_service; flags interval; elements = { 51820 } } set network_required_udp { type inet_service; flags interval; elements = { 53, 67, 68, 546, 547 } } set firewall_out_tcp_accepted { type inet_service; flags interval; elements = { 22, 53, 80, 443, 853 } } set firewall_out_udp_accepted { type inet_service; flags interval; elements = { 53, 123, 67, 68, 546, 547 } } chain global { ct state { established, related } accept ct state invalid drop ip protocol icmp accept ip6 nexthdr icmpv6 accept } chain reject_politely { reject with icmp type port-unreachable } chain bridge_in { tcp dport @hosted_services_tcp ct state new accept comment "Allow bridge access to router services" } chain bridge_out { accept } chain devices_in {} chain devices_out { udp dport 123 ct state new accept comment "Allow NTP from devices network" tcp dport { 80, 443 } ct state new accept comment "Allow HTTP/S from devices network" } chain wifi_in {} chain wifi_out { accept } chain rate_limit { flow table rate-limit-ftable { ip saddr limit rate 2/minute } accept comment "Allow rate limited" } chain forward { type filter hook forward priority filter; policy drop; jump global oifname vmap { $BRIDGE : jump bridge_in, $DEVICES : jump devices_in, $WIFI : jump wifi_in } oifname $WAN iifname vmap { $BRIDGE : jump bridge_out, $DEVICES : jump devices_out, $WIFI : jump wifi_out } } chain input { type filter hook input priority 0; policy drop; jump global iifname lo accept tcp dport @internal_access_tcp ct state new iifname vmap { $BRIDGE : accept, $DEVICES : jump reject_politely, $WIFI : jump rate_limit, $WAN : jump rate_limit } udp dport @internal_access_udp ct state new iifname vmap { $BRIDGE : accept, $DEVICES : jump reject_politely, $WIFI : jump rate_limit, $WAN : jump rate_limit } udp dport @network_required_udp ct state new accept comment "Allow internal network required stuff" jump reject_politely } chain output { type filter hook output priority 100; policy drop; jump global tcp dport @firewall_out_tcp_accepted ct state new accept udp dport @firewall_out_udp_accepted ct state new accept jump reject_politely } } table ip nat { chain prerouting { type nat hook prerouting priority -100; policy accept; fib daddr type local tcp dport { 80, 443 } dnat to $HTTP_HOST fib daddr type local tcp dport 22 dnat to $FORGEJO_HOST:$FORGEJO_SSH_PORT fib daddr type local tcp dport $DRAWPILE_TCP_PORT dnat to $DRAWPILE_HOST } chain postrouting { type nat hook postrouting priority 100; policy accept; oifname $WAN masquerade oifname $BRIDGE masquerade } } ''; }; }; services.openssh.ports = [ 22 3128 ]; services.resolved.enable = false; services.dnsmasq = { enable = true; settings = { server = [ "9.9.9.9" "9.9.9.10" ]; domain-needed = true; bogus-priv = true; no-resolv = true; # dhcpv6 stuff # enable-ra = true; # dhcp-authoritative = true; # strict-order = true; cache-size = 1000; dhcp-range = [ # format TAG,START,END,?MASK,?options,LEASE "${bridge},192.168.20.50,192.168.20.90,24h" "${devices},192.168.30.10,192.168.30.240,24h" "${wifi},192.168.40.10,192.168.40.240,24h" ]; interface = [ bridge devices wifi ]; dhcp-option = [ "${bridge},option:router,192.168.20.1" "${bridge},option:dns-server,192.168.20.1" "${devices},option:router,192.168.30.1" "${devices},option:dns-server,192.168.30.1" "${wifi},option:router,192.168.40.1" "${wifi},option:dns-server,192.168.40.1" ]; local = "/lan/"; domain = "lan"; expand-hosts = true; no-hosts = true; address = [ "/router.lan/192.168.20.1" ]; }; }; services.irqbalance.enable = false; }