Fend yourself against pervasive monitoring, response manipulation1 and at best ISPs selling your nameserver usage data. As the Let's Encrypt programme, the DnsPrivacy initiative offers to fill a gaping hole. There are different approaches that will probably coexist and each have pros and cons. One of the DoT developers gives an excellent introduction in her talk(slides) from IETF99. It also discusses rfc 7626, a short document outlining the privacy risks associated with DNS traffic. The DoH outlook is an interesting read and somebody said "Resolverless DNS"2. To follow the DPRIVE ietf working group will keep you updated. As it is only a simple change in a mostly vanilla OpenWrt, I opted for DNS-over-TLS.
In a first step we tell dnsmasq to not query the ISP nameservers anymore. Instead it will relay to stubby and its getdns utility, forwarding the query to one of the configured nameservers capable of transport encryption3.
Somebody did the work and stubby for OpenWrt (even with
uci, thanks!). Consult the readme and decide what options you want to set, balancing privacy and speed.
opkg install stubby opkg install getdns opkg install ca-certificates
Depending if you already use libopenssl and ca-certificates, this will use 400 - 1600 KB.
/etc/config/dhcp add the stubby port you will forward to and edit the resolvfile, then restart dnsmasq. Make sure to have only 127.0.0.1 in the given resolvfile or use
option noresolv '1'.
config dnsmasq ... option resolvfile '/etc/resolv.conf' list server '127.0.0.1#5453'
/etc/config/stubby check tls_authentication to be required with no transport fallback to anything else than tls.
config stubby 'global' list dns_transport 'GETDNS_TRANSPORT_TLS' option tls_authentication '1'
If you want to use this feature, you have to install
dnsmasq-full to do validation. The
proxy-dnssec config flag can reply to validating clients downstream without doing it itself though. Remember: your dnsclient (in every system) has to do validation too, or the BOGUS reply by a validating forwarder upstream will be taken for a proper return. I don't conceptionally understand yet why I can't configure stubby or dnsmasq return an error to dnssec-incapable clients when the validation fails.
config stubby 'global' option dnssec_return_status '1' option dnssec_trust_anchors '/var/lib/stubby/getdns-root.key'
config dnsmasq option dnssec '1' option dnsseccheckunsigned '1' # some perf penalty on this
I'm not sure if a small router CPUs openssl speed is a major parameter in latency, or if it's just the additional network packets.
To use DoT servers close to you, check the network path and latency with
mtr. It won't say how quickly your queries will be answered though on average. The servers are listed online and in
/etc/stubby/stubby.yml.default. Globally, Cloudflare is often close and would be an easy config, but as nonprofit and EU-based nameservers are within 25-35 ms for me, I went with
dot.securedns.eu (privately run) and
getdnsapi.net (NLlabs). Of the nameservers that are closer, digitalcourage.de has DoT planned for rollout soon, as250.net has it on their roadmap and from dnscache.berlin.ccc.de I haven't heard back yet.
Randomization of queries is another concern, but for now I checked latency only. When I couldn't explain some slow queries I even disabled roundrobin temporarily until I can benchmark this better (because of TLS negotiation? the nameserver didn't have the domain cached? DNSSEC validation?). With roundrobin disabled, stubby will use a nameserver until it gets unavailable.
config stubby 'global' option round_robin_upstreams '1'
# check on tls pubkey pinset: # echo | openssl s_client -connect $ip:$port -servername $domain 2>/dev/null \| # openssl x509 -pubkey -noout | openssl pkey -pubin -outform der \| # openssl dgst -sha256 -binary | openssl enc -base64 # DIGITALCOURAGE config resolver option address '184.108.40.206' option tls_auth_name 'dns2.digitalcourage.de' #list spki 'sha256/v7rm6OtQQD3x/wbsdHDZjiDg+utMZvnoX3jq3Vi8tGU=' # SECUREDNS config resolver option address '220.127.116.11' option tls_auth_name 'dot.securedns.eu' #list spki 'sha256/h3mufC43MEqRD6uE4lz6gAgULZ5/riqH/E+U+jE3H8g=' # GETDNSAPI config resolver option address '18.104.22.168' option tls_auth_name 'getdnsapi.net' #list spki 'sha256/foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9Q='
Reload stubby and dnsmasq
/etc/init.d/stubby reload /etc/init.d/dnsmasq reload
That's it, almost no5 DNS related plaintext data going through your uplink anymore. Though this moves the trust to another upstream to neither leak, log or even sell the query data, it's a conscious decision which nameservers you trust, the address is now verified, queries not easily seen and DNSSEC signature checked at your local device too. I recommend to set it up on any mobile device6. Your general network activity is still visible, only a VPN or similar can help to move the exit point of that metadata.
Preliminary tests with dnsdiag show a delay of 40+ ms for DNSSEC enabled TLS queries to 22.214.171.124, ~15 ms total without DNSSEC - the others are udp dns queries, no DNSSEC. Run with
dnseval.py -f resolv.conf -c 100 old.reddit.com (pipenv helps with dnseval install).
Global lists do not help too much, check your network path and make your own observations about availability.
To have a historical look at timestamps and delays, I temporarily run dnsmasq with logging when diagnosing latencies. Those can be seen via
/etc/dnsmasq.conf: log-queries=extra log-async=20 dnssec-debug
stubby itself has a logging mode (-l), and brings along its query tool, have a look at its options (-h)
stubby -C /etc/stubby/stubby.yml -l getdns_query @126.96.36.199 +dnssec_return_all_statuses www.sinodun.com a
See which resolver you're currently using
dig -t txt resolver.dnscrypt.info # or nslookup -type=TXT resolver.dnscrypt.info
if bind-dig is compiled with -DDIG_SIGCHASE it can do dnssec validation
dig +dnssec +sigchase -t a dnssec-failed.org @127.0.0.1
test online or use their instructions, but make sure if to enable validation on your machine too
nslookup sigok.verteiltesysteme.net 127.0.0.1 # should return A record nslookup sigfail.verteiltesysteme.net 127.0.0.1 # should return SERVFAIL
killall -s SIGUSR1 dnsmasq ... cache size 150, 364/2744 cache insertions re-used unexpired cache entries.
there's a CHAOS query class? dnsmasqs manual page has it, querying for stats:
for domain in cachesize.bind insertions.bind evictions.bind misses.bind hits.bind auth.bind servers.bind; do echo -n "$type: "; dig +short -c CHAOS -t TXT $domain; done
Doing your own recursive DNS querying and caching is another topic. You'll lose "hiding" behind a DNS used by many and its caching pool for quick anwers. If the TLD zone and authorative nameservers do not offer transport encryption your queries are again in the open for "Eve". But you can configure options like QNAME minimisation to avoid data leakage to nameservers before the authorative. I wonder to which degree query times increase, as without prefetching your own resolver will have an unfilled cache. Another addition could be to serve the root-zones yourself (rfc7706), but this will only spare you the first in at least three hops. An AXFR for a complete TLD zone could help skip the second too. Somehow "subscribing" to prefered domains, but this is as far as I know not on the horizon.
ObliviousDNS tries to decouple "Who is asking?" from "What is queried for?". Though keep in mind: after the name resolution, subsequent traffic will give a passive global eavesdropper metadata anyway. Using transport encryption for more protocols aims at raising costs for "Eve" as DNS today is still too cheap to mine.
Further Funcionality and Links
- use pi-holes FTLDNS for blocking before handing to dnsmasq, or use an adblocking DNS upstream as as250.net offers one
- though dnsmasq can use a larger "cache-size" too, Unbound has more knobs, can do DoT and blocklists
- beyond the scope of "DNS Privacy" but nonetheless relevant, the The DNS Camel talk laments how rising complexity in DNS makes the standards body loosing touch with the practioneers
on a tangent: there was the convergence.io(2011) effort, implemented as browser extension. "Do other persons get the same (SSL certificate)/answer that I do?". I think this was a interesting approach opposite hierachical trust models (CAs) and it was usable for https for quite some time ↩
to get to captive portals, you might have to disable custom nameservers temporarily ↩