Parallel DNS lookup using dnsmasq

Well up until now I did believe that a DNS query would cause all nameserver in /etc/resolv.conf to be queried in parallel and the first (and hence fastest) answer would be taken. Just noticed I’m wrong.

The manpage of resolv.conf states that „the algorithm used is to try a name server, and if the query times out, try the next, until out of name servers, then repeat trying all the name servers until a maximum number of retries are made.“. Which basically explains the following graph (secondary resolver on the right)

You may improve that by setting rotate as option which would spread queries in a round-robin fashion over the available nameserver. I am looking for something which would ask my resolvers in parallel (hence both will fill their cache) and the fastest response would be taken. So I do need a very lightweight DNS Forwarder/Proxy. I wish Unbound would offer that functionality – it doesn’t. Dnsmasq does.

Dnsmasq is really really simple to configure. Just edit your /etc/resolv.conf so that it contains

nameserver 127.0.0.1
nameserver your-resolver-1
nameserver your-resolver-2

Obviously replace your-resolver-X with the IPs of your resolvers. Dnsmasq is smart and detects:

May 28 14:28:24 janice dnsmasq[16889]: ignoring nameserver 127.0.0.1 - local interface

The default configuration of dnsmasq in Debian stretch is not so smart:

root@janice:~# dig jeanbruenn.info | grep ";; flags"
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

Noticed the missing ad-flag? Dnsmasq in its default configuration is not DNSSEC-aware. To enable it the configuration states to just uncomment:

# Uncomment these to enable DNSSEC validation and caching:
# (Requires dnsmasq to be built with DNSSEC option.)
#conf-file=%%PREFIX%%/share/dnsmasq/trust-anchors.conf
#dnssec

Probably they should have explained that you have to replace %%PREFIX%% (more likely this is a bug). Dnsmasq won’t start if you simple uncomment that. The proper lines are:

conf-file=/usr/share/dnsmasq-base/trust-anchors.conf
dnssec

Now restart dnsmasq and test again:

root@janice:~# dig jeanbruenn.info | grep ";; flags"
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

There we go – the ad-flag is set. Another test to verify DNSSEC is working:

root@janice:~# dig dnssec-failed.org 
 
; <<>> DiG 9.10.3-P4-Debian <<>> dnssec-failed.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 46356
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
 
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;dnssec-failed.org.		IN	A
 
;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sun May 28 14:38:26 CEST 2017
;; MSG SIZE  rcvd: 46

the SERVFAIL indicates it does work as expected. However. This is not enough to get Dnsmasq to make parallel requests. For that you do need to enable –all-servers. You can do so by editing /etc/default/dnsmasq and adding –all-servers to DNSMASQ_OPTS like so:

DNSMASQ_OPTS="--all-servers"

Starts looking differently:

Mind that the upstream servers I am forwarding to are my own resolvers and not public ones.

No Comments

Post a Comment