BIND9 as DNS server unable to fallback not defined directions to public DNS

The Setup

I have a containerized named service which is given their own IP with the following container file

FROM alpine:latest
RUN apk --no-cache add bind bind-tools bind-dnssec-tools bind-dnssec-root

COPY --chmod=500 --chown=root:root init.sh /usr/sbin/init

COPY --chmod=444 --chown=root:root bindetc/named.conf /etc/bind/named.conf

RUN chmod 770 /var/bind
RUN chown root:named /var/bind

COPY --chmod=440 --chown=root:named bindetc/direct.db /var/bind/direct.db
COPY --chmod=440 --chown=root:named bindetc/reverse.db /var/bind/reverse.db

VOLUME "/var/bind"
EXPOSE 53/tcp 53/udp
CMD /usr/sbin/named -f -g -u named

I have a mix of an authority server and an recursive one with the following configuration
bindetec/named.conf

acl LAN {
  192.168.0.0/24;
}

options {
  directory "/var/bind";

  allow-recursion {
    192.168.0.0/24;
    127.0.0.1/32; // localhost      
  };

  forwarders {          
    1.1.1.1; // Cloudflare
    208.67.222.222; // OpenDNS
  };

  listen-on { 192.168.0.136; 127.0.0.1; };
  listen-on-v6 { none; };

  allow-transfer port 53 { 192.168.0.136; 0.0.0.0; };
  allow-query { localhost; LAN; };

  recursion yes;

  pid-file "/var/run/named/named.pid";
  dump-file "/var/bind/data/cache_dump.db";
  statistics-file "/var/bind/data/named_stats.txt";
  memstatistics-file "/var/bind/data/named_mem_stats.txt";
};

zone "." IN {
  type master;
  file "/var/bind/direct.db";
  allow-update { none; };
};

zone "in-addr.arpa" IN {
  type master;
  file "/var/bind/reverse.db";
  allow-update { none; };
};

With the the following bindetc/direct.db:

$TTL 3600
$ORIGIN intranet.domain.
@ IN SOA ns1.intranet.domain. postmaster.intranet.domain. (909090 9000 900 604800 1800)

@ IN NS ns1.intranet.domain.

ns1    IN A 192.168.0.136

and the following bindetc/reverse.db:

$TTL 604800
@ IN SOA ns1.intranet.domain. postmaster.intranet.domain. (909090 9000 900 604800 1800)

@   IN NS ns1.intranet.domain.

136.0.168.192   IN PTR ns1.intranet.domain.

The IP of the container is 192.168.0.136.

The problem

When trying to resolve any public dns record like for example google.com it gives basically and empty response like the following instead of asking Cloudflare or OpenDNS what is the IP of such DNS record.


; <<>> DiG 9.16.44 <<>> google.com @192.168.0.136
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 27326
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 1f5514b62f24a19b0100000065ed3501a3ae047abe73afef (good)
;; QUESTION SECTION:
;google.com.            IN  A

;; Query time: 48 msec
;; SERVER: 192.168.0.136#53(192.168.0.136)
;; WHEN: Sat Mar 09 22:20:17 CST 2024
;; MSG SIZE  rcvd: 67
Asked By: Delfin

||

The dig command indicates your BIND is responding with a SERVFAIL error code, so it probably thinks your configuration has a fatal error. You really should see what log messages BIND is producing.

Your zone declaration zone "." IN specifies your BIND is type master for the DNS root zone, so effectively you’re telling BIND that it already knows all the top level domains in existence. So why should it ask someone else about "google.com" when it already knows there is no such top-level domain as ".com"?

Unless you really want to declare a separate DNS universe for yourself, or are actually maintaining a root nameserver, you should never configure your nameserver as a master of zone ".".

A more normal declaration for the root zone might be:

// prime the server with knowledge of the root servers
zone "." {
        type hint;
        file "/usr/share/dns/root.hints";
};

where /usr/share/dns/root.hints is a standard list of root DNS servers, available at https://www.internic.net/domain/named.cache . At startup, BIND will use this list to contact one of the root name servers, to get an absolutely up-to-date version of the same list.

Because you are planning to use forwarders, you can also omit it entirely: BIND will use its built-in list of root DNS servers if you don’t specify it. The zone "." of type hint is just a way to replace the built-in list if it becomes out of date.

Since your BIND should send queries for any zones it isn’t authoritative for to the forwarders, you shouldn’t need to care whether BIND has an up-to-date list of root nameservers or not.

If you don’t want your BIND to start attempting to contact other nameservers on its own if the forwarders are not responding, you may want to add the line forward only; to the options{ ... }; segment of your configuration.

You should declare your intranet.domain forward zone as:

zone "intranet.domain" IN {
  type master;
  file "/var/bind/direct.db";
  allow-update { none; };
};

Since you have allow-query { localhost; LAN; };, you probably should have an acl LAN { ... }; block somewhere, too.

Answered By: telcoM
Categories: Answers Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.