Encrypted DNS: Difference between revisions
imported>Valodim add more info about stubby |
m from `services.dnscrypt-proxy2` to `services.dnscrypt-proxy` https://search.nixos.org/options?channel=unstable&show=services.dnscrypt-proxy.configFile&query=dnscrypt-proxy |
||
(22 intermediate revisions by 16 users not shown) | |||
Line 3: | Line 3: | ||
'''Encrypted DNS''' protocols aim to address this hole by encrypting queries and responses in transit between DNS resolvers and clients; the most widely deployed ones are [[wikipedia:DNS over HTTPS|DNS over HTTPS]] (DoH), [[wikipedia:DNS over TLS|DNS over TLS]] (DoT), and [https://dnscrypt.info/ DNSCrypt]. | '''Encrypted DNS''' protocols aim to address this hole by encrypting queries and responses in transit between DNS resolvers and clients; the most widely deployed ones are [[wikipedia:DNS over HTTPS|DNS over HTTPS]] (DoH), [[wikipedia:DNS over TLS|DNS over TLS]] (DoT), and [https://dnscrypt.info/ DNSCrypt]. | ||
NixOS has modules for multiple encrypted DNS proxies, including [https://github.com/DNSCrypt/dnscrypt-proxy dnscrypt-proxy 2] and [https://dnsprivacy.org/wiki/display/DP/DNS+Privacy+Daemon+-+Stubby Stubby]. <code>services.dnscrypt- | NixOS has modules for multiple encrypted DNS proxies, including [https://github.com/DNSCrypt/dnscrypt-proxy dnscrypt-proxy 2], [https://github.com/AdguardTeam/dnsproxy dnsproxy] and [https://dnsprivacy.org/wiki/display/DP/DNS+Privacy+Daemon+-+Stubby Stubby]. <code>services.dnscrypt-proxy</code> is generally recommended, as it has the widest protocol and feature support, and is written in a memory-safe language. For DNS over TLS (DoT) support, <code>services.dnsproxy</code> can be used. Detailed comparison of DNS proxies can be found on [https://wiki.archlinux.org/title/Domain_name_resolution#DNS_servers ArchLinux Wiki]. | ||
== Setting nameservers == | == Setting nameservers == | ||
Line 12: | Line 12: | ||
{ | { | ||
networking = { | networking = { | ||
nameservers = [ "::1" ] | nameservers = [ "127.0.0.1" "::1" ]; | ||
# If using dhcpcd: | # If using dhcpcd: | ||
dhcpcd.extraConfig = "nohook resolv.conf"; | dhcpcd.extraConfig = "nohook resolv.conf"; | ||
Line 25: | Line 24: | ||
If you'd prefer to keep using resolvconf then you can set <code>networking.resolvconf.useLocalResolver</code> instead. Note that it uses the IPv4 loopback address only. | If you'd prefer to keep using resolvconf then you can set <code>networking.resolvconf.useLocalResolver</code> instead. Note that it uses the IPv4 loopback address only. | ||
== Secure DNS and Captive Portal == | |||
Secure DNS will break most captive portals like those of public or hotel wifi access points, resulting in inability to gain internet access through such access points. | |||
In that case, use <code>networkctl status ${wlan interface}</code> to show the default DNS provided by the network, and temporarily change nameserver inside <code>/etc/resolv.conf</code> from <code>127.0.0.53</code> to the provided one. | |||
Alternatively, if you have Chromium installed, you can use the <code>programs.captive-browser.enable</code> Chromium wrapper, which is "Dedicated Chrome instance to log into captive portals without messing with DNS settings". | |||
== dnscrypt-proxy2 == | == dnscrypt-proxy2 == | ||
=== | === Basic configuration === | ||
<syntaxhighlight lang="nixos"> | |||
<syntaxhighlight lang=" | let | ||
hasIPv6Internet = true; | |||
StateDirectory = "dnscrypt-proxy"; | |||
in | |||
{ | { | ||
services.dnscrypt- | # See https://wiki.nixos.org/wiki/Encrypted_DNS | ||
services.dnscrypt-proxy = { | |||
enable = true; | enable = true; | ||
# See https://github.com/DNSCrypt/dnscrypt-proxy/blob/master/dnscrypt-proxy/example-dnscrypt-proxy.toml | |||
settings = { | settings = { | ||
sources.public-resolvers = { | sources.public-resolvers = { | ||
urls = [ | urls = [ | ||
"https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/ | "https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/public-resolvers.md" | ||
"https://download.dnscrypt.info/resolvers-list/ | "https://download.dnscrypt.info/resolvers-list/v3/public-resolvers.md" | ||
]; | ]; | ||
minisign_key = "RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3"; # See https://github.com/DNSCrypt/dnscrypt-resolvers/blob/master/v3/public-resolvers.md | |||
cache_file = "/var/lib/${StateDirectory}/public-resolvers.md"; | |||
}; | }; | ||
# | # Use servers reachable over IPv6 -- Do not enable if you don't have IPv6 connectivity | ||
ipv6_servers = hasIPv6Internet; | |||
block_ipv6 = ! (hasIPv6Internet); | |||
require_dnssec = true; | |||
require_nolog = false; | |||
require_nofilter = true; | |||
# If you want, choose a specific set of servers that come from your sources. | |||
# Here it's from https://github.com/DNSCrypt/dnscrypt-resolvers/blob/master/v3/public-resolvers.md | |||
# If you don't specify any, dnscrypt-proxy will automatically rank servers | |||
# that match your criteria and choose the best one. | |||
# server_names = [ ... ]; | # server_names = [ ... ]; | ||
}; | }; | ||
}; | }; | ||
systemd.services.dnscrypt- | systemd.services.dnscrypt-proxy.serviceConfig.StateDirectory = StateDirectory; | ||
} | |||
</syntaxhighlight> | |||
See [https://github.com/DNSCrypt/dnscrypt-proxy/blob/master/dnscrypt-proxy/example-dnscrypt-proxy.toml the upstream example configuration file] for more configuration options. | |||
=== Blocklist === | |||
Fetch a blocklist file (e.g. oisd) as a flake input:<syntaxhighlight lang="nix"> | |||
# flake.nix | |||
{ | |||
inputs = { | |||
oisd = { | |||
url = "https://big.oisd.nl/domainswild"; | |||
flake = false; | |||
}; | |||
# Your configuration | |||
}; | }; | ||
outputs = | |||
{ self, nixpkgs, oisd, ... }@inputs: | |||
{ | |||
# Your configuration | |||
}; | |||
} | |||
</syntaxhighlight><syntaxhighlight lang="nixos"> | |||
{ config, lib, pkgs, inputs, ... }: | |||
let | |||
blocklist_base = builtins.readFile inputs.oisd; | |||
extraBlocklist = ''''; | |||
blocklist_txt = pkgs.writeText "blocklist.txt" '' | |||
${extraBlocklist} | |||
${blocklist_base} | |||
''; | |||
in | |||
{ | |||
services.dnscrypt-proxy.settings.blocked_names.blocked_names_file = blocklist_txt; | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Local network - Forwarding rules === | |||
Maybe you'd like queries for your local domain to go to your router, and not to an upstream DNS resolver. By doing so, names of your local online devices can be found. For this you have to create a file with [https://github.com/DNSCrypt/dnscrypt-proxy/blob/master/dnscrypt-proxy/example-forwarding-rules.txt forwarding rules] which you then include in your config: | |||
<syntaxhighlight lang="nix"> | |||
{ | |||
services.dnscrypt-proxy = { | |||
enable = true; | |||
settings = { | |||
... | |||
forwarding_rules = "/etc/nixos/services/networking/forwarding-rules.txt"; | |||
... | |||
}; | |||
}; | |||
.... | |||
} | |||
</syntaxhighlight> | |||
=== Using alongside another DNS server === | === Using alongside another DNS server === | ||
Line 68: | Line 142: | ||
networking.nameservers = [ "::1" ]; | networking.nameservers = [ "::1" ]; | ||
services.dnscrypt- | services.dnscrypt-proxy = { | ||
enable = true; | enable = true; | ||
settings = { | settings = { | ||
Line 89: | Line 163: | ||
Note that you can still access the other DNS server locally through the non-loopback interface (e.g. by using your server's external IP). | Note that you can still access the other DNS server locally through the non-loopback interface (e.g. by using your server's external IP). | ||
== dnsproxy == | |||
dnsproxy is a simple DNS proxy server with the widest protocol support. | |||
=== Example configuration === | |||
<syntaxhighlight lang="nix"> | |||
{ | |||
services.dnsproxy = { | |||
enable = true; | |||
settings = { | |||
# Plain DNS upstream | |||
upstream = [ "1.1.1.1:53" ]; | |||
# DNS over TLS upstream | |||
upstream = [ "tls://dns.adguard.com" ]; | |||
# DNS over HTTPS upstream | |||
upstream = [ "https://dns.adguard.com/dns-query" ]; | |||
listen-addrs = [ "0.0.0.0" ]; | |||
# Plain DNS server | |||
listen-ports = [ 53 ]; | |||
# DNS over TLS server | |||
tls-port = [ 853 ]; | |||
# DNS over HTTPS server | |||
https-port = [ 443 ]; | |||
# Certificate for encrypted DNS server | |||
tls-crt = "/var/lib/acme/example.org/fullchain.pem"; | |||
tls-key = "/var/lib/acme/example.org/key.pem"; | |||
}; | |||
# Additional launch flags | |||
flags = [ "--verbose" ]; | |||
}; | |||
} | |||
</syntaxhighlight> | |||
== Stubby == | == Stubby == | ||
Stubby is a very lightweight resolver (40kb binary) that performs DNS-over-TLS, and nothing else. While stubby can be used as a system resolver on its own, it is typically combined with another resolver (such as unbound) to add caching and forwarding rules for local domains. See the [https://nixos.org/ | Stubby is a very lightweight resolver (40kb binary) that performs DNS-over-TLS, and nothing else. While stubby can be used as a system resolver on its own, it is typically combined with another resolver (such as unbound) to add caching and forwarding rules for local domains. See the [https://search.nixos.org/options/?query=services.stubby options documentation for <code>services.stubby.*</code>] for configuration. | ||
Example configuration for Cloudflare. Note that digests change and need to be updated: | |||
<syntaxhighlight lang="nix"> | |||
{ | |||
services.stubby = { | |||
enable = true; | |||
settings = pkgs.stubby.passthru.settingsExample // { | |||
upstream_recursive_servers = [{ | |||
address_data = "1.1.1.1"; | |||
tls_auth_name = "cloudflare-dns.com"; | |||
tls_pubkey_pinset = [{ | |||
digest = "sha256"; | |||
value = "GP8Knf7qBae+aIfythytMbYnL+yowaWVeD6MoLHkVRg="; | |||
}]; | |||
} { | |||
address_data = "1.0.0.1"; | |||
tls_auth_name = "cloudflare-dns.com"; | |||
tls_pubkey_pinset = [{ | |||
digest = "sha256"; | |||
value = "GP8Knf7qBae+aIfythytMbYnL+yowaWVeD6MoLHkVRg="; | |||
}]; | |||
}]; | |||
}; | |||
}; | |||
} | |||
</syntaxhighlight> | |||
To update digests get the TLS certificate that signs the responses and calculate the digest: | |||
<syntaxhighlight lang="bash"> | |||
echo | openssl s_client -connect '1.1.1.1:853' 2>/dev/null | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64 | |||
</syntaxhighlight> | |||
Or using <code>kdig</code> from <code>knot-dns</code> | |||
<syntaxhighlight lang="bash"> | |||
kdig -d @1.1.1.1 +tls-ca +tls-host=one.one.one.one example.com | |||
</syntaxhighlight> | |||
[[Category:Networking]] | |||
[[Category:DNS]] |