Merge pull request #6702 from joachifm/dnscrypt-proxy

nixos: some improvements for dnscrypt-proxy
This commit is contained in:
James Cook 2015-07-12 00:17:46 -07:00
commit a456168e5b
4 changed files with 118 additions and 82 deletions

View File

@ -382,7 +382,7 @@
seeks = 148; seeks = 148;
prosody = 149; prosody = 149;
i2pd = 150; i2pd = 150;
#dnscrypt-proxy = 151; # unused dnscrypt-proxy = 151;
systemd-network = 152; systemd-network = 152;
systemd-resolve = 153; systemd-resolve = 153;
systemd-timesync = 154; systemd-timesync = 154;

View File

@ -141,6 +141,9 @@ in zipModules ([]
++ obsolete [ "services" "xserver" "windowManager" "xbmc" ] [ "services" "xserver" "desktopManager" "kodi" ] ++ obsolete [ "services" "xserver" "windowManager" "xbmc" ] [ "services" "xserver" "desktopManager" "kodi" ]
++ obsolete [ "services" "xserver" "desktopManager" "xbmc" ] [ "services" "xserver" "desktopManager" "kodi" ] ++ obsolete [ "services" "xserver" "desktopManager" "xbmc" ] [ "services" "xserver" "desktopManager" "kodi" ]
# DNSCrypt-proxy
++ obsolete [ "services" "dnscrypt-proxy" "port" ] [ "services" "dnscrypt-proxy" "localPort" ]
# Options that are obsolete and have no replacement. # Options that are obsolete and have no replacement.
++ obsolete' [ "boot" "loader" "grub" "bootDevice" ] ++ obsolete' [ "boot" "loader" "grub" "bootDevice" ]
++ obsolete' [ "boot" "initrd" "luks" "enable" ] ++ obsolete' [ "boot" "initrd" "luks" "enable" ]

View File

@ -5,38 +5,35 @@ let
apparmorEnabled = config.security.apparmor.enable; apparmorEnabled = config.security.apparmor.enable;
dnscrypt-proxy = pkgs.dnscrypt-proxy; dnscrypt-proxy = pkgs.dnscrypt-proxy;
cfg = config.services.dnscrypt-proxy; cfg = config.services.dnscrypt-proxy;
uid = config.ids.uids.dnscrypt-proxy; resolverListFile = "${dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv";
localAddress = "${cfg.localAddress}:${toString cfg.localPort}";
daemonArgs = daemonArgs =
[ "--daemonize" [ "--local-address=${localAddress}"
"--user=dnscrypt-proxy"
"--local-address=${cfg.localAddress}:${toString cfg.port}"
(optionalString cfg.tcpOnly "--tcp-only") (optionalString cfg.tcpOnly "--tcp-only")
"--resolvers-list=${dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv" ]
"--resolver-name=${cfg.resolverName}" ++ resolverArgs;
]; resolverArgs = if (cfg.customResolver != null)
then
[ "--resolver-address=${cfg.customResolver.address}:${toString cfg.customResolver.port}"
"--provider-name=${cfg.customResolver.name}"
"--provider-key=${cfg.customResolver.key}"
]
else
[ "--resolvers-list=${resolverListFile}"
"--resolver-name=${toString cfg.resolverName}"
];
in in
{ {
##### interface
options = { options = {
services.dnscrypt-proxy = { services.dnscrypt-proxy = {
enable = mkEnableOption ''
enable = mkOption { Enable dnscrypt-proxy. The proxy relays regular DNS queries to a
default = false; DNSCrypt enabled upstream resolver. The traffic between the
type = types.bool; client and the upstream resolver is encrypted and authenticated,
description = '' which may mitigate the risk of MITM attacks and third-party
Enable dnscrypt-proxy. snooping (assuming the upstream is trustworthy).
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 { localAddress = mkOption {
default = "127.0.0.1"; default = "127.0.0.1";
type = types.string; type = types.string;
@ -44,96 +41,128 @@ in
Listen for DNS queries on this address. Listen for DNS queries on this address.
''; '';
}; };
localPort = mkOption {
port = mkOption {
default = 53; default = 53;
type = types.int; type = types.int;
description = '' description = ''
Listen on this port. Listen on this port.
''; '';
}; };
resolverName = mkOption { resolverName = mkOption {
default = "opendns"; default = "opendns";
type = types.string; type = types.nullOr types.string;
description = '' description = ''
The name of the upstream DNSCrypt resolver to use. The name of the upstream DNSCrypt resolver to use. See
See <literal>${dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv</literal> <literal>${resolverListFile}</literal> for alternative resolvers
for alternative resolvers (e.g., if you are concerned about logging (e.g., if you are concerned about logging and/or server
and/or server location). location).
''; '';
}; };
customResolver = mkOption {
default = null;
description = ''
Use a resolver not listed in the upstream list (e.g.,
a private DNSCrypt provider). For advanced users only.
If specified, this option takes precedence.
'';
type = types.nullOr (types.submodule ({ ... }: { options = {
address = mkOption {
type = types.str;
description = "Resolver IP address";
example = "208.67.220.220";
};
port = mkOption {
type = types.int;
description = "Resolver port";
default = 443;
};
name = mkOption {
type = types.str;
description = "Provider fully qualified domain name";
example = "2.dnscrypt-cert.opendns.com";
};
key = mkOption {
type = types.str;
description = "Provider public key";
example = "B735:1140:206F:225D:3E2B:D822:D7FD:691E:A1C3:3CC8:D666:8D0C:BE04:BFAB:CA43:FB79";
}; }; }));
};
tcpOnly = mkOption { tcpOnly = mkOption {
default = false; default = false;
type = types.bool; type = types.bool;
description = '' description = ''
Force sending encrypted DNS queries to the upstream resolver Force sending encrypted DNS queries to the upstream resolver
over TCP instead of UDP (on port 443). over TCP instead of UDP (on port 443). Enabling this option may
Enabling this option may help circumvent filtering, but should help circumvent filtering, but should not be used otherwise.
not be used otherwise.
''; '';
}; };
}; };
}; };
##### implementation
config = mkIf cfg.enable { config = mkIf cfg.enable {
### AppArmor profile assertions = [
{ assertion = (cfg.customResolver != null) || (cfg.resolverName != null);
security.apparmor.profiles = mkIf apparmorEnabled [ message = "please configure upstream DNSCrypt resolver";
(pkgs.writeText "apparmor-dnscrypt-proxy" '' }
${dnscrypt-proxy}/bin/dnscrypt-proxy {
network inet stream,
network inet6 stream,
network inet dgram,
network inet6 dgram,
capability ipc_lock,
capability net_bind_service,
capability net_admin,
capability sys_chroot,
capability setgid,
capability setuid,
/dev/null rw,
/dev/urandom r,
${pkgs.glibc}/lib/*.so mr,
${pkgs.tzdata}/share/zoneinfo/** r,
${dnscrypt-proxy}/share/dnscrypt-proxy/** r,
${pkgs.gcc.cc}/lib/libssp.so.* mr,
${pkgs.libsodium}/lib/libsodium.so.* mr,
}
'')
]; ];
### User security.apparmor.profiles = mkIf apparmorEnabled (singleton (pkgs.writeText "apparmor-dnscrypt-proxy" ''
${dnscrypt-proxy}/bin/dnscrypt-proxy {
/dev/null rw,
/dev/urandom r,
users.extraUsers = singleton { /etc/passwd r,
inherit uid; /etc/group r,
name = "dnscrypt-proxy"; ${config.environment.etc."nsswitch.conf".source} r,
${pkgs.glibc}/lib/*.so mr,
${pkgs.tzdata}/share/zoneinfo/** r,
network inet stream,
network inet6 stream,
network inet dgram,
network inet6 dgram,
${pkgs.gcc.cc}/lib/libssp.so.* mr,
${pkgs.libsodium}/lib/libsodium.so.* mr,
${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,
${resolverListFile} r,
}
''));
users.extraUsers.dnscrypt-proxy = {
uid = config.ids.uids.dnscrypt-proxy;
description = "dnscrypt-proxy daemon user"; description = "dnscrypt-proxy daemon user";
}; };
users.extraGroups.dnscrypt-proxy.gid = config.ids.gids.dnscrypt-proxy;
### Service definition systemd.sockets.dnscrypt-proxy = {
description = "dnscrypt-proxy listening socket";
socketConfig = {
ListenStream = "${localAddress}";
ListenDatagram = "${localAddress}";
};
wantedBy = [ "sockets.target" ];
};
systemd.services.dnscrypt-proxy = { systemd.services.dnscrypt-proxy = {
description = "dnscrypt-proxy daemon"; description = "dnscrypt-proxy daemon";
after = [ "network.target" ] ++ optional apparmorEnabled "apparmor.service"; after = [ "network.target" ] ++ optional apparmorEnabled "apparmor.service";
requires = mkIf apparmorEnabled [ "apparmor.service" ]; requires = [ "dnscrypt-proxy.socket "] ++ optional apparmorEnabled "apparmor.service";
wantedBy = [ "multi-user.target" ];
serviceConfig = { serviceConfig = {
Type = "forking"; Type = "simple";
NonBlocking = "true";
ExecStart = "${dnscrypt-proxy}/bin/dnscrypt-proxy ${toString daemonArgs}"; ExecStart = "${dnscrypt-proxy}/bin/dnscrypt-proxy ${toString daemonArgs}";
User = "dnscrypt-proxy";
Group = "dnscrypt-proxy";
PrivateTmp = true;
PrivateDevices = true;
}; };
}; };
}; };
} }

View File

@ -1,4 +1,4 @@
{ stdenv, fetchurl, libsodium }: { stdenv, fetchurl, libsodium, pkgconfig, systemd }:
stdenv.mkDerivation rec { stdenv.mkDerivation rec {
name = "dnscrypt-proxy-${version}"; name = "dnscrypt-proxy-${version}";
@ -9,7 +9,11 @@ stdenv.mkDerivation rec {
sha256 = "1cp3ivxngrihil6i7b659d39v9v6iwjs16s2kj9wz1anzyx0j6nx"; sha256 = "1cp3ivxngrihil6i7b659d39v9v6iwjs16s2kj9wz1anzyx0j6nx";
}; };
buildInputs = [ libsodium ]; configureFlags = ''
${stdenv.lib.optionalString stdenv.isLinux "--with-systemd"}
'';
buildInputs = [ pkgconfig libsodium ] ++ stdenv.lib.optional stdenv.isLinux systemd;
meta = { meta = {
description = "A tool for securing communications between a client and a DNS resolver"; description = "A tool for securing communications between a client and a DNS resolver";