BIND Secondary for Active Directory DNS on Red Hat-compatible Linux

My DNS is hosted locally, on-prem, behind a consumer-grade internet connection. When my internet connection at home goes down, my off-prem cloud-hosted servers that rely on my Active Directory DNS can’t communicate with eachother.

Rather than having a cloud-hosted Windows Server installation primarily to host DNS, why not create a BIND secondary that replicates from AD DNS?

What?

Creating a BIND DNS secondary on a Red Hat-compatible linux distribution, that transfers zones from Windows Server / Active Directory DNS.

I have found a guide that targets Debian-compatible distros, but not for Red Hat.

This is strongly based on a guide for Debian-compatibale distros by Mike (vswitchzero).

Why?

I have on-prem self-hosted Active Directory for DNS, but the uplink for that is a consumer-grade NBN connection. There are often NBN outages, so when DNS goes down my off-site network connectivity dies. My non-self hosted servers connect back via Tailscale.

I want to have BIND secondary in one of my cloud-based VPCs which I can point everything off-prem to, so that a NBN outage doesn’t effect everything else.

Assumptions

It is assumed that you have your server connected to whatever network you are wanting to host DNS on, and that it can communicate back to the master DNS server.

For this example, I have a Rocky 9.2 installation, connected to my Tailscale network, and bound to my self-hosted Active Directory domain.

I have set up firewalld to add the tailscale0 Tailscale interface to the internal zone. This makes the internal zone accessible only via Tailscale.

firewall-cmd --zone=internal --add-interface=tailscale0 --permanent

In this example, DNS will be accessible only via Tailscale.

In this example, the details about the environment are:

  • Tailscale address: 100.84.10.150
  • Tailscale subnet: 10.84.0.0/10
  • Local networks: 10.69.0.0/16
  • Hostname: bne-dns.spd.internal
  • Master DNS servers: 10.69.100.161, 10.69.100.162

Install and Configure BIND

Install bind:

yum install bind dnsutils bind-utils

Configure the firewall to only accept DNS requests from the internal zone– which is the tailscale interface:

firewall-cmd --permanent --add-service=dns --zone=internal
firewall-cmd --reload

Then, edit the /etc/named.conf file:

Update the listen-on and listen-on-v6 statements to specify on which IPv4 and IPv6 interfaces BIND should listen:

listen-on port 53 { 127.0.0.1; 100.84.10.150; };

This makes BIND listen on localhost and the Tailscale interface only. I don’t use IPv6, so I have left the listen-on-v6 to default.

Update the allow-query statement to configure from which IP addresses and ranges clients can query this DNS server:

allow-query { localhost; 10.69.0.0/16; 100.64.0.0/10; };

Add an allow-recursion statement to define from which IP addresses and ranges BIND accepts recursive queries:

allow-recursion { localhost; 10.69.0.0/16; 100.64.0.0/10; };

By default, BIND resolves queries by recursively querying from the root servers to an authoritative DNS server. Alternatively, you can configure BIND to forward queries to other DNS servers, such as the ones of your provider. In this case, add a forwarders statement with the list of IP addresses of the DNS servers that BIND should forward queries to:

forwarders { 1.1.1.1; 1.0.0.1; };

The addition of zones to your named.conf varies based on what zones you want to have in your secondary. The basic format is:

zone "<domain-name>" IN {
    type slave;
    file "<filename>";
    masters { <master-server-ip>; };
};

In my example, I want to transfer all of my forward lookup zones, as well as my reverse lookup zone for 100.69.10.0/24.

I added these four zone statments to my named.conf:

zone "spd.internal" IN {
    type slave;
    file "forward.spd.internal.db";
    masters { 10.69.100.161; 10.69.100.162; };
};

zone "traefik.internal" IN {
    type slave;
    file "forward.traefik.spd.internal.db";
    masters { 10.69.100.161; 10.69.100.162; };
};

zone "_msdcs.spd.internal" IN {
    type slave;
    file "forward._msdcs.spd.internal.db";
    masters { 10.69.100.161; 10.69.100.162; };
};

zone "100.69.10.in-addr.arpa" IN {
    type slave;
    file "reverse.spd.internal.100.69.10.db";
    masters { 10.69.100.161; 10.69.100.162; };
};

You can check the syntax of your freshly edited named.conf file with the named-checkconf command.

Enable Zone transfers on Windows DNS

Some changes need to be made to the Windows DNS server to allow connections from your BIND secondary. Start by opening dnsmgmt.msc. Check your Forward Lookup Zone to ensure that your secondary has an A record. If it doesn’t, create one.

Enable BIND secondaries by right clicking on the DNS server, and selecting Properties. Go to the Advanced tab. In Server option check Enable BIND secondaries. Click Apply.

Add your BIND secondary to the Name Servers tab of your first forward lookup zone. In this case, it’s spd.internal. Right click on the forward lookup zone, and select Properties. Click the Name Servers tab, and add the hostname of the DNS Secondary.

Repeat this step for each forward lookup and reverse lookup zone you want to forward to the secondary.

Start BIND

Start BIND and enable the systemd unit:

systemctl enable --now named

Now, check to see if it works! journalctl -fu named should display logs like:

Nov 18 18:30:38 bne-dns.spd.internal named[34002]: zone 100.69.10.in-addr.arpa/IN: transferred serial 23
Nov 18 18:30:38 bne-dns.spd.internal named[34002]: transfer of '100.69.10.in-addr.arpa/IN' from 10.69.100.161#53: Transfer status: success
Nov 18 18:30:38 bne-dns.spd.internal named[34002]: transfer of '100.69.10.in-addr.arpa/IN' from 10.69.100.161#53: Transfer completed: 17 messages, 17 records, 1424 bytes, 0.002 secs (712000 bytes/sec) (serial 23)

Confirm that you can pull records locally:

nslookup spd.internal 127.0.0.1
Server:         127.0.0.1
Address:        127.0.0.1#53

Name:   spd.internal
Address: 10.69.100.162
Name:   spd.internal
Address: 10.69.100.161

Confirm you can pull records from other servers:

$ nslookup spd.internal 100.84.10.150
Server:         100.84.10.150
Address:        100.84.10.150#53

Name:   spd.internal
Address: 10.69.100.161
Name:   spd.internal
Address: 10.69.100.162

Now, go ahead and update /etc/resolve.conf or use nmcli to update name servers to point to this BIND secondary.

References

  1. Linux and BIND9 as a DNS Secondary for Active Directory
  2. Setting up and configuring a BIND DNS server