Made helper functions to remap data in more config-friendly ways
commit
fcb8a4d0f8
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"root": {}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
description = "Do we have agnenix-rekey?";
|
||||||
|
|
||||||
|
outputs = { self, ... }:
|
||||||
|
{
|
||||||
|
nixosModules.myModule = import ./wire.nix;
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
{config, lib, ...}:
|
||||||
|
let
|
||||||
|
has-rekey = config ? rekey;
|
||||||
|
infoRemapper = import ./peer-info-remapper.nix {inherit lib;} config.modules.wirenix.config;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
{lib}: wirenix-config:
|
||||||
|
let
|
||||||
|
# Math
|
||||||
|
inList = elem: list: builtins.any (e: e == elem) list;
|
||||||
|
# IP
|
||||||
|
add-colons = string:
|
||||||
|
if ((builtins.stringLength string) > 4)
|
||||||
|
then
|
||||||
|
((builtins.substring 0 4 string) + ":" + (add-colons (builtins.substring 4 32 string)))
|
||||||
|
else string;
|
||||||
|
|
||||||
|
# Peer Information
|
||||||
|
peerInfo = {
|
||||||
|
peerSuffix = peerName: builtins.substring 0 20 (builtins.hashString "sha256" peerName);
|
||||||
|
peerSubnets = peer: builtins.filter (subnet: inList subnet.name peer.subnets) wirenix-config.subnets;
|
||||||
|
peerGroups = peer: builtins.catAttrs "group" peer.peers;
|
||||||
|
directPeers = peer: builtins.catAttrs "peer" peer.peers;
|
||||||
|
peerFromName = peerName: builtins.head (builtins.filter (peer: peer.name == peerName) wirenix-config.peers);
|
||||||
|
peersInGroup = groupName: builtins.filter (peer: inList groupName peer.groups) wirenix-config.peers;
|
||||||
|
peerPeersUnfiltered = peer: (builtins.map (peerInfo.peerFromName) (peerInfo.directPeers peer)) ++ (builtins.concatMap (group: peerInfo.peersInGroup group) (peerInfo.peerGroups peer));
|
||||||
|
peerIP = subnetName: PeerName: (add-colons ((subnetInfo.subnetPrefix subnetName) + (peerInfo.peerSuffix PeerName))) + "/80";
|
||||||
|
};
|
||||||
|
# Subnet Information
|
||||||
|
subnetInfo = {
|
||||||
|
subnetPrefix = subnetName: "fd" + (builtins.substring 0 10 (builtins.hashString "sha256" subnetName));
|
||||||
|
subnetPeers = subnet: builtins.filter (peer: inList subnet.name peer.subnets) wirenix-config.peers;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
peer = peer:
|
||||||
|
rec {
|
||||||
|
subnets = peerInfo.peerSubnets peer;
|
||||||
|
peers = lib.lists.remove peer (lib.lists.unique (peerInfo.peerPeersUnfiltered peer));
|
||||||
|
ip = subnet: peerInfo.peerIP subnet.name peer.name;
|
||||||
|
peersOnSubnet = subnet: builtins.filter (otherPeer: inList subnet.name otherPeer.subnets) peers;
|
||||||
|
publicKey = peer.publicKey;
|
||||||
|
privateKeyFile = peer.privateKeyFile;
|
||||||
|
};
|
||||||
|
subnet = subnet:
|
||||||
|
{
|
||||||
|
peers = subnetInfo.subnetPeers subnet;
|
||||||
|
ip = (add-colons (subnetInfo.subnetPrefix subnet.name)) + "::/80";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
# subnets:
|
||||||
|
# networkOne:
|
||||||
|
# prefix: "auto" or "none" or canonicalized ipv6
|
||||||
|
# ipv4: canonicalized ipv4 or "none"
|
||||||
|
# ipv6: canonicalized ipv6 or "auto" or "none"
|
||||||
|
# peers:
|
||||||
|
# peerOne:
|
||||||
|
# pubKey: "ABC..." Or "auto"
|
||||||
|
# subnets:
|
||||||
|
# networkOne:
|
||||||
|
# - ipv4: ip
|
||||||
|
# - ipv6: "auto" or "none" or ip
|
||||||
|
# groups:
|
||||||
|
# - "groupOne"
|
||||||
|
# peers:
|
||||||
|
# - peer: "peerTwo"
|
||||||
|
# - group: "groupOne"
|
@ -0,0 +1,94 @@
|
|||||||
|
{
|
||||||
|
subnets = [
|
||||||
|
{ name = "subnet.one"; }
|
||||||
|
{ name = "subnet.two"; }
|
||||||
|
{ name = "subnet.three"; }
|
||||||
|
];
|
||||||
|
peers = [
|
||||||
|
{
|
||||||
|
name = "peer.zero";
|
||||||
|
subnets = [
|
||||||
|
|
||||||
|
];
|
||||||
|
groups = [
|
||||||
|
|
||||||
|
];
|
||||||
|
peers = [
|
||||||
|
{ group = "everyoneConnectsToMe"; }
|
||||||
|
];
|
||||||
|
privateKeyFile = "/not/yet";
|
||||||
|
publicKey = "testData";
|
||||||
|
presharedKeyFile = "testData2";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "peer.one";
|
||||||
|
subnets = [
|
||||||
|
"subnet.one"
|
||||||
|
];
|
||||||
|
groups = [
|
||||||
|
|
||||||
|
];
|
||||||
|
peers = [
|
||||||
|
{ group = "everyoneConnectsToMe"; }
|
||||||
|
{ group = "subnet one group"; }
|
||||||
|
];
|
||||||
|
privateKeyFile = "/not/yet";
|
||||||
|
publicKey = "testData";
|
||||||
|
presharedKeyFile = "testData2";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "peer.two";
|
||||||
|
subnets = [
|
||||||
|
"subnet.one"
|
||||||
|
"subnet.two"
|
||||||
|
];
|
||||||
|
groups = [
|
||||||
|
"everyoneConnectsToMe"
|
||||||
|
"subnet two group"
|
||||||
|
];
|
||||||
|
peers = [
|
||||||
|
{ group = "everyoneConnectsToMe"; }
|
||||||
|
{ group = "subnet two group"; }
|
||||||
|
];
|
||||||
|
privateKeyFile = "/not/yet";
|
||||||
|
publicKey = "testData";
|
||||||
|
presharedKeyFile = "testData2";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "peer.three";
|
||||||
|
subnets = [
|
||||||
|
"subnet.one"
|
||||||
|
"subnet.two"
|
||||||
|
"subnet.three"
|
||||||
|
];
|
||||||
|
groups = [
|
||||||
|
"everyoneConnectsToMe"
|
||||||
|
"subnet two group"
|
||||||
|
];
|
||||||
|
peers = [
|
||||||
|
{ group = "everyoneConnectsToMe"; }
|
||||||
|
{ group = "subnet two group"; }
|
||||||
|
];
|
||||||
|
privateKeyFile = "/not/yet";
|
||||||
|
publicKey = "testData";
|
||||||
|
presharedKeyFile = "testData2";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "peer.four";
|
||||||
|
subnets = [
|
||||||
|
"subnet.three"
|
||||||
|
"subnet.one"
|
||||||
|
];
|
||||||
|
groups = [
|
||||||
|
|
||||||
|
];
|
||||||
|
peers = [
|
||||||
|
{ group = "everyoneConnectsToMe"; }
|
||||||
|
{ peer = "peer.one"; }
|
||||||
|
];
|
||||||
|
privateKeyFile = "/not/yet";
|
||||||
|
publicKey = "testData";
|
||||||
|
presharedKeyFile = "testData2";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
@ -0,0 +1,123 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
has-rekey = config ? rekey;
|
||||||
|
peerOpts = {
|
||||||
|
options = {
|
||||||
|
subnets = mkOption {
|
||||||
|
default = [];
|
||||||
|
type = with types; listOf str;
|
||||||
|
description = ''
|
||||||
|
subnets the peer belongs to
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
groups = mkOption {
|
||||||
|
default = true;
|
||||||
|
type = with types; listOf str;
|
||||||
|
description = ''
|
||||||
|
groups the peer belongs to
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
peers = {
|
||||||
|
default = true;
|
||||||
|
type = with types; listOf set;
|
||||||
|
description = mdDoc ''
|
||||||
|
Peers the peer is connected to, can be one of `{ peer = "peerName"; }`
|
||||||
|
or `{ group = "groupname"; }`. Remember to configure this for *both* peers.
|
||||||
|
The best way to do this is with a simple full mesh network, where all peers
|
||||||
|
belong to one group ("groupA"), and their peers are `{ group = "groupA"}`.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
privateKeyFile = mkOption {
|
||||||
|
example = "/private/wireguard_key";
|
||||||
|
type = with types; nullOr str;
|
||||||
|
default = null;
|
||||||
|
description = mdDoc ''
|
||||||
|
Private key file as generated by {command}`wg genkey`.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
name = mkOption {
|
||||||
|
default = config.networking.hostName;
|
||||||
|
defaultText = literalExpression "hostName";
|
||||||
|
example = "bernd";
|
||||||
|
type = types.str;
|
||||||
|
description = mdDoc "Unique name for the peer (must be unique for all subdomains this peer is a member of)";
|
||||||
|
};
|
||||||
|
publicKey = mkOption {
|
||||||
|
example = "xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=";
|
||||||
|
type = types.singleLineStr;
|
||||||
|
description = mdDoc "The base64 public key of the peer.";
|
||||||
|
};
|
||||||
|
presharedKeyFile = mkOption {
|
||||||
|
default = null;
|
||||||
|
example = "/private/wireguard_psk";
|
||||||
|
type = with types; nullOr str;
|
||||||
|
description = mdDoc ''
|
||||||
|
File pointing to preshared key as generated by {command}`wg genpsk`.
|
||||||
|
Optional, and may be omitted. This option adds an additional layer of
|
||||||
|
symmetric-key cryptography to be mixed into the already existing
|
||||||
|
public-key cryptography, for post-quantum resistance.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
subnetOpts = {
|
||||||
|
options = {
|
||||||
|
name = mkOption {
|
||||||
|
default = "wireguard";
|
||||||
|
example = "mySubnet.myDomain.me";
|
||||||
|
type = types.str;
|
||||||
|
description = mdDoc "Unique name for the subnet";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
configOpts = {
|
||||||
|
options = {
|
||||||
|
subnets = mkOption {
|
||||||
|
default = {};
|
||||||
|
type = with types; listOf (submodule subnetOpts);
|
||||||
|
description = ''
|
||||||
|
Shared configuration file that describes all clients
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
peers = mkOption {
|
||||||
|
default = {};
|
||||||
|
type = with types; listOf (submodule peerOpts);
|
||||||
|
description = ''
|
||||||
|
Shared configuration file that describes all clients
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
modules.wirenix = {
|
||||||
|
enable = mkOption {
|
||||||
|
default = true;
|
||||||
|
type = with lib.types; bool;
|
||||||
|
description = ''
|
||||||
|
Wirenix
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
config = mkOption {
|
||||||
|
default = {};
|
||||||
|
type = with types; setOf (submodule configOpts);
|
||||||
|
description = ''
|
||||||
|
Shared configuration file that describes all clients
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# --------------------------------------------------------------- #
|
||||||
|
|
||||||
|
config = lib.mkIf (config.modules.wirenix.enable) (lib.mkMerge [
|
||||||
|
(lib.mkIf (has-rekey) {
|
||||||
|
environment.etc.rekey.text = "yes";
|
||||||
|
})
|
||||||
|
(lib.mkIf (!has-rekey ) {
|
||||||
|
environment.etc.rekey.text = "no";
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
}
|
Loading…
Reference in New Issue