From ecfe589b60d9d789f26cc4b3f2e8c5d9d697dfbc Mon Sep 17 00:00:00 2001 From: Stefan Junker Date: Thu, 28 Dec 2023 11:22:39 +0100 Subject: [PATCH] router0-dmz0: dnssec, local names, code cleanup --- nix/os/devices/router0-dmz0/configuration.nix | 151 +++++++++++++----- nix/os/devices/router0-dmz0/default.nix | 5 +- nix/os/devices/router0-dmz0/flake.nix | 1 - 3 files changed, 114 insertions(+), 43 deletions(-) diff --git a/nix/os/devices/router0-dmz0/configuration.nix b/nix/os/devices/router0-dmz0/configuration.nix index 2279647..98bc922 100644 --- a/nix/os/devices/router0-dmz0/configuration.nix +++ b/nix/os/devices/router0-dmz0/configuration.nix @@ -5,6 +5,7 @@ config, nodeFlake, nodeName, + localDomainName, system, ... }: let @@ -32,7 +33,7 @@ [ "192" "168" (toString (vlanid + offset)) "${toString host}${lib.strings.optionalString cidr "/24"}" ]; defaultVlan = { - name = "internal"; + name = "${localDomainName}"; packet_priority = 0; }; @@ -55,6 +56,13 @@ "15".name = "iot2"; "15".packet_priority = -10; }; + + vlansByName = lib.attrsets.mapAttrs' (vlanid': attrs: + lib.attrsets.nameValuePair + attrs.name + (attrs // { id = lib.strings.toInt vlanid'; id' = vlanid';}) + ) vlans; + getVlanDomain = { vlanid }: if vlanid == 0 then @@ -62,6 +70,13 @@ else vlans."${toString vlanid}".name + "." + defaultVlan.name ; + + bridgeInterfaceName = "br-lan"; + mkInterfaceName = { vlanid }: + if vlanid == 0 + then bridgeInterfaceName + else "${bridgeInterfaceName}.${toString vlanid}" + ; in { imports = [ repoFlake.inputs.sops-nix.nixosModules.sops @@ -164,13 +179,16 @@ in { firewall = { enable = true; zones = { - lan.interfaces = [ "br-lan" ]; - vlan.interfaces = builtins.map (vlanid: "br-lan.${toString vlanid}") vlanRange; + lan.interfaces = [ (mkInterfaceName {vlanid = 0;}) ]; + vlan.interfaces = builtins.map (vlanid: (mkInterfaceName {inherit vlanid;})) vlanRange; # lan.ipv4Addresses = ["192.168.0.0/16"]; wan.interfaces = ["wan" "lan0"]; } // - # TODO: generate a zone for each vlan - {} + # generate a zone for each vlan + lib.attrsets.mapAttrs (key: value: { + interfaces = [ (mkInterfaceName { vlanid = value.id; }) ]; + }) + vlansByName ; rules = let ipv6IcmpTypes = [ @@ -194,6 +212,12 @@ in { verdict = "accept"; }; + office-to-dmz = { + from = ["office"]; + to = ["dmz"]; + verdict = "accept"; + }; + lan-to-fw = { from = ["lan"]; to = ["fw" "lan"]; @@ -258,10 +282,10 @@ in { wait-online.anyInterface = true; netdevs = { # Create the bridge interface - "20-br-lan" = { + "20-${bridgeInterfaceName}" = { netdevConfig = { Kind = "bridge"; - Name = "br-lan"; + Name = bridgeInterfaceName; }; extraConfig = '' @@ -280,10 +304,10 @@ in { {} (builtins.map ({ vlanid, vlanid' }: { - "20-br-lan.${vlanid'}" = { + "20-${mkInterfaceName { inherit vlanid; }}" = { netdevConfig = { Kind = "vlan"; - Name = "br-lan.${vlanid'}"; + Name = "${mkInterfaceName { inherit vlanid; }}"; }; vlanConfig.Id = vlanid; }; @@ -331,24 +355,45 @@ in { "30-lan1" = { matchConfig.Name = "lan1"; networkConfig = { - Bridge = "br-lan"; + Bridge = bridgeInterfaceName; ConfigureWithoutCarrier = true; }; linkConfig.RequiredForOnline = "enslaved"; + + bridgeVLANs = [ + { + bridgeVLANConfig = { + VLAN = vlansByName.dmz.id; + PVID = vlansByName.dmz.id; + EgressUntagged = vlansByName.dmz.id; + }; + } + ]; }; + "30-lan2" = { matchConfig.Name = "lan2"; networkConfig = { - Bridge = "br-lan"; + Bridge = bridgeInterfaceName; ConfigureWithoutCarrier = true; }; linkConfig.RequiredForOnline = "enslaved"; + + bridgeVLANs = [ + { + bridgeVLANConfig = { + VLAN = vlansByName.office.id; + PVID = vlansByName.office.id; + EgressUntagged = vlansByName.office.id; + }; + } + ]; }; "30-lan3" = { matchConfig.Name = "lan3"; networkConfig = { - Bridge = "br-lan"; + Bridge = bridgeInterfaceName; ConfigureWithoutCarrier = true; }; linkConfig.RequiredForOnline = "enslaved"; @@ -360,11 +405,10 @@ in { }; } ]; - }; # Configure the bridge for its desired function - "40-br-lan" = { - matchConfig.Name = "br-lan"; + "40-${bridgeInterfaceName}" = { + matchConfig.Name = bridgeInterfaceName; bridgeConfig = {}; address = [ (mkVlanIpv4HostAddr { vlanid = 0; host = 1;}) @@ -385,7 +429,7 @@ in { ]; vlan = (builtins.map - (vlanid: "br-lan.${builtins.toString vlanid}") + (vlanid: (mkInterfaceName { inherit vlanid; })) vlanRange ); }; @@ -404,8 +448,8 @@ in { # configure the tagged vlan device with an address and vlan filtering. # dnsmasq is configured to serve the respective /24 range on each tagged device. # this device only receives traffic for the given vlanid and sends tagged traffic to the bridge. - "41-br-lan.${vlanid'}" = { - matchConfig.Name = "br-lan.${vlanid'}"; + "41-${mkInterfaceName { inherit vlanid; }}" = { + matchConfig.Name = "${mkInterfaceName { inherit vlanid; }}"; address = [ (mkVlanIpv4HostAddr { inherit vlanid; host = 1; }) ]; @@ -432,7 +476,7 @@ in { "41-wlan0.${vlanid'}" = { matchConfig.Name = "wlan0.${vlanid'}"; networkConfig = { - Bridge = "br-lan"; + Bridge = bridgeInterfaceName; ConfigureWithoutCarrier = true; }; @@ -449,8 +493,8 @@ in { ]; }; - "50-br-lan.${vlanid'}" = { - matchConfig.Name = "br-lan.${vlanid'}"; + "50-${mkInterfaceName { inherit vlanid; }}" = { + matchConfig.Name = "${mkInterfaceName { inherit vlanid; }}"; address = [ (mkVlanIpv4HostAddr { inherit vlanid; host = 1; }) ]; @@ -498,15 +542,17 @@ in { authentication.wpaPskFile = config.sops.secrets."${iface}_wpaPskFile".path; authentication.saePasswordsFile = config.sops.secrets."${iface}_saePasswordsFile".path; + # see https://w1.fi/cgit/hostap/plain/hostapd/hostapd.conf for reference settings = { - # bridge = "br-lan"; + # bridge = bridgeInterfaceName; # wpa_psk_file = config.sops.secrets.wlan0_wpaPskFile.path; # not yet supported on hostapd 2.10 # sae_password_file = config.sops.secrets.wlan0_saePasswordsFile.path; - logger_stdout_level= lib.mkForce 0; - logger_syslog_level= lib.mkForce 0; + # enables debug logging + # logger_stdout_level= lib.mkForce 0; + # logger_syslog_level= lib.mkForce 0; # resources on vlan tagging # https://wireless.wiki.kernel.org/en/users/Documentation/hostapd#dynamic_vlan_tagging @@ -517,7 +563,7 @@ in { vlan_no_bridge = 1; /* not used due to the above vlan_no_bridge setting - vlan_tagged_interface = "br-lan"; + vlan_tagged_interface = bridgeInterfaceName; vlan_naming = 1; vlan_bridge = "br-${iface}."; */ @@ -568,7 +614,7 @@ in { # bssid = mkBssid 1; # settings = { - # bridge = "br-lan"; + # bridge = bridgeInterfaceName; # }; # }; @@ -581,7 +627,7 @@ in { # managementFrameProtection = "optional"; # bssid = "e6:02:43:07:00:00"; # settings = { - # bridge = "br-lan"; + # bridge = bridgeInterfaceName; # wpa = lib.mkForce 2; # wpa_key_mgmt = "WPA-PSK"; # wpa_pairwise = "CCMP"; @@ -673,7 +719,7 @@ in { # }; # bssid = "36:b9:02:21:08:a2"; # settings = { - # bridge = "br-lan"; + # bridge = bridgeInterfaceName; # }; # }; # }; @@ -683,15 +729,24 @@ in { services.resolved.enable = false; - services.dnsmasq = let - mkIfName = { vlanid }: if vlanid == 0 then "br-lan" else "br-lan.${toString vlanid}"; - in { + services.dnsmasq = { enable = true; settings = { - # sensible behaviours domain-needed = true; bogus-priv = true; no-resolv = true; + localise-queries = true; + + proxy-dnssec = true; + conntrack = true; + + log-debug = true; + log-queries = true; + + # disable negative caching + no-negcache = true; + local-ttl = 0; + dhcp-ttl = 0; dhcp-range = let mkDhcpRange = { tag, vlanid }: builtins.concatStringsSep "," [ @@ -703,12 +758,12 @@ in { in builtins.map (vlanid: - mkDhcpRange { tag = mkIfName {inherit vlanid;}; inherit vlanid; } + mkDhcpRange { tag = mkInterfaceName {inherit vlanid;}; inherit vlanid; } ) vlanRangeWith0 ; - # interface = "br-lan"; + # interface = bridgeInterfaceName; # bind-interfaces = true; # dhcp-host = "192.168.10.1"; @@ -720,12 +775,27 @@ in { # don't use /etc/hosts as this would advertise ${nodeName} as localhost no-hosts = true; + # address = "/${nodeName}.lan/${fwLanHostAddr}"; server = [ - # upstream DNS servers - "9.9.9.9" "8.8.8.8" "1.1.1.1" + # upstream DNS servers + + # https://dnsforge.de/ + "176.9.93.198" + "176.9.1.117" + "2a01:4f8:151:34aa::198" + "2a01:4f8:141:316d::117" + + # cloudflare and google + # "9.9.9.9" "8.8.8.8" "1.1.1.1" + ]; + + domain = [ + "/${getVlanDomain {vlanid = 0;}}/,local" ] ++ builtins.map - (vlanid: "/${getVlanDomain {inherit vlanid;}}/") + (vlanid: + "${getVlanDomain {inherit vlanid;}},${mkVlanIpv4HostAddr { inherit vlanid; host = 0; cidr = true; }},local" + ) vlanRangeWith0 ; @@ -734,18 +804,17 @@ in { ] ++ builtins.map (vlanid: builtins.concatStringsSep "," [ - "${nodeName}.${getVlanDomain{inherit vlanid;}}" "0.0.0.1" (mkIfName {inherit vlanid;}) + # "${getVlanDomain{inherit vlanid;}}" "0.0.0.1" (mkInterfaceName {inherit vlanid;}) + "${nodeName}.${getVlanDomain{inherit vlanid;}}" "0.0.0.1" (mkInterfaceName {inherit vlanid;}) ] ) vlanRangeWith0 ; dhcp-option-force = builtins.map - (vlanid: "${mkIfName {inherit vlanid;}},option:domain-search,${getVlanDomain{inherit vlanid;}}") + (vlanid: "${mkInterfaceName {inherit vlanid;}},option:domain-search,${getVlanDomain{inherit vlanid;}}") vlanRangeWith0 ; - - localise-queries = true; }; }; diff --git a/nix/os/devices/router0-dmz0/default.nix b/nix/os/devices/router0-dmz0/default.nix index e29beb2..9dd8d5e 100644 --- a/nix/os/devices/router0-dmz0/default.nix +++ b/nix/os/devices/router0-dmz0/default.nix @@ -3,6 +3,7 @@ nodeName, repoFlake, nodeFlake, + localDomainName ? "internal", ... }: { meta.nodeSpecialArgs.${nodeName} = { @@ -14,6 +15,8 @@ (nodeFlake.inputs.bpir3.packages.${system}) armTrustedFirmwareMT7986 ; + + inherit localDomainName; }; meta.nodeNixpkgs.${nodeName} = @@ -23,7 +26,7 @@ }; ${nodeName} = { - deployment.targetHost = "router0.dmz0.noosphere.life"; + deployment.targetHost = "${nodeName}.${localDomainName}"; deployment.replaceUnknownProfiles = true; # nixpkgs.pkgs = nodeFlake.inputs.nixpkgs.legacyPackages.${system}; diff --git a/nix/os/devices/router0-dmz0/flake.nix b/nix/os/devices/router0-dmz0/flake.nix index 027bdac..494551e 100644 --- a/nix/os/devices/router0-dmz0/flake.nix +++ b/nix/os/devices/router0-dmz0/flake.nix @@ -60,7 +60,6 @@ nixpkgs.lib.attrsets.recursiveUpdate attrs { - # TODO: it would be nice if this were the same as meta.nodeSpecialArgs.${nodeName} as in the default.nix specialArgs = (import ./default.nix { system = nativeSystem; inherit nodeName;