1
1
Fork 1
mirror of https://github.com/oddlama/nix-config.git synced 2025-10-10 14:50:40 +02:00

wip: prepare switch to vlans

This commit is contained in:
oddlama 2024-12-19 20:31:26 +01:00
parent 70cae77452
commit d0448757bf
No known key found for this signature in database
GPG key ID: 14EFE510775FE39A
5 changed files with 285 additions and 217 deletions

View file

@ -28,15 +28,63 @@ in
};
home-lan = {
cidrv4 = "192.168.1.0/24";
vlans = {
personal = {
id = 10;
cidrv4 = "192.168.10.0/24";
cidrv6 = "fd10::/64";
hosts.ward.id = 1;
hosts.sire.id = 2;
hosts.ward-adguardhome.id = 3;
hosts.ward-web-proxy.id = 4;
hosts.sire-samba.id = 10;
hosts.wallbox.id = 40;
hosts.home-assistant-temp.id = 85;
};
services = {
id = 20;
cidrv4 = "192.168.20.0/24";
cidrv6 = "fd20::/64";
hosts.ward.id = 1;
hosts.sire.id = 2;
hosts.ward-adguardhome = {
id = 3;
inherit (nodes.ward-adguardhome.config.lib.microvm.interfaces.vlan-services) mac;
};
hosts.ward-web-proxy = {
id = 4;
inherit (nodes.ward-web-proxy.config.lib.microvm.interfaces.vlan-services) mac;
};
hosts.sire-samba = {
id = 10;
inherit (nodes.sire-samba.config.lib.microvm.interfaces.vlan-services) mac;
};
};
devices = {
id = 30;
cidrv4 = "192.168.30.0/24";
cidrv6 = "fd30::/64";
hosts.ward.id = 1;
hosts.ward-adguardhome.id = 3;
hosts.wallbox = {
id = 40;
mac = globals.macs.wallbox;
};
hosts.home-assistant-temp = {
id = 85;
mac = globals.macs.home-assistant;
};
};
iot = {
id = 40;
cidrv4 = "192.168.40.0/24";
cidrv6 = "fd40::/64";
hosts.ward.id = 1;
hosts.ward-adguardhome.id = 3;
};
guests = {
id = 50;
cidrv4 = "192.168.50.0/24";
cidrv6 = "fd50::/64";
hosts.ward.id = 1;
hosts.ward-adguardhome.id = 3;
};
};
};
proxy-home = {

View file

@ -2,7 +2,6 @@
lib,
globals,
utils,
nodes,
...
}:
let
@ -30,58 +29,42 @@ in
renew-timer = 3600;
interfaces-config = {
# XXX: BUG: why does this bind other macvtaps?
interfaces = [ "lan-self" ];
interfaces = map (name: "me-${name}") (builtins.attrNames globals.net.home-lan.vlans);
service-sockets-max-retries = -1;
};
option-data = [
subnet4 = lib.mapAttrsToList globals.net.home-lan.vlans (
vlanName: vlanCfg: [
{
name = "domain-name-servers";
data = globals.net.home-lan.hosts.ward-adguardhome.ipv4;
}
];
subnet4 = [
{
id = 1;
interface = "lan-self";
subnet = globals.net.home-lan.cidrv4;
inherit (vlanCfg) id;
interface = "me-${vlanName}";
subnet = vlanCfg.cidrv4;
pools = [
{
pool = "${net.cidr.host 20 globals.net.home-lan.cidrv4} - ${
net.cidr.host (-6) globals.net.home-lan.cidrv4
}";
pool = "${net.cidr.host 20 vlanCfg.cidrv4} - ${net.cidr.host (-6) vlanCfg.cidrv4}";
}
];
option-data = [
{
name = "routers";
data = globals.net.home-lan.hosts.ward.ipv4; # FIXME: how to advertise v6 address also?
data = vlanCfg.hosts.ward.ipv4; # FIXME: how to advertise v6 address also?
}
{
name = "domain-name-servers";
data = vlanCfg.hosts.ward-adguardhome.ipv4;
}
];
# FIXME: map this over globals.guests or smth. marker tag for finding: ipv4 192.168.1.1
reservations = [
{
hw-address = nodes.ward-adguardhome.config.lib.microvm.mac;
ip-address = globals.net.home-lan.hosts.ward-adguardhome.ipv4;
reservations = lib.concatLists (
lib.forEach (builtins.attrValues vlanCfg.hosts) (
hostCfg:
lib.optional (hostCfg.mac != null) {
hw-address = hostCfg.mac;
ip-address = hostCfg.ipv4;
}
{
hw-address = nodes.ward-web-proxy.config.lib.microvm.mac;
ip-address = globals.net.home-lan.hosts.ward-web-proxy.ipv4;
)
);
}
{
hw-address = nodes.sire-samba.config.lib.microvm.mac;
ip-address = globals.net.home-lan.hosts.sire-samba.ipv4;
}
{
hw-address = globals.macs.wallbox;
ip-address = globals.net.home-lan.hosts.wallbox.ipv4;
}
{
hw-address = globals.macs.home-assistant;
ip-address = globals.net.home-lan.hosts.home-assistant-temp.ipv4;
}
];
}
];
]
);
};
};

View file

@ -4,12 +4,6 @@
lib,
...
}:
let
vlans.personal = 10;
vlans.devices = 20;
vlans.iot = 30;
vlans.guest = 40;
in
{
boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
networking.hostId = config.repo.secrets.local.networking.hostId;
@ -17,11 +11,19 @@ in
globals.monitoring.ping.ward = {
hostv4 = lib.net.cidr.ip globals.net.home-lan.hosts.ward.cidrv4;
hostv6 = lib.net.cidr.ip globals.net.home-lan.hosts.ward.cidrv6;
network = "home-lan";
network = "home-lan.vlans.devices";
};
boot.initrd.availableKernelModules = [ "8021q" ];
boot.initrd.systemd.network = {
enable = true;
netdevs."30-vlan-home" = {
netdevConfig = {
Kind = "vlan";
Name = "vlan-home";
};
vlanConfig.Id = globals.net.home-lan.vlans.home.id;
};
networks = {
"10-wan" = {
address = [ globals.net.home-wan.hosts.ward.cidrv4 ];
@ -30,12 +32,21 @@ in
networkConfig.IPv6PrivacyExtensions = "yes";
linkConfig.RequiredForOnline = "routable";
};
"20-lan" = {
"10-lan" = {
matchConfig.MACAddress = config.repo.secrets.local.networking.interfaces.lan.mac;
# This interface should only be used from attached vlans.
# So don't acquire a link local address and only wait for
# this interface to gain a carrier.
networkConfig.LinkLocalAddressing = "no";
linkConfig.RequiredForOnline = "carrier";
vlan = [ "vlan-home" ];
};
"30-vlan-home" = {
address = [
globals.net.home-lan.hosts.ward.cidrv4
globals.net.home-lan.hosts.ward.cidrv6
];
matchConfig.MACAddress = config.repo.secrets.local.networking.interfaces.lan.mac;
matchConfig.Name = "vlan-home";
networkConfig = {
IPv4Forwarding = "yes";
IPv6PrivacyExtensions = "yes";
@ -48,11 +59,18 @@ in
# Create a MACVTAP for ourselves too, so that we can communicate with
# our guests on the same interface.
systemd.network.netdevs =
{
"10-lan-self" = {
systemd.network.netdevs = lib.flip lib.concatMapAttrs globals.net.home-lan.vlans (
vlanName: vlanCfg: {
"30-vlan-${vlanName}" = {
netdevConfig = {
Name = "lan-self";
Kind = "vlan";
Name = "vlan-${vlanName}";
};
vlanConfig.Id = vlanCfg.id;
};
"40-me-${vlanName}" = {
netdevConfig = {
Name = "me-${vlanName}";
Kind = "macvlan";
};
extraConfig = ''
@ -61,30 +79,18 @@ in
'';
};
}
// lib.flip lib.mapAttrs' vlans (
vlanName: vlanId:
lib.nameValuePair "40-vlan-${vlanName}" {
netdevConfig = {
Kind = "vlan";
Name = "vlan-${vlanName}";
};
vlanConfig.Id = vlanId;
}
);
systemd.network.networks =
{
"10-lan" = {
matchConfig.MACAddress = config.repo.secrets.local.networking.interfaces.lan.mac;
# This interface should only be used from attached macvtaps.
# This interface should only be used from attached vlans.
# So don't acquire a link local address and only wait for
# this interface to gain a carrier.
networkConfig.LinkLocalAddressing = "no";
linkConfig.RequiredForOnline = "carrier";
extraConfig = ''
[Network]
MACVLAN=lan-self
'';
vlan = map (name: "vlan-${name}") (builtins.attrNames globals.net.home-lan.vlans);
};
"10-wan" = {
#DHCP = "yes";
@ -95,46 +101,13 @@ in
gateway = [ globals.net.home-wan.hosts.fritzbox.ipv4 ];
matchConfig.MACAddress = config.repo.secrets.local.networking.interfaces.wan.mac;
networkConfig.IPv6PrivacyExtensions = "yes";
dhcpV6Config.PrefixDelegationHint = "::/64";
# dhcpV6Config.PrefixDelegationHint = "::/64";
# FIXME: This should not be needed, but for some reason part of networkd
# isn't seeing the RAs and not triggering DHCPv6. Even though some other
# part of networkd is properly seeing them and logging accordingly.
dhcpV6Config.WithoutRA = "solicit";
linkConfig.RequiredForOnline = "routable";
};
"20-lan-self" = {
address = [
globals.net.home-lan.hosts.ward.cidrv4
globals.net.home-lan.hosts.ward.cidrv6
];
matchConfig.Name = "lan-self";
networkConfig = {
IPv4Forwarding = "yes";
IPv6PrivacyExtensions = "yes";
IPv6SendRA = true;
IPv6AcceptRA = false;
DHCPPrefixDelegation = true;
MulticastDNS = true;
};
dhcpPrefixDelegationConfig.UplinkInterface = "wan";
dhcpPrefixDelegationConfig.Token = "::ff";
# Announce a static prefix
ipv6Prefixes = [
{ Prefix = globals.net.home-lan.cidrv6; }
];
# Delegate prefix
dhcpPrefixDelegationConfig = {
SubnetId = "22";
};
# Provide a DNS resolver
# ipv6SendRAConfig = {
# Managed = true;
# EmitDNS = true;
# FIXME: this is not the true ipv6 of adguardhome DNS = globals.net.home-lan.hosts.ward-adguardhome.ipv6;
# FIXME: todo assign static additional to reservation in kea
# };
linkConfig.RequiredForOnline = "routable";
};
# Remaining macvtap interfaces should not be touched.
"90-macvtap-ignore" = {
matchConfig.Kind = "macvtap";
@ -142,10 +115,53 @@ in
linkConfig.Unmanaged = "yes";
};
}
// lib.flip lib.mapAttrs' vlans (
vlanName: _:
lib.nameValuePair "40-vlan-${vlanName}" {
// lib.flip lib.concatMapAttrs globals.net.home-lan.vlans (
vlanName: vlanCfg: {
"30-vlan-${vlanName}" = {
matchConfig.Name = "vlan-${vlanName}";
# This interface should only be used from attached macvlans.
# So don't acquire a link local address and only wait for
# this interface to gain a carrier.
networkConfig.LinkLocalAddressing = "no";
linkConfig.RequiredForOnline = "carrier";
extraConfig = ''
[Network]
MACVLAN=me-${vlanName}
'';
};
"40-me-${vlanName}" = {
address = [
vlanCfg.hosts.ward.cidrv4
vlanCfg.hosts.ward.cidrv6
];
matchConfig.Name = "me-${vlanName}";
networkConfig = {
IPv4Forwarding = "yes";
IPv6PrivacyExtensions = "yes";
IPv6SendRA = true;
IPv6AcceptRA = false;
# DHCPPrefixDelegation = true;
MulticastDNS = true;
};
# dhcpPrefixDelegationConfig.UplinkInterface = "wan";
# dhcpPrefixDelegationConfig.Token = "::ff";
# Announce a static prefix
ipv6Prefixes = [
{ Prefix = vlanCfg.cidrv6; }
];
# Delegate prefix
# dhcpPrefixDelegationConfig = {
# SubnetId = vlanCfg.id;
# };
# Provide a DNS resolver
# ipv6SendRAConfig = {
# Managed = true;
# EmitDNS = true;
# FIXME: this is not the true ipv6 of adguardhome DNS = globals.net.home-lan.hosts.ward-adguardhome.ipv6;
# FIXME: todo assign static additional to reservation in kea
# };
linkConfig.RequiredForOnline = "routable";
};
}
);
@ -155,31 +171,35 @@ in
"nd-router-solicit"
];
zones = {
zones =
{
untrusted.interfaces = [ "wan" ];
lan.interfaces = [ "lan-self" ];
proxy-home.interfaces = [ "proxy-home" ];
};
}
// lib.flip lib.concatMapAttrs globals.net.home-lan.vlans (
vlanName: _: {
"me-${vlanName}".interfaces = [ "me-${vlanName}" ];
}
);
rules = {
masquerade = {
from = [ "lan" ];
to = [ "untrusted" ];
masquerade = true;
};
outbound = {
from = [ "lan" ];
masquerade-internet = {
from = [
"vlan-home"
"vlan-services"
"vlan-devices"
"vlan-guests"
];
to = [
"lan"
"untrusted"
];
masquerade = true;
late = true; # Only accept after any rejects have been processed
verdict = "accept";
};
lan-to-local = {
from = [ "lan" ];
services-to-local = {
from = [ "vlan-services" ];
to = [ "local" ];
allowedUDPPorts = [ config.wireguard.proxy-home.server.port ];
@ -191,19 +211,6 @@ in
to = [ "proxy-home" ];
verdict = "accept";
};
#masquerade-vpn = {
# from = ["wg-home"];
# to = ["lan"];
# masquerade = true;
#};
#outbound-vpn = {
# from = ["wg-home"];
# to = ["lan"];
# late = true; # Only accept after any rejects have been processed
# verdict = "accept";
#};
};
};

View file

@ -15,35 +15,8 @@ let
description = "The network to which this endpoint is associated.";
};
};
in
{
options = {
globals = mkOption {
default = { };
type = types.submodule {
options = {
root = {
hashedPassword = mkOption {
type = types.str;
description = "My root user's password hash.";
};
};
myuser = {
name = mkOption {
type = types.str;
description = "My unix username.";
};
hashedPassword = mkOption {
type = types.str;
description = "My unix password hash.";
};
};
net = mkOption {
type = types.attrsOf (
types.submodule (netSubmod: {
options = {
networkOptions = netSubmod: {
cidrv4 = mkOption {
type = types.nullOr types.net.cidrv4;
description = "The CIDRv4 of this network";
@ -57,6 +30,7 @@ in
};
hosts = mkOption {
default = { };
type = types.attrsOf (
types.submodule (hostSubmod: {
options = {
@ -65,6 +39,12 @@ in
description = "The id of this host in the network";
};
mac = mkOption {
type = types.nullOr types.net.mac;
description = "The MAC of this host, if known. May be used to reserve an address in DHCP resolution.";
default = null;
};
ipv4 = mkOption {
type = types.nullOr types.net.ipv4;
description = "The IPv4 of this host";
@ -113,6 +93,56 @@ in
);
};
};
in
{
options = {
globals = mkOption {
default = { };
type = types.submodule {
options = {
root = {
hashedPassword = mkOption {
type = types.str;
description = "My root user's password hash.";
};
};
myuser = {
name = mkOption {
type = types.str;
description = "My unix username.";
};
hashedPassword = mkOption {
type = types.str;
description = "My unix password hash.";
};
};
net = mkOption {
default = { };
type = types.attrsOf (
types.submodule (netSubmod: {
options = networkOptions netSubmod // {
vlans = mkOption {
default = { };
type = types.attrsOf (
types.submodule (vlanNetSubmod: {
options = networkOptions vlanNetSubmod // {
id = mkOption {
type = types.ints.between 1 4094;
description = "The VLAN id";
};
name = mkOption {
description = "The name of this VLAN";
default = vlanNetSubmod.config._module.args.name;
type = types.str;
};
};
})
);
};
};
})
);
};

View file

@ -57,8 +57,8 @@ in
"eth7"
]
];
connections.eth1 = mkConnection "ward" "lan-self";
connections.eth2 = mkConnection "sire" "lan-self";
connections.eth1 = mkConnection "ward" "lan";
connections.eth2 = mkConnection "sire" "lan";
connections.eth7 = mkConnection "zackbiene" "lan1";
};