mirror of
https://github.com/gensokyo-zone/infrastructure.git
synced 2026-02-09 12:29:19 -08:00
modules/{wireguard{,-tf},bird,policyrouting}: Init from hexchen
This commit is contained in:
parent
1c700905c3
commit
70d95acddb
16 changed files with 459 additions and 6 deletions
176
config/modules/nixos/bird.nix
Normal file
176
config/modules/nixos/bird.nix
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
bcfg = config.network.bird;
|
||||
cfg = config.network.bird.ospf;
|
||||
in
|
||||
{
|
||||
options.network.bird = {
|
||||
routerId = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Router ID to use. Must be an IPv4 address.";
|
||||
};
|
||||
kernel4Config = mkOption {
|
||||
type = types.lines;
|
||||
default = ''
|
||||
ipv4 {
|
||||
import none;
|
||||
export filter {
|
||||
if source = RTS_STATIC then reject;
|
||||
accept;
|
||||
};
|
||||
};
|
||||
scan time 15;
|
||||
'';
|
||||
};
|
||||
kernel6Config = mkOption {
|
||||
type = types.lines;
|
||||
default = ''
|
||||
ipv6 {
|
||||
import none;
|
||||
export filter {
|
||||
if source = RTS_STATIC then reject;
|
||||
accept;
|
||||
};
|
||||
};
|
||||
scan time 15;
|
||||
'';
|
||||
};
|
||||
staticRoutes4 = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
};
|
||||
extraStatic4 = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
};
|
||||
staticRoutes6 = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
};
|
||||
extraStatic6 = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
};
|
||||
};
|
||||
options.network.bird.ospf = {
|
||||
enable = mkEnableOption "OSPF-based network routing";
|
||||
protocols = mkOption {
|
||||
default = { };
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
version = mkOption { type = types.enum [ 2 3 ]; default = 2; };
|
||||
extra = mkOption { type = types.lines; default = ""; };
|
||||
areas = mkOption {
|
||||
description = "areas to configure in bird";
|
||||
default = { };
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
extra = mkOption { type = types.lines; default = ""; };
|
||||
networks = mkOption {
|
||||
description = "Definition of area IP ranges. This is used in summary LSA origination.";
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
};
|
||||
external = mkOption {
|
||||
description = "Definition of external area IP ranges for NSSAs. This is used for NSSA-LSA translation.";
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
};
|
||||
interfaces = mkOption {
|
||||
description = "Interfaces to assign to the area";
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
cost = mkOption { type = types.int; default = 10; };
|
||||
poll = mkOption { type = types.int; default = 20; };
|
||||
retransmit = mkOption { type = types.int; default = 5; };
|
||||
priority = mkOption { type = types.int; default = 1; };
|
||||
deadCount = mkOption { type = types.int; default = 4; };
|
||||
type = mkOption {
|
||||
type = types.enum [
|
||||
null
|
||||
"broadcast"
|
||||
"bcast"
|
||||
"pointopoint"
|
||||
"ptp"
|
||||
"nonbroadcast"
|
||||
"nbma"
|
||||
"pointomultipoint"
|
||||
"ptmp"
|
||||
];
|
||||
default = null;
|
||||
};
|
||||
extra = mkOption { type = types.lines; default = ""; };
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.bird2 = {
|
||||
enable = true;
|
||||
config = ''
|
||||
${optionalString (bcfg.routerId != null) "router id ${bcfg.routerId};"}
|
||||
|
||||
protocol device {
|
||||
scan time 10;
|
||||
}
|
||||
|
||||
protocol kernel kernel4 {
|
||||
${bcfg.kernel4Config}
|
||||
}
|
||||
protocol kernel kernel6 {
|
||||
${bcfg.kernel6Config}
|
||||
}
|
||||
|
||||
protocol static static4 {
|
||||
ipv4 { import all; export none; };
|
||||
${concatMapStringsSep "\n" (x: "route ${x};") bcfg.staticRoutes4}
|
||||
${bcfg.extraStatic4}
|
||||
}
|
||||
protocol static static6 {
|
||||
ipv6 { import all; export none; };
|
||||
${concatMapStringsSep "\n" (x: "route ${x};") bcfg.staticRoutes6}
|
||||
${bcfg.extraStatic6}
|
||||
}
|
||||
|
||||
${concatStringsSep "\n" (mapAttrsToList (protoName: proto: ''
|
||||
protocol ospf v${toString proto.version} ${protoName} {
|
||||
${concatStringsSep "\n" (mapAttrsToList (areaName: area: ''
|
||||
area ${areaName} {
|
||||
${optionalString
|
||||
(area.networks != [])
|
||||
"networks { ${concatStringsSep "\n" (map (x: "${x};") area.networks)} };"}
|
||||
${optionalString
|
||||
(area.external != [])
|
||||
"external { ${concatStringsSep "\n" (map (x: "${x};") area.external)} };"}
|
||||
${concatStringsSep "\n" (mapAttrsToList (ifacePattern: iface: ''
|
||||
interface "${ifacePattern}" {
|
||||
cost ${toString iface.cost};
|
||||
poll ${toString iface.poll};
|
||||
retransmit ${toString iface.retransmit};
|
||||
priority ${toString iface.priority};
|
||||
dead count ${toString iface.deadCount};
|
||||
${optionalString (iface.type != null) "type ${iface.type};"}
|
||||
${iface.extra}
|
||||
};
|
||||
'') area.interfaces)}
|
||||
${area.extra}
|
||||
};
|
||||
'') proto.areas)}
|
||||
${proto.extra}
|
||||
}
|
||||
'') cfg.protocols)}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
51
config/modules/nixos/policyrouting.nix
Normal file
51
config/modules/nixos/policyrouting.nix
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.networking.policyrouting;
|
||||
|
||||
ruleOpts = { ... }: {
|
||||
options = {
|
||||
prio = mkOption {
|
||||
type = types.int;
|
||||
};
|
||||
rule = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
in
|
||||
{
|
||||
options = {
|
||||
networking.policyrouting = {
|
||||
enable = mkEnableOption "Declarative Policy-Routing";
|
||||
rules = mkOption {
|
||||
type = with types; listOf (submodule ruleOpts);
|
||||
default = [ ];
|
||||
};
|
||||
rules6 = mkOption {
|
||||
type = with types; listOf (submodule ruleOpts);
|
||||
default = [ ];
|
||||
};
|
||||
rules4 = mkOption {
|
||||
type = with types; listOf (submodule ruleOpts);
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
networking.policyrouting.rules = [
|
||||
{ rule = "lookup main"; prio = 32000; }
|
||||
];
|
||||
networking.localCommands = ''
|
||||
set -x
|
||||
ip -6 rule flush
|
||||
ip -4 rule flush
|
||||
${concatMapStringsSep "\n" ({ prio, rule }: "ip -6 rule add ${rule} prio ${toString prio}") (cfg.rules ++ cfg.rules6)}
|
||||
${concatMapStringsSep "\n" ({ prio, rule }: "ip -4 rule add ${rule} prio ${toString prio}") (cfg.rules ++ cfg.rules4)}
|
||||
'';
|
||||
};
|
||||
}
|
||||
54
config/modules/nixos/wireguard-tf.nix
Normal file
54
config/modules/nixos/wireguard-tf.nix
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
{ config, pkgs, lib, tf, ... }: with lib; let
|
||||
inherit (tf.lib.tf) terraformSelf;
|
||||
cfg = config.network.wireguard;
|
||||
dataDir = toString tf.terraform.dataDir;
|
||||
in {
|
||||
options.network.wireguard.tf = {
|
||||
enable = mkEnableOption "using terraform for wireguard module";
|
||||
};
|
||||
config = mkIf config.network.wireguard.tf.enable {
|
||||
deploy.tf = {
|
||||
resources = {
|
||||
"${config.networking.hostName}-wgmesh-gen" = {
|
||||
provider = "null";
|
||||
type = "resource";
|
||||
provisioners = singleton {
|
||||
local-exec.command = let
|
||||
wg = "${pkgs.buildPackages.wireguard}/bin/wg";
|
||||
in "${wg} genkey | tee ${dataDir + "/wg-private-${terraformSelf "id"}"} | ${wg} pubkey > ${dataDir + "/wg-public-${terraformSelf "id"}"}";
|
||||
};
|
||||
};
|
||||
"${config.networking.hostName}-wgmesh-public-key" = {
|
||||
provider = "local";
|
||||
type = "file";
|
||||
dataSource = true;
|
||||
inputs.filename = dataDir + "/wg-public-${tf.resources."${config.networking.hostName}-wgmesh-gen".refAttr "id"}";
|
||||
};
|
||||
};
|
||||
deploy.systems.${config.networking.hostName}.triggers.switch = {
|
||||
wg = tf.resources."${config.networking.hostName}-wgmesh-public-key".refAttr "content";
|
||||
};
|
||||
};
|
||||
|
||||
secrets.files."${config.networking.hostName}-wgmesh-private-key" = rec {
|
||||
source = dataDir + "/wg-private-${tf.resources."${config.networking.hostName}-wgmesh-gen".refAttr "id"}";
|
||||
text = source;
|
||||
};
|
||||
|
||||
network.wireguard = {
|
||||
magicNumber = mkDefault (hexToInt (substring 0 2 (builtins.hashString "sha256" config.networking.hostName)));
|
||||
keyPath = config.secrets.files."${config.networking.hostName}-wgmesh-private-key".path;
|
||||
pubkey = let
|
||||
pubKeyRes = tf.resources."${config.networking.hostName}-wgmesh-public-key";
|
||||
in mkIf (tf.state.resources ? ${pubKeyRes.out.reference}) (removeSuffix "\n" (pubKeyRes.importAttr "content"));
|
||||
publicAddress4 = mkDefault (if config.network.addresses.public.nixos.ipv4.enable then
|
||||
config.network.addresses.public.nixos.ipv4.address
|
||||
else if config.network.addresses.private.nixos.ipv4.enable then
|
||||
config.network.addresses.private.nixos.ipv4.address else null);
|
||||
publicAddress6 = mkDefault (if config.network.addresses.public.nixos.ipv6.enable then
|
||||
config.network.addresses.public.nixos.ipv6.address
|
||||
else if config.network.addresses.private.nixos.ipv6.enable then
|
||||
config.network.addresses.private.nixos.ipv6.address else null);
|
||||
};
|
||||
};
|
||||
}
|
||||
85
config/modules/nixos/wireguard.nix
Normal file
85
config/modules/nixos/wireguard.nix
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
{ config, lib, pkgs, nodes, name, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.network.wireguard;
|
||||
hcfg = _: h: h.network.wireguard;
|
||||
netHostsSelf = mapAttrs hcfg (filterAttrs (_: x: x.network.wireguard.enable or false) nodes);
|
||||
netHosts = filterAttrs (n: x: n != name) netHostsSelf;
|
||||
in
|
||||
{
|
||||
options.network.wireguard = {
|
||||
enable = mkEnableOption "semi-automatic wireguard mesh";
|
||||
magicNumber = mkOption { type = types.ints.u8; };
|
||||
prefixV4 = mkOption {
|
||||
type = types.str;
|
||||
default = "172.23.1";
|
||||
};
|
||||
prefixV6 = mkOption {
|
||||
type = types.str;
|
||||
default = "fe80:";
|
||||
};
|
||||
keyPath = mkOption {
|
||||
type = types.str;
|
||||
default = "/etc/wireguard/mesh";
|
||||
};
|
||||
pubkey = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
};
|
||||
publicAddress4 = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
};
|
||||
publicAddress6 = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
};
|
||||
fwmark = mkOption {
|
||||
type = with types; nullOr ints.u16;
|
||||
default = null;
|
||||
};
|
||||
mtu = mkOption {
|
||||
type = types.ints.u16;
|
||||
default = 1500;
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
networking.wireguard.interfaces = mapAttrs'
|
||||
(hname: hconf:
|
||||
let
|
||||
magicPort = 51820 + hconf.magicNumber + cfg.magicNumber;
|
||||
iname = "wgmesh-${substring 0 8 hname}";
|
||||
in
|
||||
nameValuePair iname {
|
||||
allowedIPsAsRoutes = false;
|
||||
privateKeyFile = cfg.keyPath;
|
||||
ips = [
|
||||
"${cfg.prefixV4}.${toString cfg.magicNumber}/24"
|
||||
"${cfg.prefixV6}:${toString cfg.magicNumber}/64"
|
||||
];
|
||||
listenPort = magicPort;
|
||||
peers = optional (hconf.pubkey != null) {
|
||||
publicKey = hconf.pubkey;
|
||||
allowedIPs = [ "0.0.0.0/0" "::0/0" ];
|
||||
endpoint = with hconf; mkIf (publicAddress4 != null || publicAddress6 != null) (
|
||||
if (publicAddress4 != null)
|
||||
then "${publicAddress4}:${toString magicPort}"
|
||||
else "[${publicAddress6}]:${toString magicPort}"
|
||||
);
|
||||
persistentKeepalive = with hconf; mkIf (publicAddress4 == null && publicAddress6 == null) 25;
|
||||
};
|
||||
postSetup = ''
|
||||
ip route add ${cfg.prefixV4}.${toString hconf.magicNumber}/32 dev ${iname}
|
||||
${optionalString (cfg.fwmark != null) "wg set ${iname} fwmark ${toString cfg.fwmark}"}
|
||||
ip link set ${iname} mtu ${toString cfg.mtu}
|
||||
'';
|
||||
}
|
||||
)
|
||||
netHosts;
|
||||
networking.firewall.allowedUDPPorts =
|
||||
mapAttrsToList (_: hconf: 51820 + hconf.magicNumber + cfg.magicNumber) netHosts;
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue