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 ${dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv - 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 + ${resolverListFile} 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" '' - - ${dnscrypt-proxy}/bin/dnscrypt-proxy { - network inet stream, - network inet6 stream, - network inet dgram, - network inet6 dgram, - - capability ipc_lock, - capability net_bind_service, - capability net_admin, - capability sys_chroot, - capability setgid, - capability setuid, - - /dev/null rw, - /dev/urandom r, - - ${pkgs.glibc}/lib/*.so mr, - ${pkgs.tzdata}/share/zoneinfo/** r, - - ${dnscrypt-proxy}/share/dnscrypt-proxy/** r, - ${pkgs.gcc.cc}/lib/libssp.so.* mr, - ${pkgs.libsodium}/lib/libsodium.so.* mr, - } - '') + assertions = [ + { assertion = (cfg.customResolver != null) || (cfg.resolverName != null); + message = "please configure upstream DNSCrypt resolver"; + } ]; - ### User + security.apparmor.profiles = mkIf apparmorEnabled (singleton (pkgs.writeText "apparmor-dnscrypt-proxy" '' + ${dnscrypt-proxy}/bin/dnscrypt-proxy { + /dev/null rw, + /dev/urandom r, - users.extraUsers = singleton { - inherit uid; - name = "dnscrypt-proxy"; + /etc/passwd r, + /etc/group r, + ${config.environment.etc."nsswitch.conf".source} r, + + ${pkgs.glibc}/lib/*.so mr, + ${pkgs.tzdata}/share/zoneinfo/** r, + + network inet stream, + network inet6 stream, + network inet dgram, + network inet6 dgram, + + ${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, + + ${resolverListFile} r, + } + '')); + + 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";