WIP: router0-dmz0: use bridge vlan filtering for the dynamic wlan interfaces

This commit is contained in:
steveej 2023-12-26 00:37:20 +01:00
parent c365970cdf
commit 8bcb433257
3 changed files with 202 additions and 64 deletions

View file

@ -16,35 +16,46 @@
nixos-nftables-firewall nixos-nftables-firewall
; ;
mkVlanIpv4HostAddr = { vlanid, host, ipv4Offset ? 20, cidr ? true }: vlanRangeStart = builtins.head vlanRange;
builtins.concatStringsSep "." vlanRangeEnd = builtins.elemAt vlanRange ((builtins.length vlanRange)-1);
[ "192" "168" (toString (ipv4Offset + vlanid)) "${toString host}${lib.strings.optionalString cidr "/24"}" ];
# vlanRangeStart = 1;
# vlanRangeEnd = 20;
# vlanRange = (lib.lists.range vlanRangeStart vlanRangeEnd);
vlanRange = builtins.map (vlanid: (lib.strings.toInt vlanid)) (builtins.attrNames vlans); vlanRange = builtins.map (vlanid: (lib.strings.toInt vlanid)) (builtins.attrNames vlans);
vlanRangeWith0 = [ 0 ] ++ vlanRange; 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 = { defaultVlan = {
name = "internal"; name = "internal";
packet_priority = 0; packet_priority = 0;
}; };
vlans = { vlans = {
"1".name = "dmz"; "10".name = "mgmt";
"1".packet_priority = -5; "10".packet_priority = 0;
"2".name = "iot"; "11".name = "dmz";
"2".packet_priority = -5; "11".packet_priority = -5;
"3".name = "office"; "12".name = "iot";
"3".packet_priority = -10; "12".packet_priority = -5;
"4".name = "guests"; "13".name = "office";
"4".packet_priority = 10; "13".packet_priority = -10;
"5".name = "smarties"; "14".name = "guests";
"14".packet_priority = 10;
"15".name = "iot2";
"15".packet_priority = -10;
}; };
getVlanDomain = { vlanid }: getVlanDomain = { vlanid }:
if vlanid == 0 if vlanid == 0
@ -72,6 +83,9 @@ in {
"nix-command" "nix-command"
"flakes" "flakes"
]; ];
nix.settings.max-jobs = lib.mkDefault "auto";
nix.settings.cores = lib.mkDefault 0;
} }
# TODO # TODO
@ -156,7 +170,7 @@ in {
enable = true; enable = true;
zones = { zones = {
lan.interfaces = [ "br-lan" ]; lan.interfaces = [ "br-lan" ];
vlan.interfaces = builtins.map (vlanid: "br-vlan.${toString vlanid}") vlanRange; vlan.interfaces = builtins.map (vlanid: "br-lan.${toString vlanid}") vlanRange;
# lan.ipv4Addresses = ["192.168.0.0/16"]; # lan.ipv4Addresses = ["192.168.0.0/16"];
wan.interfaces = ["wan" "lan0"]; wan.interfaces = ["wan" "lan0"];
} // } //
@ -180,9 +194,14 @@ in {
"ip6 nexthdr icmpv6 icmpv6 type { ${builtins.concatStringsSep ", " ipv6IcmpTypes} } accept" "ip6 nexthdr icmpv6 icmpv6 type { ${builtins.concatStringsSep ", " ipv6IcmpTypes} } accept"
]; ];
in { in {
fw = {
from = ["fw"];
verdict = "accept";
};
lan-to-fw = { lan-to-fw = {
from = ["lan"]; from = ["lan"];
to = ["fw"]; to = ["fw" "lan"];
verdict = "accept"; verdict = "accept";
}; };
@ -206,6 +225,7 @@ in {
allowedTCPPortRanges = [ allowedTCPPortRanges = [
{ from = 22; to = 22; } { from = 22; to = 22; }
{ from = 53; to = 53; } { from = 53; to = 53; }
{ from = 5201; to = 5201; }
]; ];
from = ["vlan"]; from = ["vlan"];
to = ["fw"]; to = ["fw"];
@ -247,16 +267,25 @@ in {
netdevConfig = { netdevConfig = {
Kind = "bridge"; Kind = "bridge";
Name = "br-lan"; Name = "br-lan";
}; };
extraConfig = '' extraConfig = ''
[Bridge] [Bridge]
STP=true STP=yes
# VLANFiltering=yes VLANFiltering=yes
# DefaultPVID=1 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 = { networks = {
# use lan0 as secondary WAN interface # use lan0 as secondary WAN interface
@ -308,6 +337,7 @@ in {
}; };
linkConfig.RequiredForOnline = "enslaved"; linkConfig.RequiredForOnline = "enslaved";
}; };
"30-lan3" = { "30-lan3" = {
matchConfig.Name = "lan3"; matchConfig.Name = "lan3";
networkConfig = { networkConfig = {
@ -315,6 +345,15 @@ in {
ConfigureWithoutCarrier = true; ConfigureWithoutCarrier = true;
}; };
linkConfig.RequiredForOnline = "enslaved"; linkConfig.RequiredForOnline = "enslaved";
bridgeVLANs = [
{
bridgeVLANConfig = {
VLAN = "${toString vlanRangeStart}-${toString vlanRangeEnd}";
};
}
];
}; };
# Configure the bridge for its desired function # Configure the bridge for its desired function
"40-br-lan" = { "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 # Don't wait for it as it also would wait for wlan and DFS which takes around 5 min
linkConfig.RequiredForOnline = "no"; linkConfig.RequiredForOnline = "no";
linkConfig.ActivationPolicy = "always-up";
# TODO: understand when this would be needed bridgeVLANs = [
# bridgeVLANs = [ {
# { bridgeVLANConfig = {
# bridgeVLANConfig = { VLAN = "${toString vlanRangeStart}-${toString vlanRangeEnd}";
# VLAN = "${vlanRangeStart}-${vlanRangeEnd}";
# };
# }
# ];
}; };
} }
# VLAN interface addresses ];
//
lib.attrsets.foldlAttrs vlan = [
(acc: _: value: acc // value) "br-lan.15"
{} ];
(lib.attrsets.genAttrs };
(builtins.map
builtins.toString # TODO: generate one of these for each vlanid
vlanRange "41-br-lan.15" = let
) vlanid = 15;
(vlanid: { in {
"50-br-vlan.${vlanid}" = { matchConfig.Name = "br-lan.15";
matchConfig.Name = "br-vlan.${toString vlanid}";
address = [ address = [
(mkVlanIpv4HostAddr { vlanid = (lib.strings.toInt vlanid); host = 1; }) (mkVlanIpv4HostAddr { inherit vlanid; host = 1; })
]; ];
networkConfig = { networkConfig = {
ConfigureWithoutCarrier = true; ConfigureWithoutCarrier = true;
}; };
# Don't wait for it as it also would wait for wlan and DFS which takes around 5 min
linkConfig.RequiredForOnline = "no"; 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"]; capabilities = ["HT40+" "LDPC" "SHORT-GI-20" "SHORT-GI-40" "TX-STBC" "RX-STBC1" "MAX-AMSDU-7935"];
}; };
networks = { networks = {
wlan0 = { wlan0 = let
iface = "wlan0";
in {
ssid = "mlsia"; ssid = "mlsia";
bssid = mkBssid 0; bssid = mkBssid 0;
# authentication.mode = "wpa3-sae"; # authentication.mode = "wpa3-sae";
authentication.mode = "wpa3-sae-transition"; authentication.mode = "wpa3-sae-transition";
authentication.wpaPskFile = config.sops.secrets.wlan0_wpaPskFile.path; authentication.wpaPskFile = config.sops.secrets."${iface}_wpaPskFile".path;
authentication.saePasswordsFile = config.sops.secrets.wlan0_saePasswordsFile.path; authentication.saePasswordsFile = config.sops.secrets."${iface}_saePasswordsFile".path;
settings = { settings = {
# bridge = "br-lan"; # bridge = "br-lan";
@ -410,16 +523,18 @@ in {
vlan_tagged_interface = "br-lan"; vlan_tagged_interface = "br-lan";
vlan_naming = 1; vlan_naming = 1;
vlan_bridge = "br-vlan."; vlan_bridge = "br-${iface}.";
dynamic_vlan = 1; dynamic_vlan = 1;
vlan_file = toString (pkgs.writeText "hostapd.vlan" '' vlan_file = toString (pkgs.writeText "hostapd.vlan" ''
# Optional wildcard entry matching all VLAN IDs. The first # in the interface # 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 # name will be replaced with the VLAN ID. The network interfaces are created
# (and removed) dynamically based on the use. # (and removed) dynamically based on the use.
# see https://w1.fi/cgit/hostap/tree/hostapd/hostapd.vlan # see https://w1.fi/cgit/hostap/tree/hostapd/hostapd.vlan
* wlan0.# * ${iface}.#
''); '');
vlan_no_bridge = 1;
wpa_key_mgmt = lib.mkForce (builtins.concatStringsSep " " [ wpa_key_mgmt = lib.mkForce (builtins.concatStringsSep " " [
"WPA-PSK" "WPA-PSK"
@ -563,7 +678,7 @@ in {
services.resolved.enable = false; services.resolved.enable = false;
services.dnsmasq = let 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 { in {
enable = true; enable = true;
settings = { settings = {
@ -695,5 +810,22 @@ in {
environment.systemPackages = [ environment.systemPackages = [
pkgs.ethtool 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
'')
]; ];
} }

View file

@ -96,6 +96,12 @@
hostapd_main = pkgs.hostapd.overrideDerivation(attrs: { hostapd_main = pkgs.hostapd.overrideDerivation(attrs: {
src = self.inputs.hostapd; src = self.inputs.hostapd;
version = self.inputs.hostapd.rev; 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";
})
];
}); });
}; };
}; };

View file

@ -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_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:tFGQ77X5Y1TRR2F0EJ4hmauE9ABILP6V0CSmzb1QLaH6VlhriXSE1UQcQ2Rc73CR7+JLjLbggL7RKpkA8gJQq/ubhiXHJokBEo6rfBXETVepv0HlyX5UvzWhi6iKBE5YsYyyBI1VWDcx+oTR8+daqnKwbbqPeDUpC2coT3S9svEsKXeb3YOMxJ9X/Rvh96UtMmlk7WeZa2JvOP3k62HROVo8QRYXeQWTO87TCzVdU7OWnbRIuC6bu+32Uy70AsIu39fazX7WqIUxaeO/oNHsay0/TBXKNu2El0JRG8tHCHdXe1tahniGbGH5xeEZmgLTOjHntw5UIdxZbgvcbxmt9seDXUxjhhEMS8eHWaxnRDSI7n2KOb/3UaBQ3BHnYpuRjW++uFBgRHxxANlYfpfEdz/LNexdPb9+QCw80r38uZxP8yD5/PxFV/Y+gSX+WnNE0YQnBDtHFjKhHpqpm2P4Ek3hLzjXh6CPzUZru6LAO/FklcLCGaq94fDC5wW3K0x1UvyfMjBwwyeSymcV95YcZu8Ty280jRhG8l719KkEJjnBdnB25PQ5gEwc34dG5xH5HwVUDPIM9v9m+cXtldUIk3BH4PiTEI1aZsZx50BtBhxybAxhTqNElrP+/2W73muTSQboDIB1Xb2NhArLB6XnnVhVUD/Pg/9wiDUY0mYyr0eIp9AmBfSmSIDjFyVUB9o+gv/B+LpxwxPKmsPt3MRKWoZw+bIGTI82UqBv0eX6Xqq71H4DYFnJ3J+n+Jzp5ww5mSPPHffZZFSBbZSpTk8El4L5II/hyyxk7yJopt19AAsw+UgLJDO31XnyiGAEbbDdwjuCWQMmuzKJ6H7c7UGDXLO92jAlXwEWT5fwzG6Wvu5+n/OToz3CN1Cv40uwVb/fOqmzep9hoOrXeuzmnGULfGmwItjuJoMkfmPUq8obAuj5ml0YduU2eLbe15OlD2Vg2I+BH0WuCPYnnCrLyX8ixhJEuGGDkhGhaKMHaMjNuMOGmDQ6oRCVU8BA/zDgnF/GrcHgIe742Yh68PyaH2j+iX6/5YvUB+R1sDnrgfXlgET1V+nny+fD4GBnP+RKYtdGG0P4y3AYlACQE9sJ6Nkb8CTVb2Va6L3rXzeyJG2FtYkUKxxwDUv/KyieclHiJpdawunOLVkmI6p/iaZIThrdGA5p7b01/WOyJFA9aI3oU2f2rMYBLGHYirrRs3WtS7ExhKriHpgax574UIcW0mecFto9dHkGlBOTQy+Zp1GARnePXKZcyKm2qhTIjw0ho/DUe3+t1knbR6WJCwl1LDtfpPD2KPDDH+HpHm3EoiA1mDSp6lYMVxwBr2eBmFPKuPkkAL/3Bf6SKlEp1UCDee7BPlzS9kwmIEt/EuIohbMDdyaHtulW31Hdrsai8fCxc7AAzgsmoMBp2Smwoe3C8K5K8RaNp6v4boY8WBH3rLjAFTmOPB7TiZfplQjV8triZS3JFopNjvCglfZSXxSs+RjZUgSgL/1fFLT2m0Mp1XPMvGZlD73TzJ5RH5WWlxliaau42Q4vXRFUK+ZFx0SvwOO5xZvRNtAOfipEoqscKOopV+HHl74DJEk/xLibWJmkEBqoVbf1BFDUAiRSSb/0RdfCAGaj1mqV68szVtLt3jB1AJm9iu9RNU047HHQeOi++8g6lOpHmhsksfQLAucLVtLTrXpHDEAugDbSXrwPkhWa2Ej+Iva1p2vteIExcT+8h3WiXkamDBZALpJcLkDSazgAmmrB+6u6odsyin9Z5zB55EN2iz24nGNgyylt9FehC4/2SNHMX42hZ/JPQw51+vZQLoLQv+oOJAVXGBHeDy3kDl60fL6Fr5jZ0YOfO+rFGk4bDpXYjq27ahLv763tVs8SrgMseNWNWTakZUAXuYPbP3GBFEjTPHM4216WABj2cC3zSmrnbEyNRMWTdsm46ASZvhZo4wO8eTrndvy44Q2UKOFOh1sYCY4jjCWCI74pEV3rRcBJASuUipep65ZwXOlFOXu7uiaG01/KWofn4JzzrlX3MfhKsUBaEDTUXwDGw0RAEHQXb3rvfiIjCQBcpy8kM1fBR97K5LFJzZ2/qf2bPGs0yxma1O0Z6TT/2Uk2n62jK2xIM7gvTjPOVDP2etHKVxMpMjhTAbRj4K3568HZM/POBC5AORLAtBAo14CNxRMN8f05Gs13wn9ZI+pqiaOpTTnfH1xL9fd/6I03utzMKnoR8IVhrQLDLT6OAIkdeJX8s99R/J/nTOApk3XACWqjmMTcWtwt6g3x2iTk/1jTTn70rYVr8JLHHCt+bd5H/eDUiq9HpG1oFEZPXuvgATOovru0YVtmVx+yea0jWpJOsK+/SZjYAfvAKh0ZNr8dKHug/gGEpp6SfFBI+c4ywR1kM83OUHLaI/dOU9rLeCKktB+UcvTPoLhHLbTAlTrizeRmYY16Z1a+47LvwX944js3TZZkxqylz73cekWidYiiLNbiHwACftOK/GwZCG0WrVfcSi6pJYDgPgbcqFohaKI7ltKZgTlHGT1mZr1IH1RnauZmN/MkBEKVHO3E/PFgKkWNcXQi4uV2P3j8aHHc0RJrxx7qAFFXCYEwu02pv9nmul/HClLMmDYHDY1lHZvIIyPcsmr1ZkCFRV4UtnZRtXhHNAZCGFRX+y5HQXnubjPmV5I2R/gcLLi//2vIE6V2i8SpEJZlVweLpjRYwb6H6xFTuvHN+9Y5pd3rFx2BapR0AzYdOXUVqKF5ewrfE/1iitsEeDJj8OqmNzpmLBrnROnPyPh/+KGWBG5Nm4QKVMhP7XN1F+Fr7sTxw1ignXsfSwH8v/ELMzxVLu3ijWxvmk3/eOsrKYB/x3h6I1SFWZUoTjVPAmlNAnYl90Xf+FMPiII11+zrYwsJbCh25gmSvtKR+hmoTxXbJ2w5E2cFoVHMBOmS8Uo8L0BDOUzUE64cPl/v119BafVUOohLF1l3Ob19td+sMvqX8OHLGgB+/r6jKmUPnNNEzbDAogMydcVVjtPRIoDScw4ExxuxILN4/V+VulyAgU29OvFWS6+r5Y+bjqgqMg55Of0le3HUqt65qMuqiaUR5P/9WP+H666GsYTSg5I5gPJv0FF6tqXCWE9mpQ4sk2/BiWWaNeojxyhyH/cv4fbUmcee6K3+P+liXyFGGAWdBP5uGb+BzIfSaXVN3xEBPWAAe+BMkJrxbc6FSS12Wkh+bLM+NJH7XaoDl6+8LtF3bstsCoXvQgNlXHlbt4/aIIFEBShlYSQwLMDcey1VB4pu4SBv2HXwaX9zXPd+MGH77DeQU4yBkrElly51/68yzdSGpe6mNFy57Hc3UJBW1pNbds5Gxu+jFbQ6Phxvn38u9V8cphjxzgig0uZjkKHYx0EwFjBqmfrP0hQDnpcyg5QCPhnXOthmVL4jkJs3OrRHhoYRgbXpaVRMpVMLFeeSqcQABaRK5ibpB81WP8yCJPIMsbWW7sDTCiIyLq6qW5pKNq8/l3sq042+6bJgJ3CfDYdNKJCTF/09F5JKkpXeIxL4MGqvg5nOoyiahDQsUzMT3dwGg7IWqxQidcJ576XSBkR2qNwUrl6qq87JP+Zo3RJbA5bpPubm6sUonWE3hRGg4LWceVBO34J/wutWVt4W7dXnK5WVhJv8UHJcbgWR9dMpWkbeMpakqlRRLOTibztMFkx3xyIMmZS+cNyhRyatw+DwX/opuY+bl8X4yKgNOuW/w6r06r4MrL78MTjqZDQ4xkCSL3x3KWr2Tf4lAX6sdwKTzdBdzvFuLeuijngrvRYRyk/3jk/o4ujfHMdrergMjlP5Js7ICZSLhXHHOc2Hc5oPaBIx59r6FynA+W6ROmk5kVF2BNkRlP6/oV5Apn3MMUnDc4YjHaowt8UVkIHZOEL8hxymYDR4g9y1wOoIwKCorBQa5jsXH+AEop3hlsv4uqzrrcGGQhfQEW0Vb1fG4N0VAyWEodaw7wOY3XCrW7yHjIgRM3Is+juT7jMeACW+OQuvQHTS/9bc9n9sXjjVwsvoHROLxsXMFO9HablXaEKzFL1oGXpnavYf/MuZMwALsPish2Mmj9fONNMBo1yYy/j+8GzHCqByDS1ZPnlzPQD0ztGNwNfOOhNOqamqaE9GNHv92yQIf/KKGhnjFH/I9IlzA28eaaSVql/1vdhRAI2G1WxpgyQ1ryRPLYHA/Qw9OYrb+jIxHj9uqfohShgIqnv6TCXRmByfyU6Te3oqKLyezKj7tPCqv1la1ostycmE4msAs4EI7pe1OZcRulPkUJrZCPkvo+EYTw8AfGmwHFb5foQ4wk8pkjTvo1zHmjy0GjMAZpcmDHfyHAyoaED6DUKAHRBbMdSqQJWmzhHkzn5oRCR6UlWSyxRZ1wBIKn+T+kcn28XiLlJrJVK3n2CQkE1c3EfFemnimo0Yc9yNQZygfZjr2W2TnmtAZ5jHiMmv7E8CPxBQBd/pf29z/uAEwQIqVFSHxkVaVjHW5wlhfWwOuj0xZFly,iv:mXE8xpXFBYSJce9pg+g3OedMS9+ZHOHHwydCY0NbGRQ=,tag:cEqbUu9Y1PFKXwaeqioXWA==,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] 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_saePasswordsFile: ENC[AES256_GCM,data:ylY1LwMYlHdvYIVPIIr65BuxkW/BHCikkbGO5nNSU9WVekWiDXNIt2EQ2sYcdqnvZMGvcG0G4SQvCwpNO8ihh/RqcLYpTxldI8zwSqAwvATu7prV8l2bCvBQ+NXZ3yAW,iv:L6ncjd0u316gF/3InI7cuqO1kDpH7ahWGcsssYfb2YU=,tag:IAqt8vSDjW3OasOTJ44PeQ==,type:str]
wlan0_wpaPskFile: ENC[AES256_GCM,data:TnQ794CQ8jEBT7BTynPpU0S1VpT2oS2rgKmaxfkW7v3mhV4ijgnsypixkCD6GmQdAL0vsKFq0tu76TqeqcpJ1tWTGdfg3UtTmZ/ARFu2y3jYVNhmFziBpYlOAd2e/oo0DpXhYUVZN3TvALF1dJ7aGt8XQewTaIYQBL04aietPXPHzPvecOLwNhnxMer6BAZG0HC/wpuwmmQ0CsR7Wbw/6Efn25oGXvITbndVbZoyC85bsckptYTSQmORKZH0Ew==,iv:UzOFbHZT37uDfaLVmOFGUG/Pv3kmq3pZLaZ0mkBCUQc=,tag:oq+dZefYEPneXiNeXVgHSw==,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: sops:
kms: [] kms: []
gcp_kms: [] gcp_kms: []
@ -21,8 +21,8 @@ sops:
THRNR0tEUzhPdFFhWWxvZlpKYmZKM2MKxc5s1jsci8jPOrvZAoofVNvHT4o9P6yv THRNR0tEUzhPdFFhWWxvZlpKYmZKM2MKxc5s1jsci8jPOrvZAoofVNvHT4o9P6yv
J8rALQQXgql6obK51Q/Doyzvo1RJ0T7epiWEAZm5B3vDrf6KqbWBYw== J8rALQQXgql6obK51Q/Doyzvo1RJ0T7epiWEAZm5B3vDrf6KqbWBYw==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2023-12-24T22:39:23Z" lastmodified: "2023-12-25T21:25:35Z"
mac: ENC[AES256_GCM,data:eNbO9GqcrcKg3qAMZDkOOcihUhWeXWCUHrbdiIIKomdp8hZdou6He1Dd5hPZJMrwuTfiYx9NcuRph/XXXYEMLIfRhb2Kw2LoKW4e/gZDj6rFSnRx/kqg/+oZLnnsZWnNYEhQTOEknpYNsjoBd1YOHqj9EvdABLCELvB9KfL7DnQ=,iv:bXlTOq1qeFldVH9dBotUoxHDNh/pG6eJOzS2SBI2R8s=,tag:foDEWwGMiYXpS6LiRual5w==,type:str] mac: ENC[AES256_GCM,data:Sk3eyBaxhL7cX78YprYsv75oO+auEoxxGHCk1MRYGcAkat3vrc2vXjmKn6SsVQC8SWvu2YR2dOGU85Z7FCUUmmnwKeh+1PKMsurwfrNkB4umADXjaESNUWNevzAK9LR4pI1I6rGzl7mFEFYGEPd948JMOfkIfwNm1KMmETGkkI0=,iv:UzfDF94UFjPuEgRkpkRyLxSwZGymZclboHYQ/HxulJQ=,tag:MIBhvegV4NaZF+nGShotPw==,type:str]
pgp: pgp:
- created_at: "2023-08-11T16:15:11Z" - created_at: "2023-08-11T16:15:11Z"
enc: |- enc: |-