skynetservices/skydns

CNAME and A records are returned in random order, confusing (at least some) clients

Opened this issue · 7 comments

nbaum commented

Running a freshly pulled and compiled SkyDNS with the default configuration.

$ etcdctl set /skydns/local/skydns/foo '{"host":"bar.skydns.local"}'
$ etcdctl set /skydns/local/skydns/bar '{"host":"127.0.0.1"}'

Look up the domain:

$ dig foo.skydns.local @127.0.0.1

Randomly

foo.skydns.local.   3600    IN  CNAME   bar.skydns.local.
bar.skydns.local.   3600    IN  A   127.0.0.1

or

bar.skydns.local.   3600    IN  A   127.0.0.1
foo.skydns.local.   3600    IN  CNAME   bar.skydns.local.

Which when pinging randomly results in

$ ping foo.skydns.local.
PING bar.skydns.local (127.0.0.1) 56(84) bytes of data.
....
Everything's fine.

or

$ ping foo.skydns.local.
ping: unknown host foo.skydns.local.

A tcpdump shows that ping fails when the order of the result is A and then CNAME. It works the other way around.

My reading of RFC1034 is that the CNAME record should appear first, and the A record should appear last.

miekg commented

Where does it actually specify does in 1034? I think a resolver should be able to handle any order, but there are braindead resolver out there, like the one in glibc.

The resolvers are allowed to be simple, and there are many implementations of them.

named in the early 4.3BSD would append the CNAME answer first and then set to work again before appending the A answer. Its code to read these replies assumes the CNAME precedes A.

http://tools.ietf.org/html/rfc1034#section-4.3.2 3.a talks of copying the CNAME RR to the answer, changing QNAME to the CNAME's value, and looping again, implying the CNAME will be before the A.

http://tools.ietf.org/html/rfc1034#section-4.3.1 talks about the answer to the query, possibly preface[d] by one or more CNAME RRs that specify aliases encountered on the way to an answer.

Many resolvers take the view, like glibc, that CNAMEs to get to A precede A and that the reply can be processed in order in a single pass.

Is there a widely used DNS server, e.g. BIND, that often replies A, CNAME? I doubt it, else this issue would have been flushed out long ago. Whether the RFC states it or not, it would seem CNAME, A is a established, de facto, required order. As skydns's aim is that DNS provides an easy means of lookup, it would seem it should support the wide range of resolvers out there and their long-held assumptions.

nbaum commented

I now believe that RFC 1034 section 3.6 means that the order should be irrelevant. Still, it'd be nice if it worked with software that uses glibc!

On further investigation, I've found that this doesn't happen with --round-robin=false. That option should only round robin A/AAAA replies according to the help.

It looks like although the result is only shuffled when an A/AAAA is added to it, the shuffle involves all the records, rather than just A/AAAA records. I think that's a bug.

I don't need round robinning right now, so I can work around the issue by turning it off.

miekg commented

Ack and thanks for the info. I think something like this, ie clean-up
message should be put in go dns.
On 8 Aug 2015 15:20, "Nathan Baum" notifications@github.com wrote:

I now believe that RFC 1034 section 3.6
https://tools.ietf.org/html/rfc1034#section-3.6 means that the order should
be
irrelevant. Still, it'd be nice if it worked with software that uses
glibc!

On further investigation, I've found that this doesn't happen with
--round-robin=false. That option should only round robin A/AAAA replies
according to the help.

It looks like although the result is only shuffled when an A/AAAA is added
to it, the shuffle involves all the records, rather than just A/AAAA
records. I think that's a bug.

I don't need round robinning right now, so I can work around the issue by
turning it off.


Reply to this email directly or view it on GitHub
#217 (comment)
.

The full quote from 3.6 is

The set of resource information associated with a particular name
is composed of separate resource records (RRs).
The order of RRs in a set is not significant,
and need not be preserved by name servers, resolvers,
or other parts of the DNS.

This is only stating order is not significant for the members of the set, e.g. all A associated with a particular name. It doesn't cover the order between the CNAME for one name and the A for the name that's the CNAME's value.

Discussion off-issue with @nbaum and one of the co-authors of RFC 2181, Clarifications to the DNS Specification, has concluded that the DNS RFCs don't explicitly say order doesn't matter, that implementations, included dominant ones, ensured CNAME came before the related A, that clients took advantage of this to simplify their implementation, and that servers need to continue to satisfy this assumption to work with the many clients, most of which are never going to be updated.

miekg commented

I wonder if we can get away with just sorting all cnames before the other records.

miekg commented

This actually happens because of the dedupping of RRs in a message, that uses a map internally and randomizes the order.