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