nixos/l2mesh: Initial VXLAN mesh support
This commit is contained in:
parent
2a99bc032c
commit
681ad3fe9f
24
flake.lock
generated
24
flake.lock
generated
@ -167,11 +167,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs-mine": {
|
"nixpkgs-mine": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1665003636,
|
"lastModified": 1665936538,
|
||||||
"narHash": "sha256-hZw6brIzr0xIQnhhIFqVD+qUjFWc8Nbhv4/PfSUhv8w=",
|
"narHash": "sha256-iOG64H3nsdQ0kVLN84bNEnzhxhtiGoR+WeUneEKD7II=",
|
||||||
"owner": "devplayer0",
|
"owner": "devplayer0",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "5e97ac47c943f04f7c06d16fcc7cdb16419d0dc4",
|
"rev": "d23938373f803710a8c223c8715eb61299f2e92a",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -183,11 +183,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs-mine-stable": {
|
"nixpkgs-mine-stable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1662202463,
|
"lastModified": 1665936575,
|
||||||
"narHash": "sha256-Be5CmzLWGiLtrwYn/NO79ZM6x0H0z+tlWkmW23hNW38=",
|
"narHash": "sha256-zIJSDh2US8Y2CrVZSgm8RHFEkz1UAXgMR1zYLsbBhK4=",
|
||||||
"owner": "devplayer0",
|
"owner": "devplayer0",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "8f64505d3c782ba5d04e1703c466626ea9199716",
|
"rev": "e01cbf49941d23928ffc2e362449b9500af2c4c5",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -199,11 +199,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs-stable": {
|
"nixpkgs-stable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1664883812,
|
"lastModified": 1665856284,
|
||||||
"narHash": "sha256-wqBAcVRBxls2nVaNeQaOy9SRg/bvEUiD26TQDprIg8U=",
|
"narHash": "sha256-FQusb2DuFo8UF0jhUSPFhDKc40jRbHcdyyw4anN20WA=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "fe76645aaf2fac3baaa2813fd0089930689c53b5",
|
"rev": "be44bf672c61a284f759898d1e59077b00655c4c",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -214,11 +214,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs-unstable": {
|
"nixpkgs-unstable": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1664780719,
|
"lastModified": 1665848363,
|
||||||
"narHash": "sha256-Oxe6la5dSqRfJogjtY4sRzJjDDqvroJIVkcGEOT87MA=",
|
"narHash": "sha256-3Jow1YxzPtQnck1bAAvbVxgRH4gNnkIdw871Vm6UtAU=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "fd54651f5ffb4a36e8463e0c327a78442b26cbe7",
|
"rev": "83b198a2083774844962c854f811538323f9f7b1",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -46,7 +46,7 @@ let
|
|||||||
];
|
];
|
||||||
|
|
||||||
_module.args = {
|
_module.args = {
|
||||||
inherit (cfg) secretsPath;
|
inherit (cfg) secretsPath vpns;
|
||||||
inherit (config') assignments;
|
inherit (config') assignments;
|
||||||
pkgs' = allPkgs;
|
pkgs' = allPkgs;
|
||||||
};
|
};
|
||||||
@ -116,6 +116,24 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
l2PeerOpts = with lib.types; {
|
||||||
|
options = {
|
||||||
|
addr = mkOpt' str null "Address.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
l2MeshOpts = with lib.types; { name, ... }: {
|
||||||
|
options = {
|
||||||
|
interface = mkOpt' str name "Name of VXLAN interface.";
|
||||||
|
firewall = mkBoolOpt' true "Whether to generate firewall rules.";
|
||||||
|
vni = mkOpt' ints.unsigned 1 "VXLAN VNI.";
|
||||||
|
peers = mkOpt' (attrsOf (submodule l2PeerOpts)) { } "Peers.";
|
||||||
|
security = {
|
||||||
|
enable = mkBoolOpt' true "Whether to enable IPsec authentication.";
|
||||||
|
encrypt = mkBoolOpt' false "Whether to enable IPsec encryption.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
systemOpts = with lib.types; { name, ... }@args:
|
systemOpts = with lib.types; { name, ... }@args:
|
||||||
let
|
let
|
||||||
config' = args.config;
|
config' = args.config;
|
||||||
@ -161,6 +179,9 @@ in
|
|||||||
secretsPath = mkOpt' path null "Path to encrypted secret files.";
|
secretsPath = mkOpt' path null "Path to encrypted secret files.";
|
||||||
modules = mkOpt' (attrsOf commonOpts.moduleType) { } "NixOS modules to be exported by nixfiles.";
|
modules = mkOpt' (attrsOf commonOpts.moduleType) { } "NixOS modules to be exported by nixfiles.";
|
||||||
systems = mkOpt' (attrsOf (submodule systemOpts)) { } "NixOS systems to be exported by nixfiles.";
|
systems = mkOpt' (attrsOf (submodule systemOpts)) { } "NixOS systems to be exported by nixfiles.";
|
||||||
|
vpns = {
|
||||||
|
l2 = mkOpt' (attrsOf (submodule l2MeshOpts)) { } "Layer 2 meshes.";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,5 +15,6 @@
|
|||||||
pdns = ./pdns.nix;
|
pdns = ./pdns.nix;
|
||||||
nginx-sso = ./nginx-sso.nix;
|
nginx-sso = ./nginx-sso.nix;
|
||||||
gui = ./gui.nix;
|
gui = ./gui.nix;
|
||||||
|
l2mesh = ./l2mesh.nix;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
78
nixos/modules/l2mesh.nix
Normal file
78
nixos/modules/l2mesh.nix
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
{ lib, pkgs, config, vpns, ... }:
|
||||||
|
let
|
||||||
|
inherit (lib) optionalString mapAttrsToList concatStringsSep filterAttrs mkIf mkMerge;
|
||||||
|
inherit (lib.my) isIPv6;
|
||||||
|
|
||||||
|
vxlanPort = 4789;
|
||||||
|
|
||||||
|
selfName = config.system.name;
|
||||||
|
memberMeshes = filterAttrs (_: c: c.peers ? "${selfName}") vpns.l2;
|
||||||
|
|
||||||
|
info = mesh: {
|
||||||
|
ownAddr = mesh.peers."${selfName}".addr;
|
||||||
|
otherPeers = filterAttrs (n: _: n != selfName) mesh.peers;
|
||||||
|
};
|
||||||
|
|
||||||
|
mkNetConfig = name: mesh: with info mesh; {
|
||||||
|
netdevs."30-l2mesh-${name}" = {
|
||||||
|
netdevConfig = {
|
||||||
|
Name = mesh.interface;
|
||||||
|
Kind = "vxlan";
|
||||||
|
};
|
||||||
|
vxlanConfig = {
|
||||||
|
VNI = mesh.vni;
|
||||||
|
Local = ownAddr;
|
||||||
|
MacLearning = true;
|
||||||
|
DestinationPort = vxlanPort;
|
||||||
|
Independent = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
networks."90-l2mesh-${name}" = {
|
||||||
|
matchConfig.Name = mesh.interface;
|
||||||
|
extraConfig = concatStringsSep "\n" (mapAttrsToList (n: peer: ''
|
||||||
|
[BridgeFDB]
|
||||||
|
MACAddress=00:00:00:00:00:00
|
||||||
|
Destination=${peer.addr}
|
||||||
|
'') otherPeers);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
mkLibreswanConfig = name: mesh: with info mesh; {
|
||||||
|
enable = true;
|
||||||
|
# TODO: finish this...
|
||||||
|
connections."l2mesh-${name}" = ''
|
||||||
|
keyexchange=ike
|
||||||
|
type=transport
|
||||||
|
left=${ownAddr}
|
||||||
|
|
||||||
|
auto=start
|
||||||
|
phase2=esp
|
||||||
|
ikev2=yes
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
mkFirewallConfig = name: mesh: with info mesh;
|
||||||
|
let
|
||||||
|
netProto = if (isIPv6 ownAddr) then "ip6" else "ip";
|
||||||
|
in
|
||||||
|
''
|
||||||
|
table inet filter {
|
||||||
|
chain l2mesh-${name} {
|
||||||
|
${optionalString mesh.security.enable "meta l4proto esp accept"}
|
||||||
|
udp dport ${toString vxlanPort} @th,96,24 ${toString mesh.vni} accept
|
||||||
|
return
|
||||||
|
}
|
||||||
|
chain input {
|
||||||
|
${netProto} daddr ${ownAddr} ${netProto} saddr { ${concatStringsSep ", " (mapAttrsToList (_: p: p.addr) otherPeers)} } jump l2mesh-${name}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
config = {
|
||||||
|
systemd.network = mkMerge (mapAttrsToList mkNetConfig memberMeshes);
|
||||||
|
# TODO: finish this...
|
||||||
|
#services.libreswan = mkMerge (mapAttrsToList mkLibreswanConfig (filterAttrs (_: c: c.security.enable) memberMeshes));
|
||||||
|
my.firewall.extraRules = concatStringsSep "\n" (mapAttrsToList mkFirewallConfig (filterAttrs (_: c: c.firewall) memberMeshes));
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user