summary refs log tree commit diff
path: root/nixos/modules/services/networking/wireguard.nix
diff options
context:
space:
mode:
authorEric Sagnes <eric.sagnes@gmail.com>2016-08-23 13:34:31 +0900
committerJörg Thalheim <joerg@higgsboson.tk>2016-10-06 09:41:38 +0200
commit0bd263ecc3adf3e2bc60293436244d9a8f58966d (patch)
tree87d6fd75a6d46e812c7862639076f03faa50bbe2 /nixos/modules/services/networking/wireguard.nix
parent66d622fbd0f2561b841b629179ffb914eff8147f (diff)
downloadnixpkgs-0bd263ecc3adf3e2bc60293436244d9a8f58966d.tar
nixpkgs-0bd263ecc3adf3e2bc60293436244d9a8f58966d.tar.gz
nixpkgs-0bd263ecc3adf3e2bc60293436244d9a8f58966d.tar.bz2
nixpkgs-0bd263ecc3adf3e2bc60293436244d9a8f58966d.tar.lz
nixpkgs-0bd263ecc3adf3e2bc60293436244d9a8f58966d.tar.xz
nixpkgs-0bd263ecc3adf3e2bc60293436244d9a8f58966d.tar.zst
nixpkgs-0bd263ecc3adf3e2bc60293436244d9a8f58966d.zip
wireguard: add module
fixes #17933
Diffstat (limited to 'nixos/modules/services/networking/wireguard.nix')
-rw-r--r--nixos/modules/services/networking/wireguard.nix225
1 files changed, 225 insertions, 0 deletions
diff --git a/nixos/modules/services/networking/wireguard.nix b/nixos/modules/services/networking/wireguard.nix
new file mode 100644
index 00000000000..35918e42b40
--- /dev/null
+++ b/nixos/modules/services/networking/wireguard.nix
@@ -0,0 +1,225 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.networking.wireguard;
+
+  kernel = config.boot.kernelPackages;
+
+  # interface options
+
+  interfaceOpts = { name, ... }: {
+
+    options = {
+
+      ips = mkOption {
+        example = [ "192.168.2.1/24" ];
+        default = [];
+        type = with types; listOf str;
+        description = "The IP addresses of the interface.";
+      };
+
+      privateKey = mkOption {
+        example = "yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=";
+        type = types.str;
+        description = "Base64 private key generated by wg genkey.";
+      };
+
+      presharedKey = mkOption {
+        default = null;
+        example = "rVXs/Ni9tu3oDBLS4hOyAUAa1qTWVA3loR8eL20os3I=";
+        type = with types; nullOr str;
+        description = ''base64 preshared key generated by wg genpsk. Optional,
+        and may be omitted. This option adds an additional layer of
+        symmetric-key cryptography to be mixed into the already existing
+        public-key  cryptography, for post-quantum resistance.'';
+      };
+
+      listenPort = mkOption {
+        default = null;
+        type = with types; nullOr int;
+        example = 51820;
+        description = ''16-bit port for listening. Optional; if not specified,
+        automatically generated based on interface name.'';
+      };
+
+      preSetup = mkOption {
+        example = literalExample [''
+          ${pkgs.iproute}/bin/ip netns add foo
+        ''];
+        default = [];
+        type = with types; listOf str;
+        description = ''A list of commands called at the start of the interface
+        setup.'';
+      };
+
+      postSetup = mkOption {
+        example = literalExample [''
+          ${pkgs.bash} -c 'printf "nameserver 10.200.100.1" | ${pkgs.openresolv}/bin/resolvconf -a wg0 -m 0'
+        ''];
+        default = [];
+        type = with types; listOf str;
+        description = "A list of commands called at the end of the interface setup.";
+      };
+
+      postShutdown = mkOption {
+        example = literalExample ["${pkgs.openresolv}/bin/resolvconf -d wg0"];
+        default = [];
+        type = with types; listOf str;
+        description = "A list of commands called after shutting down the interface.";
+      };
+
+      peers = mkOption {
+        default = [];
+        description = "Peers linked to the interface.";
+        type = with types; listOf (submodule peerOpts);
+      };
+
+    };
+
+  };
+
+  # peer options
+
+  peerOpts = {
+
+    options = {
+
+      publicKey = mkOption {
+        example = "xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=";
+        type = types.str;
+        description = "The base64 public key the peer.";
+      };
+
+      allowedIPs = mkOption {
+        example = [ "10.192.122.3/32" "10.192.124.1/24" ];
+        type = with types; listOf str;
+        description = ''List of IP (v4 or v6) addresses with CIDR masks from
+        which this peer is allowed to send incoming traffic and to which
+        outgoing traffic for this peer is directed. The catch-all 0.0.0.0/0 may
+        be specified for matching all IPv4 addresses, and ::/0 may be specified
+        for matching all IPv6 addresses.'';
+      };
+
+      endpoint = mkOption {
+        default = null;
+        example = "demo.wireguard.io:12913";
+        type = with types; nullOr str;
+        description = ''Endpoint IP or hostname of the peer, followed by a colon,
+        and then a port number of the peer.'';
+      };
+
+      persistentKeepalive = mkOption {
+        default = null;
+        type = with types; nullOr int;
+        example = 25;
+        description = ''This is optional and is by default off, because most
+        users will not need it. It represents, in seconds, between 1 and 65535
+        inclusive, how often to send an authenticated empty packet to the peer,
+        for the purpose of keeping a stateful firewall or NAT mapping valid
+        persistently. For example, if the interface very rarely sends traffic,
+        but it might at anytime receive traffic from a peer, and it is behind
+        NAT, the interface might benefit from having a persistent keepalive
+        interval of 25 seconds; however, most users will not need this.'';
+      };
+
+    };
+
+  };
+
+  generateConf = name: values: pkgs.writeText "wireguard-${name}.conf" ''
+    [Interface]
+    PrivateKey = ${values.privateKey}
+    ${optionalString (values.presharedKey != null) "PresharedKey = ${values.presharedKey}"}
+    ${optionalString (values.listenPort != null)   "ListenPort = ${toString values.listenPort}"}
+
+    ${concatStringsSep "\n\n" (map (peer: ''
+    [Peer]
+    PublicKey = ${peer.publicKey}
+    ${optionalString (peer.allowedIPs != []) "AllowedIPs = ${concatStringsSep ", " peer.allowedIPs}"}
+    ${optionalString (peer.endpoint != null) "Endpoint = ${peer.endpoint}"}
+    ${optionalString (peer.persistentKeepalive != null) "PersistentKeepalive = ${toString peer.persistentKeepalive}"}
+    '') values.peers)}
+  '';
+
+  ipCommand = "${pkgs.iproute}/bin/ip";
+  wgCommand = "${pkgs.wireguard}/bin/wg";
+
+  generateUnit = name: values:
+    nameValuePair "wireguard-${name}"
+      {
+        description = "WireGuard Tunnel - ${name}";
+        wantedBy = [ "ip-up.target" ];
+        serviceConfig = {
+          Type = "oneshot";
+          RemainAfterExit = true;
+          ExecStart = lib.flatten([
+            values.preSetup
+
+            "-${ipCommand} link del dev ${name}"
+            "${ipCommand} link add dev ${name} type wireguard"
+            "${wgCommand} setconf ${name} ${generateConf name values}"
+
+            (map (ip:
+            ''${ipCommand} address add ${ip} dev ${name}''
+            ) values.ips)
+
+            "${ipCommand} link set up dev ${name}"
+
+            (flatten (map (peer: (map (ip:
+            "${ipCommand} route add ${ip} dev ${name}"
+            ) peer.allowedIPs)) values.peers))
+
+            values.postSetup
+          ]);
+
+          ExecStop = [ ''${ipCommand} link del dev "${name}"'' ] ++ values.postShutdown;
+        };
+      };
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    networking.wireguard = {
+
+      interfaces = mkOption {
+        description = "Wireguard interfaces.";
+        default = {};
+        example = {
+          wg0 = {
+            ips = [ "192.168.20.4/24" ];
+            privateKey = "yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=";
+            peers = [
+              { allowedIPs = [ "192.168.20.1/32" ];
+                publicKey  = "xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=";
+                endpoint   = "demo.wireguard.io:12913"; }
+            ];
+          };
+        };
+        type = with types; attrsOf (submodule interfaceOpts);
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf (cfg.interfaces != {}) {
+
+    boot.extraModulePackages = [ kernel.wireguard ];
+    environment.systemPackages = [ pkgs.wireguard ];
+
+    systemd.services = mapAttrs' generateUnit cfg.interfaces;
+
+  };
+
+}