.@ Tony Finch – blog


The main interop problem with DNSSEC is that it makes large DNS packets a lot more common. This leads to problems with misconfigured firewalls, and with qmail.

When delivering a message, qmail makes an ANY query on the recipient domain. This is not, as some people have speculated, a "clever" attempt to get the MX or fallback A and AAAA records in one go - and in fact if any MTA tried to do that then it wouldn't avoid queries or save time. If a DNS cache already has any records for a domain, an ANY query won't make its resolver fetch the other types. So if there are A records but no MX records in an ANY response, the MTA cannot assume that it should use the fallback-to-A implicit MX logic. It has to make an MX query to verify if MX records exist, so trying the ANY query has not actually reduced the number of queries. The code ends up more complicated and slower than straightforwardly making MX+A+AAAA queries as RFC 5321 specifies.

So what are qmail's ANY queries for? There is exactly one point where it makes this query, which is when it is doing domain canonicalization of the envelope of outgoing messages. This is as specified by RFC 1123 section 5.2.2. However this requirement is obsolete and modern MTAs don't do it. You could fix qmail's ANY query bugs by just deleting the canonicalization code.

There are two bugs in the implementation which turn this unnecessary feature into an interoperability problem.

Originally qmail made a CNAME query in order to look up the canonical version of a domain, but this caused interop problems with BIND 4. This was replaced with an ANY query, which had fewer interop problems but is still wrong. Both of these queries are wrong because they don't trigger alias processing, so if there is a CNAME chain the response will not actually yield the canonical name. Because of this qmail has code that makes a series of queries to follow CNAME chains. If instead qmail made the correct query, an MX query (or A - it doesn't matter which), the response will include all the CNAME RRs that qmail wants to know about, and it would not need its inefficient CNAME chain handling code.

The other problem is that qmail uses a small DNS packet buffer, and does not resize and retry if a response is truncated. ANY queries make it much more likely for truncated-response failures to happen. The simplest fix is just to change the buffer size from 512 to 65536 (which is the maximum DNS message size) and let the virtual memory system do lazy memory allocation. This one-line patch is enough to fix qmail's DNSSEC problems, but it doesn't fix its CNAME chain problem. (Edit: but see the comments for a patch that does fix it by disabling the canonicalization code. That is the patch you want to work around DNS providers that have disabled support for ANY queries.)

--- dns.c~      1998-06-15 11:53:16.000000000 +0100
+++ dns.c       2013-01-10 12:33:56.000000000 +0000
@@ -21,7 +21,7 @@
 static unsigned short getshort(c) unsigned char *c;
 { unsigned short u; u = c[0]; return (u << 8) + c[1]; }

-static union { HEADER hdr; unsigned char buf[PACKETSZ]; } response;
+static union { HEADER hdr; unsigned char buf[65536]; } response;
 static int responselen;
 static unsigned char *responseend;
 static unsigned char *responsepos;