You've come to this page as a result of a question similar to the following:
What are the known problems with Dan Bernstein's djbdns?
This is the Frequently Given Answer to that question.
As of version 1.05, there are various problems with djbdns:
The patches fixing these problems, hyperlinked-to here, are all incorporated into the djbwares packages.
None of these problems are security problems. You won't be able to claim a reward by reporting them. djbdns may be doing the wrong things, but it isn't exposing a security vulnerability as a result.
Ironically, although there are a handful of vociferous people who like to propagate various myths about djbdns, in the several years that it has been published none of those people has spotted any of these actual problems with djbdns. ( But then these problems are only discovered through experience of using the package, whereas several of the myths are so obviously wrong that they can only be believed by those who haven't even read the documentation, let alone actually obtained and used the software. )
Stock djbdns fails to build (with an error at the link stage complaining about an undefined reference to the symbol errno
) when using modern versions of GNU's C library.
This is because it contains a programming error that was pointed out and described in detail back in July 2001.
It assumes something that has never been true for Standard C, even at its inception in 1989.
Heretofore, djbdns has only built successfully because Unix and Linux C implementations accidentally happen to work the way that it needs them to.
But now, they do not.
This programming error is prevalent throughout all of Dan Bernstein's softwares. The same bug occurs in qmail and in daemontools, for example.
Mate Weirdl published patches that correct this error for many of Dan Bernstein's softwares, including djbdns, on his FTP site.
Shantanu completed the job, and in 2003 published a set of patches for correcting this error in all of Dan Bernstein's softwares, on his web site. (Unfortunately, now, both <URL:http://tyskyshop.com./patches/patches.html> and <URL:http://www.shantanu.cjb.net./> no longer point to Shantanu's web site and Shantanu himself has disappeared.)
Stock tinydns-data doesn't handle semantic errors in its input:
Location codes are silently truncated to their first 2 characters. Forgetting the ':' in a '%' line is a common error, that goes undetected because of this. tinydns-data treats the entire line as a location code with no IP address prefix, and silently truncates it to 2 characters. This can result in "internal" records being published to the outside world.
Characters in TTL values that are not decimal digit characters cause the remainder of the TTL field from that point onwards to be silently ignored. Accidentally inserting an extra ':' before a TTL is a common error that goes undetected because of this. tinydns-data silently uses the default TTL, and the TTL field is transposed to the timestamp. Accidentally using non-digit characters in a TTL is another common error that goes undetected because of this. tinydns-data silently ignores the field contents from that point onwards, and either the record ends up with a TTL different to what the administrator intended or the record ends up with a "time to die" unexpectedly.
Characters in timestamps that are not lowercase hexadecimal characters are treated as though they were the '0' character. Forgetting the extra ':' before a location code, when the timestamp field is intended to be empty, is a common error, that goes undetected because of this. tinydns-data silently parses what is intended to be location code as a timestamp with the value zero, and the record ends up with no location code. This can result in "internal" records being published to the outside world. Using uppercase hexadecimal characters in a timestamp is another common error, that goes undetected because of this. tinydns-data silently converts the uppercase characters to zeroes, and the value of the timestamp that is actually used is not what the administrator intended.
Timestamps are silently truncated to their first 16 characters. Accidentally typing one too many '0' characters when transcribing a timestamp is a common error, that goes undetected because of this. tinydns-data silently truncates the timestamp after the 16th character, and the actual value of the timestamp is not what the administrator intended.
If the second field of a '.', '&', or '@' record does not contain an IP address, tinydns-data simply ignores the bogus value. Forgetting the extra ':' in a '.', '&', or '@' line, where one wants the IP address field to be empty, is a common error that goes undetected because of this. Instead, surprising data end up being published because the various values are in the wrong fields.
If the second field of a '+' or '=' record is omitted, tinydns-data simply ignores the entire line and no data end up being published. A '+' or '=' line with no IP address makes no sense. Yet this error goes undetected.
This patch fixes all of these problems.
According to the algorithm in RFC 1034 § 4.3.2, a content DNS server must search for a "CNAME" resource record for the domain name being queried, and if it finds one it must substitute the domain name from the data portion, add the resource record to the answer section of the response, and restart processing.
Other content DNS server softwares all do this. ISC's BIND does. Microsoft's DNS server does.
But tinydns and axfrdns don't do this.
Instead, tinydns and axfrdns add the resource record and finish. The result is that instead of publishing a complete answer, comprising the entire alias chain and then the resource record set for the eventual target domain name, they publish a partial answer, comprising just the first link in the alias chain and then a referral. tinydns and axfrdns think that they are publishing authority data about the "CNAME" resource record. But in fact, according to the rules in RFC 2308 § 2.1, what they are publishing is properly interpreted as an alias chain ending with a referral.
Furthermore, and somewhat ironically, because tinydns and axfrdns think that they are publishing authority data, the delegation information in the referral is for the query domain itself or for some enclosing superdomain. In most cases, this is either a referral that is outside of the bailiwick for the content DNS server or a referral from that server back to itself. Resolving proxy DNS servers regard both kinds of referral as indications of a "lame server". Some resolving proxy DNS servers will mark "lame" content DNS servers as bad and try not to talk to them for a period. (dnscache does this. However, to additionally compound the irony, it contains a bug in its response handling whereby it doesn't properly detect lame referrals in the presence of client-side aliases, and so completely masks this problem. Other resolving proxy DNS server softwares correctly note tinydns+axfrdns servers as being "lame", however; albeit that BIND specifically recognises this particular error and logs it under its own heading as a "dangling CNAME pointer".)
Example 1:
Consider tinydns and axfrdns serving up the DNS database
and responding to an "A" query for "test.cname.example".
.example: Ctest.cname.example:target.cname.exampleThe correct response is a type 2 response from RFC 2308 § 2.1, giving the alias for "test.cname.example" and with the "no such name" error code indicating, as RFC 2308 § 2.1 says, that "target.cname.example" does not exist:
1 test.cname.example: 107 bytes, 1+1+1+0 records, response, authoritative, nxdomain query: 1 test.cname.example answer: test.cname.example 86400 CNAME target.cname.example authority: example 2560 SOA ns.example hostmaster.example 1057502685 16384 2048 1048576 2560And, indeed, that is the response that other content DNS server softwares all give (when provided with equivalent DNS database content). With the patch applied, tinydns and axfrdns do so too.
Uncorrected, however, the response published by tinydns and axfrdns is:
1 test.cname.example: 74 bytes, 1+1+1+0 records, response, authoritative, noerror query: 1 test.cname.example answer: test.cname.example 86400 CNAME target.cname.example authority: example 259200 NS ns.exampleThis response means something entirely different. It is a referral response from RFC 2308 § 2, giving the alias for "test.cname.example" as before and a referral (which is, of course, a lame self-referral) for "example.".
Example 2:
Run
to see stock tinydns following its incorrect algorithm.
dnsq a cname.ketil.froyn.name a.ns.ketil.froyn.name.Run
to see several content DNS servers, running other content DNS server softwares, following the correct algorithm.
dnsq a ia.imdb.com. dns1.imdb.com. dnsq a visit.geocities.com. ns1.yahoo.com. dnsq a www.likesystems.com. ns1.granitecanyon.com. dnsq a www.idi.oclc.org. ns2.opentext.com.
The reason that tinydns and axfrdns do what they do appears to stem from a false taxonomy of DNS responses. Whilst a resolving proxy DNS server is free to choose to ignore everything in a response apart from the first link in the chain of client-side aliases, that is not what the response is deemed to actually contain. The algorithm in RFC 1034 and the response taxonomy in RFC 2308 both agree that a response contains a chain of client-side aliases followed by the information (an error, a referral, or a resource record set) for the name at the end of the chain.
This patch fixes this problem.
Stock dnscache has lots of problems with client-side aliases:
No "CNAME" resource record sets are cached at all. Every "CNAME" query from a client thus results in a back-end "CNAME" query being sent to content DNS servers. In an environment that generates lots of "CNAME" queries, such as qmail after having been patched to remove the workaround for a BIND version 4 problem, all of those queries will pass straight through the cache, even if they are querying the same data repeatedly (as happens with qmail-remote performing parallel deliveries of multiple messages to a single domain, for example).
Even were "CNAME" resource record sets to be cached, dnscache crashes if there is a cached "CNAME" resource record set that happens to be empty (which will happen if an explicit "CNAME" query is made against a domain name that has no client-side aliases and a later query is made against that same domain name).
A client-side alias will result in the issuance of further back-end queries for the second and subsequent links in a client-side alias chain, and for the data for the target domain name, even though all of those data might well have been in the response that dnscache already had and the query traffic thus entirely unnecessary.
No information received from lame servers is cached, even if it happens to be in-bailiwick information that might be useful for freshening the cache.
Because not caching information received from lame servers would reveal the problems caused by an error in tinydns, dnscache contains a bodge to prevent lame servers from being correctly recognised as such in certain situations. A lame delegation is not noticed if it is present at the end of a chain of client-side aliases. Lame delegations are only noticed if there are no client-side aliases in a response.
This patch fixes all of these problems.
On 2002-11, 21 months after the release of version 1.05 of djbdns, ICANN changed the IP address of one of its "." content DNS servers from 198.41.0.10 to 192.58.128.30. As of 2003-05, and "for the forseeable future" (to quote the ICANN announcement), the two content DNS servers are running in parallel, with the old one serving up the same data as the new one.
Later, on 2004-01-29, ICANN changed the IP address of another of its "." content DNS servers from 128.9.0.107 to 192.228.79.201. This time, an explicit cutoff was given. For 24 months from the change, the service will be provided in parallel on both addresses.
When, eventually, the old ICANN content DNS servers are taken down (and presuming that one has chosen to remain using the diminutive root and ICANN's "." content DNS servers), every time that dnscache has to start query resolution from the root of the namespace, it will query a non-existent server 2/13ths of the time. This will slow query resolution down slightly, as processing will have to time out before dnscache then tries asking another server.
These instructions show how to update the lists of "." content DNS servers that are used by djbdns. They apply generally, whatever "." content DNS server organization one has chosen to use. They will update the list to be whatever the list of "." content DNS servers for one's chosen organization currently is.
This patch specifically and solely updates the list of ICANN's "." content DNS servers to reflect the change that ICANN made on 2002-11.
This patch specifically and solely updates the list of ICANN's "." content DNS servers to reflect the two changes that ICANN made on 2002-11 and 2004-01.
In stock djbdns, the DNS Client library allows multiple proxy DNS servers to be specified in the value of the ${DNSCACHEIP} environment variable, but uses the unfortunate syntax of separating those addresses with the full stop ('.') character. This has two problems:
The full stop character is also used to separate the octects in (the human-readable form of) an IP version 4 address, creating the possibility of typing errors caused by confusion as to which octet one is typing.
The most intuitive use of dnsip in this context doesn't work. The output of dnsip cannot be directly used as the value of the ${DNSCACHEIP} environment variable if the result contains more than one IP address, since the parser in the DNS Client library will stop parsing IP addresses at the first space.
To see why one would want to do this, consider that the third argument of dnsq can be a domain name:
dnsq a cr.yp.to a.ns.yp.to
If that domain name maps to multiple IP addresses, dnsq will
try all of those IP addresses when querying the server.
dnsqr takes only two arguments, and uses the djbdns DNS Client library's normal mechanism for locating which proxy DNS server to query. One might want a tool for querying proxy DNS servers that has the same syntax as dnsq, and might write a dnsqrx script to achieve this.
However, this script doesn't work properly if the domain name maps to multiple IP addresses, because the parser in the djbdns DNS Client library for the value of the ${DNSCACHEIP} environment variable stops after the first IP address and ignores the others. dnsqr thus ends up querying only the first IP address that dnsip happens to output, instead of all of them as is desired.
This patch fixes this problem.
When used as a resolving proxy DNS server, stock dnscache avoids proxy loops by using the RD bit. It sends its back-end queries with the RD bit set to 0, and only responds to front-end queries that it receives that have the RD bit set to 1.
dnscache can also be configured to (almost) be a
forwarding proxy DNS server,
by setting the ${FORWARDONLY}
environment variable (to
anything). In this mode, it sends its back-end queries with the RD bit
set to 1. The RD bit is thus unusable as a mechanism for avoiding proxy loops
in "forwardonly" mode.
With a proper forwarding proxy DNS server, eliminating proxy loops is purely a local administrative matter. The DNS administrator is responsible for simply ensuring that the server is not configured to forward back to itself (either directly or indirectly, via other forwarding proxy DNS servers).
However, in "forwardonly" mode stock dnscache is not a proper purely forwarding proxy DNS server. The manual page for dnscache says that in "forwardonly" mode it
forwards queries […], rather than contacting a chain of servers according to NS records.but this is not actually true in practice. Even in "forwardonly" mode, stock dnscache will follow referral responses if it receives them, and thus proceed to contact a chain of servers according to "NS" resource records.
This error creates the possibility of a proxy loop caused by data outside of the control of the local DNS administrator. The circumstances that trigger it are:
dnscache is configured in "forwardonly" mode.
A domain is delegated to content DNS servers whose IP address(es)
match ${IP}
or one of its equivalents.
The domain that
brought this to light
was aereolineas.com.ar.
whose delegation data were:
aereolineas.com.ar. IN NS ns1.aereolineas.com.ar.
aereolineas.com.ar. IN NS ns2.aereolineas.com.ar.
ns1.aereolineas.com.ar. IN A 127.0.0.1
ns2.aereolineas.com.ar. IN A 127.0.0.2
One of the forwardees to which dnscache is forwarding responds with a referral for that domain containing those delegation data.
(Strictly speaking, this is a configuration error. A forwarding proxy DNS server should never be configured to talk to anything other than proxy DNS servers, and proxy DNS servers never respond with partial answers ending in referrals. So in a correct configuration dnscache performing forwarding proxy DNS service should never see a referral response. However, and unfortunately, some authorities have encouraged the use of such mis-configured systems.)
Something issues a query against that domain or one of its subdomains.
When dnscache resolves queries for that domain or for one of its subdomains, it queries the forwardee. Because of the forwarding misconfiguration, the forwardee responds with a referral containing the delegation data. Despite being in "forwardonly" mode, dnscache follows the referral to the next server(s) in the chain, according to the "NS" resource records. It sends a query to the delegated server(s).
Because of the duff delegation data, one or more of those servers happen to be itself, so it ends up sending the query to itself. Because the query has the RD bit set to 1 (as a result of dnscache being in "forwardonly" mode), dnscache accepts it. Because dnscache does not combine identical front-end queries from separate clients, it starts a second, parallel, query resolution for the same query. This, in turn, sends a query back to dnscache and generates a third query. And so forth.
Very quickly (within a few seconds), most reasonably-sized dnscache logs are completely flooded and all available query resolution slots are in use, processing the same query over and over again. dnscache becomes CPU bound, continuously processing queries that it has sent to itself (usually over a loopback network interface and thus involving no actual I/O at all) and generating new ones.
Each query resolution times out without receiving an answer, and so never sends an answer itself. The delegation is effectively lame, and the cycle never breaks.
It is relatively easy to replicate this problem by
.example.:
&forwarding-bug.example:127.0.0.1:a
andcd /service/dnscache echo 127.53.0.1 > root/servers/example svc -t .
DNSCACHEIP=127.0.0.1 dnsqr a x.forwarding-bug.example
Dan Bernstein flatly denies that this problem exists.
This patch fixes this problem.