refactor vlan and firewall config into modules
fix bug with vlans module fix vlans
This commit is contained in:
committed by
Joakim Repomaa
parent
6026e064fd
commit
2a36964fcc
@@ -49,19 +49,19 @@
|
|||||||
freun-dev = nixpkgs.lib.nixosSystem {
|
freun-dev = nixpkgs.lib.nixosSystem {
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
specialArgs = { inherit inputs; };
|
specialArgs = { inherit inputs; };
|
||||||
modules = [ ./hosts/freun.dev ];
|
modules = [ ./modules ./hosts/freun.dev ];
|
||||||
};
|
};
|
||||||
|
|
||||||
radish = nixpkgs.lib.nixosSystem {
|
radish = nixpkgs.lib.nixosSystem {
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
specialArgs = { inherit inputs; };
|
specialArgs = { inherit inputs; };
|
||||||
modules = [ ./hosts/radish ];
|
modules = [ ./modules ./hosts/radish ];
|
||||||
};
|
};
|
||||||
|
|
||||||
apu = nixpkgs.lib.nixosSystem {
|
apu = nixpkgs.lib.nixosSystem {
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
specialArgs = { inherit inputs; };
|
specialArgs = { inherit inputs; };
|
||||||
modules = [ ./hosts/apu ];
|
modules = [ ./modules ./hosts/apu ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,100 +4,6 @@
|
|||||||
|
|
||||||
{ lib, pkgs, config, ... }:
|
{ lib, pkgs, config, ... }:
|
||||||
let
|
let
|
||||||
services = {
|
|
||||||
ssh = { tcp = [ 22 ]; };
|
|
||||||
dhcp = { udp = [ 67 68 ]; };
|
|
||||||
dns = { udp = [ 53 ]; };
|
|
||||||
web = { tcp = [ 80 443 ]; };
|
|
||||||
};
|
|
||||||
|
|
||||||
vlans = {
|
|
||||||
koti = {
|
|
||||||
id = 10;
|
|
||||||
ipv6 = true;
|
|
||||||
availableServices = with services; [ dhcp dns ssh ];
|
|
||||||
};
|
|
||||||
gast = {
|
|
||||||
id = 20;
|
|
||||||
ipv6 = true;
|
|
||||||
staticLeases = [
|
|
||||||
{ macAddress = "dc:a6:32:05:08:5d"; address = "10.20.1.235"; }
|
|
||||||
];
|
|
||||||
availableServices = with services; [ dhcp dns ];
|
|
||||||
};
|
|
||||||
iot = {
|
|
||||||
id = 30;
|
|
||||||
availableServices = with services; [ dhcp dns ];
|
|
||||||
};
|
|
||||||
cfg = {
|
|
||||||
id = 40;
|
|
||||||
staticLeases = [
|
|
||||||
{ macAddress = "8c:3b:ad:c5:b8:ee"; address = "10.40.0.10"; }
|
|
||||||
];
|
|
||||||
availableServices = with services; [ dhcp dns ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
pvid = vlans.cfg.id;
|
|
||||||
vlanIds = lib.map ({ id, ... }: id) (lib.attrValues vlans);
|
|
||||||
vlanRange = {
|
|
||||||
min = lib.foldr lib.min 999 vlanIds;
|
|
||||||
max = lib.foldr lib.max 0 vlanIds;
|
|
||||||
};
|
|
||||||
|
|
||||||
buildVlanNetdev = name: { id, ... }: {
|
|
||||||
name = "20-${name}";
|
|
||||||
value = {
|
|
||||||
netdevConfig = {
|
|
||||||
Name = name;
|
|
||||||
Kind = "vlan";
|
|
||||||
MACAddress = "00:0d:b9:49:d2:${toString id}";
|
|
||||||
};
|
|
||||||
vlanConfig = { Id = id; };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
buildStaticLease = { macAddress, address }: ''
|
|
||||||
[DHCPServerStaticLease]
|
|
||||||
MACAddress=${macAddress}
|
|
||||||
Address=${address}
|
|
||||||
'';
|
|
||||||
|
|
||||||
buildBridgeVLANConfig = id: { VLAN = id; };
|
|
||||||
|
|
||||||
buildVlanNetwork = name: { id, ipv6 ? false, staticLeases ? [ ], ... }: {
|
|
||||||
name = "30-${name}";
|
|
||||||
value = {
|
|
||||||
matchConfig = {
|
|
||||||
Name = name;
|
|
||||||
};
|
|
||||||
networkConfig = {
|
|
||||||
Address = "10.${toString id}.0.1/23";
|
|
||||||
IPMasquerade = "ipv4";
|
|
||||||
DHCPServer = true;
|
|
||||||
IPv6AcceptRA = false;
|
|
||||||
IPv6SendRA = ipv6;
|
|
||||||
DHCPPrefixDelegation = ipv6;
|
|
||||||
};
|
|
||||||
dhcpServerConfig = {
|
|
||||||
PoolOffset = 255;
|
|
||||||
DNS = "10.${toString id}.0.1";
|
|
||||||
};
|
|
||||||
extraConfig = lib.concatLines (lib.map buildStaticLease staticLeases);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
buildFirewallRules = name: { availableServices ? [ ], ... }: {
|
|
||||||
allowedUDPPorts = lib.flatten (lib.map ({ udp ? [ ], ... }: udp) availableServices);
|
|
||||||
allowedTCPPorts = lib.flatten (lib.map ({ tcp ? [ ], ... }: tcp) availableServices);
|
|
||||||
};
|
|
||||||
|
|
||||||
vlanNetdevs = lib.mapAttrs' buildVlanNetdev vlans;
|
|
||||||
vlanNetworks = lib.mapAttrs' buildVlanNetwork vlans;
|
|
||||||
firewallRules = lib.mapAttrs buildFirewallRules (
|
|
||||||
vlans // { "tailscale*".availableServices = with services; [ ssh web ]; }
|
|
||||||
);
|
|
||||||
|
|
||||||
nginxVhost = options: {
|
nginxVhost = options: {
|
||||||
http2 = true;
|
http2 = true;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
@@ -129,6 +35,51 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
modules.vlans = {
|
||||||
|
enable = true;
|
||||||
|
networks = {
|
||||||
|
koti = {
|
||||||
|
id = 10;
|
||||||
|
ipv6 = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
gast = {
|
||||||
|
id = 20;
|
||||||
|
ipv6 = true;
|
||||||
|
staticLeases = {
|
||||||
|
"dc:a6:32:05:08:5d" = "10.20.1.235";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
iot = {
|
||||||
|
id = 30;
|
||||||
|
};
|
||||||
|
|
||||||
|
cfg = {
|
||||||
|
id = 40;
|
||||||
|
staticLeases = {
|
||||||
|
"8c:3b:ad:c5:b8:ee" = "10.40.0.10";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
bridge = {
|
||||||
|
enable = true;
|
||||||
|
pvid = config.modules.vlans.networks.cfg.id;
|
||||||
|
netdev = "20-lan";
|
||||||
|
network = "30-lan";
|
||||||
|
bindNetwork = "30-bind-lan";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
modules.firewall.rules = {
|
||||||
|
koti = [ "dhcp" "dns" "ssh" ];
|
||||||
|
gast = [ "dhcp" "dns" ];
|
||||||
|
iot = [ "dhcp" "dns" ];
|
||||||
|
cfg = [ "dhcp" "dns" ];
|
||||||
|
"tailscale*" = [ "ssh" "web" ];
|
||||||
|
};
|
||||||
|
|
||||||
systemd.network = {
|
systemd.network = {
|
||||||
enable = true;
|
enable = true;
|
||||||
config.networkConfig.IPv6Forwarding = true;
|
config.networkConfig.IPv6Forwarding = true;
|
||||||
@@ -147,18 +98,16 @@ in
|
|||||||
linkConfig.Name = "intern1";
|
linkConfig.Name = "intern1";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
netdevs = {
|
netdevs = {
|
||||||
"20-lan" = {
|
"20-lan" = {
|
||||||
netdevConfig = {
|
netdevConfig = {
|
||||||
Name = "lan";
|
Name = "lan";
|
||||||
Kind = "bridge";
|
Kind = "bridge";
|
||||||
};
|
};
|
||||||
bridgeConfig = {
|
|
||||||
VLANFiltering = true;
|
|
||||||
DefaultPVID = pvid;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
} // vlanNetdevs;
|
|
||||||
networks = {
|
networks = {
|
||||||
"30-bind-lan" = {
|
"30-bind-lan" = {
|
||||||
matchConfig = {
|
matchConfig = {
|
||||||
@@ -167,13 +116,8 @@ in
|
|||||||
networkConfig = {
|
networkConfig = {
|
||||||
Bridge = "lan";
|
Bridge = "lan";
|
||||||
};
|
};
|
||||||
extraConfig = ''
|
|
||||||
[BridgeVLAN]
|
|
||||||
VLAN=${toString vlanRange.min}-${toString vlanRange.max}
|
|
||||||
EgressUntagged=${toString pvid}
|
|
||||||
PVID=${toString pvid}
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
"30-lan" = {
|
"30-lan" = {
|
||||||
matchConfig = {
|
matchConfig = {
|
||||||
Name = "lan";
|
Name = "lan";
|
||||||
@@ -182,9 +126,8 @@ in
|
|||||||
IPv6AcceptRA = false;
|
IPv6AcceptRA = false;
|
||||||
ConfigureWithoutCarrier = true;
|
ConfigureWithoutCarrier = true;
|
||||||
};
|
};
|
||||||
vlan = lib.attrNames vlans;
|
|
||||||
bridgeVLANs = lib.map buildBridgeVLANConfig vlanIds;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
"30-wan" = {
|
"30-wan" = {
|
||||||
matchConfig = {
|
matchConfig = {
|
||||||
Name = "extern0";
|
Name = "extern0";
|
||||||
@@ -202,7 +145,7 @@ in
|
|||||||
Use6RD = true;
|
Use6RD = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
} // vlanNetworks;
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.networkd-dispatcher = {
|
services.networkd-dispatcher = {
|
||||||
@@ -316,7 +259,6 @@ in
|
|||||||
networking.nftables.enable = true;
|
networking.nftables.enable = true;
|
||||||
networking.firewall.enable = true;
|
networking.firewall.enable = true;
|
||||||
networking.useDHCP = false;
|
networking.useDHCP = false;
|
||||||
networking.firewall.interfaces = firewallRules;
|
|
||||||
|
|
||||||
system.stateVersion = "24.05";
|
system.stateVersion = "24.05";
|
||||||
}
|
}
|
||||||
|
|||||||
7
modules/default.nix
Normal file
7
modules/default.nix
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./vlans.nix
|
||||||
|
./firewall.nix
|
||||||
|
];
|
||||||
|
}
|
||||||
33
modules/firewall.nix
Normal file
33
modules/firewall.nix
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{ lib, config, ... }:
|
||||||
|
let
|
||||||
|
services = {
|
||||||
|
ssh = { tcp = [ 22 ]; };
|
||||||
|
dhcp = { udp = [ 67 68 ]; };
|
||||||
|
dns = { udp = [ 53 ]; };
|
||||||
|
web = { tcp = [ 80 443 ]; };
|
||||||
|
};
|
||||||
|
|
||||||
|
rulesForServices = enabledServices:
|
||||||
|
lib.foldr
|
||||||
|
(service: { allowedUDPPorts, allowedTCPPorts }: {
|
||||||
|
allowedUDPPorts = allowedUDPPorts ++ services.${service}.udp or [ ];
|
||||||
|
allowedTCPPorts = allowedTCPPorts ++ services.${service}.tcp or [ ];
|
||||||
|
})
|
||||||
|
{ allowedUDPPorts = [ ]; allowedTCPPorts = [ ]; }
|
||||||
|
enabledServices;
|
||||||
|
|
||||||
|
cfg = config.modules.firewall.rules;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.modules.firewall.rules = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf (lib.types.listOf (lib.types.enum (lib.attrNames services)));
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf (lib.length (lib.attrNames cfg) > 0) {
|
||||||
|
networking.firewall = {
|
||||||
|
enable = lib.mkDefault true;
|
||||||
|
interfaces = lib.mapAttrs (_: enabledServices: rulesForServices enabledServices) cfg;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
161
modules/vlans.nix
Normal file
161
modules/vlans.nix
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
{ lib, config, ... }:
|
||||||
|
let
|
||||||
|
types = {
|
||||||
|
portList = lib.types.listOf lib.types.int;
|
||||||
|
|
||||||
|
service = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
tcp = lib.mkOption {
|
||||||
|
type = types.portList;
|
||||||
|
default = [ ];
|
||||||
|
};
|
||||||
|
udp = lib.mkOption {
|
||||||
|
type = types.portList;
|
||||||
|
default = [ ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
vlan = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
id = lib.mkOption {
|
||||||
|
type = lib.types.int;
|
||||||
|
};
|
||||||
|
staticLeases = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf lib.types.str;
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
ipv6 = lib.mkEnableOption "ipv6";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
bridge = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
enable = lib.mkEnableOption "Enable bridge";
|
||||||
|
|
||||||
|
pvid = lib.mkOption {
|
||||||
|
type = lib.types.int;
|
||||||
|
};
|
||||||
|
bindNetwork = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
};
|
||||||
|
network = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
};
|
||||||
|
netdev = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cfg = config.modules.vlans;
|
||||||
|
vlans = lib.mapAttrsToList (attrName: { name ? attrName, ... }@vlan: ({ inherit name; } // vlan)) cfg.networks;
|
||||||
|
vlanAttrs = lib.listToAttrs (lib.map ({ name, ... }@value: { inherit name value; }) vlans);
|
||||||
|
|
||||||
|
buildNetdev = name: { id, ... }: {
|
||||||
|
name = "20-${name}";
|
||||||
|
value = {
|
||||||
|
netdevConfig = {
|
||||||
|
Name = name;
|
||||||
|
Kind = "vlan";
|
||||||
|
MACAddress = "00:0d:b9:49:d2:${toString id}";
|
||||||
|
};
|
||||||
|
vlanConfig = { Id = id; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
buildStaticLease = macAddress: address: ''
|
||||||
|
[DHCPServerStaticLease]
|
||||||
|
MACAddress=${macAddress}
|
||||||
|
Address=${address}
|
||||||
|
'';
|
||||||
|
|
||||||
|
buildNetwork = name: { id, ipv6, staticLeases, ... }: {
|
||||||
|
name = "30-${name}";
|
||||||
|
value = {
|
||||||
|
matchConfig = {
|
||||||
|
Name = name;
|
||||||
|
};
|
||||||
|
networkConfig = {
|
||||||
|
Address = "10.${toString id}.0.1/23";
|
||||||
|
IPMasquerade = "ipv4";
|
||||||
|
DHCPServer = true;
|
||||||
|
IPv6AcceptRA = false;
|
||||||
|
IPv6SendRA = ipv6;
|
||||||
|
DHCPPrefixDelegation = ipv6;
|
||||||
|
};
|
||||||
|
dhcpServerConfig = {
|
||||||
|
PoolOffset = 255;
|
||||||
|
DNS = "10.${toString id}.0.1";
|
||||||
|
};
|
||||||
|
extraConfig = lib.concatLines (lib.mapAttrsToList buildStaticLease staticLeases);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
vlanIds = lib.mapAttrsToList (_: { id, ... }: id) vlanAttrs;
|
||||||
|
|
||||||
|
vlanRange = {
|
||||||
|
min = lib.foldr lib.min 999 vlanIds;
|
||||||
|
max = lib.foldr lib.max 0 vlanIds;
|
||||||
|
};
|
||||||
|
|
||||||
|
bridgeVLANConfig = ''
|
||||||
|
[BridgeVLAN]
|
||||||
|
VLAN=${toString vlanRange.min}-${toString vlanRange.max}
|
||||||
|
EgressUntagged=${toString cfg.bridge.pvid}
|
||||||
|
PVID=${toString cfg.bridge.pvid}
|
||||||
|
'';
|
||||||
|
|
||||||
|
bridgeNetDev =
|
||||||
|
if (cfg.bridge.enable) then {
|
||||||
|
"${cfg.bridge.netdev}".bridgeConfig = {
|
||||||
|
VLANFiltering = true;
|
||||||
|
DefaultPVID = cfg.bridge.pvid;
|
||||||
|
};
|
||||||
|
} else { };
|
||||||
|
|
||||||
|
bridgeBindNetwork =
|
||||||
|
if (cfg.bridge.enable) then {
|
||||||
|
${cfg.bridge.bindNetwork}.extraConfig = bridgeVLANConfig;
|
||||||
|
} else { };
|
||||||
|
|
||||||
|
bridgeNetwork =
|
||||||
|
if (cfg.bridge.enable) then {
|
||||||
|
"${cfg.bridge.network}" = {
|
||||||
|
vlan = lib.map ({ name, ... }: name) vlans;
|
||||||
|
bridgeVLANs = lib.map ({ id, ... }: { VLAN = id; }) vlans;
|
||||||
|
};
|
||||||
|
} else { };
|
||||||
|
|
||||||
|
netdevs = lib.mergeAttrsList [
|
||||||
|
(lib.mapAttrs' buildNetdev vlanAttrs)
|
||||||
|
bridgeNetDev
|
||||||
|
];
|
||||||
|
|
||||||
|
networks = lib.mergeAttrsList [
|
||||||
|
(lib.mapAttrs' buildNetwork vlanAttrs)
|
||||||
|
bridgeBindNetwork
|
||||||
|
bridgeNetwork
|
||||||
|
];
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.modules.vlans = {
|
||||||
|
enable = lib.mkEnableOption "Enable VLANs";
|
||||||
|
|
||||||
|
networks = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf types.vlan;
|
||||||
|
};
|
||||||
|
|
||||||
|
bridge = lib.mkOption {
|
||||||
|
type = types.bridge;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
systemd.network = {
|
||||||
|
enable = lib.mkDefault true;
|
||||||
|
inherit netdevs networks;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user