Bind 9.2 – Server Refuses to Resolve CNAME from Sub-Zone

binddomain-name-systemlinux

I've got an old master nameserver running Bind 9.2 and a newer slave running 9.8. Right now we've got a project going on where we're essentially splitting a cloud in two and we're using subzones and CNAMEs to keep our services running smoothly. However, the cranky old 9.2 server doesn't seem to want to resolve the CNAMEs to the subzone and returns REFUSED: recursion requested but not available. On the other hand the 9.8 server serves the requests just fine.

Disclaimer: I know these nameservers are horribly out of date, and even worse the one running 9.2's OS is waaaaay out of support as well, so I'm not likely to find a reputable package to upgrade it. The project immediately after this cloud split is rebuilding our DNS servers/services from scratch.

How can I get the older server to resolve these CNAMEs properly?

dig results

dig @ NS1 [Bind 9.2]

# dig foo.domain.com @ns1.domain.com

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.30.rc1.el6_6.3 <<>> foo.domain.com @ns1.domain.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 5937
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;foo.domain.com.        IN      A

;; Query time: 116 msec
;; SERVER: 4.3.2.1#53(4.3.2.1)
;; WHEN: Fri Jul 31 16:18:36 2015
;; MSG SIZE  rcvd: 48

dig @ NS2 [Bind 9.8]

# dig foo.domain.com @ns2.domain.com

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.30.rc1.el6_6.3 <<>> foo.domain.com @ns2.domain.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59986
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 2, ADDITIONAL: 2
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;foo.domain.com.        IN      A

;; ANSWER SECTION:
foo.domain.com. 300 IN  CNAME   foo.sub.domain.com.
foo.sub.domain.com. 300 IN A     5.6.7.8

;; AUTHORITY SECTION:
sub.domain.com.  300     IN      NS      ns1.domain.com.
sub.domain.com.  300     IN      NS      ns2.domain.com.

;; ADDITIONAL SECTION:
ns1.domain.com.     30      IN      A       4.3.2.1
ns2.domain.com.     30      IN      A       1.2.3.4

;; Query time: 80 msec
;; SERVER: 1.2.3.4#53(1.2.3.4)
;; WHEN: Fri Jul 31 16:22:29 2015
;; MSG SIZE  rcvd: 161

Config

Below are the config files for the servers, trimmed down to the bare essentials.

NS1 [Bind 9.2]

options {
        recursion no;
        additional-from-auth no;
        additional-from-cache no;
        blackhole { bogon; };
        directory "/var/named";
        notify yes;
};
zone "domain.com" {
        type master;
        file "/var/named/domain.com.hosts";
        also-notify { 1.2.3.4; };
        notify yes;
};
zone "sub.domain.com" {
        type master;
        file "/var/named/sub.domain.com.hosts";
        also-notify { 1.2.3.4; };
        notify yes;
};

NS2 [Bind 9.8]

options {
        directory       "/var/named";
        recursion no;
        blackhole{ bogon; };
        dnssec-enable yes;
        dnssec-validation yes;
        dnssec-lookaside auto;
};
zone "domain.com" {
        type slave;
        masters { 4.3.2.1; };
        allow-transfer { 4.3.2.1; };
        file "/var/named/slaves/domain.com.hosts";
};
zone "sub.domain.com" {
        type slave;
        masters { 4.3.2.1; };
        allow-transfer { 4.3.2.1; };
        file "/var/named/slaves/sub.domain.com.hosts";
};

domain.com.hosts

$ORIGIN .
$TTL 300        ; 5 minutes
domain.com      IN SOA  ns1.domain.com. servers.domain.com. ( ... )
    NS      ns1.domain.com.
    NS      ns2.domain.com.
$ORIGIN domain.com.
sub NS ns1.domain.com.
sub NS ns2.domain.com.
foo CNAME foo.sub

sub.domain.com.hosts

$ORIGIN .
$TTL 300        ; 5 minutes
sub.domain.com   IN SOA  ns1.domain.com. servers.domain.com. ( ... )
    NS      ns1.domain.com.
    NS      ns2.domain.com.
$ORIGIN sub.domain.com.
foo A 5.6.7.8

Best Answer

I tossed this question at some smart dudes on IRC and got the answer:

options {
    additional-from-auth yes;
    additional-from-cache yes;
}

Where both were explicitly set to no in my config.

http://www.zytrax.com/books/dns/ch7/queries.html#additional-from-auth

additional-from-auth and additional-from-cache control the behaviour when zones have additional (out-of-zone) data or when following CNAME or DNAME records. These options are for used for configuring authoritative-only (non-caching) servers and are only effective if recursion no is specified in a global options clause or in a view clause. The default in both cases is yes. These statements may be used in a global options or in a view clause. The behaviour is defined by the table below:

And then the table basically boils down to:

If they're not both set to yes the type of query referenced in this question is going to be refused more or less all the time.