diff options
author | Florian Klink <flokli@flokli.de> | 2019-05-31 23:17:18 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-31 23:17:18 +0200 |
commit | b3dd39ca0e9a8da121154e59fea86143232c0ab7 (patch) | |
tree | a3ad1965b714bfafa90cc413a53f3a60213946cc /nixos | |
parent | a41b38eb266a6ddb6f4ed28d77db155e400a5c59 (diff) | |
parent | 1de35c7f5ecbfe3c5bae252f660068669eb62b7a (diff) |
Merge pull request #62325 from grahamc/wireguard-master
wireguard: 0.0.20190406 -> 0.0.20190531 and Change peers without tearing down the interface, handle DNS failures better
Diffstat (limited to 'nixos')
-rw-r--r-- | nixos/modules/services/networking/wireguard.nix | 96 |
1 files changed, 70 insertions, 26 deletions
diff --git a/nixos/modules/services/networking/wireguard.nix b/nixos/modules/services/networking/wireguard.nix index 3a65f7ff32c73..c07481582c2f6 100644 --- a/nixos/modules/services/networking/wireguard.nix +++ b/nixos/modules/services/networking/wireguard.nix @@ -229,8 +229,61 @@ let ''; }; + generatePeerUnit = { interfaceName, interfaceCfg, peer }: + let + keyToUnitName = replaceChars + [ "/" "-" " " "+" "=" ] + [ "-" "\\x2d" "\\x20" "\\x2b" "\\x3d" ]; + unitName = keyToUnitName peer.publicKey; + psk = + if peer.presharedKey != null + then pkgs.writeText "wg-psk" peer.presharedKey + else peer.presharedKeyFile; + in nameValuePair "wireguard-${interfaceName}-peer-${unitName}" + { + description = "WireGuard Peer - ${interfaceName} - ${peer.publicKey}"; + requires = [ "wireguard-${interfaceName}.service" ]; + after = [ "wireguard-${interfaceName}.service" ]; + wantedBy = [ "multi-user.target" ]; + environment.DEVICE = interfaceName; + environment.WG_ENDPOINT_RESOLUTION_RETRIES = "infinity"; + path = with pkgs; [ iproute wireguard-tools ]; + + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + + script = let + wg_setup = "wg set ${interfaceName} peer ${peer.publicKey}" + + optionalString (psk != null) " preshared-key ${psk}" + + optionalString (peer.endpoint != null) " endpoint ${peer.endpoint}" + + optionalString (peer.persistentKeepalive != null) " persistent-keepalive ${toString peer.persistentKeepalive}" + + optionalString (peer.allowedIPs != []) " allowed-ips ${concatStringsSep "," peer.allowedIPs}"; + route_setup = + optionalString (interfaceCfg.allowedIPsAsRoutes != false) + (concatMapStringsSep "\n" + (allowedIP: + "ip route replace ${allowedIP} dev ${interfaceName} table ${interfaceCfg.table}" + ) peer.allowedIPs); + in '' + ${wg_setup} + ${route_setup} + ''; - generateSetupServiceUnit = name: values: + postStop = let + route_destroy = optionalString (interfaceCfg.allowedIPsAsRoutes != false) + (concatMapStringsSep "\n" + (allowedIP: + "ip route delete ${allowedIP} dev ${interfaceName} table ${interfaceCfg.table}" + ) peer.allowedIPs); + in '' + wg set ${interfaceName} peer ${peer.publicKey} remove + ${route_destroy} + ''; + }; + + generateInterfaceUnit = name: values: # exactly one way to specify the private key must be set #assert (values.privateKey != null) != (values.privateKeyFile != null); let privKey = if values.privateKeyFile != null then values.privateKeyFile else pkgs.writeText "wg-key" values.privateKey; @@ -245,9 +298,7 @@ let path = with pkgs; [ kmod iproute wireguard-tools ]; serviceConfig = { - Type = "simple"; - Restart = "on-failure"; - RestartSec = "5s"; + Type = "oneshot"; RemainAfterExit = true; }; @@ -265,25 +316,8 @@ let wg set ${name} private-key ${privKey} ${ optionalString (values.listenPort != null) " listen-port ${toString values.listenPort}"} - ${concatMapStringsSep "\n" (peer: - assert (peer.presharedKeyFile == null) || (peer.presharedKey == null); # at most one of the two must be set - let psk = if peer.presharedKey != null then pkgs.writeText "wg-psk" peer.presharedKey else peer.presharedKeyFile; - in - "wg set ${name} peer ${peer.publicKey}" + - optionalString (psk != null) " preshared-key ${psk}" + - optionalString (peer.endpoint != null) " endpoint ${peer.endpoint}" + - optionalString (peer.persistentKeepalive != null) " persistent-keepalive ${toString peer.persistentKeepalive}" + - optionalString (peer.allowedIPs != []) " allowed-ips ${concatStringsSep "," peer.allowedIPs}" - ) values.peers} - ip link set up dev ${name} - ${optionalString (values.allowedIPsAsRoutes != false) (concatStringsSep "\n" (concatMap (peer: - (map (allowedIP: - "ip route replace ${allowedIP} dev ${name} table ${values.table}" - ) peer.allowedIPs) - ) values.peers))} - ${values.postSetup} ''; @@ -335,7 +369,12 @@ in ###### implementation - config = mkIf cfg.enable { + config = mkIf cfg.enable (let + all_peers = flatten + (mapAttrsToList (interfaceName: interfaceCfg: + map (peer: { inherit interfaceName interfaceCfg peer;}) interfaceCfg.peers + ) cfg.interfaces); + in { assertions = (attrValues ( mapAttrs (name: value: { @@ -346,19 +385,24 @@ in mapAttrs (name: value: { assertion = value.generatePrivateKeyFile -> (value.privateKey == null); message = "networking.wireguard.interfaces.${name}.generatePrivateKey must not be set if networking.wireguard.interfaces.${name}.privateKey is set."; - }) cfg.interfaces)); - + }) cfg.interfaces)) + ++ map ({ interfaceName, peer, ... }: { + assertion = (peer.presharedKey == null) || (peer.presharedKeyFile == null); + message = "networking.wireguard.interfaces.${interfaceName} peer «${peer.publicKey}» has both presharedKey and presharedKeyFile set, but only one can be used."; + }) all_peers; boot.extraModulePackages = [ kernel.wireguard ]; environment.systemPackages = [ pkgs.wireguard-tools ]; - systemd.services = (mapAttrs' generateSetupServiceUnit cfg.interfaces) + systemd.services = + (mapAttrs' generateInterfaceUnit cfg.interfaces) + // (listToAttrs (map generatePeerUnit all_peers)) // (mapAttrs' generateKeyServiceUnit (filterAttrs (name: value: value.generatePrivateKeyFile) cfg.interfaces)); systemd.paths = mapAttrs' generatePathUnit (filterAttrs (name: value: value.privateKeyFile != null) cfg.interfaces); - }; + }); } |