diff options
| -rw-r--r-- | modules/yggdrasil-wg/default.nix | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/modules/yggdrasil-wg/default.nix b/modules/yggdrasil-wg/default.nix index d73c7f3f..9ecbe663 100644 --- a/modules/yggdrasil-wg/default.nix +++ b/modules/yggdrasil-wg/default.nix | |||
| @@ -4,6 +4,7 @@ with lib; | |||
| 4 | 4 | ||
| 5 | let | 5 | let |
| 6 | listenPort = 51820; | 6 | listenPort = 51820; |
| 7 | udp2rawPort = 51821; | ||
| 7 | subnet = "2a03:4000:52:ada:1"; | 8 | subnet = "2a03:4000:52:ada:1"; |
| 8 | subnetLength = 80; | 9 | subnetLength = 80; |
| 9 | hostLength = subnetLength + 16; | 10 | hostLength = subnetLength + 16; |
| @@ -47,13 +48,13 @@ let | |||
| 47 | hostLinks = filter ({ from, to, ... }: from == hostName || to == hostName) links; | 48 | hostLinks = filter ({ from, to, ... }: from == hostName || to == hostName) links; |
| 48 | hostRoutes = filter ({ from, to, ... }: from == hostName || to == hostName) routes; | 49 | hostRoutes = filter ({ from, to, ... }: from == hostName || to == hostName) routes; |
| 49 | isRouter = inNetwork && any ({via, ...}: via == hostName) routes; | 50 | isRouter = inNetwork && any ({via, ...}: via == hostName) routes; |
| 50 | linkToPeer = opts@{from, to, ...}: | 51 | linkToPeer = ix: opts@{from, to, ...}: |
| 51 | let | 52 | let |
| 52 | other = if from == hostName then to else from; | 53 | other = if from == hostName then to else from; |
| 53 | in { | 54 | in { |
| 54 | allowedIPs = hostIPs.${other} ++ concatMap (rArgs: if rArgs.from != hostName || rArgs.via != to then [] else hostIPs.${rArgs.to}) routes; | 55 | allowedIPs = hostIPs.${other} ++ concatMap (rArgs: if rArgs.from != hostName || rArgs.via != to then [] else hostIPs.${rArgs.to}) routes; |
| 55 | publicKey = trim (readFile (mkPublicKeyPath other)); | 56 | publicKey = trim (readFile (mkPublicKeyPath other)); |
| 56 | } // (optionalAttrs (from == hostName) (filterAttrs (n: _v: !(elem n ["from" "to" "endpointHost"])) opts // optionalAttrs (opts ? "endpointHost") { endpoint = "${opts.endpointHost}:${toString listenPort}"; })); | 57 | } // (optionalAttrs (from == hostName) (filterAttrs (n: _v: !(elem n ["from" "to" "endpointHost"])) opts // optionalAttrs (opts ? "endpointHost") { endpoint = "localhost:${toString (udp2rawPort + ix)}"; })); |
| 57 | 58 | ||
| 58 | trim = str: if hasSuffix "\n" str then trim (removeSuffix "\n" str) else str; | 59 | trim = str: if hasSuffix "\n" str then trim (removeSuffix "\n" str) else str; |
| 59 | stripSubnet = addr: let matchRes = builtins.match "^(.*)/[0-9]+$" addr; in if matchRes == null then addr else elemAt matchRes 0; | 60 | stripSubnet = addr: let matchRes = builtins.match "^(.*)/[0-9]+$" addr; in if matchRes == null then addr else elemAt matchRes 0; |
| @@ -73,7 +74,7 @@ in { | |||
| 73 | allowedIPsAsRoutes = false; | 74 | allowedIPsAsRoutes = false; |
| 74 | inherit listenPort; | 75 | inherit listenPort; |
| 75 | ips = hostIPs.${hostName}; | 76 | ips = hostIPs.${hostName}; |
| 76 | peers = map linkToPeer hostLinks; | 77 | peers = imap0 linkToPeer hostLinks; |
| 77 | privateKeyFile = config.sops.secrets."yggdrasil-wg.priv".path; | 78 | privateKeyFile = config.sops.secrets."yggdrasil-wg.priv".path; |
| 78 | postSetup = '' | 79 | postSetup = '' |
| 79 | ${concatMapStringsSep "\n" (linkArgs: let other = if linkArgs.from == hostName then linkArgs.to else linkArgs.from; in concatMapStringsSep "\n" (otherIP: "ip route replace \"${otherIP}\" dev \"yggdrasil\" table \"main\"") hostIPs.${other}) hostLinks} | 80 | ${concatMapStringsSep "\n" (linkArgs: let other = if linkArgs.from == hostName then linkArgs.to else linkArgs.from; in concatMapStringsSep "\n" (otherIP: "ip route replace \"${otherIP}\" dev \"yggdrasil\" table \"main\"") hostIPs.${other}) hostLinks} |
| @@ -82,6 +83,16 @@ in { | |||
| 82 | }; | 83 | }; |
| 83 | }; | 84 | }; |
| 84 | 85 | ||
| 86 | systemd.services = listToAttrs (filter ({ value, ...}: value != null) (imap0 (ix: opts@{to, from, ...}: let other = if from == hostName then to else from; in nameValuePair "yggdrasil-udp2raw@${other}" (if opts ? "endpointHost" then { | ||
| 87 | requiredBy = ["wireguard-yggdrasil.service"]; | ||
| 88 | |||
| 89 | serviceConfig = { | ||
| 90 | ExecStart = "${pkgs.udp2raw}/bin/udp2raw ${if from == hostName then "-c -l localhost:${toString (udp2rawPort + ix)} -r ${opts.endpointHost}:${toString (udp2rawPort + ix)}" else "-s -l 0.0.0.0:${toString (udp2rawPort + ix)} -r localhost:${toString listenPort}"} -k tmpkey --auth-mode hmac_sha1 --raw-mode faketcp -a"; | ||
| 91 | }; | ||
| 92 | } else null)) hostLinks)) // { | ||
| 93 | firewall.path = optionals isRouter [pkgs.procps]; | ||
| 94 | }; | ||
| 95 | |||
| 85 | sops.secrets = mkIf (pathExists privateKeyPath) { | 96 | sops.secrets = mkIf (pathExists privateKeyPath) { |
| 86 | "yggdrasil-wg.priv" = { | 97 | "yggdrasil-wg.priv" = { |
| 87 | format = "binary"; | 98 | format = "binary"; |
| @@ -91,7 +102,6 @@ in { | |||
| 91 | 102 | ||
| 92 | networking.hosts = mkIf inNetwork (listToAttrs (concatMap ({name, value}: map (ip: nameValuePair (stripSubnet ip) ["${name}.yggdrasil"]) value) (mapAttrsToList nameValuePair hostIPs))); | 103 | networking.hosts = mkIf inNetwork (listToAttrs (concatMap ({name, value}: map (ip: nameValuePair (stripSubnet ip) ["${name}.yggdrasil"]) value) (mapAttrsToList nameValuePair hostIPs))); |
| 93 | 104 | ||
| 94 | systemd.services.firewall.path = optionals isRouter [pkgs.procps]; | ||
| 95 | networking.firewall = mkIf isRouter { | 105 | networking.firewall = mkIf isRouter { |
| 96 | extraCommands = '' | 106 | extraCommands = '' |
| 97 | ip6tables -A FORWARD -i yggdrasil -o yggdrasil -j nixos-fw-accept | 107 | ip6tables -A FORWARD -i yggdrasil -o yggdrasil -j nixos-fw-accept |
