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;
prosody = 149;
i2pd = 150;
#dnscrypt-proxy = 151; # unused
dnscrypt-proxy = 151;
systemd-network = 152;
systemd-resolve = 153;
systemd-timesync = 154;

View File

@ -141,6 +141,9 @@ in zipModules ([]
++ obsolete [ "services" "xserver" "windowManager" "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.
++ obsolete' [ "boot" "loader" "grub" "bootDevice" ]
++ obsolete' [ "boot" "initrd" "luks" "enable" ]

View File

@ -5,38 +5,35 @@ let
apparmorEnabled = config.security.apparmor.enable;
dnscrypt-proxy = pkgs.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 =
[ "--daemonize"
"--user=dnscrypt-proxy"
"--local-address=${cfg.localAddress}:${toString cfg.port}"
[ "--local-address=${localAddress}"
(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
{
##### 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).
'';
};
enable = mkEnableOption ''
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;
@ -44,96 +41,128 @@ in
Listen for DNS queries on this address.
'';
};
port = mkOption {
localPort = mkOption {
default = 53;
type = types.int;
description = ''
Listen on this port.
'';
};
resolverName = mkOption {
default = "opendns";
type = types.string;
type = types.nullOr 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).
The name of the upstream DNSCrypt resolver to use. See
<literal>${resolverListFile}</literal> for alternative resolvers
(e.g., if you are concerned about logging and/or server
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 {
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.
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" ''
${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,
}
'')
assertions = [
{ assertion = (cfg.customResolver != null) || (cfg.resolverName != null);
message = "please configure upstream DNSCrypt resolver";
}
];
### 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 {
inherit uid;
name = "dnscrypt-proxy";
/etc/passwd r,
/etc/group r,
${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";
};
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 = {
description = "dnscrypt-proxy daemon";
after = [ "network.target" ] ++ optional apparmorEnabled "apparmor.service";
requires = mkIf apparmorEnabled [ "apparmor.service" ];
wantedBy = [ "multi-user.target" ];
requires = [ "dnscrypt-proxy.socket "] ++ optional apparmorEnabled "apparmor.service";
serviceConfig = {
Type = "forking";
Type = "simple";
NonBlocking = "true";
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 {
name = "dnscrypt-proxy-${version}";
@ -9,7 +9,11 @@ stdenv.mkDerivation rec {
sha256 = "1cp3ivxngrihil6i7b659d39v9v6iwjs16s2kj9wz1anzyx0j6nx";
};
buildInputs = [ libsodium ];
configureFlags = ''
${stdenv.lib.optionalString stdenv.isLinux "--with-systemd"}
'';
buildInputs = [ pkgconfig libsodium ] ++ stdenv.lib.optional stdenv.isLinux systemd;
meta = {
description = "A tool for securing communications between a client and a DNS resolver";