2014-11-11 20:12:28 +01:00
|
|
|
{ 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;
|
2014-11-21 15:42:11 +01:00
|
|
|
daemonArgs =
|
2015-03-07 19:13:12 +01:00
|
|
|
[ "--user=dnscrypt-proxy"
|
2014-11-21 15:42:11 +01:00
|
|
|
"--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}"
|
|
|
|
];
|
2014-11-11 20:12:28 +01:00
|
|
|
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 <literal>${dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv</literal>
|
|
|
|
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" ''
|
|
|
|
|
2015-01-09 13:57:04 +01:00
|
|
|
${dnscrypt-proxy}/bin/dnscrypt-proxy {
|
|
|
|
network inet stream,
|
|
|
|
network inet6 stream,
|
|
|
|
network inet dgram,
|
|
|
|
network inet6 dgram,
|
|
|
|
|
2014-11-11 20:12:28 +01:00
|
|
|
capability ipc_lock,
|
|
|
|
capability net_bind_service,
|
|
|
|
capability net_admin,
|
|
|
|
capability sys_chroot,
|
|
|
|
capability setgid,
|
|
|
|
capability setuid,
|
|
|
|
|
|
|
|
/dev/null rw,
|
|
|
|
/dev/urandom r,
|
|
|
|
|
2015-02-23 18:02:12 +01:00
|
|
|
/etc/passwd r,
|
|
|
|
/etc/group r,
|
|
|
|
${config.environment.etc."nsswitch.conf".source} r,
|
|
|
|
|
2014-11-11 20:12:28 +01:00
|
|
|
${pkgs.glibc}/lib/*.so mr,
|
|
|
|
${pkgs.tzdata}/share/zoneinfo/** r,
|
|
|
|
|
|
|
|
${dnscrypt-proxy}/share/dnscrypt-proxy/** r,
|
2015-01-15 05:44:00 +01:00
|
|
|
${pkgs.gcc.cc}/lib/libssp.so.* mr,
|
2014-11-11 20:12:28 +01:00
|
|
|
${pkgs.libsodium}/lib/libsodium.so.* mr,
|
2015-03-07 19:13:12 +01:00
|
|
|
${pkgs.systemd}/lib/libsystemd.so.* mr,
|
|
|
|
${pkgs.xz}/lib/liblzma.so.* mr,
|
|
|
|
${pkgs.libgcrypt}/lib/libgcrypt.so.* mr,
|
|
|
|
${pkgs.libgpgerror}/lib/libgpg-error.so.* mr,
|
2014-11-11 20:12:28 +01:00
|
|
|
}
|
|
|
|
'')
|
|
|
|
];
|
|
|
|
|
|
|
|
### User
|
|
|
|
|
|
|
|
users.extraUsers = singleton {
|
|
|
|
inherit uid;
|
|
|
|
name = "dnscrypt-proxy";
|
|
|
|
description = "dnscrypt-proxy daemon user";
|
|
|
|
};
|
|
|
|
|
|
|
|
### Service definition
|
|
|
|
|
2015-03-07 19:13:12 +01:00
|
|
|
## derived from upstream dnscrypt-proxy.socket
|
|
|
|
systemd.sockets.dnscrypt-proxy = {
|
|
|
|
description = "dnscrypt-proxy listening socket";
|
|
|
|
|
|
|
|
socketConfig = {
|
|
|
|
ListenStream = "${cfg.localAddress}:${toString cfg.port}";
|
|
|
|
ListenDatagram = "${cfg.localAddress}:${toString cfg.port}";
|
|
|
|
};
|
|
|
|
|
|
|
|
wantedBy = [ "sockets.target" ];
|
|
|
|
};
|
|
|
|
|
|
|
|
# derived from upstream dnscrypt-proxy.service
|
2014-11-11 20:12:28 +01:00
|
|
|
systemd.services.dnscrypt-proxy = {
|
|
|
|
description = "dnscrypt-proxy daemon";
|
|
|
|
after = [ "network.target" ] ++ optional apparmorEnabled "apparmor.service";
|
2015-03-07 19:13:12 +01:00
|
|
|
requires = [ "dnscrypt-proxy.socket "] ++ optional apparmorEnabled "apparmor.service";
|
2014-11-11 20:12:28 +01:00
|
|
|
serviceConfig = {
|
2015-03-07 19:13:12 +01:00
|
|
|
Type = "simple";
|
|
|
|
## note: NonBlocking is required for socket activation to work
|
|
|
|
NonBlocking = "true";
|
2015-01-09 13:57:04 +01:00
|
|
|
ExecStart = "${dnscrypt-proxy}/bin/dnscrypt-proxy ${toString daemonArgs}";
|
2014-11-11 20:12:28 +01:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
};
|
|
|
|
}
|