From 52f0553209ad8f102eefd0d46ad336ff95f398be Mon Sep 17 00:00:00 2001 From: Joachim Fasting Date: Tue, 11 Nov 2014 20:12:28 +0100 Subject: [PATCH] Add dnscrypt-proxy service The dnscrypt-proxy service 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 a trustworthy upstream). Though dnscrypt-proxy can run as a standalone DNS client, the recommended setup is to use it as a forwarder for a caching DNS client. To use dnscrypt-proxy as a forwarder for dnsmasq, do ```nix { # ... networking.nameservers = [ "127.0.0.1" ]; networking.dhcpcd.extraConfig = "nohook resolv.conf"; services.dnscrypt-proxy.enable = true; services.dnscrypt-proxy.localAddress = "127.0.0.1"; services.dnscrypt-proxy.port = 40; services.dnsmasq.enable = true; services.dnsmasq.extraConfig = '' no-resolv server=127.0.0.1#40 listen-address=127.0.0.1 ''; # ... } ``` --- nixos/modules/misc/ids.nix | 1 + nixos/modules/module-list.nix | 1 + .../services/networking/dnscrypt-proxy.nix | 133 ++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 nixos/modules/services/networking/dnscrypt-proxy.nix diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index 7388cfc9a07..4eeaa2008fd 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -158,6 +158,7 @@ seeks = 148; prosody = 149; i2pd = 150; + dnscrypt-proxy = 151; # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399! diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index c6187125abb..bdfe183d07c 100755 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -221,6 +221,7 @@ ./services/networking/ddclient.nix ./services/networking/dhcpcd.nix ./services/networking/dhcpd.nix + ./services/networking/dnscrypt-proxy.nix ./services/networking/dnsmasq.nix ./services/networking/ejabberd.nix ./services/networking/firewall.nix diff --git a/nixos/modules/services/networking/dnscrypt-proxy.nix b/nixos/modules/services/networking/dnscrypt-proxy.nix new file mode 100644 index 00000000000..d847e10a936 --- /dev/null +++ b/nixos/modules/services/networking/dnscrypt-proxy.nix @@ -0,0 +1,133 @@ +{ config, lib, pkgs, ... }: +with lib; + +let + apparmorEnabled = config.security.apparmor.enable; + dnscrypt-proxy = pkgs.dnscrypt-proxy; + cfg = config.services.dnscrypt-proxy; + uid = config.ids.uids.dnscrypt-proxy; + daemonArgs = [ "--daemonize" + "--user=dnscrypt-proxy" + "--local-address=${cfg.localAddress}:${toString cfg.port}" + (optionalString cfg.tcpOnly "--tcp-only") + "--resolvers-list=${dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv" + "--resolver-name=${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). + ''; + }; + + localAddress = mkOption { + default = "127.0.0.1"; + type = types.string; + description = '' + Listen for DNS queries on this address. + ''; + }; + + port = mkOption { + default = 53; + type = types.int; + description = '' + Listen on this port. + ''; + }; + + resolverName = mkOption { + default = "opendns"; + type = 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). + ''; + }; + + 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. + ''; + }; + + }; + + }; + + ##### implementation + + config = mkIf cfg.enable { + + ### AppArmor profile + + security.apparmor.profiles = mkIf apparmorEnabled [ + (pkgs.writeText "apparmor-dnscrypt-proxy" '' + + ${dnscrypt-proxy}/sbin/dnscrypt-proxy { + 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.gcc}/lib/libssp.so.* mr, + ${pkgs.libsodium}/lib/libsodium.so.* mr, + } + '') + ]; + + ### User + + users.extraUsers = singleton { + inherit uid; + name = "dnscrypt-proxy"; + description = "dnscrypt-proxy daemon user"; + }; + + ### Service definition + + systemd.services.dnscrypt-proxy = { + description = "dnscrypt-proxy daemon"; + after = [ "network.target" ] ++ optional apparmorEnabled "apparmor.service"; + requires = mkIf apparmorEnabled [ "apparmor.service" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "forking"; + ExecStart = "${dnscrypt-proxy}/sbin/dnscrypt-proxy ${toString daemonArgs}"; + }; + }; + + }; +}