diff --git a/nix/os/devices/router0-dmz0/configuration.nix b/nix/os/devices/router0-dmz0/configuration.nix index b1d1fa0..497ba07 100644 --- a/nix/os/devices/router0-dmz0/configuration.nix +++ b/nix/os/devices/router0-dmz0/configuration.nix @@ -16,35 +16,46 @@ nixos-nftables-firewall ; - mkVlanIpv4HostAddr = { vlanid, host, ipv4Offset ? 20, cidr ? true }: - builtins.concatStringsSep "." - [ "192" "168" (toString (ipv4Offset + vlanid)) "${toString host}${lib.strings.optionalString cidr "/24"}" ]; - - # vlanRangeStart = 1; - # vlanRangeEnd = 20; - # vlanRange = (lib.lists.range vlanRangeStart vlanRangeEnd); + vlanRangeStart = builtins.head vlanRange; + vlanRangeEnd = builtins.elemAt vlanRange ((builtins.length vlanRange)-1); vlanRange = builtins.map (vlanid: (lib.strings.toInt vlanid)) (builtins.attrNames vlans); vlanRangeWith0 = [ 0 ] ++ vlanRange; + mkVlanIpv4HostAddr = { vlanid, host, thirdIpv4SegmentMin ? 20, cidr ? true }: let + # reserve the first subnet for vlanid == 0 + # number the other subnets continously from there + offset = + if vlanid == 0 + then thirdIpv4SegmentMin + else thirdIpv4SegmentMin + 1 - vlanRangeStart; + + in + builtins.concatStringsSep "." + [ "192" "168" (toString (vlanid + offset)) "${toString host}${lib.strings.optionalString cidr "/24"}" ]; + defaultVlan = { name = "internal"; packet_priority = 0; }; vlans = { - "1".name = "dmz"; - "1".packet_priority = -5; + "10".name = "mgmt"; + "10".packet_priority = 0; - "2".name = "iot"; - "2".packet_priority = -5; + "11".name = "dmz"; + "11".packet_priority = -5; - "3".name = "office"; - "3".packet_priority = -10; + "12".name = "iot"; + "12".packet_priority = -5; - "4".name = "guests"; - "4".packet_priority = 10; + "13".name = "office"; + "13".packet_priority = -10; - "5".name = "smarties"; + "14".name = "guests"; + "14".packet_priority = 10; + + "15".name = "iot2"; + "15".packet_priority = -10; }; getVlanDomain = { vlanid }: if vlanid == 0 @@ -72,6 +83,9 @@ in { "nix-command" "flakes" ]; + + nix.settings.max-jobs = lib.mkDefault "auto"; + nix.settings.cores = lib.mkDefault 0; } # TODO @@ -155,8 +169,8 @@ in { firewall = { enable = true; zones = { - lan.interfaces = ["br-lan"]; - vlan.interfaces = builtins.map (vlanid: "br-vlan.${toString vlanid}") vlanRange; + lan.interfaces = [ "br-lan" ]; + vlan.interfaces = builtins.map (vlanid: "br-lan.${toString vlanid}") vlanRange; # lan.ipv4Addresses = ["192.168.0.0/16"]; wan.interfaces = ["wan" "lan0"]; } // @@ -180,9 +194,14 @@ in { "ip6 nexthdr icmpv6 icmpv6 type { ${builtins.concatStringsSep ", " ipv6IcmpTypes} } accept" ]; in { + fw = { + from = ["fw"]; + verdict = "accept"; + }; + lan-to-fw = { from = ["lan"]; - to = ["fw"]; + to = ["fw" "lan"]; verdict = "accept"; }; @@ -206,6 +225,7 @@ in { allowedTCPPortRanges = [ { from = 22; to = 22; } { from = 53; to = 53; } + { from = 5201; to = 5201; } ]; from = ["vlan"]; to = ["fw"]; @@ -247,16 +267,25 @@ in { netdevConfig = { Kind = "bridge"; Name = "br-lan"; - }; extraConfig = '' [Bridge] - STP=true - # VLANFiltering=yes - # DefaultPVID=1 + STP=yes + VLANFiltering=yes + VLANProtocol=802.1q + DefaultPVID=0 ''; }; + + # TODO: generate one of these for each vlanid + "20-br-lan.15" = { + netdevConfig = { + Kind = "vlan"; + Name = "br-lan.15"; + }; + vlanConfig.Id = 15; + }; }; networks = { # use lan0 as secondary WAN interface @@ -308,6 +337,7 @@ in { }; linkConfig.RequiredForOnline = "enslaved"; }; + "30-lan3" = { matchConfig.Name = "lan3"; networkConfig = { @@ -315,6 +345,15 @@ in { ConfigureWithoutCarrier = true; }; linkConfig.RequiredForOnline = "enslaved"; + + bridgeVLANs = [ + { + bridgeVLANConfig = { + VLAN = "${toString vlanRangeStart}-${toString vlanRangeEnd}"; + }; + } + ]; + }; # Configure the bridge for its desired function "40-br-lan" = { @@ -328,40 +367,112 @@ in { }; # Don't wait for it as it also would wait for wlan and DFS which takes around 5 min linkConfig.RequiredForOnline = "no"; + linkConfig.ActivationPolicy = "always-up"; - # TODO: understand when this would be needed - # bridgeVLANs = [ - # { - # bridgeVLANConfig = { - # VLAN = "${vlanRangeStart}-${vlanRangeEnd}"; - # }; - # } - # ]; - }; - } - # VLAN interface addresses - // - lib.attrsets.foldlAttrs - (acc: _: value: acc // value) - {} - (lib.attrsets.genAttrs - (builtins.map - builtins.toString - vlanRange - ) - (vlanid: { - "50-br-vlan.${vlanid}" = { - matchConfig.Name = "br-vlan.${toString vlanid}"; - address = [ - (mkVlanIpv4HostAddr { vlanid = (lib.strings.toInt vlanid); host = 1; }) - ]; - networkConfig = { - ConfigureWithoutCarrier = true; + bridgeVLANs = [ + { + bridgeVLANConfig = { + VLAN = "${toString vlanRangeStart}-${toString vlanRangeEnd}"; }; - # Don't wait for it as it also would wait for wlan and DFS which takes around 5 min - linkConfig.RequiredForOnline = "no"; + } + ]; + + vlan = [ + "br-lan.15" + ]; + }; + + # TODO: generate one of these for each vlanid + "41-br-lan.15" = let + vlanid = 15; + in { + matchConfig.Name = "br-lan.15"; + address = [ + (mkVlanIpv4HostAddr { inherit vlanid; host = 1; }) + ]; + networkConfig = { + ConfigureWithoutCarrier = true; + }; + + linkConfig.RequiredForOnline = "no"; + linkConfig.ActivationPolicy = "always-up"; + + bridgeVLANs = [ + { + bridgeVLANConfig = { + # TODO debug this: each vlanid is native to each port + VLAN = vlanid; + }; + } + ]; + }; + + # TODO: generate one of these for each vlanid + # configure the wlan interface as a bridge member that + # * only gets traffic for vid 15 + # * untags traffic after receiving it + # * tags traffic that comes out of it + "41-wlan0.15" = let + vlanid = 15; + in { + matchConfig.Name = "wlan0.15"; + networkConfig = { + Bridge = "br-lan"; + ConfigureWithoutCarrier = true; + }; + + linkConfig.RequiredForOnline = "no"; + + bridgeVLANs = [ + { + bridgeVLANConfig = { + # TODO debug this: each vlanid is native to each port + VLAN = vlanid; + PVID = vlanid; + EgressUntagged = vlanid; + }; + } + ]; + }; + + } + + # configuration for the hostapd dynamic interfaces + # TODO: refactor this to configure the following per vlanid + # * netdev type vlan + # * host address for vlan + # * vlan config for wlan interface + // + builtins.foldl' + (acc: cur: acc // cur) + {} + (builtins.map + ({ vlanid, vlanid' }: { + "50-br-lan.${vlanid'}" = { + matchConfig.Name = "br-lan.${vlanid'}"; + address = [ + (mkVlanIpv4HostAddr { inherit vlanid; host = 1; }) + ]; + networkConfig = { + ConfigureWithoutCarrier = true; }; - }) + linkConfig.RequiredForOnline = "no"; + + bridgeVLANs = [ + { + bridgeVLANConfig = { + # TODO debug this: each vlanid is native to each port + VLAN = vlanid; + PVID = vlanid; + }; + } + ]; + }; + }) + (builtins.map + (vlanid: { inherit vlanid; vlanid' = builtins.toString vlanid; }) + vlanRange + ) ); }; @@ -384,15 +495,17 @@ in { capabilities = ["HT40+" "LDPC" "SHORT-GI-20" "SHORT-GI-40" "TX-STBC" "RX-STBC1" "MAX-AMSDU-7935"]; }; networks = { - wlan0 = { + wlan0 = let + iface = "wlan0"; + in { ssid = "mlsia"; bssid = mkBssid 0; # authentication.mode = "wpa3-sae"; authentication.mode = "wpa3-sae-transition"; - authentication.wpaPskFile = config.sops.secrets.wlan0_wpaPskFile.path; - authentication.saePasswordsFile = config.sops.secrets.wlan0_saePasswordsFile.path; + authentication.wpaPskFile = config.sops.secrets."${iface}_wpaPskFile".path; + authentication.saePasswordsFile = config.sops.secrets."${iface}_saePasswordsFile".path; settings = { # bridge = "br-lan"; @@ -410,16 +523,18 @@ in { vlan_tagged_interface = "br-lan"; vlan_naming = 1; - vlan_bridge = "br-vlan."; + vlan_bridge = "br-${iface}."; dynamic_vlan = 1; vlan_file = toString (pkgs.writeText "hostapd.vlan" '' # Optional wildcard entry matching all VLAN IDs. The first # in the interface # name will be replaced with the VLAN ID. The network interfaces are created # (and removed) dynamically based on the use. # see https://w1.fi/cgit/hostap/tree/hostapd/hostapd.vlan - * wlan0.# + * ${iface}.# ''); + vlan_no_bridge = 1; + wpa_key_mgmt = lib.mkForce (builtins.concatStringsSep " " [ "WPA-PSK" @@ -563,7 +678,7 @@ in { services.resolved.enable = false; services.dnsmasq = let - mkIfName = { vlanid }: if vlanid == 0 then "br-lan" else "br-vlan.${toString vlanid}"; + mkIfName = { vlanid }: if vlanid == 0 then "br-lan" else "br-lan.${toString vlanid}"; in { enable = true; settings = { @@ -695,5 +810,22 @@ in { environment.systemPackages = [ pkgs.ethtool + pkgs.neovim + + (pkgs.writeShellScriptBin "dbg-ip" '' + echo links: + ip -br -c l + echo + echo addresses: + ip -br -c a + echo + echo vlans: + bridge -c vlan + '') + + (pkgs.writeShellScriptBin "dbg-dnsmasq" '' + # get the rendered in-use config + pgrep -a dnsmasq | grep -Eo '[^ ]*conf' | xargs cat | grep -Eo '[^=]*conf' | xargs cat + '') ]; } diff --git a/nix/os/devices/router0-dmz0/flake.nix b/nix/os/devices/router0-dmz0/flake.nix index 24f5f16..bd9e3b4 100644 --- a/nix/os/devices/router0-dmz0/flake.nix +++ b/nix/os/devices/router0-dmz0/flake.nix @@ -96,6 +96,12 @@ hostapd_main = pkgs.hostapd.overrideDerivation(attrs: { src = self.inputs.hostapd; version = self.inputs.hostapd.rev; + patches = attrs.patches ++ [ + (builtins.fetchurl { + url = "https://raw.githubusercontent.com/openwrt/openwrt/main/package/network/services/hostapd/patches/710-vlan_no_bridge.patch"; + sha256 = "sha256:1p6fjjdwx5xrxyvllfrmvdkiji7bgx997k1qmp199bbic1fq6ks9"; + }) + ]; }); }; }; diff --git a/secrets/router0-dmz0/secrets.yaml b/secrets/router0-dmz0/secrets.yaml index 911924f..56e013e 100644 --- a/secrets/router0-dmz0/secrets.yaml +++ b/secrets/router0-dmz0/secrets.yaml @@ -4,8 +4,8 @@ ssh_host_ed25519_key: ENC[AES256_GCM,data:XQjTqNADLhisxPBIJ7x0bs3qgQk0u4q9HKSDuk ssh_host_ed25519_key_pub: ENC[AES256_GCM,data:MQ0q/I6clKNz6uzoztGA06vOjIbpK6Dsf3WbgddRA0B8nEJ4EUmRBT0KkX3o+LZmQPhmURHWWFtOSqvAzkyoxAoBZEh98H3IDsLE5PgcNbxK3dAh36+AAMPLzVFnHLyaWLQW,iv:9XIw29PkSHCeU7C2GuSJ+J+mBrwOrbSMmm7kOtCkiyI=,tag:x3JqFF08f2eVfOrrQ1gzYw==,type:str] ssh_host_rsa_key: ENC[AES256_GCM,data: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,iv:mXE8xpXFBYSJce9pg+g3OedMS9+ZHOHHwydCY0NbGRQ=,tag:cEqbUu9Y1PFKXwaeqioXWA==,type:str] ssh_host_rsa_key_pub: ENC[AES256_GCM,data:N60bGf/6KNRhVUq1EIbPVo3aBDDKEpMBr5+Gt3+FMPt3uQEaKk8jBg5mOdxWMTPoLg1ZP/Pme8afoM+Skc0b50WnpErF3Ox1w+4eM0oMJYOhIvHLGURNM3Dba5MgA7YfhPdTsVdjD2yks2vYqhdtEvzTTgCJbFimVJlp+wDqE6czPgMjD03c7oJDtv38OBtc1vRMzVw3cIuyxz2yNnXQxiMgTR6pZN7+Brami2dfXOHEVgymmlU5PRE8Ykerq2fB36N5uqu4/xSPaHaM+/f2OA/TLlYYB+sGMDExZfbO/vsiRBLvTY/f4KG2mEkmH+IFH1bk6UF47xTFEe8tHN/TlLo+9OmjZTph221ZYnOsIqBY+F822ctZEe8Ikz9Ti4F1ApvxxRcWHajbgQnDJdDiHJvt3OHal4rNBtYwxxV/MDZtvKSVxmFwgx7nwNP0oKhAigQkU7Mvp1q5p3dZsdbGCUeFm2S5/qIxWPfr7wg4xocLNSsLW1EpGo6A2RUXWIV+lPuZd9dNEjGC5zKKAgMI94is6MtMXgqlFqTcZuQ9hvhoVDcFhVSJylu8pzk9d/tKviwcd98jHAhdfGpnc9eJbtyBU6/HvxLzQpsbFjwa3LGirEdtgxRZn2nJx++0U6XuLcbGwjOVAhkde6g2vFv5hsC6KaZQcp4AFvMvEdJyrnb0b2TOeOD8zEljb8u2q/eexCRSjGpobEINwu5qV+tF9eHIJ1YFzhCSmmLGKXjc7bC8uv5ffl39JmAbUrffd18zqae+Xpijd+QzwF425NG9+PksAt+PPzt4SDgGfKBIpMNFxIb18oo88z4YDLuNzRy/HVF90JV0LlAxES4ZOxoWUjJPrR6dGxNRANYOyFGmoN+yG3B9kd1NRGRNGh5P9EtZBxlPIi24djzF1n4GQSW1NFDgoGcxaXhk0PlpPxwuHK0X9FkFDDzQUYNBhx7py+hev5rBUCs7Yhj5xgcM88fdLRZi8MulNws=,iv:8c3hDcJ8wzTugmJ3Mhzx/qEXnnlpFefBmRTG/MqyeEg=,tag:uSz6+CYu9uQa0C2DXnHPUA==,type:str] -wlan0_saePasswordsFile: ENC[AES256_GCM,data:p0M99C2Q6UrLzp5XZ/AvPpukzgaiZqFIWbIRGFFOOKygVt5r2zk4SZ6vCvoZQ0AfdlL+R6xsKZ4V6u9CZJsmHGgWewoTbszi4AGhWrwoFjhrWb+LWMBGZI7lOWjGclR0BoDgRYTtVDQDiLqUWjxQJBX7cgG2vf4V/ajnokRClNe1bRPN4fzaQskb,iv:g8m1SKRSAumXAQdFL6PlUeq2YWjl3LGDDv6nq9aA0yk=,tag:ODCqjfB2kEepcaJEzVEYFA==,type:str] -wlan0_wpaPskFile: ENC[AES256_GCM,data:TnQ794CQ8jEBT7BTynPpU0S1VpT2oS2rgKmaxfkW7v3mhV4ijgnsypixkCD6GmQdAL0vsKFq0tu76TqeqcpJ1tWTGdfg3UtTmZ/ARFu2y3jYVNhmFziBpYlOAd2e/oo0DpXhYUVZN3TvALF1dJ7aGt8XQewTaIYQBL04aietPXPHzPvecOLwNhnxMer6BAZG0HC/wpuwmmQ0CsR7Wbw/6Efn25oGXvITbndVbZoyC85bsckptYTSQmORKZH0Ew==,iv:UzOFbHZT37uDfaLVmOFGUG/Pv3kmq3pZLaZ0mkBCUQc=,tag:oq+dZefYEPneXiNeXVgHSw==,type:str] +wlan0_saePasswordsFile: ENC[AES256_GCM,data:ylY1LwMYlHdvYIVPIIr65BuxkW/BHCikkbGO5nNSU9WVekWiDXNIt2EQ2sYcdqnvZMGvcG0G4SQvCwpNO8ihh/RqcLYpTxldI8zwSqAwvATu7prV8l2bCvBQ+NXZ3yAW,iv:L6ncjd0u316gF/3InI7cuqO1kDpH7ahWGcsssYfb2YU=,tag:IAqt8vSDjW3OasOTJ44PeQ==,type:str] +wlan0_wpaPskFile: ENC[AES256_GCM,data:I/30uOrCPoWqnNq4WelPsDMevrmO+TuzmNrjMtPeCLS5MncX7BnX20YV5LxLsLCJS0NmCEqE58pgpeQEaUUcR0YRejCdO0yZnpMRbla6IR/irNSR/xctDQmMV6HYe6IKWE2d2LA/qWTkj+uBGJ0NtAsPIRLknuCwT8SLjClzF4/WCdoqHvxhBCESxhd3OTYr9op9uxk94iRxKsFfUBuNnckIeT/tQKqOQIHlkpperGBNRtTZ9q+Glb6lqFO1o/BJ8tAGpw0qyNO48jrRAtiIG3sauMH+UPWp86AYPhwQjwA6iDReFoH5KhZsohJSTX4vwoj46yycOTPu/loHrxySBSrYuRyOuIv7mwpRVZgJP+c3ZcngVncE3YQhLA==,iv:AlQIFKqcFSnyH1LrRN/XaTTocsMjZM20YHWcz7S3gCE=,tag:octNvum5lOOUOS6ALJ0x4g==,type:str] sops: kms: [] gcp_kms: [] @@ -21,8 +21,8 @@ sops: THRNR0tEUzhPdFFhWWxvZlpKYmZKM2MKxc5s1jsci8jPOrvZAoofVNvHT4o9P6yv J8rALQQXgql6obK51Q/Doyzvo1RJ0T7epiWEAZm5B3vDrf6KqbWBYw== -----END AGE ENCRYPTED FILE----- - lastmodified: "2023-12-24T22:39:23Z" - mac: ENC[AES256_GCM,data:eNbO9GqcrcKg3qAMZDkOOcihUhWeXWCUHrbdiIIKomdp8hZdou6He1Dd5hPZJMrwuTfiYx9NcuRph/XXXYEMLIfRhb2Kw2LoKW4e/gZDj6rFSnRx/kqg/+oZLnnsZWnNYEhQTOEknpYNsjoBd1YOHqj9EvdABLCELvB9KfL7DnQ=,iv:bXlTOq1qeFldVH9dBotUoxHDNh/pG6eJOzS2SBI2R8s=,tag:foDEWwGMiYXpS6LiRual5w==,type:str] + lastmodified: "2023-12-25T21:25:35Z" + mac: ENC[AES256_GCM,data:Sk3eyBaxhL7cX78YprYsv75oO+auEoxxGHCk1MRYGcAkat3vrc2vXjmKn6SsVQC8SWvu2YR2dOGU85Z7FCUUmmnwKeh+1PKMsurwfrNkB4umADXjaESNUWNevzAK9LR4pI1I6rGzl7mFEFYGEPd948JMOfkIfwNm1KMmETGkkI0=,iv:UzfDF94UFjPuEgRkpkRyLxSwZGymZclboHYQ/HxulJQ=,tag:MIBhvegV4NaZF+nGShotPw==,type:str] pgp: - created_at: "2023-08-11T16:15:11Z" enc: |-