forked from zentralwerk/network
100 lines
2.7 KiB
Nix
100 lines
2.7 KiB
Nix
{ hostName, config, lib, pkgs, ... }:
|
|
|
|
let
|
|
gateway = "upstream1";
|
|
|
|
tunnels = lib.filterAttrs (_: wireguard:
|
|
wireguard != null
|
|
) config.site.hosts.${hostName}.wireguard;
|
|
firstTunnel =
|
|
if builtins.length (builtins.attrNames tunnels) > 0
|
|
then builtins.head (builtins.attrNames tunnels)
|
|
else null;
|
|
enabled = firstTunnel != null;
|
|
|
|
privateKeyFile = ifName:
|
|
"/run/wireguard-keys/${ifName}.key";
|
|
in
|
|
{
|
|
systemd.services = builtins.foldl' (services: ifName: services // {
|
|
"wireguard-key-${ifName}" = {
|
|
description = "Create key file for wireguard interface '${ifName}'";
|
|
requiredBy = [ "systemd-networkd.service" ];
|
|
before = [ "systemd-networkd.service" ];
|
|
serviceConfig.Type = "oneshot";
|
|
script = ''
|
|
#! ${pkgs.runtimeShell} -e
|
|
|
|
F=${privateKeyFile ifName}
|
|
mkdir -p -m 0700 $(dirname $F)
|
|
chown systemd-network:systemd-network $(dirname $F)
|
|
rm -f $F
|
|
cat >$F <<EOF
|
|
${tunnels.${ifName}.privateKey}
|
|
EOF
|
|
chmod 0400 $F
|
|
chown systemd-network:systemd-network $F
|
|
'';
|
|
};
|
|
}) {} (builtins.attrNames tunnels);
|
|
|
|
environment.systemPackages = lib.optionals enabled [
|
|
pkgs.wireguard-tools
|
|
];
|
|
|
|
systemd.network.netdevs = builtins.mapAttrs (ifName: wireguard: {
|
|
netdevConfig = {
|
|
Name = ifName;
|
|
Kind = "wireguard";
|
|
};
|
|
wireguardConfig.PrivateKeyFile = privateKeyFile ifName;
|
|
wireguardPeers = [ {
|
|
wireguardPeerConfig = {
|
|
PublicKey = wireguard.publicKey;
|
|
Endpoint = wireguard.endpoint;
|
|
AllowedIPs = "0.0.0.0/0, ::/0";
|
|
};
|
|
} ];
|
|
}) tunnels;
|
|
|
|
systemd.network.networks = {
|
|
# Endpoint host-routes
|
|
core.routes = map (wireguard: {
|
|
routeConfig = {
|
|
Destination = builtins.head (builtins.match "(.+):.*" wireguard.endpoint) + "/32";
|
|
Gateway = config.site.net.core.hosts4.${gateway};
|
|
};
|
|
}) (builtins.attrValues tunnels);
|
|
} // builtins.mapAttrs (ifName: wireguard: {
|
|
# Wireguard interfaces
|
|
matchConfig.Name = ifName;
|
|
|
|
addresses = map (addr: {
|
|
addressConfig.Address = addr;
|
|
}) wireguard.addresses;
|
|
|
|
# IPv4 default route
|
|
networkConfig.DefaultRouteOnDevice = true;
|
|
# IPv6 default route
|
|
routes = [ {
|
|
routeConfig.Destination = "::/0";
|
|
} ];
|
|
|
|
extraConfig = ''
|
|
[CAKE]
|
|
Parent = root
|
|
# DOCSIS overhead
|
|
OverheadBytes = 18
|
|
Bandwidth = ${toString wireguard.upBandwidth}K
|
|
'';
|
|
}) tunnels;
|
|
|
|
networking.nat = lib.optionalAttrs enabled {
|
|
enable = true;
|
|
enableIPv6 = true;
|
|
internalInterfaces = [ "core" ];
|
|
externalInterface = firstTunnel;
|
|
forwardPorts = config.site.hosts.${hostName}.forwardedPorts;
|
|
};
|
|
}
|