at 16.09-beta 6.9 kB view raw
1{ config, lib, pkgs, ... }: 2with lib; 3 4let 5 apparmorEnabled = config.security.apparmor.enable; 6 dnscrypt-proxy = pkgs.dnscrypt-proxy; 7 cfg = config.services.dnscrypt-proxy; 8 9 localAddress = "${cfg.localAddress}:${toString cfg.localPort}"; 10 11 daemonArgs = 12 [ "--local-address=${localAddress}" 13 (optionalString cfg.tcpOnly "--tcp-only") 14 (optionalString cfg.ephemeralKeys "-E") 15 ] 16 ++ resolverArgs; 17 18 resolverArgs = if (cfg.customResolver != null) 19 then 20 [ "--resolver-address=${cfg.customResolver.address}:${toString cfg.customResolver.port}" 21 "--provider-name=${cfg.customResolver.name}" 22 "--provider-key=${cfg.customResolver.key}" 23 ] 24 else 25 [ "--resolvers-list=${cfg.resolverList}" 26 "--resolver-name=${toString cfg.resolverName}" 27 ]; 28in 29 30{ 31 meta = { 32 maintainers = with maintainers; [ joachifm ]; 33 doc = ./dnscrypt-proxy.xml; 34 }; 35 36 options = { 37 services.dnscrypt-proxy = { 38 enable = mkEnableOption "DNSCrypt client proxy"; 39 40 localAddress = mkOption { 41 default = "127.0.0.1"; 42 type = types.str; 43 description = '' 44 Listen for DNS queries to relay on this address. The only reason to 45 change this from its default value is to proxy queries on behalf 46 of other machines (typically on the local network). 47 ''; 48 }; 49 50 localPort = mkOption { 51 default = 53; 52 type = types.int; 53 description = '' 54 Listen for DNS queries to relay on this port. The default value 55 assumes that the DNSCrypt proxy should relay DNS queries directly. 56 When running as a forwarder for another DNS client, set this option 57 to a different value; otherwise leave the default. 58 ''; 59 }; 60 61 resolverName = mkOption { 62 default = "dnscrypt.eu-nl"; 63 type = types.nullOr types.str; 64 description = '' 65 The name of the upstream DNSCrypt resolver to use, taken from the 66 list named in the <literal>resolverList</literal> option. 67 The default resolver is located in Holland, supports DNS security 68 extensions, and claims to not keep logs. 69 ''; 70 }; 71 72 resolverList = mkOption { 73 description = '' 74 The list of upstream DNSCrypt resolvers. By default, we use the most 75 recent list published by upstream. 76 ''; 77 example = literalExample "${pkgs.dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv"; 78 default = pkgs.fetchurl { 79 url = https://raw.githubusercontent.com/jedisct1/dnscrypt-proxy/master/dnscrypt-resolvers.csv; 80 sha256 = "1i9wzw4zl052h5nyp28bwl8d66cgj0awvjhw5wgwz0warkjl1g8g"; 81 }; 82 defaultText = "pkgs.fetchurl { url = ...; sha256 = ...; }"; 83 }; 84 85 customResolver = mkOption { 86 default = null; 87 description = '' 88 Use an unlisted resolver (e.g., a private DNSCrypt provider). For 89 advanced users only. If specified, this option takes precedence. 90 ''; 91 type = types.nullOr (types.submodule ({ ... }: { options = { 92 address = mkOption { 93 type = types.str; 94 description = "IP address"; 95 example = "208.67.220.220"; 96 }; 97 98 port = mkOption { 99 type = types.int; 100 description = "Port"; 101 default = 443; 102 }; 103 104 name = mkOption { 105 type = types.str; 106 description = "Fully qualified domain name"; 107 example = "2.dnscrypt-cert.opendns.com"; 108 }; 109 110 key = mkOption { 111 type = types.str; 112 description = "Public key"; 113 example = "B735:1140:206F:225D:3E2B:D822:D7FD:691E:A1C3:3CC8:D666:8D0C:BE04:BFAB:CA43:FB79"; 114 }; 115 }; })); 116 }; 117 118 tcpOnly = mkOption { 119 default = false; 120 type = types.bool; 121 description = '' 122 Force sending encrypted DNS queries to the upstream resolver over 123 TCP instead of UDP (on port 443). Use only if the UDP port is blocked. 124 ''; 125 }; 126 127 ephemeralKeys = mkOption { 128 default = false; 129 type = types.bool; 130 description = '' 131 Compute a new key pair for every query. Enabling this option 132 increases CPU usage, but makes it more difficult for the upstream 133 resolver to track your usage of their service across IP addresses. 134 The default is to re-use the public key pair for all queries, making 135 tracking trivial. 136 ''; 137 }; 138 }; 139 }; 140 141 config = mkIf cfg.enable { 142 143 assertions = [ 144 { assertion = (cfg.customResolver != null) || (cfg.resolverName != null); 145 message = "please configure upstream DNSCrypt resolver"; 146 } 147 ]; 148 149 security.apparmor.profiles = mkIf apparmorEnabled (singleton (pkgs.writeText "apparmor-dnscrypt-proxy" '' 150 ${dnscrypt-proxy}/bin/dnscrypt-proxy { 151 /dev/null rw, 152 /dev/urandom r, 153 154 /etc/passwd r, 155 /etc/group r, 156 ${config.environment.etc."nsswitch.conf".source} r, 157 158 ${getLib pkgs.glibc}/lib/*.so mr, 159 ${pkgs.tzdata}/share/zoneinfo/** r, 160 161 network inet stream, 162 network inet6 stream, 163 network inet dgram, 164 network inet6 dgram, 165 166 ${getLib pkgs.gcc.cc}/lib/libssp.so.* mr, 167 ${getLib pkgs.libsodium}/lib/libsodium.so.* mr, 168 ${getLib pkgs.systemd}/lib/libsystemd.so.* mr, 169 ${getLib pkgs.xz}/lib/liblzma.so.* mr, 170 ${getLib pkgs.libgcrypt}/lib/libgcrypt.so.* mr, 171 ${getLib pkgs.libgpgerror}/lib/libgpg-error.so.* mr, 172 ${getLib pkgs.libcap}/lib/libcap.so.* mr, 173 ${getLib pkgs.lz4}/lib/liblz4.so.* mr, 174 ${getLib pkgs.attr}/lib/libattr.so.* mr, 175 176 ${cfg.resolverList} r, 177 } 178 '')); 179 180 users.users.dnscrypt-proxy = { 181 description = "dnscrypt-proxy daemon user"; 182 isSystemUser = true; 183 group = "dnscrypt-proxy"; 184 }; 185 users.groups.dnscrypt-proxy = {}; 186 187 systemd.sockets.dnscrypt-proxy = { 188 description = "dnscrypt-proxy listening socket"; 189 socketConfig = { 190 ListenStream = "${localAddress}"; 191 ListenDatagram = "${localAddress}"; 192 }; 193 wantedBy = [ "sockets.target" ]; 194 }; 195 196 systemd.services.dnscrypt-proxy = { 197 description = "dnscrypt-proxy daemon"; 198 199 after = [ "network.target" ] ++ optional apparmorEnabled "apparmor.service"; 200 requires = [ "dnscrypt-proxy.socket "] ++ optional apparmorEnabled "apparmor.service"; 201 202 serviceConfig = { 203 Type = "simple"; 204 NonBlocking = "true"; 205 ExecStart = "${dnscrypt-proxy}/bin/dnscrypt-proxy ${toString daemonArgs}"; 206 207 User = "dnscrypt-proxy"; 208 209 PrivateTmp = true; 210 PrivateDevices = true; 211 ProtectHome = true; 212 }; 213 }; 214 }; 215}