This removes the original dnscrypt-proxy module as well. Co-authored-by: Atemu <atemu.main@gmail.com> Co-authored-by: Silvan Mosberger <contact@infinisil.com> Co-authored-by: ryneeverett <ryneeverett@gmail.com> Co-authored-by: worldofpeace <worldofpeace@protonmail.ch>wip/yesman
parent
0036573d30
commit
92d689d66b
@ -1,328 +0,0 @@ |
||||
{ config, lib, pkgs, ... }: |
||||
with lib; |
||||
|
||||
let |
||||
cfg = config.services.dnscrypt-proxy; |
||||
|
||||
stateDirectory = "/var/lib/dnscrypt-proxy"; |
||||
|
||||
# The minisign public key used to sign the upstream resolver list. |
||||
# This is somewhat more flexible than preloading the key as an |
||||
# embedded string. |
||||
upstreamResolverListPubKey = pkgs.fetchurl { |
||||
url = https://raw.githubusercontent.com/dyne/dnscrypt-proxy/master/minisign.pub; |
||||
sha256 = "18lnp8qr6ghfc2sd46nn1rhcpr324fqlvgsp4zaigw396cd7vnnh"; |
||||
}; |
||||
|
||||
# Internal flag indicating whether the upstream resolver list is used. |
||||
useUpstreamResolverList = cfg.customResolver == null; |
||||
|
||||
# The final local address. |
||||
localAddress = "${cfg.localAddress}:${toString cfg.localPort}"; |
||||
|
||||
# The final resolvers list path. |
||||
resolverList = "${stateDirectory}/dnscrypt-resolvers.csv"; |
||||
|
||||
# Build daemon command line |
||||
|
||||
resolverArgs = |
||||
if (cfg.customResolver == null) |
||||
then |
||||
[ "-L ${resolverList}" |
||||
"-R ${cfg.resolverName}" |
||||
] |
||||
else with cfg.customResolver; |
||||
[ "-N ${name}" |
||||
"-k ${key}" |
||||
"-r ${address}:${toString port}" |
||||
]; |
||||
|
||||
daemonArgs = |
||||
[ "-a ${localAddress}" ] |
||||
++ resolverArgs |
||||
++ cfg.extraArgs; |
||||
in |
||||
|
||||
{ |
||||
meta = { |
||||
maintainers = with maintainers; [ joachifm ]; |
||||
doc = ./dnscrypt-proxy.xml; |
||||
}; |
||||
|
||||
options = { |
||||
# Before adding another option, consider whether it could |
||||
# equally well be passed via extraArgs. |
||||
|
||||
services.dnscrypt-proxy = { |
||||
enable = mkOption { |
||||
default = false; |
||||
type = types.bool; |
||||
description = "Whether to enable the DNSCrypt client proxy"; |
||||
}; |
||||
|
||||
localAddress = mkOption { |
||||
default = "127.0.0.1"; |
||||
type = types.str; |
||||
description = '' |
||||
Listen for DNS queries to relay on this address. The only reason to |
||||
change this from its default value is to proxy queries on behalf |
||||
of other machines (typically on the local network). |
||||
''; |
||||
}; |
||||
|
||||
localPort = mkOption { |
||||
default = 53; |
||||
type = types.int; |
||||
description = '' |
||||
Listen for DNS queries to relay on this port. The default value |
||||
assumes that the DNSCrypt proxy should relay DNS queries directly. |
||||
When running as a forwarder for another DNS client, set this option |
||||
to a different value; otherwise leave the default. |
||||
''; |
||||
}; |
||||
|
||||
resolverName = mkOption { |
||||
default = "random"; |
||||
example = "dnscrypt.eu-nl"; |
||||
type = types.nullOr types.str; |
||||
description = '' |
||||
The name of the DNSCrypt resolver to use, taken from |
||||
<filename>${resolverList}</filename>. The default is to |
||||
pick a random non-logging resolver that supports DNSSEC. |
||||
''; |
||||
}; |
||||
|
||||
customResolver = mkOption { |
||||
default = null; |
||||
description = '' |
||||
Use an unlisted resolver (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 = "IP address"; |
||||
example = "208.67.220.220"; |
||||
}; |
||||
|
||||
port = mkOption { |
||||
type = types.int; |
||||
description = "Port"; |
||||
default = 443; |
||||
}; |
||||
|
||||
name = mkOption { |
||||
type = types.str; |
||||
description = "Fully qualified domain name"; |
||||
example = "2.dnscrypt-cert.example.com"; |
||||
}; |
||||
|
||||
key = mkOption { |
||||
type = types.str; |
||||
description = "Public key"; |
||||
example = "B735:1140:206F:225D:3E2B:D822:D7FD:691E:A1C3:3CC8:D666:8D0C:BE04:BFAB:CA43:FB79"; |
||||
}; |
||||
}; })); |
||||
}; |
||||
|
||||
extraArgs = mkOption { |
||||
default = []; |
||||
type = types.listOf types.str; |
||||
description = '' |
||||
Additional command-line arguments passed verbatim to the daemon. |
||||
See <citerefentry><refentrytitle>dnscrypt-proxy</refentrytitle> |
||||
<manvolnum>8</manvolnum></citerefentry> for details. |
||||
''; |
||||
example = [ "-X libdcplugin_example_cache.so,--min-ttl=60" ]; |
||||
}; |
||||
}; |
||||
}; |
||||
|
||||
config = mkIf cfg.enable (mkMerge [{ |
||||
assertions = [ |
||||
{ assertion = (cfg.customResolver != null) || (cfg.resolverName != null); |
||||
message = "please configure upstream DNSCrypt resolver"; |
||||
} |
||||
]; |
||||
|
||||
# make man 8 dnscrypt-proxy work |
||||
environment.systemPackages = [ pkgs.dnscrypt-proxy ]; |
||||
|
||||
users.users.dnscrypt-proxy = { |
||||
description = "dnscrypt-proxy daemon user"; |
||||
isSystemUser = true; |
||||
group = "dnscrypt-proxy"; |
||||
}; |
||||
users.groups.dnscrypt-proxy = {}; |
||||
|
||||
systemd.sockets.dnscrypt-proxy = { |
||||
description = "dnscrypt-proxy listening socket"; |
||||
documentation = [ "man:dnscrypt-proxy(8)" ]; |
||||
|
||||
wantedBy = [ "sockets.target" ]; |
||||
|
||||
socketConfig = { |
||||
ListenStream = localAddress; |
||||
ListenDatagram = localAddress; |
||||
}; |
||||
}; |
||||
|
||||
systemd.services.dnscrypt-proxy = { |
||||
description = "dnscrypt-proxy daemon"; |
||||
documentation = [ "man:dnscrypt-proxy(8)" ]; |
||||
|
||||
before = [ "nss-lookup.target" ]; |
||||
after = [ "network.target" ]; |
||||
requires = [ "dnscrypt-proxy.socket "]; |
||||
|
||||
serviceConfig = { |
||||
NonBlocking = "true"; |
||||
ExecStart = "${pkgs.dnscrypt-proxy}/bin/dnscrypt-proxy ${toString daemonArgs}"; |
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; |
||||
|
||||
User = "dnscrypt-proxy"; |
||||
|
||||
PrivateTmp = true; |
||||
PrivateDevices = true; |
||||
ProtectHome = true; |
||||
}; |
||||
}; |
||||
} |
||||
|
||||
(mkIf config.security.apparmor.enable { |
||||
systemd.services.dnscrypt-proxy.after = [ "apparmor.service" ]; |
||||
|
||||
security.apparmor.profiles = singleton (pkgs.writeText "apparmor-dnscrypt-proxy" '' |
||||
${pkgs.dnscrypt-proxy}/bin/dnscrypt-proxy { |
||||
/dev/null rw, |
||||
/dev/random r, |
||||
/dev/urandom r, |
||||
|
||||
/etc/passwd r, |
||||
/etc/group r, |
||||
${config.environment.etc."nsswitch.conf".source} r, |
||||
|
||||
${getLib pkgs.glibc}/lib/*.so mr, |
||||
${pkgs.tzdata}/share/zoneinfo/** r, |
||||
|
||||
network inet stream, |
||||
network inet6 stream, |
||||
network inet dgram, |
||||
network inet6 dgram, |
||||
|
||||
${getLib pkgs.dnscrypt-proxy}/lib/dnscrypt-proxy/libdcplugin*.so mr, |
||||
|
||||
${getLib pkgs.gcc.cc}/lib/libssp.so.* mr, |
||||
${getLib pkgs.libsodium}/lib/libsodium.so.* mr, |
||||
${getLib pkgs.systemd}/lib/libsystemd.so.* mr, |
||||
${getLib pkgs.utillinuxMinimal.out}/lib/libmount.so.* mr, |
||||
${getLib pkgs.utillinuxMinimal.out}/lib/libblkid.so.* mr, |
||||
${getLib pkgs.utillinuxMinimal.out}/lib/libuuid.so.* mr, |
||||
${getLib pkgs.xz}/lib/liblzma.so.* mr, |
||||
${getLib pkgs.libgcrypt}/lib/libgcrypt.so.* mr, |
||||
${getLib pkgs.libgpgerror}/lib/libgpg-error.so.* mr, |
||||
${getLib pkgs.libcap}/lib/libcap.so.* mr, |
||||
${getLib pkgs.lz4}/lib/liblz4.so.* mr, |
||||
${getLib pkgs.attr}/lib/libattr.so.* mr, # */ |
||||
|
||||
${resolverList} r, |
||||
|
||||
/run/systemd/notify rw, |
||||
} |
||||
''); |
||||
}) |
||||
|
||||
(mkIf useUpstreamResolverList { |
||||
systemd.services.init-dnscrypt-proxy-statedir = { |
||||
description = "Initialize dnscrypt-proxy state directory"; |
||||
|
||||
wantedBy = [ "dnscrypt-proxy.service" ]; |
||||
before = [ "dnscrypt-proxy.service" ]; |
||||
|
||||
script = '' |
||||
mkdir -pv ${stateDirectory} |
||||
chown -c dnscrypt-proxy:dnscrypt-proxy ${stateDirectory} |
||||
cp -uv \ |
||||
${pkgs.dnscrypt-proxy}/share/dnscrypt-proxy/dnscrypt-resolvers.csv \ |
||||
${stateDirectory} |
||||
''; |
||||
|
||||
serviceConfig = { |
||||
Type = "oneshot"; |
||||
RemainAfterExit = true; |
||||
}; |
||||
}; |
||||
|
||||
systemd.services.update-dnscrypt-resolvers = { |
||||
description = "Update list of DNSCrypt resolvers"; |
||||
|
||||
requires = [ "init-dnscrypt-proxy-statedir.service" ]; |
||||
after = [ "init-dnscrypt-proxy-statedir.service" ]; |
||||
|
||||
path = with pkgs; [ curl diffutils dnscrypt-proxy minisign ]; |
||||
script = '' |
||||
cd ${stateDirectory} |
||||
domain=raw.githubusercontent.com |
||||
get="curl -fSs --resolve $domain:443:$(hostip -r 8.8.8.8 $domain | head -1)" |
||||
$get -o dnscrypt-resolvers.csv.tmp \ |
||||
https://$domain/dyne/dnscrypt-proxy/master/dnscrypt-resolvers.csv |
||||
$get -o dnscrypt-resolvers.csv.minisig.tmp \ |
||||
https://$domain/dyne/dnscrypt-proxy/master/dnscrypt-resolvers.csv.minisig |
||||
mv dnscrypt-resolvers.csv.minisig{.tmp,} |
||||
if ! minisign -q -V -p ${upstreamResolverListPubKey} \ |
||||
-m dnscrypt-resolvers.csv.tmp -x dnscrypt-resolvers.csv.minisig ; then |
||||
echo "failed to verify resolver list!" >&2 |
||||
exit 1 |
||||
fi |
||||
[[ -f dnscrypt-resolvers.csv ]] && mv dnscrypt-resolvers.csv{,.old} |
||||
mv dnscrypt-resolvers.csv{.tmp,} |
||||
if cmp dnscrypt-resolvers.csv{,.old} ; then |
||||
echo "no change" |
||||
else |
||||
echo "resolver list updated" |
||||
fi |
||||
''; |
||||
|
||||
serviceConfig = { |
||||
PrivateTmp = true; |
||||
PrivateDevices = true; |
||||
ProtectHome = true; |
||||
ProtectSystem = "strict"; |
||||
ReadWritePaths = "${dirOf stateDirectory} ${stateDirectory}"; |
||||
SystemCallFilter = "~@mount"; |
||||
}; |
||||
}; |
||||
|
||||
systemd.timers.update-dnscrypt-resolvers = { |
||||
wantedBy = [ "timers.target" ]; |
||||
timerConfig = { |
||||
OnBootSec = "5min"; |
||||
OnUnitActiveSec = "6h"; |
||||
}; |
||||
}; |
||||
}) |
||||
]); |
||||
|
||||
imports = [ |
||||
(mkRenamedOptionModule [ "services" "dnscrypt-proxy" "port" ] [ "services" "dnscrypt-proxy" "localPort" ]) |
||||
|
||||
(mkChangedOptionModule |
||||
[ "services" "dnscrypt-proxy" "tcpOnly" ] |
||||
[ "services" "dnscrypt-proxy" "extraArgs" ] |
||||
(config: |
||||
let val = getAttrFromPath [ "services" "dnscrypt-proxy" "tcpOnly" ] config; in |
||||
optional val "-T")) |
||||
|
||||
(mkChangedOptionModule |
||||
[ "services" "dnscrypt-proxy" "ephemeralKeys" ] |
||||
[ "services" "dnscrypt-proxy" "extraArgs" ] |
||||
(config: |
||||
let val = getAttrFromPath [ "services" "dnscrypt-proxy" "ephemeralKeys" ] config; in |
||||
optional val "-E")) |
||||
|
||||
(mkRemovedOptionModule [ "services" "dnscrypt-proxy" "resolverList" ] '' |
||||
The current resolver listing from upstream is always used |
||||
unless a custom resolver is specified. |
||||
'') |
||||
]; |
||||
} |
@ -1,66 +0,0 @@ |
||||
<chapter xmlns="http://docbook.org/ns/docbook" |
||||
xmlns:xlink="http://www.w3.org/1999/xlink" |
||||
xmlns:xi="http://www.w3.org/2001/XInclude" |
||||
version="5.0" |
||||
xml:id="sec-dnscrypt-proxy"> |
||||
<title>DNSCrypt client proxy</title> |
||||
<para> |
||||
The DNSCrypt client proxy relays DNS queries to a DNSCrypt enabled upstream |
||||
resolver. The traffic between the client and the upstream resolver is |
||||
encrypted and authenticated, mitigating the risk of MITM attacks, DNS |
||||
poisoning attacks, and third-party snooping (assuming the upstream is |
||||
trustworthy). |
||||
</para> |
||||
<sect1 xml:id="sec-dnscrypt-proxy-configuration"> |
||||
<title>Basic configuration</title> |
||||
|
||||
<para> |
||||
To enable the client proxy, set |
||||
<programlisting> |
||||
<xref linkend="opt-services.dnscrypt-proxy.enable"/> = true; |
||||
</programlisting> |
||||
</para> |
||||
|
||||
<para> |
||||
Enabling the client proxy does not alter the system nameserver; to relay |
||||
local queries, prepend <literal>127.0.0.1</literal> to |
||||
<option>networking.nameservers</option>. |
||||
</para> |
||||
</sect1> |
||||
<sect1 xml:id="sec-dnscrypt-proxy-forwarder"> |
||||
<title>As a forwarder for another DNS client</title> |
||||
|
||||
<para> |
||||
To run the DNSCrypt proxy client as a forwarder for another DNS client, |
||||
change the default proxy listening port to a non-standard value and point |
||||
the other client to it: |
||||
<programlisting> |
||||
<xref linkend="opt-services.dnscrypt-proxy.localPort"/> = 43; |
||||
</programlisting> |
||||
</para> |
||||
|
||||
<sect2 xml:id="sec-dnscrypt-proxy-forwarder-dsnmasq"> |
||||
<title>dnsmasq</title> |
||||
<para> |
||||
<programlisting> |
||||
{ |
||||
<xref linkend="opt-services.dnsmasq.enable"/> = true; |
||||
<xref linkend="opt-services.dnsmasq.servers"/> = [ "127.0.0.1#43" ]; |
||||
} |
||||
</programlisting> |
||||
</para> |
||||
</sect2> |
||||
|
||||
<sect2 xml:id="sec-dnscrypt-proxy-forwarder-unbound"> |
||||
<title>unbound</title> |
||||
<para> |
||||
<programlisting> |
||||
{ |
||||
<xref linkend="opt-services.unbound.enable"/> = true; |
||||
<xref linkend="opt-services.unbound.forwardAddresses"/> = [ "127.0.0.1@43" ]; |
||||
} |
||||
</programlisting> |
||||
</para> |
||||
</sect2> |
||||
</sect1> |
||||
</chapter> |
@ -0,0 +1,61 @@ |
||||
{ config, lib, pkgs, ... }: with lib; |
||||
|
||||
let |
||||
cfg = config.services.dnscrypt-proxy2; |
||||
in |
||||
|
||||
{ |
||||
options.services.dnscrypt-proxy2 = { |
||||
enable = mkEnableOption "dnscrypt-proxy2"; |
||||
|
||||
settings = mkOption { |
||||
description = '' |
||||
Attrset that is converted and passed as TOML config file. |
||||
For available params, see: <link xlink:href="https://github.com/DNSCrypt/dnscrypt-proxy/blob/master/dnscrypt-proxy/example-dnscrypt-proxy.toml"/> |
||||
''; |
||||
example = literalExample '' |
||||
{ |
||||
sources.public-resolvers = { |
||||
urls = [ "https://download.dnscrypt.info/resolvers-list/v2/public-resolvers.md" ]; |
||||
cache_file = "public-resolvers.md"; |
||||
minisign_key = "RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3"; |
||||
refresh_delay = 72; |
||||
}; |
||||
} |
||||
''; |
||||
type = types.attrs; |
||||
default = {}; |
||||
}; |
||||
|
||||
configFile = mkOption { |
||||
description = '' |
||||
Path to TOML config file. See: <link xlink:href="https://github.com/DNSCrypt/dnscrypt-proxy/blob/master/dnscrypt-proxy/example-dnscrypt-proxy.toml"/> |
||||
If this option is set, it will override any configuration done in options.services.dnscrypt-proxy2.settings. |
||||
''; |
||||
example = "/etc/dnscrypt-proxy/dnscrypt-proxy.toml"; |
||||
type = types.path; |
||||
default = pkgs.runCommand "dnscrypt-proxy.toml" { |
||||
json = builtins.toJSON cfg.settings; |
||||
passAsFile = [ "json" ]; |
||||
} '' |
||||
${pkgs.remarshal}/bin/json2toml < $jsonPath > $out |
||||
''; |
||||
defaultText = literalExample "TOML file generated from services.dnscrypt-proxy2.settings"; |
||||
}; |
||||
}; |
||||
|
||||
config = mkIf cfg.enable { |
||||
|
||||
networking.nameservers = lib.mkDefault [ "127.0.0.1" ]; |
||||
|
||||
systemd.services.dnscrypt-proxy2 = { |
||||
after = [ "network.target" ]; |
||||
wantedBy = [ "multi-user.target" ]; |
||||
serviceConfig = { |
||||
AmbientCapabilities = "CAP_NET_BIND_SERVICE"; |
||||
DynamicUser = true; |
||||
ExecStart = "${pkgs.dnscrypt-proxy2}/bin/dnscrypt-proxy -config ${cfg.configFile}"; |
||||
}; |
||||
}; |
||||
}; |
||||
} |
Loading…
Reference in new issue