···
apparmorEnabled = config.security.apparmor.enable;
dnscrypt-proxy = pkgs.dnscrypt-proxy;
cfg = config.services.dnscrypt-proxy;
8
-
uid = config.ids.uids.dnscrypt-proxy;
8
+
resolverListFile = "${dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv";
9
+
localAddress = "${cfg.localAddress}:${toString cfg.localPort}";
11
-
"--user=dnscrypt-proxy"
12
-
"--local-address=${cfg.localAddress}:${toString cfg.port}"
11
+
[ "--local-address=${localAddress}"
(optionalString cfg.tcpOnly "--tcp-only")
14
-
"--resolvers-list=${dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv"
15
-
"--resolver-name=${cfg.resolverName}"
15
+
resolverArgs = if (cfg.customResolver != null)
17
+
[ "--resolver-address=${cfg.customResolver.address}:${toString cfg.customResolver.port}"
18
+
"--provider-name=${cfg.customResolver.name}"
19
+
"--provider-key=${cfg.customResolver.key}"
22
+
[ "--resolvers-list=${resolverListFile}"
23
+
"--resolver-name=${toString cfg.resolverName}"
services.dnscrypt-proxy = {
30
-
Enable dnscrypt-proxy.
31
-
The proxy relays regular DNS queries to a DNSCrypt enabled
33
-
The traffic between the client and the upstream resolver is
34
-
encrypted and authenticated, which may mitigate the risk of MITM
35
-
attacks and third-party snooping (assuming the upstream is
30
+
enable = mkEnableOption ''
31
+
Enable dnscrypt-proxy. The proxy relays regular DNS queries to a
32
+
DNSCrypt enabled upstream resolver. The traffic between the
33
+
client and the upstream resolver is encrypted and authenticated,
34
+
which may mitigate the risk of MITM attacks and third-party
35
+
snooping (assuming the upstream is trustworthy).
localAddress = mkOption {
···
Listen for DNS queries on this address.
44
+
localPort = mkOption {
resolverName = mkOption {
58
-
type = types.string;
53
+
type = types.nullOr types.string;
55
+
The name of the upstream DNSCrypt resolver to use. See
56
+
<literal>${resolverListFile}</literal> for alternative resolvers
57
+
(e.g., if you are concerned about logging and/or server
61
+
customResolver = mkOption {
60
-
The name of the upstream DNSCrypt resolver to use.
61
-
See <literal>${dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv</literal>
62
-
for alternative resolvers (e.g., if you are concerned about logging
63
-
and/or server location).
64
+
Use a resolver not listed in the upstream list (e.g.,
65
+
a private DNSCrypt provider). For advanced users only.
66
+
If specified, this option takes precedence.
68
+
type = types.nullOr (types.submodule ({ ... }: { options = {
69
+
address = mkOption {
71
+
description = "Resolver IP address";
72
+
example = "208.67.220.220";
76
+
description = "Resolver port";
81
+
description = "Provider fully qualified domain name";
82
+
example = "2.dnscrypt-cert.opendns.com";
86
+
description = "Provider public key";
87
+
example = "B735:1140:206F:225D:3E2B:D822:D7FD:691E:A1C3:3CC8:D666:8D0C:BE04:BFAB:CA43:FB79";
Force sending encrypted DNS queries to the upstream resolver
72
-
over TCP instead of UDP (on port 443).
73
-
Enabling this option may help circumvent filtering, but should
74
-
not be used otherwise.
95
+
over TCP instead of UDP (on port 443). Enabling this option may
96
+
help circumvent filtering, but should not be used otherwise.
82
-
##### implementation
config = mkIf cfg.enable {
86
-
### AppArmor profile
105
+
{ assertion = (cfg.customResolver != null) || (cfg.resolverName != null);
106
+
message = "please configure upstream DNSCrypt resolver";
88
-
security.apparmor.profiles = mkIf apparmorEnabled [
89
-
(pkgs.writeText "apparmor-dnscrypt-proxy" ''
110
+
security.apparmor.profiles = mkIf apparmorEnabled (singleton (pkgs.writeText "apparmor-dnscrypt-proxy" ''
111
+
${dnscrypt-proxy}/bin/dnscrypt-proxy {
91
-
${dnscrypt-proxy}/bin/dnscrypt-proxy {
92
-
network inet stream,
93
-
network inet6 stream,
95
-
network inet6 dgram,
117
+
${config.environment.etc."nsswitch.conf".source} r,
97
-
capability ipc_lock,
98
-
capability net_bind_service,
99
-
capability net_admin,
100
-
capability sys_chroot,
119
+
${pkgs.glibc}/lib/*.so mr,
120
+
${pkgs.tzdata}/share/zoneinfo/** r,
122
+
network inet stream,
123
+
network inet6 stream,
124
+
network inet dgram,
125
+
network inet6 dgram,
107
-
${pkgs.glibc}/lib/*.so mr,
108
-
${pkgs.tzdata}/share/zoneinfo/** r,
110
-
${dnscrypt-proxy}/share/dnscrypt-proxy/** r,
111
-
${pkgs.gcc.cc}/lib/libssp.so.* mr,
112
-
${pkgs.libsodium}/lib/libsodium.so.* mr,
127
+
${pkgs.gcc.cc}/lib/libssp.so.* mr,
128
+
${pkgs.libsodium}/lib/libsodium.so.* mr,
129
+
${pkgs.systemd}/lib/libsystemd.so.* mr,
130
+
${pkgs.xz}/lib/liblzma.so.* mr,
131
+
${pkgs.libgcrypt}/lib/libgcrypt.so.* mr,
132
+
${pkgs.libgpgerror}/lib/libgpg-error.so.* mr,
134
+
${resolverListFile} r,
119
-
users.extraUsers = singleton {
121
-
name = "dnscrypt-proxy";
138
+
users.extraUsers.dnscrypt-proxy = {
139
+
uid = config.ids.uids.dnscrypt-proxy;
description = "dnscrypt-proxy daemon user";
142
+
users.extraGroups.dnscrypt-proxy.gid = config.ids.gids.dnscrypt-proxy;
125
-
### Service definition
144
+
systemd.sockets.dnscrypt-proxy = {
145
+
description = "dnscrypt-proxy listening socket";
147
+
ListenStream = "${localAddress}";
148
+
ListenDatagram = "${localAddress}";
150
+
wantedBy = [ "sockets.target" ];
systemd.services.dnscrypt-proxy = {
description = "dnscrypt-proxy daemon";
after = [ "network.target" ] ++ optional apparmorEnabled "apparmor.service";
130
-
requires = mkIf apparmorEnabled [ "apparmor.service" ];
131
-
wantedBy = [ "multi-user.target" ];
156
+
requires = [ "dnscrypt-proxy.socket "] ++ optional apparmorEnabled "apparmor.service";
159
+
NonBlocking = "true";
ExecStart = "${dnscrypt-proxy}/bin/dnscrypt-proxy ${toString daemonArgs}";
161
+
User = "dnscrypt-proxy";
162
+
Group = "dnscrypt-proxy";
164
+
PrivateDevices = true;