DNS Architecture

This handbook is here to make sure that DNS-related knowledge and past evolutions will not be lost. The reference DNS architecture is described in the DNS blueprint.

DNS forwarding optimization

Because DNS metrics like the NXDOMAIN response rate is now monitored, we’ve discovered that the NSS resolver combined with dnsmasq is not optimal.

In fact, we’ve seen 2 main problems:

  1. Plain names (without dots) are forwarded by dnsmasq and the upstream DNS server always responds NXDOMAIN.

  2. When dnsmasq cache isn’t populated, most of queries are either NULL or NXDOMAIN ones.

  3. localhost like queries are forwarded

A typical query (getent hosts $HOST), with an empty dnsmasq cache, generates the following queries:

  • N AAAA queries where N is the number of domains to search ie. the number of domain names in search of resolv.conf.

  • 1 AAAA query for $HOST (which may be a plain name).

  • At most N A queries until the name is correctly resolved

And even with a populated cache, there is still a AAAA query if $HOST is a plain name.

PTR queries are correctly handled and forwarded if not present in cache.

Plain names

This a quick-win with dnsmasq’s domain-needed setting.

This setting tells dnsmasq to never forward A or AAAA for plain names (without dots or domain parts). If the name isn’t present locally, the NXDOMAIN is returned.

In the above query sequence, this setting prevent 1 query from being forwarded.

AAAA query filtering

AAAA filtering is quite a subject for glibc* guys or sysadmins. Currently, the glibc always do AAAA queries even is no IPv6 is available locally.

The only way to prevent AAAA queries to travel through the network is to filter them using a local DNS server. Thanks to Ocean’s architecture, all nodes have a local dnsmasq process that is the unique interface with upstream DNS server.

dnsmasq have a configuration subtility (not very well documented) that makes it possible.

The dnsmasq configuration (or command-line flags) allow 2 settings:

address=/<domain>/[domain/][<ipaddr>]

Specify an IP Address to return for any host in the given domain. If ipaddr is not present, it returns a NXDOMAIN for all name within that domains.

server=/[<domain>]/[domain/][<ipaddr>]

Note

For clarity, the option format has been simplified.

Specify the IP address of upstream servers for the given domains. If # is given as ipaddr, then the standard servers will be used.

The subtility comes when both options are applied on the same domain names like the following :

[...]
address=/some.domain.fr/
server=/some.domain.fr/#

According the source code comments (src/forward.c, v2.76 l.159), precedence between both options is done the following way:

/* implement priority rules for --address and --server for same domain.
--address wins if the address is for the correct AF
--server wins otherwise. */

The means that if a A query is done and upstream servers are addressed using IPv4 addresses then server wins. On the other side, is a AAAA query is done and upstream servers are addressed using IPv4 addresses then address wins.

Which is exactly what we want:

  • For AAAA, return NXDOMAIN

  • For A, use upstream servers

In the above query sequence, these settings prevents all AAAA queries from being forwarded.

The only couterpart is that we have to list all (sub-)domains names in dnsmasq configuration file.