forked from mirrors_public/oddlama_nix-config
feat: implement cidr coersion to automatically determine wireguard network size from participants
This commit is contained in:
parent
6d8f8ab2e3
commit
4057ee9051
14 changed files with 240 additions and 29 deletions
|
@ -142,8 +142,8 @@
|
|||
static = {
|
||||
matchConfig.Name = vmCfg.networking.mainLinkName;
|
||||
address = [
|
||||
vmCfg.networking.static.ipv4
|
||||
vmCfg.networking.static.ipv6
|
||||
"${vmCfg.networking.static.ipv4}/${toString (net.cidr.length cfg.networking.static.baseCidrv4)}"
|
||||
"${vmCfg.networking.static.ipv6}/${toString (net.cidr.length cfg.networking.static.baseCidrv6)}"
|
||||
];
|
||||
gateway = [
|
||||
cfg.networking.host
|
||||
|
@ -161,13 +161,14 @@
|
|||
boot.initrd.systemd.enable = mkForce false;
|
||||
|
||||
# Create a firewall zone for the bridged traffic and secure vm traffic
|
||||
# TODO mkForce nftables
|
||||
networking.nftables.firewall = {
|
||||
zones = lib.mkForce {
|
||||
zones = mkForce {
|
||||
"${vmCfg.networking.mainLinkName}".interfaces = [vmCfg.networking.mainLinkName];
|
||||
"local-vms".interfaces = ["wg-local-vms"];
|
||||
};
|
||||
|
||||
rules = lib.mkForce {
|
||||
rules = mkForce {
|
||||
"${vmCfg.networking.mainLinkName}-to-local" = {
|
||||
from = [vmCfg.networking.mainLinkName];
|
||||
to = ["local"];
|
||||
|
@ -184,8 +185,8 @@
|
|||
# We have a resolvable hostname / static ip, so all peers can directly communicate with us
|
||||
server = optionalAttrs (cfg.networking.host != null) {
|
||||
inherit (vmCfg.networking) host;
|
||||
port = 51829;
|
||||
openFirewallInRules = ["${vmCfg.networking.mainLinkName}-to-local"];
|
||||
inherit (cfg.networking.wireguard) port;
|
||||
openFirewallRules = ["${vmCfg.networking.mainLinkName}-to-local"];
|
||||
};
|
||||
# If We don't have such guarantees, so we must use a client-server architecture.
|
||||
client = optionalAttrs (cfg.networking.host == null) {
|
||||
|
@ -262,6 +263,18 @@ in {
|
|||
description = mdDoc "The ipv6 network address range to use for internal vm traffic.";
|
||||
default = "fddd::/64";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
default = 51829;
|
||||
type = types.port;
|
||||
description = mdDoc "The port to listen on.";
|
||||
};
|
||||
|
||||
openFirewallRules = mkOption {
|
||||
default = [];
|
||||
type = types.listOf types.str;
|
||||
description = mdDoc "The {option}`port` will be opened for all of the given rules in the nftable-firewall.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -387,8 +400,7 @@ in {
|
|||
extra.wireguard."${nodeName}-local-vms" = {
|
||||
server = {
|
||||
inherit (cfg.networking) host;
|
||||
port = 51829;
|
||||
openFirewallInRules = ["lan-to-local"];
|
||||
inherit (cfg.networking.wireguard) openFirewallRules port;
|
||||
};
|
||||
cidrv4 = net.cidr.hostCidr 1 cfg.networking.wireguard.cidrv4;
|
||||
cidrv6 = net.cidr.hostCidr 1 cfg.networking.wireguard.cidrv6;
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
mkOption
|
||||
optionalAttrs
|
||||
optionals
|
||||
splitString
|
||||
types
|
||||
;
|
||||
|
||||
|
@ -54,6 +53,7 @@
|
|||
peerPrivateKeySecret
|
||||
peerPublicKeyPath
|
||||
usedAddresses
|
||||
toNetworkAddr
|
||||
;
|
||||
|
||||
isServer = wgCfg.server.host != null;
|
||||
|
@ -82,7 +82,7 @@
|
|||
# Figure out if there are duplicate peers or addresses so we can
|
||||
# make an assertion later.
|
||||
duplicatePeers = duplicates externalPeerNamesRaw;
|
||||
duplicateAddrs = duplicates (map (x: head (splitString "/" x)) usedAddresses);
|
||||
duplicateAddrs = duplicates (map net.cidr.ip usedAddresses);
|
||||
|
||||
# Adds context information to the assertions for this network
|
||||
assertionPrefix = "Wireguard network '${wgName}' on '${nodeName}'";
|
||||
|
@ -118,16 +118,27 @@
|
|||
(isServer && wgCfg.server.openFirewall)
|
||||
[wgCfg.server.port];
|
||||
|
||||
# TODO mkForce nftables
|
||||
networking.nftables.firewall.rules =
|
||||
mkIf
|
||||
(isServer && wgCfg.server.openFirewallInRules != [])
|
||||
(genAttrs wgCfg.server.openFirewallInRules (_: {allowedUDPPorts = [wgCfg.server.port];}));
|
||||
(isServer && wgCfg.server.openFirewallRules != [])
|
||||
(lib.mkForce (genAttrs wgCfg.server.openFirewallRules (_: {allowedUDPPorts = [wgCfg.server.port];})));
|
||||
|
||||
rekey.secrets =
|
||||
concatAttrs (map
|
||||
(other: {${peerPresharedKeySecret nodeName other}.file = peerPresharedKeyPath nodeName other;})
|
||||
(other: {
|
||||
${peerPresharedKeySecret nodeName other} = {
|
||||
file = peerPresharedKeyPath nodeName other;
|
||||
owner = "systemd-network";
|
||||
};
|
||||
})
|
||||
neededPeers)
|
||||
// {${peerPrivateKeySecret nodeName}.file = peerPrivateKeyPath nodeName;};
|
||||
// {
|
||||
${peerPrivateKeySecret nodeName} = {
|
||||
file = peerPrivateKeyPath nodeName;
|
||||
owner = "systemd-network";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.network.netdevs."${toString wgCfg.priority}-${wgName}" = {
|
||||
netdevConfig = {
|
||||
|
@ -156,21 +167,18 @@
|
|||
# plus each external peer's addresses,
|
||||
# plus each client's addresses that is connected via that node.
|
||||
AllowedIPs = snCfg.addresses;
|
||||
# TODO this needed? or even wanted at all?
|
||||
# ++ attrValues snCfg.server.externalPeers;
|
||||
# ++ map (n: (wgCfgOf n).addresses) snCfg.ourClientNodes;
|
||||
Endpoint = "${snCfg.server.host}:${toString snCfg.server.port}";
|
||||
};
|
||||
})
|
||||
(filterSelf associatedServerNodes)
|
||||
# All our external peers
|
||||
++ mapAttrsToList (extPeer: allowedIPs: let
|
||||
++ mapAttrsToList (extPeer: ips: let
|
||||
peerName = externalPeerName extPeer;
|
||||
in {
|
||||
wireguardPeerConfig = {
|
||||
PublicKey = builtins.readFile (peerPublicKeyPath peerName);
|
||||
PresharedKeyFile = config.rekey.secrets.${peerPresharedKeySecret nodeName peerName}.path;
|
||||
AllowedIPs = allowedIPs;
|
||||
AllowedIPs = map (net.cidr.make 128) ips;
|
||||
# Connections to external peers should always be kept alive
|
||||
PersistentKeepalive = 25;
|
||||
};
|
||||
|
@ -207,7 +215,7 @@
|
|||
|
||||
systemd.network.networks."${toString wgCfg.priority}-${wgName}" = {
|
||||
matchConfig.Name = wgName;
|
||||
networkConfig.Address = wgCfg.addresses;
|
||||
address = map toNetworkAddr wgCfg.addresses;
|
||||
};
|
||||
};
|
||||
in {
|
||||
|
@ -239,16 +247,16 @@ in {
|
|||
description = mdDoc "Whether to open the firewall for the specified {option}`port`.";
|
||||
};
|
||||
|
||||
openFirewallInRules = mkOption {
|
||||
openFirewallRules = mkOption {
|
||||
default = [];
|
||||
type = types.listOf types.str;
|
||||
description = mdDoc "The {option}`port` will be opened for all of the given rules in the nftable-firewall.";
|
||||
};
|
||||
|
||||
externalPeers = mkOption {
|
||||
type = types.attrsOf (types.listOf (net.types.cidr-in config.addresses));
|
||||
type = types.attrsOf (types.listOf (net.types.ip-in config.addresses));
|
||||
default = {};
|
||||
example = {my-android-phone = ["10.0.0.97/32"];};
|
||||
example = {my-android-phone = ["10.0.0.97"];};
|
||||
description = mdDoc ''
|
||||
Allows defining an extra set of peers that should be added to this wireguard network,
|
||||
but will not be managed by this flake. (e.g. phones)
|
||||
|
@ -329,6 +337,7 @@ in {
|
|||
description = mdDoc ''
|
||||
The addresses (with cidr mask) to configure for this interface.
|
||||
The cidr mask determines this peers allowed address range as configured on other peers.
|
||||
The actual network cidr will automatically be derived from all network participants.
|
||||
By default this will just include {option}`cidrv4` and {option}`cidrv6` as configured.
|
||||
'';
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue