The dnscache, tinydns, axfrdns, and walldns services

The Bernstein dnscache, tinydns, axfrdns, and walldns tools from djbdns can be run as services, and the proxy and content DNS services are preconfigured with certain defaults.

Ways to run the services

There are two ways in which these tools can be run as services.

One global instance each

The service bundles package comes with one predefined system-level service bundle for each of dnscache, tinydns, axfrdns, and walldns; and an associated service bundle for each of the associated log services cyclog@dnscache, cyclog@tinydns, cyclog@axfrdns, and cyclog@walldns. The external formats import subsystem enables these service bundles according to the usual presets such as a dnscache_enable="YES" flag in /etc/rc.conf.

These service bundles are configured in the conventional ways for djbdns services: variables named ROOT, IP, CACHESIZE and so forth stored in an environment variable directory in the conventional place for a service. These can be accessed and modified in the conventional ways:

The exceptions are:

In both cases this is because the run program is not a shell script and does not have shell variable expansion mechanisms for parameterizing what it passes to hardlimit and tcp-socket-listen. The axfrdns service uses ucspi-socket-rules-check, though, which is how one can arrange to restrict client access.

One generated instance per network address

For each of the network addresses listed as network_addresses in /etc/rc.conf the external formats import subsystem generates a dnscache@address, a axfrdns@address, and a tinydns@address service. If there are no network addresses, it generates dnscache@127.0.0.1, axfrdns@127.53.0.1, tinydns@127.53.0.1, and walldns@127.53.1.1.

This requires the modified dnscache and tinydns tools from djbwares, because service management arranges to pass in their listening socket(s), already opened and bound to address, as open file descriptors. The djbwares versions of the dnscache and tinydns tools have been enhanced to be capable of this (the former requiring two open file descriptors, one a TCP listening socket and one a UDP listening socket).

Again, the service bundles are configured in the conventional ways for djbdns services: variables in a conventionally-placed environment variable directory, read by envdir and understood by rcctl and other tools. However, the IP environment variables are ignored by the djbwares versions of the programs, when they find that they have been supplied the listening socket file descriptors already opened. The DATALIMIT variable is also ignored in favour of a hardwired hardlimit invocation.

The generated per-address services are set up to have their log outputs directed into the log services of the single global services.

The external formats import subsystem again enables these service bundles according to the usual presets, although a flag in /etc/rc.conf is less convenient than (say) a systemd-style preset file in /etc/system-control/presets/20-dns.preset containing:

enable dnscache@127.0.0.1
enable cyclog@dnscache
enable axfrdns@127.53.0.1
enable cyclog@axfrdns
enable tinydns@127.53.0.1
enable cyclog@tinydns
enable walldns@127.53.0.1
enable cyclog@walldns

Content server databases

By default, each tinydns service bundle is set up with its own private service/root directory, and each axfrdns is set up with its service/root symbolically linked to that. Each service/root directory contains an individual Makefile, data source file, and tools such as add-ns (which are short scripts that need Laurent Bercot's execlineb script interpreter). However, they can be pointed at shared databases in three simple ways, if one wants content served from a common shared database:

How and what one does in this area, and the tradeoffs and design decisions, are well beyond the scope of this Guide however.

Proxy server configuration

By default, each dnscache service bundle is set up with its own private service/root/ip and service/root/servers directories telling it whom to contact with back-end queries and whom to answer on the front end. It is a rare configuration where one wants to share these amongst multiple dnscache services, and usually one will not want to do so.

Note that service/seed files are not used by these services. A fresh seed is copied directly from /dev/urandom for every invocation of the dæmon and sent through a pipe from which it can only be read once. dnscache does not require seeds to remain the same from run to run of the server, and a seed in a file has to be (a) only readable by the superuser, (b) specifically not readable by the dnscache-d user, and (c) not shared amongst multiple dnscache services. This makes use of the pipe utility which can set up a pipeline with the main dæmon process as one of the elements of the pipe (something which cannot be done directly in shell script).

What one gets with the default setup

You do not have to turn anything else on if the content DNS server on 127.53.0.1 is the tinydns@127.53.0.1 service, the proxy DNS server on 127.0.0.1 is the dnscache@127.0.0.1 service, and your DNS client library defaults to contacting 127.0.0.1 for proxy DNS service.