nixos: additional hardening for dnscrypt-proxy

- Run as unprivileged user/group via systemd, obviating the need to
specify capabilities, etc.
- Run with private tmp and minimal device name space

+22 -28
+1 -1
nixos/modules/misc/ids.nix
··· 376 376 seeks = 148; 377 377 prosody = 149; 378 378 i2pd = 150; 379 - #dnscrypt-proxy = 151; # unused 379 + dnscrypt-proxy = 151; 380 380 systemd-network = 152; 381 381 systemd-resolve = 153; 382 382 systemd-timesync = 154;
+21 -27
nixos/modules/services/networking/dnscrypt-proxy.nix
··· 5 5 apparmorEnabled = config.security.apparmor.enable; 6 6 dnscrypt-proxy = pkgs.dnscrypt-proxy; 7 7 cfg = config.services.dnscrypt-proxy; 8 - uid = config.ids.uids.dnscrypt-proxy; 8 + resolverListFile = "${dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv"; 9 9 daemonArgs = 10 - [ "--user=dnscrypt-proxy" 11 - "--local-address=${cfg.localAddress}:${toString cfg.port}" 10 + [ "--local-address=${cfg.localAddress}:${toString cfg.port}" 12 11 (optionalString cfg.tcpOnly "--tcp-only") 13 - "--resolvers-list=${dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv" 12 + "--resolvers-list=${resolverListFile}" 14 13 "--resolver-name=${cfg.resolverName}" 15 14 ]; 16 15 in ··· 56 55 default = "opendns"; 57 56 type = types.string; 58 57 description = '' 59 - The name of the upstream DNSCrypt resolver to use. 60 - See <literal>${dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv</literal> 61 - for alternative resolvers (e.g., if you are concerned about logging 62 - and/or server location). 58 + The name of the upstream DNSCrypt resolver to use. See 59 + <literal>${resolverListFile}</literal> for alternative resolvers 60 + (e.g., if you are concerned about logging and/or server 61 + location). 63 62 ''; 64 63 }; 65 64 ··· 88 87 (pkgs.writeText "apparmor-dnscrypt-proxy" '' 89 88 90 89 ${dnscrypt-proxy}/bin/dnscrypt-proxy { 91 - network inet stream, 92 - network inet6 stream, 93 - network inet dgram, 94 - network inet6 dgram, 95 - 96 - capability ipc_lock, 97 - capability net_bind_service, 98 - capability net_admin, 99 - capability sys_chroot, 100 - capability setgid, 101 - capability setuid, 102 90 103 91 /dev/null rw, 104 92 /dev/urandom r, ··· 110 98 ${pkgs.glibc}/lib/*.so mr, 111 99 ${pkgs.tzdata}/share/zoneinfo/** r, 112 100 113 - ${dnscrypt-proxy}/share/dnscrypt-proxy/** r, 101 + network inet stream, 102 + network inet6 stream, 103 + network inet dgram, 104 + network inet6 dgram, 105 + 114 106 ${pkgs.gcc.cc}/lib/libssp.so.* mr, 115 107 ${pkgs.libsodium}/lib/libsodium.so.* mr, 116 108 ${pkgs.systemd}/lib/libsystemd.so.* mr, 117 109 ${pkgs.xz}/lib/liblzma.so.* mr, 118 110 ${pkgs.libgcrypt}/lib/libgcrypt.so.* mr, 119 111 ${pkgs.libgpgerror}/lib/libgpg-error.so.* mr, 112 + 113 + ${resolverListFile} r, 120 114 } 121 115 '') 122 116 ]; 123 117 124 - ### User 125 - 126 - users.extraUsers = singleton { 127 - inherit uid; 128 - name = "dnscrypt-proxy"; 118 + users.extraUsers.dnscrypt-proxy = { 119 + uid = config.ids.uids.dnscrypt-proxy; 129 120 description = "dnscrypt-proxy daemon user"; 130 121 }; 131 - 132 - ### Service definition 122 + users.extraGroups.dnscrypt-proxy.gid = config.ids.gids.dnscrypt-proxy; 133 123 134 124 ## derived from upstream dnscrypt-proxy.socket 135 125 systemd.sockets.dnscrypt-proxy = { ··· 153 143 ## note: NonBlocking is required for socket activation to work 154 144 NonBlocking = "true"; 155 145 ExecStart = "${dnscrypt-proxy}/bin/dnscrypt-proxy ${toString daemonArgs}"; 146 + User = "dnscrypt-proxy"; 147 + Group = "dnscrypt-proxy"; 148 + PrivateTmp = true; 149 + PrivateDevices = true; 156 150 }; 157 151 }; 158 152