Search code examples
dnscnamediga-records

dig returns wrong record type


This seems like I am either missing something obvious, or it would have been asked before. When I query dig using the -t parameter to specify a DNS record type, the result seems to contain an answer even if the record returned is a different record type. Here is an example:

$ dig -t A -q polestar.databaseguy.com.

; <<>> DiG 9.11.3-1ubuntu1.3-Ubuntu <<>> -t A polestar.databaseguy.com.
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33130
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;polestar.databaseguy.com.      IN      A

;; ANSWER SECTION:
polestar.databaseguy.com. 3600  IN      CNAME   databaseguy.ddns.net.
databaseguy.ddns.net.   60      IN      A       173.19.127.251

;; Query time: 30 msec
;; SERVER: 10.0.10.1#53(10.0.10.1)
;; WHEN: Mon Dec 10 14:41:50 STD 2018
;; MSG SIZE  rcvd: 103

The CNAME and A records listed in the ANSWER SECTION are correct. However, the CNAME is for polestar.databaseguy.com. and the A is for databaseguy.ddns.net.. There is no A record forpolestar.databaseguy.com., which is what I queried for, so I expected there to be no results.

I am pretty confident this is the correct behavior, but I don't understand it and didn't see any explanation in the man dig pages. I also could not find other discussions online, either on this site or elsewhere. Can someone help me understand this?


Solution

  • This is the expected behaviour, that decreases the amount of exchanges needed, and is specific of the CNAME record.

    It is covered by the core documents on DNS: RFC1034, section 3.6.2

    See this:

    CNAME RRs cause special action in DNS software. When a name server fails to find a desired RR in the resource set associated with the domain name, it checks to see if the resource set consists of a CNAME record with a matching class. If so, the name server includes the CNAME record in the response and restarts the query at the domain name specified in the data field of the CNAME record. The one exception to this rule is that queries which match the CNAME type are not restarted.

    With the clear example that completely matches your case:

    For example, suppose a name server was processing a query with for USC-ISIC.ARPA, asking for type A information, and had the following resource records:

    USC-ISIC.ARPA   IN      CNAME   C.ISI.EDU
    
    C.ISI.EDU       IN      A       10.0.0.52
    

    Both of these RRs would be returned in the response to the type A query, while a type CNAME or * query should return just the CNAME.

    See section 5.2.2 for other points. Sections 6.2.7 and 6.2.8 also gives examples.

    It also depends if you query a recursive or an authoritative nameserver.

    databaseguy.com has for nameservers:

    pdns01.domaincontrol.com.
    pdns02.domaincontrol.com.
    

    If you query one of them:

    $ dig A polestar.databaseguy.com. @pdns01.domaincontrol.com.
    
    ; <<>> DiG 9.12.0 <<>> A polestar.databaseguy.com. @pdns01.domaincontrol.com.
    ;; global options: +cmd
    ;; Sending:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 64115
    ;; flags: rd ad; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
    
    ;; OPT PSEUDOSECTION:
    ; EDNS: version: 0, flags:; udp: 4096
    ; COOKIE: e45ebc418c94c90a
    ;; QUESTION SECTION:
    ;polestar.databaseguy.com. IN A
    
    ;; QUERY SIZE: 65
    
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 64115
    ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
    ;; WARNING: recursion requested but not available
    
    ;; OPT PSEUDOSECTION:
    ; EDNS: version: 0, flags:; udp: 4096
    ;; QUESTION SECTION:
    ;polestar.databaseguy.com. IN A
    
    ;; ANSWER SECTION:
    polestar.databaseguy.com. 1h IN CNAME databaseguy.ddns.net.
    

    You get only the CNAME value because this authoritative nameserver knows only that, and is not authoritative for ddns.net.

    But if you ask any recursive nameserver it does the job of recursing and giving you the "full" reply:

    $ for ns in 1.1.1.1 8.8.8.8 9.9.9.9 80.80.80.80 ; do dig A polestar.databaseguy.com. @$ns +noall +ans ; done
    
    ; <<>> DiG 9.12.0 <<>> A polestar.databaseguy.com. @1.1.1.1 +noall +ans
    ;; global options: +cmd
    ;; connection timed out; no servers could be reached
    
    ; <<>> DiG 9.12.0 <<>> A polestar.databaseguy.com. @8.8.8.8 +noall +ans
    ;; global options: +cmd
    polestar.databaseguy.com. 59m59s IN CNAME databaseguy.ddns.net.
    databaseguy.ddns.net.   59s IN A 173.19.127.251
    
    ; <<>> DiG 9.12.0 <<>> A polestar.databaseguy.com. @9.9.9.9 +noall +ans
    ;; global options: +cmd
    polestar.databaseguy.com. 1h IN CNAME databaseguy.ddns.net.
    databaseguy.ddns.net.   1m IN A 173.19.127.251
    
    ; <<>> DiG 9.12.0 <<>> A polestar.databaseguy.com. @80.80.80.80 +noall +ans
    ;; global options: +cmd
    polestar.databaseguy.com. 1h IN CNAME databaseguy.ddns.net.
    databaseguy.ddns.net.   1m IN A 173.19.127.251
    

    (1.1.1.1 did not reply to my query but this is irrelevant here for this question)

    So about "There is no A record forpolestar.databaseguy.com., which is what I queried for, so I expected there to be no results." this is halfway wrong because that name has a CNAME which means another canonical name and this canonical name has an A record so at the end of the day it is exactly as if the starting name had an A record. Any application locally asking the OS for the IP address of that host will get the A record, as the OS will take care of the full recursive resolution and "dereferencing" the CNAME.