Name

djbdns-client — configuring the DNS client in djbdns

Description

The DNS client library common to all djbwares utilities is centred upon a dns_resolve() function. Like other DNS client libraries, it talks to one or more (local) proxy DNS servers, which do most of the actual lookup work. Several domain names are handled by the library internally, however, without contacting any servers at all.

There are separate DNS server configuration settings for:

  • DNS-SD lookups under service.arpa., per RFC 9665;

  • onion. lookups, per RFC 7686;

  • mDNS lookups under local. and several subdomains of ip-addr.arpa. and ip6.arpa. corresponding to link-local IP addresses, per RFC 8375;

  • homenet lookups under home.arpa., per RFC 8375; and

  • regular lookups, for everything else.

There is also a name qualification procedure that some tools apply to some input names before performing the name lookups proper.

Note

Generally, debugging tools do not apply qualification to the domain names that they are given to perform lookups on, but non-debugging utilities apply name qualification.

Short circuits and internally synthesized answers

If the input string to be passed through name qualification is the human-readable form of an IP address, the DNS client simply synthesizes and returns corresponding A and AAAA resource records (and empty resource record sets for other types) without performing any name qualification or lookups. This is designed to accommodate a common mis-usage where people supply human-readable form IP addresses where domain names should be supplied. Renormalization is performed, so leading zeroes are discarded; but numeric values that are not legal for an IP address mean that the string will not take this short circuit synthesis route.

Note

dnscache(1) also filters queries for such errors, but the DNS client library tries not to send such queries in the first place.

Note

IP version 6 addresses are currently not recognized in abbreviated form. ::1 is not taken to be a human-readable form of an IP version 6 address, for example. It must be spelled out in full as the single-label pseudo domain name 0:0:0:0:0:0:0:1.

Historic mis-behaviour

Caution

In the original Bernstein DNS client library, if the input string was to be passed through name qualification, and was an arbitrary length string of arbitrary valued dot-separated numbers it would be converted, without any name qualification or lookups being performed, into possibly more than 1 IPv4 address, not caring about numeric overflow or values larger than 256, and not caring about partially-complete addresses. This wholly undocumented mechanism would lead to stupid consequences and real-world risks such as:

  • the domain name 6.2.8.2.999999999999 apparently existing and having an IPv4 address,

  • the domain name 24.75.345.200 (from a Sandra Bullock movie in the 1990s) apparently existing and having someone's real (and not reserved-use) IPv4 address, and

  • the domain name 1729.86400.99999.2147483647.100000000.10000000.10000000.10000000 apparently existing and having two IPv4 addresses.

This undocumented behaviour, that for one thing would make the deliberately invalid or malformed IPv4 addresses used in movies and television dramas work and have surprising consequences for unsuspecting people who just happened to be assigned the real IP addresses, is not present in this version of the DNS client library.

After name qualification

When name qualification is used, various queries have directly synthesized answers created by the DNS client library itself, short-circuiting any query to a proxy DNS server.

Per RFC 7686, if there are no configured onion. proxy DNS servers, onion. and all of its subdomains are synthetic "no such domain" errors. Per RFC 6761, invalid. and all of its subdomains are synthetic "no such domain" errors.

Per the implication of RFC 6761 and long-standing /etc/hosts convention, reverse lookups of 127.a.b.c IPv4 addresses map to c.b.a.127.localhost., except that 127.0.0.1 maps to localhost.. Likewise, reverse lookups of the ::1 IPv6 address map to localhost.. In the forward direction, A and AAAA lookups of localhost. map to 127.0.0.1 and ::1 respectively, and A and AAAA lookups of c.b.a.127.localhost. map to 127.a.b.c and ::FFFF:127.a.b.c respectively.

Per RFC 8880, ipv4only.arpa. exists synthetically with the fixed IPv4 addresses 192.0.0.170 and 192.0.0.171, reverse lookups of those IPv4 addresses synthetically map back to it, and all of its subdomains are synthetic "no such domain" errors. NAT64 prefix discovery is supposed not to be using this DNS client library.

Note

dnscache(1) and walldns(1)also synthesize data for some of these domain names. But what answers a proxy DNS server can synthesize are different to what answers a content DNS server can synthesize and different to what answers a DNS client library can synthesize. Many "special-use domain names" have different rules for all three.

Location of the proxy DNS servers

The IP addresses of the one or more proxy DNS servers are determined as follows:

  1. The primary configuration setting is the process environment of whatever tool is running. The values of two environment variables are taken to be a list of whitespace-separated IP addresses and a numeric port number:

    DNSCACHEIP_DNSSD and DNSCACHEPORT_DNSSD

    the proxy DNS server(s) used for DNS Service Discovery

    DNSCACHEIP_HOME and DNSCACHEPORT_HOME

    the proxy DNS server(s) used for homenet

    DNSCACHEIP_ONION and DNSCACHEPORT_ONION

    the proxy DNS server(s) used for onion.

    DNSCACHEIP_MDNS and DNSCACHEPORT_MDNS

    the proxy DNS server(s) used for multicast DNS

    DNSCACHEIP and DNSCACHEPORT

    the regular proxy DNS server(s) used for everything else

  2. If this environment variable is not found, the library falls back to resolv.conf(5). The values of various directives are likewise taken to be a list of whitespace-separated IP addresses.

    nameserver-dnssd

    the proxy DNS server(s) used for DNS Service Discovery

    nameserver-home

    the proxy DNS server(s) used for homenet

    nameserver-onion

    the proxy DNS server(s) used for onion.

    nameserver-mdns

    the proxy DNS server(s) used for multicast DNS

    nameserver

    the regular proxy DNS server(s) used for everything else

    Note

    All other configuration settings in resolv.conf(5) are ignored. This is a compatibility configuration mechanism only.

    Note

    Several of these are extensions to the conventional resolv.conf(5) as used by ISC's BIND DNS client library.
  3. If no other configuration is specified, the library falls back to hardwired default IP address of 127.0.0.1 and ::1 for everything except for mDNS for which the hardwired defaults are 224.0.0.251 and FF02::FB. This is the same fallback as other DNS client libraries, and running an instance of dnscache(1) listening on either 127.0.0.1 or ::1 is a conventional system configuration.

Name qualification

Several tools pass input strings through a name qualification phase before performing lookups with the dns_resolve() function. The name qualification procedure is the simple iterative application of a set of string matching and replacement rules.

Construction of the ruleset

The ruleset is determined as follows:

  1. The primary configuration setting is the process environment of whatever tool is running. The value of the DNSREWRITEFILE environment variable is taken to be the name of a file from which rewrite rules are read.

  2. If this environment variable is not found, the library falls back to /etc/dnsrewrite as the name of the file.

  3. If the rules file is not found, the library falls back to the LOCALDOMAIN environment variable. If it exists, its value is used to synthesize rules. Its value is treated as a whitespace-separated list of domains and is turned into a ?:.domain+.domain rewrite rule with the domains separated by +. A final *.: rule is appended.

  4. If neither the rules file nor the LOCALDOMAIN environment variable are found, the library falls back to resolv.conf(5) and synthesizes rules from its directives. The first search or a domain directive followed by a whitespace-separated list of domains is turned into a ?:.domain+.domain rewrite rule with the domains separated by +. A final *.: rule is appended.

    Note

    All other configuration settings in resolv.conf(5) are ignored. This is a compatibility configuration mechanism only.
  5. If not even a suitable directive in resolv.conf(5) is found, the library falls back on the result of the operating system's gethostname(2) library function. A ?:.domain rewrite rule is synthesized where domain is the part of the (dynamic) hostname that follows the first dot. A final *.: rule is appended.

Syntax of rewrite rules

Rules comprise a single leading character, then a match, a :, and a replacement.

=match:replacement

An exact match rule and complete replacement rule. If the input string exactly matches match then the replacement is substituted.

-match:replacement

A suffix match and complete replacement rule. If a suffix of the input string exactly matches match then the replacement is substituted.

*match:replacement

An unconstrained suffix match and suffix replacement rule. If a suffix of the input string exactly matches match then the replacement is suffixed instead to the non-matching prefix part of the input string.

?match:replacements

A constrained suffix match and suffix replacement rule. If a suffix of the input string exactly matches match and the remaining prefix does not contain a dot, then the replacement is suffixed instead to the non-matching prefix part of the input string.

If the resultant string, after applying all of the rules, contains + characters, it is deemed to be a search path of the form prefix+suffix+suffix. A search path list of names to try looking up is constructed by each suffix in order being appended to prefix

Examples

A common final rule in a ruleset.
*.:

This simply removes trailing dots. The djbwares DNS client library does not need the trailing dots after qualification, as the output, search path, list of one or more names is taken to be the "fully-qualified" name(s) to actually look up.

A simple 1-result qualification for dot-less names.
?:.example.org

If the input string is curtin, the resultant name is curtin.example.org. But this rule will not apply if the input string is saint.james or curtin..

Note

This is the search path behaviour that some users expect, and is thus the form into which the LOCALDOMAIN environment variable and search directives in resolv.conf(5) are converted when they have 1 entry, even though it is not actually traditional DNS client library behaviour.
A search path for dot-less names.
?:.intranet.example.org+.example.org+

If the input string is curtin, the resultant search list is curtin.intranet.example.org then curtin.example.org then curtin. But this rule will not apply if the input string is saint.james or curtin..

Note

This rule yields the bogus top-level domain curtin if the input string is curtin, which is one way in which the world often generates bogus query traffic to the "." content DNS servers (or, worse, happens to match one of the lesser-known global top-level domains unexpectedly).

Converting the LOCALDOMAIN environment variable and search directives in resolv.conf(5) when they have more than 1 entry does not append an extra final blank search path beyond the search path that is given. But, rather, it yields the form:

?:.intranet.example.org+.example.org

If the input string is curtin, the resultant search list is curtin.intranet.example.org then curtin.example.org.

Caution

Search paths with more than 1 entry are usually poor ideas, as they lead to finding names in subdomains or superdomains that can surprise users. Users generally expect 1 domain name as the single domain name that is appended by name qualification.
A search path for any names (dots or no) that searches multiple parts of an organization.
*:.work.example.org+.school.example.org+

If the input string is curtin, the resultant search list is curtin.work.example.org then curtin.school.example.org then curtin. If the input string is saint.james, the resultant search list is saint.james.work.example.org then saint.james.school.example.org then saint.james.

Caution

There is a common misconception amongst users that names that have an internal dot, rather than a trailing dot, are "fully qualified"; even though this has not in fact traditionally been the case, and (rather) this form of search path is in fact how other DNS client libraries traditionally worked for many years. Such users will be surprised by example.com becoming example.com.work.example.org and example.com.school.example.org here before example.com is finally tried.

Caution

This rule is also applied if the input string is saint.james. or curtin., which definitely surprises many users, even the ones that thought that they knew to use trailing dots.

In general, despite being the traditional DNS client library behaviour of yore, this is almost never a good rule.

A superdomain rename for subdomain names with and without dots.
*.example.org:.example.net

If the input string is saint.james.example.org, the resultant name is saint.james.example.net. However, if the input string is saint.james.example.org., this rule does not apply, following the usual convention that a trailing dot indicates an already qualified name.

Note

Matching commonly happens at a dot as in this example, but does not actually have to.
A collapse of all subdomains onto a single name.
-.example.com:example.com

If the input string is smith.example.com or meyers.example.com, the resultant name is simply example.com. Again however, if the input string is instead smith.example.com. or meyers.example.com., this rule does not apply, following the usual convention. The input string example.com sans any subdomain is also not matched by this rule; a separate extra = rule being necessary for that if appropriate.

The most common real world use for this are the subdomains of localhost. and of invalid. all being their equivalents.

-.localhost:localhost
-.invalid:invalid

But those are already special-use domain names handled by the DNS client library.

See also

dnsq(1)
dnsqr(1)
dnsip(1)
dnsmx(1)
dnsname(1)
dnsnamex(1)
dnsns(1)
dnstxt(1)
dnsipq(1)
host(1)

History

The DNSCACHEIP, DNSREWRITEFILE, and LOCALDOMAIN environment variables and limited compatibililty processing of resolv.conf(5) were originally part of Daniel J. Bernstein's djbdns toolset, begun in 1999.

At the time, many of the additional systems and special-use domain names had not even been invented. The formal documentation of conventional DNS results for subdomains of localhost. and invalid. did not occur until 2013, for instance.

The additional environment variables and mechanisms for special-use domain names were added in 2025.

The caution against using search paths is also Bernstein's, and remains as true today as it did then.

Author

Original code by Daniel J. Bernstein. Documentation and modernizations by Jonathan de Boyne Pollard.