os/modules/wireguard/tunnel.nix

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

146 lines
4 KiB
Nix
Raw Normal View History

{
lib,
config,
pkgs,
...
2024-08-18 22:22:59 +00:00
}: let
cfg = config.pub-solar.wireguard.tunnel;
in {
options.pub-solar.wireguard.tunnel = {
ownIPs = lib.mkOption {
description = "Internal ips in wireguard used for cluster control-plane communication.";
type = lib.types.listOf lib.types.str;
default = [];
};
privateKeyFile = lib.mkOption {
description = "Location of private key file";
type = lib.types.path;
};
peer = {
publicKey = lib.mkOption {
description = "Public key of the peer";
type = lib.types.str;
};
endpoint = lib.mkOption {
description = "Peer endpoint address";
type = lib.types.str;
};
};
useDNS = lib.mkOption {
description = "Whether to use the DNS of the interface as default";
default = false;
type = lib.types.bool;
};
};
2024-08-18 22:22:59 +00:00
config = lib.mkIf (lib.length cfg.ownIPs != 0) {
networking.firewall.allowedUDPPorts = [51820];
2024-08-18 22:22:59 +00:00
systemd.network.wait-online.ignoredInterfaces = ["wg-tunnel"];
systemd.targets.wireguard-wg-tunnel = {
wantedBy = lib.mkForce [];
};
systemd.services.wireguard-wg-tunnel = {
wants = [
"wireguard-wg-private.service"
];
preStart = ''
while true; do
if ${pkgs.netcat}/bin/nc -w 5 -z 10.13.12.7 22 2>/dev/null; then
exit 0;
else
sleep 1;
fi
done;
'';
2024-02-16 10:18:35 +00:00
serviceConfig = {
Type = lib.mkForce "simple";
2024-02-16 10:18:35 +00:00
Restart = "on-failure";
RestartSec = "30";
};
environment = {
WG_ENDPOINT_RESOLUTION_RETRIES = "infinity";
};
};
networking.wireguard.interfaces = let
2024-08-18 22:22:59 +00:00
splitEndpoint = lib.strings.splitString ":" cfg.peer.endpoint;
joinIPV6 = p: ip:
p
+ (
if (lib.stringLength ip > 0)
then ":"
else ""
)
+ ip;
isIPV4 = lib.length splitEndpoint < 3;
2024-08-18 22:22:59 +00:00
ipFlag =
if isIPV4
then "-4"
else "-6";
endpointIP = (
if isIPV4
then lib.elemAt splitEndpoint 0
else lib.lists.fold joinIPV6 "" ((lib.lists.take ((lib.length splitEndpoint) - 1)) splitEndpoint)
);
endpointIPStripped = lib.strings.removePrefix "[" (lib.strings.removeSuffix "]" endpointIP);
in {
wg-tunnel = {
listenPort = 51820;
ips = cfg.ownIPs;
privateKeyFile = cfg.privateKeyFile;
2024-08-18 22:22:59 +00:00
postSetup =
''
defaultRoute=$(${pkgs.iproute2}/bin/ip ${ipFlag} r | ${pkgs.gnugrep}/bin/grep "default via" | head -n 1 | ${pkgs.gawk}/bin/awk '{ print $3 " " $4 " " $5 }')
${pkgs.iproute2}/bin/ip ${ipFlag} route add "${endpointIPStripped}${
if isIPV4
then "/32"
else "/128"
}" metric 256 via $defaultRoute
ip -4 route delete default dev wg-tunnel || true
ip -4 route add default dev wg-tunnel metric 512
ip -6 route delete default dev wg-tunnel || true
ip -6 route add default dev wg-tunnel metric 512
''
+ (
if cfg.useDNS
then ''printf "nameserver 10.64.0.1" | resolvconf -a wg-tunnel -m 0 -x''
else ""
);
postShutdown =
''
addedRoute=$(${pkgs.iproute2}/bin/ip ${ipFlag} r | ${pkgs.gnugrep}/bin/grep "${endpointIPStripped}" | head -n 1 | ${pkgs.gawk}/bin/awk '{ print $1 " " $2 " " $3 " " $4 " " $5 }')
if [ -n "$addedRoute" ]; then
${pkgs.iproute2}/bin/ip ${ipFlag} route delete $addedRoute
fi
''
+ (
if cfg.useDNS
then ''resolvconf -d wg-tunnel -f''
else ""
);
peers = [
{
publicKey = cfg.peer.publicKey;
allowedIPs = [
"0.0.0.0/0"
"::/0"
];
endpoint = cfg.peer.endpoint;
persistentKeepalive = 30;
dynamicEndpointRefreshSeconds = 30;
}
];
};
};
};
}