summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--nixos/modules/misc/ids.nix2
-rw-r--r--nixos/modules/rename.nix3
-rw-r--r--nixos/modules/services/networking/dnscrypt-proxy.nix179
-rw-r--r--pkgs/tools/networking/dnscrypt-proxy/default.nix8
4 files changed, 114 insertions, 78 deletions
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index 88c860110179..fd75db1abe77 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -382,7 +382,7 @@
       seeks = 148;
       prosody = 149;
       i2pd = 150;
-      #dnscrypt-proxy = 151; # unused
+      dnscrypt-proxy = 151;
       systemd-network = 152;
       systemd-resolve = 153;
       systemd-timesync = 154;
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index dd80d0065911..a928f47f439e 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -141,6 +141,9 @@ in zipModules ([]
 ++ obsolete [ "services" "xserver" "windowManager" "xbmc" ] [ "services" "xserver" "desktopManager" "kodi" ]
 ++ obsolete [ "services" "xserver" "desktopManager" "xbmc" ] [ "services" "xserver" "desktopManager" "kodi" ]
 
+# DNSCrypt-proxy
+++ obsolete [ "services" "dnscrypt-proxy" "port" ] [ "services" "dnscrypt-proxy" "localPort" ]
+
 # Options that are obsolete and have no replacement.
 ++ obsolete' [ "boot" "loader" "grub" "bootDevice" ]
 ++ obsolete' [ "boot" "initrd" "luks" "enable" ]
diff --git a/nixos/modules/services/networking/dnscrypt-proxy.nix b/nixos/modules/services/networking/dnscrypt-proxy.nix
index 5cc33f35adb2..c724ee979c2d 100644
--- a/nixos/modules/services/networking/dnscrypt-proxy.nix
+++ b/nixos/modules/services/networking/dnscrypt-proxy.nix
@@ -5,38 +5,35 @@ let
   apparmorEnabled = config.security.apparmor.enable;
   dnscrypt-proxy = pkgs.dnscrypt-proxy;
   cfg = config.services.dnscrypt-proxy;
-  uid = config.ids.uids.dnscrypt-proxy;
+  resolverListFile = "${dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv";
+  localAddress = "${cfg.localAddress}:${toString cfg.localPort}";
   daemonArgs =
-    [ "--daemonize"
-      "--user=dnscrypt-proxy"
-      "--local-address=${cfg.localAddress}:${toString cfg.port}"
+    [ "--local-address=${localAddress}"
       (optionalString cfg.tcpOnly "--tcp-only")
-      "--resolvers-list=${dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv"
-      "--resolver-name=${cfg.resolverName}"
-    ];
+    ]
+    ++ resolverArgs;
+  resolverArgs = if (cfg.customResolver != null)
+    then
+      [ "--resolver-address=${cfg.customResolver.address}:${toString cfg.customResolver.port}"
+        "--provider-name=${cfg.customResolver.name}"
+        "--provider-key=${cfg.customResolver.key}"
+      ]
+    else
+      [ "--resolvers-list=${resolverListFile}"
+        "--resolver-name=${toString cfg.resolverName}"
+      ];
 in
 
 {
-  ##### interface
-
   options = {
-
     services.dnscrypt-proxy = {
-
-      enable = mkOption {
-        default = false;
-        type = types.bool;
-        description = ''
-          Enable dnscrypt-proxy.
-          The proxy relays regular DNS queries to a DNSCrypt enabled
-          upstream resolver.
-          The traffic between the client and the upstream resolver is
-          encrypted and authenticated, which may mitigate the risk of MITM
-          attacks and third-party snooping (assuming the upstream is
-          trustworthy).
-        '';
-      };
-
+      enable = mkEnableOption ''
+        Enable dnscrypt-proxy. The proxy relays regular DNS queries to a
+        DNSCrypt enabled upstream resolver. The traffic between the
+        client and the upstream resolver is encrypted and authenticated,
+        which may mitigate the risk of MITM attacks and third-party
+        snooping (assuming the upstream is trustworthy).
+      '';
       localAddress = mkOption {
         default = "127.0.0.1";
         type = types.string;
@@ -44,96 +41,128 @@ in
           Listen for DNS queries on this address.
         '';
       };
-
-      port = mkOption {
+      localPort = mkOption {
         default = 53;
         type = types.int;
         description = ''
           Listen on this port.
         '';
       };
-
       resolverName = mkOption {
         default = "opendns";
-        type = types.string;
+        type = types.nullOr types.string;
         description = ''
-          The name of the upstream DNSCrypt resolver to use.
-          See <literal>${dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv</literal>
-          for alternative resolvers (e.g., if you are concerned about logging
-          and/or server location).
+          The name of the upstream DNSCrypt resolver to use. See
+          <literal>${resolverListFile}</literal> for alternative resolvers
+          (e.g., if you are concerned about logging and/or server
+          location).
         '';
       };
-
+      customResolver = mkOption {
+        default = null;
+        description = ''
+          Use a resolver not listed in the upstream list (e.g.,
+          a private DNSCrypt provider). For advanced users only.
+          If specified, this option takes precedence.
+        '';
+        type = types.nullOr (types.submodule ({ ... }: { options = {
+          address = mkOption {
+            type = types.str;
+            description = "Resolver IP address";
+            example = "208.67.220.220";
+          };
+          port = mkOption {
+            type = types.int;
+            description = "Resolver port";
+            default = 443;
+          };
+          name = mkOption {
+            type = types.str;
+            description = "Provider fully qualified domain name";
+            example = "2.dnscrypt-cert.opendns.com";
+         };
+         key = mkOption {
+           type = types.str;
+           description = "Provider public key";
+           example = "B735:1140:206F:225D:3E2B:D822:D7FD:691E:A1C3:3CC8:D666:8D0C:BE04:BFAB:CA43:FB79";
+         }; }; }));
+      };
       tcpOnly = mkOption {
         default = false;
         type = types.bool;
         description = ''
           Force sending encrypted DNS queries to the upstream resolver
-          over TCP instead of UDP (on port 443).
-          Enabling this option may help circumvent filtering, but should
-          not be used otherwise.
+          over TCP instead of UDP (on port 443). Enabling this option may
+          help circumvent filtering, but should not be used otherwise.
         '';
       };
-
     };
-
   };
 
-  ##### implementation
-
   config = mkIf cfg.enable {
 
-    ### AppArmor profile
-
-    security.apparmor.profiles = mkIf apparmorEnabled [
-      (pkgs.writeText "apparmor-dnscrypt-proxy" ''
+    assertions = [
+      { assertion = (cfg.customResolver != null) || (cfg.resolverName != null);
+        message   = "please configure upstream DNSCrypt resolver";
+      }
+    ];
 
-        ${dnscrypt-proxy}/bin/dnscrypt-proxy {
-          network inet stream,
-          network inet6 stream,
-          network inet dgram,
-          network inet6 dgram,
+    security.apparmor.profiles = mkIf apparmorEnabled (singleton (pkgs.writeText "apparmor-dnscrypt-proxy" ''
+      ${dnscrypt-proxy}/bin/dnscrypt-proxy {
+        /dev/null rw,
+        /dev/urandom r,
 
-          capability ipc_lock,
-          capability net_bind_service,
-          capability net_admin,
-          capability sys_chroot,
-          capability setgid,
-          capability setuid,
+        /etc/passwd r,
+        /etc/group r,
+        ${config.environment.etc."nsswitch.conf".source} r,
 
-          /dev/null rw,
-          /dev/urandom r,
+        ${pkgs.glibc}/lib/*.so mr,
+        ${pkgs.tzdata}/share/zoneinfo/** r,
 
-          ${pkgs.glibc}/lib/*.so mr,
-          ${pkgs.tzdata}/share/zoneinfo/** r,
+        network inet stream,
+        network inet6 stream,
+        network inet dgram,
+        network inet6 dgram,
 
-          ${dnscrypt-proxy}/share/dnscrypt-proxy/** r,
-          ${pkgs.gcc.cc}/lib/libssp.so.* mr,
-          ${pkgs.libsodium}/lib/libsodium.so.* mr,
-        }
-      '')
-    ];
+        ${pkgs.gcc.cc}/lib/libssp.so.* mr,
+        ${pkgs.libsodium}/lib/libsodium.so.* mr,
+        ${pkgs.systemd}/lib/libsystemd.so.* mr,
+        ${pkgs.xz}/lib/liblzma.so.* mr,
+        ${pkgs.libgcrypt}/lib/libgcrypt.so.* mr,
+        ${pkgs.libgpgerror}/lib/libgpg-error.so.* mr,
 
-    ### User
+        ${resolverListFile} r,
+      }
+    ''));
 
-    users.extraUsers = singleton {
-      inherit uid;
-      name = "dnscrypt-proxy";
+    users.extraUsers.dnscrypt-proxy = {
+      uid = config.ids.uids.dnscrypt-proxy;
       description = "dnscrypt-proxy daemon user";
     };
+    users.extraGroups.dnscrypt-proxy.gid = config.ids.gids.dnscrypt-proxy;
 
-    ### Service definition
+    systemd.sockets.dnscrypt-proxy = {
+      description = "dnscrypt-proxy listening socket";
+      socketConfig = {
+        ListenStream = "${localAddress}";
+        ListenDatagram = "${localAddress}";
+      };
+      wantedBy = [ "sockets.target" ];
+    };
 
     systemd.services.dnscrypt-proxy = {
       description = "dnscrypt-proxy daemon";
       after = [ "network.target" ] ++ optional apparmorEnabled "apparmor.service";
-      requires = mkIf apparmorEnabled [ "apparmor.service" ];
-      wantedBy = [ "multi-user.target" ];
+      requires = [ "dnscrypt-proxy.socket "] ++ optional apparmorEnabled "apparmor.service";
       serviceConfig = {
-        Type = "forking";
+        Type = "simple";
+        NonBlocking = "true";
         ExecStart = "${dnscrypt-proxy}/bin/dnscrypt-proxy ${toString daemonArgs}";
+        User = "dnscrypt-proxy";
+        Group = "dnscrypt-proxy";
+        PrivateTmp = true;
+        PrivateDevices = true;
       };
     };
-
   };
 }
diff --git a/pkgs/tools/networking/dnscrypt-proxy/default.nix b/pkgs/tools/networking/dnscrypt-proxy/default.nix
index e975cb1e7382..206f7f2daace 100644
--- a/pkgs/tools/networking/dnscrypt-proxy/default.nix
+++ b/pkgs/tools/networking/dnscrypt-proxy/default.nix
@@ -1,4 +1,4 @@
-{ stdenv, fetchurl, libsodium }:
+{ stdenv, fetchurl, libsodium, pkgconfig, systemd }:
 
 stdenv.mkDerivation rec {
   name = "dnscrypt-proxy-${version}";
@@ -9,7 +9,11 @@ stdenv.mkDerivation rec {
     sha256 = "1cp3ivxngrihil6i7b659d39v9v6iwjs16s2kj9wz1anzyx0j6nx";
   };
 
-  buildInputs = [ libsodium ];
+  configureFlags = ''
+    ${stdenv.lib.optionalString stdenv.isLinux "--with-systemd"}
+  '';
+
+  buildInputs = [ pkgconfig libsodium ] ++ stdenv.lib.optional stdenv.isLinux systemd;
 
   meta = {
     description = "A tool for securing communications between a client and a DNS resolver";