201 lines
6 KiB
Nix
201 lines
6 KiB
Nix
{
|
|
pkgs,
|
|
lib,
|
|
config,
|
|
otherNodes,
|
|
...
|
|
}:
|
|
with lib;
|
|
let
|
|
cfg = config.xyno.services.wireguard;
|
|
wgServer = cfg.server;
|
|
ula = cfg.ula;
|
|
ulaPrefix = "${ula}:1337"; # /64 for normal vpn
|
|
monitoringUlaPrefix = "${ula}:2337"; # /64 for monitoring
|
|
v4Subnet = "10.13.12.0/24";
|
|
|
|
# uses a hash digest as the host identifier
|
|
genUlaForHost =
|
|
prefix: hostName:
|
|
let
|
|
hostHash = builtins.hashString "sha512" hostName;
|
|
localParts = map (n: builtins.substring (n * 4) 4 hostHash) (range 0 3);
|
|
localPart = concatStringsSep ":" localParts;
|
|
in
|
|
"${prefix}:${localPart}";
|
|
# peers list for networkd
|
|
wgPeersLists = attrValues (mapAttrs (
|
|
c:
|
|
let
|
|
hasV4 = c.xyno.services.wireguard.v4 && cfg.v4;
|
|
isServer = c.xyno.services.wireguard.server;
|
|
publicHostname = c.deployment.targetHost;
|
|
pubKey = c.xyno.services.wireguard.pubKey;
|
|
in
|
|
(
|
|
(optional (publicHostname != null) {
|
|
# if peer is publicly on the internet
|
|
AllowedIPs =
|
|
(optionals (isServer) [
|
|
"::/0"
|
|
])
|
|
++ (optionals (isServer && hasV4) [
|
|
"0.0.0.0/0"
|
|
])
|
|
++ (optionals (!isServer) [
|
|
"${genUlaForHost ulaPrefix c.networking.hostName}/128" # if a host is reachable but shouldn't play server, send only to the hosts ip
|
|
])
|
|
++ (optionals ((!isServer) && hasV4) [
|
|
"${c.wg.v4}/32"
|
|
]);
|
|
RouteTable = 1000;
|
|
Endpoint = "${publicHostname}:51820";
|
|
PersistentKeepalive = 25;
|
|
PublicKey = pubKey;
|
|
PresharedKeyFile = config.sops.secrets."wg/psk".path;
|
|
})
|
|
++ (optional ((publicHostname == null) && wgServer && (pubKey != null)) {
|
|
# if this is the server and the peer isn't reachable on the internet
|
|
AllowedIPs = [
|
|
"${genUlaForHost ulaPrefix c.hostName}/128"
|
|
"${genUlaForHost monitoringUlaPrefix c.hostName}/128"
|
|
]
|
|
++ (optionals (hasV4) [
|
|
"${c.wg.v4}/32"
|
|
]);
|
|
PublicKey = pubKey;
|
|
PresharedKeyFile = config.sops.secrets."wg/psk".path;
|
|
})
|
|
)
|
|
) otherNodes);
|
|
wgPeers = flatten wgPeersLists;
|
|
in
|
|
{
|
|
options.xyno.services.wireguard.enable = mkEnableOption "enables wireguard";
|
|
options.xyno.services.wireguard.monHostsDomain = mkOption {
|
|
type = types.str;
|
|
default = "mon.wg.hailsatan.eu";
|
|
};
|
|
options.xyno.services.wireguard.hostsDomain = mkOption {
|
|
type = types.str;
|
|
default = "wg.hailsatan.eu";
|
|
};
|
|
options.xyno.services.wireguard.ula = mkOption {
|
|
type = types.str;
|
|
default = "fd68:b6a4:36e4";
|
|
};
|
|
options.xyno.services.wireguard.ip6 = mkOption {
|
|
type = types.str;
|
|
default = genUlaForHost ulaPrefix config.networking.hostName;
|
|
};
|
|
options.xyno.services.wireguard.monIp6 = mkOption {
|
|
type = types.str;
|
|
default = genUlaForHost monitoringUlaPrefix config.networking.hostName;
|
|
};
|
|
options.xyno.services.wireguard.pubKey = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
};
|
|
options.xyno.services.wireguard.server = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
};
|
|
options.xyno.services.wireguard.v4 = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
|
|
};
|
|
config = mkIf cfg.enable {
|
|
# TODO: add a all traffic through this network
|
|
networking.hosts =
|
|
(mapAttrs' (
|
|
n: v:
|
|
nameValuePair (genUlaForHost ulaPrefix v.networking.hostName) [
|
|
"${v.networking.hostName}.${cfg.hostsDomain}"
|
|
]
|
|
) otherNodes)
|
|
// (mapAttrs' (
|
|
n: v:
|
|
nameValuePair (genUlaForHost monitoringUlaPrefix v.networking.hostName) [
|
|
"${v.networking.hostName}.${cfg.monHostsDomain}"
|
|
]
|
|
) otherNodes);
|
|
networking.firewall.allowedUDPPorts = optional wgServer 51820;
|
|
networking.firewall.interfaces."wg0".allowedUDPPorts = optional wgServer 53;
|
|
systemd.network.netdevs."99-wg0" = {
|
|
netdevConfig = {
|
|
Name = "wg0";
|
|
Kind = "wireguard";
|
|
Description = "main wireguard tunnel";
|
|
|
|
};
|
|
wireguardConfig = {
|
|
ListenPort = mkIf wgServer 51820;
|
|
PrivateKeyFile = config.sops.secrets."wg/privkey".path;
|
|
FirewallMark = 34952;
|
|
};
|
|
wireguardPeers = wgPeers;
|
|
};
|
|
systemd.network.networks."50-wg0" = {
|
|
matchConfig.Name = "wg0";
|
|
networkConfig = {
|
|
Description = "xyno wireguard";
|
|
IPMasquerade = mkIf wgServer "both";
|
|
IPv4Forwarding = wgServer;
|
|
IPv6Forwarding = wgServer;
|
|
};
|
|
address = [
|
|
"${(genUlaForHost ulaPrefix config.networking.hostName)}/64"
|
|
"${(genUlaForHost monitoringUlaPrefix config.networking.hostName)}/64"
|
|
]
|
|
++ (optionals (cfg.v4) [ "${cfg.v4}/24" ]);
|
|
};
|
|
systemd.network.networks."51-wg0-all-traffic" = {
|
|
matchConfig.Name = "wg0";
|
|
networkConfig = {
|
|
Description = "xyno wireguard all traffic";
|
|
DNSDefaultRoute = true;
|
|
DNS = "2a07:e340::2#dns.mullvad.net";
|
|
DNSOverTLS = true;
|
|
};
|
|
routingPolicyRules = [
|
|
{
|
|
FirewallMark = 34952;
|
|
InvertRule = true;
|
|
Table = 1000;
|
|
Priority = 10;
|
|
}
|
|
];
|
|
};
|
|
services.prometheus.exporters.wireguard =
|
|
mkIf (wgServer && config.xyno.services.monitoring.enable)
|
|
{
|
|
enable = true;
|
|
interfaces = [ "wg0" ];
|
|
};
|
|
|
|
services.coredns = mkIf wgServer {
|
|
# for non nixos devices to be able to resolve vpn hostnames
|
|
enable = true;
|
|
config = ''
|
|
. {
|
|
bind wg0
|
|
prometheus
|
|
hosts ${cfg.hostsDomain}
|
|
forward . /etc/resolv.conf
|
|
}
|
|
'';
|
|
};
|
|
xyno.services.monitoring.exporters.coredns = mkIf wgServer 9153;
|
|
xyno.services.monitoring.exporters.wireguard =
|
|
mkIf wgServer config.services.prometheus.exporters.wireguard.port;
|
|
sops.secrets."wg/privkey" = {
|
|
reloadUnits = [ "systemd-networkd.service" ];
|
|
sopsFile = ../../instances/${config.networking.hostName}/secrets/wg.yaml;
|
|
};
|
|
sops.secrets."wg/psk" = {
|
|
reloadUnits = [ "systemd-networkd.service" ];
|
|
};
|
|
|
|
};
|
|
}
|