1
1
Fork 1
mirror of https://github.com/oddlama/nix-config.git synced 2025-10-11 07:10:39 +02:00

feat: remove the need to specify cidrs in wireguard addresses and

properly derive allowed ips
This commit is contained in:
oddlama 2023-05-20 18:24:30 +02:00
parent 4057ee9051
commit 3862bd6b14
No known key found for this signature in database
GPG key ID: 14EFE510775FE39A
4 changed files with 59 additions and 53 deletions

View file

@ -23,7 +23,7 @@ This is my personal nix config.
- `envoy/` - Hetzner Cloud server. Primarily used as my mailserver and VPN provider.
- `zackbiene/` - ODROID N2+. Hosts IoT and Home Automation stuff and fully isolates that stuff from my internal network.
- not yet ready to be publicized: my main development machine, the powerful home server, some services ... (still in transition from gentoo :/)
- `modules/` additional NixOS modules that are not yet upstreamed.
- `modules/` additional NixOS modules that are not yet upstreamed, or specific to this setup.
- `nix/` library functions and plumbing
- `apps/` Additional runnable actions for this flake
- `default.nix` Collects all apps and generates a definition for a specified system

View file

@ -67,15 +67,22 @@
# > net.cidr.canonicalize "192.168.1.100/24"
# "192.168.1.0/24"
canonicalize = x: libWithNet.net.cidr.make (libWithNet.net.cidr.length x) (ip x);
# coercev4 :: [cidr4] -> (cidr4 | null)
# coercev4 :: [cidr4 | ipv4] -> (cidr4 | null)
#
# Returns the smallest cidr network that includes all given addresses
# Returns the smallest cidr network that includes all given addresses.
# If no cidr mask is given, /32 is assumed.
#
# Examples:
#
# > net.cidr.coercev4 ["192.168.1.1/24" "192.168.6.1/32"]
# "192.168.0.0/21"
coercev4 = addrs: let
coercev4 = addrs_: let
# Append /32 if necessary
addrs = map (x:
if lib.hasInfix "/" x
then x
else "${x}/32")
addrs_;
# The smallest occurring length is the first we need to start checking, since
# any greater cidr length represents a smaller address range which
# wouldn't contain all of the original addresses.
@ -101,15 +108,22 @@
if addrs == []
then null
else libWithNet.net.cidr.make bestLength firstIp;
# coercev6 :: [cidr6] -> (cidr6 | null)
# coercev6 :: [cidr6 | ipv6] -> (cidr6 | null)
#
# Returns the smallest cidr network that includes all given addresses
# Returns the smallest cidr network that includes all given addresses.
# If no cidr mask is given, /128 is assumed.
#
# Examples:
#
# > net.cidr.coercev6 ["fd00:dead:cafe::/64" "fd00:fd12:3456:7890::/56"]
# "fd00:c000::/18"
coercev6 = addrs: let
coercev6 = addrs_: let
# Append /128 if necessary
addrs = map (x:
if lib.hasInfix "/" x
then x
else "${x}/128")
addrs_;
# The smallest occurring length is the first we need to start checking, since
# any greater cidr length represents a smaller address range which
# wouldn't contain all of the original addresses.

View file

@ -193,9 +193,8 @@
via = nodeName;
keepalive = false;
};
cidrv4 = "${net.cidr.host vmCfg.id cfg.networking.wireguard.cidrv4}/32";
cidrv6 = "${net.cidr.host vmCfg.id cfg.networking.wireguard.cidrv6}/128";
# TODO check error: addresses = ["10.22.22.2/30"];
ipv4 = net.cidr.host vmCfg.id cfg.networking.wireguard.cidrv4;
ipv6 = net.cidr.host vmCfg.id cfg.networking.wireguard.cidrv6;
};
};
};
@ -402,8 +401,8 @@ in {
inherit (cfg.networking) host;
inherit (cfg.networking.wireguard) openFirewallRules port;
};
cidrv4 = net.cidr.hostCidr 1 cfg.networking.wireguard.cidrv4;
cidrv6 = net.cidr.hostCidr 1 cfg.networking.wireguard.cidrv6;
ipv4 = net.cidr.host 1 cfg.networking.wireguard.cidrv4;
ipv6 = net.cidr.host 1 cfg.networking.wireguard.cidrv6;
};
}
// extraLib.mergeToplevelConfigs ["disko" "microvm" "systemd"] (mapAttrsToList microvmConfig vms)

View file

@ -86,6 +86,23 @@
# Adds context information to the assertions for this network
assertionPrefix = "Wireguard network '${wgName}' on '${nodeName}'";
# Calculates which traffic should be routed to a given server node
# Usually we just want to allow other peers to route traffic
# for our "children" through us, additional to traffic to us of course.
# If a server exposes additional network access (global, lan, ...),
# these can be added aswell. TODO (do that)
serverAllowedIPs = serverNode: let
snCfg = wgCfgOf serverNode;
in
map (net.cidr.make 128) (
# The server accepts traffic to it's own address
snCfg.addresses
# plus traffic for any of its external peers
++ attrValues snCfg.server.externalPeers
# plus traffic for any client that is connected via that server
++ map (n: (wgCfgOf n).addresses) (filter (n: (wgCfgOf n).client.via == serverNode) associatedClientNodes)
);
in {
assertions = [
{
@ -157,16 +174,13 @@
if isServer
then
# Always include all other server nodes.
map (serverNode: {
wireguardPeerConfig = let
snCfg = wgCfgOf serverNode;
in {
map (serverNode: let
snCfg = wgCfgOf serverNode;
in {
wireguardPeerConfig = {
PublicKey = builtins.readFile (peerPublicKeyPath serverNode);
PresharedKeyFile = config.rekey.secrets.${peerPresharedKeySecret nodeName serverNode}.path;
# The allowed ips of a server node are it's own addreses,
# plus each external peer's addresses,
# plus each client's addresses that is connected via that node.
AllowedIPs = snCfg.addresses;
AllowedIPs = serverAllowedIPs serverNode;
Endpoint = "${snCfg.server.host}:${toString snCfg.server.port}";
};
})
@ -192,7 +206,7 @@
{
PublicKey = builtins.readFile (peerPublicKeyPath clientNode);
PresharedKeyFile = config.rekey.secrets.${peerPresharedKeySecret nodeName clientNode}.path;
AllowedIPs = clientCfg.addresses;
AllowedIPs = map (net.cidr.make 128) clientCfg.addresses;
}
// optionalAttrs clientCfg.keepalive {
PersistentKeepalive = 25;
@ -207,7 +221,7 @@
PublicKey = builtins.readFile (peerPublicKeyPath wgCfg.client.via);
PresharedKeyFile = config.rekey.secrets.${peerPresharedKeySecret nodeName wgCfg.client.via}.path;
# TODO this should be 0.0.0.0 if the client wants to route all traffic
AllowedIPs = (wgCfgOf wgCfg.client.via).addresses;
AllowedIPs = serverAllowedIPs wgCfg.client.via;
};
}
];
@ -301,44 +315,23 @@ in {
description = mdDoc "The order priority used when creating systemd netdev and network files.";
};
cidrv4 = mkOption {
type =
if config.client.via != null
then net.types.cidrv4-in nodes.${config.client.via}.config.extra.wireguard.${name}.cidrv4
else net.types.cidrv4;
description = mdDoc ''
The ipv4 host address (with cidr mask) to configure for this interface.
The cidr mask determines this peers allowed address range as configured on other peers.
The mask should usually be fully restricted (/32) when no external clients are configured
and no other node uses this as a via.
'';
ipv4 = mkOption {
type = net.types.ipv4;
description = mdDoc "The ipv4 address for this machine.";
};
cidrv6 = mkOption {
type =
if config.client.via != null
then net.types.cidrv6-in nodes.${config.client.via}.config.extra.wireguard.${name}.cidrv6
else net.types.cidrv6;
description = mdDoc ''
The ipv6 host address (with cidr mask) to configure for this interface.
The cidr mask determines this peers allowed address range as configured on other peers.
The mask should usually be fully restricted (/128) when no external clients are configured
and no other node uses this as a via.
'';
ipv6 = mkOption {
type = net.types.ipv6;
description = mdDoc "The ipv6 address for this machine.";
};
addresses = mkOption {
type = types.listOf (
if config.client.via != null
then net.types.cidr-in nodes.${config.client.via}.config.extra.wireguard.${name}.addresses
else net.types.cidr
);
default = [config.cidrv4 config.cidrv6];
type = types.listOf net.types.ip;
default = [config.ipv4 config.ipv6];
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 ip addresses (v4 and/or v6) to use for this machine.
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.
By default this will just include {option}`ipv4` and {option}`ipv6` as configured.
'';
};
};