coredns / coredns

CoreDNS is a DNS server that chains plugins
https://coredns.io
Apache License 2.0
12.39k stars 2.14k forks source link

Wrong response when DNAME leads to zonecut #6627

Open EchoStone1101 opened 6 months ago

EchoStone1101 commented 6 months ago

What happened:

When the file plugin chases a DNAME chain and ends up at a zonecut, the response has AA set (despite being a referral), and uses the apex NS records of the current zone as AUTHORITY, not the NS records at the zonecut. Further, if the query is for NS, the zonecut NS records is included in the ANSWER section.

How to reproduce it (as minimally and precisely as possible):

Using the following zone file (a.b.txt):

a.b.                  500 IN SOA    c.d.e. f.b.e. 3 604800 86400 2419200 604800
a.b.                  500 IN NS     c.d.e.
g.a.b.                500 IN DNAME  a.b.
h.a.b.                500 IN NS     h.b.

and this Corefile:

a.b.:1053 {
    header {
        response set ra
    }
    file a.b.txt
}

Response for querying <h.g.a.b., A> (output beautified):

root@e10adfbeed3f:/v# dig @127.0.0.1 -p 1053 h.g.a.b. A

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14209
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 1, ADDITIONAL: 1

;; QUESTION SECTION:
;h.g.a.b.                       IN      A

;; ANSWER SECTION:
g.a.b.                  500     IN      DNAME   a.b.
h.g.a.b.                500     IN      CNAME   h.a.b.

;; AUTHORITY SECTION:
a.b.                    500     IN      NS      c.d.e.

What you expected to happen:

aa should not be set (querying <h.a.b., A> directly, the aa bit is indeed not set), and the AUTHORITY section should include the h.a.b. NS record.

Further, if instead the query is for NS:

root@e10adfbeed3f:/v# dig @127.0.0.1 -p 1053 h.g.a.b. NS

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57896
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 1, ADDITIONAL: 1

;; QUESTION SECTION:
;h.g.a.b.                       IN      NS

;; ANSWER SECTION:
g.a.b.                  500     IN      DNAME   a.b.
h.g.a.b.                500     IN      CNAME   h.a.b.
h.a.b.                  500     IN      NS      h.b.

;; AUTHORITY SECTION:
a.b.                    500     IN      NS      c.d.e.

The h.a.b. NS record is in the ANSWER section, which is incorrect. Querying for h.a.b. NS directly would still end up with a referral response, where the ANSWER section is empty.

(Judging from these responses, it seems that CoreDNS is just not treating the response as a referral.)

Anything else we need to know?:

Environment:

Bind9 behavior under the same setup: the AUTHORITY is h.a.b. NS, and the ANSWER section never contains the NS record.

EchoStone1101 commented 6 months ago

After looking into how bind9 handles this case, I realize that there is one more complication.

Quoting RFC9499 section 4 on referrals:

In the case where the query matches an alias, and the server is not authoritative for the target of the alias but is authoritative for some name above the target of the alias, the resolution algorithm will produce a response that contains both the authoritative answer for the alias and a referral. Such a partial answer and referral response has data in the Answer section. It has the NS RRset for the referred-to zone in the Authority section. It may contain RRs that provide addresses in the Additional section. The AA bit is set because the first name in the Answer section matches the QNAME and the server is authoritative for that answer (see [RFC1035], Section 4.1.1).

And the RFC1035 part mentioned:

AA Authoritative Answer - this bit is valid in responses, and specifies that the responding name server is an authority for the domain name in question section. Note that the contents of the answer section may have multiple owner names because of aliases. The AA bit corresponds to the name which matches the query name, or the first owner name in the answer section.

So in this case, the AA bit should be set, and it corresponds to the g.a.b. DNAME record in the ANSWER section (I was initially surprised to see bind9 has AA set and assumed it was a bug as well..).

Anyhow, CoreDNS may be correct to have set AA, but returning zone cut NS records in the answer section is still wrong.