Skip to content

Authoritative DNS on FreeBSD

Purpose

This document explains how to build an authoritative DNS resolver using BIND9 on FreeBSD.

This example uses an example domain (also called a 'zone') and a single internal subnet. Any number of domain names and reverse zones can be added to the resolver.

All systems can use the resolver on your internal network. It will resolve and cache answers from public resolvers and answer queries for names defined on your internal network.


Procedure

Install FreeBSD

Install a recent version of FreeBSD. This guide uses version 14.1.

The system should be configured with a static IP address.

This guide will use these values as examples:

  • internal subnet: 192.168.3.0/24
  • internal domain: secure.mydomain.com
  • system's static IP address: 192.168.3.5
  • system's FQDN: ns.secure.mydomain.com

Ensure the hostname property in /etc/rc.conf is set to an FQDN that uses your 'internal' domain name.

Don't forget to update your /etc/hosts file with your FQDN and new static IP address.

Finally, install the Package database by running pkg update as the root user and following the prompts.

If you run:

ping `hostname`

You should see ICMP replies from the FQDN you configured:

user@ns:~ $ ping -c 3 `hostname`
PING ns.secure.mydomain.com (192.168.3.5): 56 data bytes
64 bytes from 192.268.3.5: icmp_seq=0 ttl=64 time=0.062 ms
64 bytes from 192.268.3.5: icmp_seq=1 ttl=64 time=0.079 ms
64 bytes from 192.268.3.5: icmp_seq=2 ttl=64 time=0.104 ms

--- ns.secure.mydomain.com ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.062/0.081/0.104/0.017 ms

Install BIND

Use the package database to install BIND9:

pkg install bind918

BIND9 configuration files are in /usr/local/etc/namedb.

Enable BIND9 and tell it to return only IPv4 addresses to clients by adding these lines to your /etc/rc.conf file:

named_enable="YES"
named_flags="-4"

BIND9's binary is named named.

BIND9 can be controlled by using /usr/local/etc/rc.d/named with the following options:

  • stop - stop the named service
  • start - start the named service
  • restart - restart the named service; this flushes all cached entries
  • reload - reload the configuration and local zone files, but do not flush any cached entries

Configure BIND

Caching Only Resolver

Most default options in the /usr/local/etc/named/namedb.conf file are sane and can be left configured as the default values.

After removing all of the comments, the namedb.conf file should look like this:

options {
        directory       "/usr/local/etc/namedb/working";
        pid-file        "/var/run/named/pid";
        dump-file       "/var/dump/named_dump.db";
        statistics-file "/var/stats/named.stats";
        zone-statistics yes;
        listen-on       { any; };
        allow-query { any; };
        disable-empty-zone "255.255.255.255.IN-ADDR.ARPA";
        disable-empty-zone "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA";
        disable-empty-zone "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA";
};

zone "." { type hint; file "/usr/local/etc/namedb/named.root"; };

Start the resolver:

/usr/local/etc/rc.d/named start

Check to make sure it started correctly and is running:

/usr/local/etc/rc.d/named status
named is running as pid 33776.

Test the resolver by using nslookup to ask the IP address of your resolver to look up a public DNS name:

root@ns:~ # nslookup - 192.168.3.5
> google.com
Server:     192.168.3.5
Address:    192.168.3.5#53

Non-authoritative answer:
Name:   google.com
Address: 142.250.72.46
Name:   google.com
Address: 2607:f8b0:400f:804::200e
> exit

The resolver listening on 192.168.3.5 is able to resolve public DNS names.

This DNS server can now be used as an internal DNS resolver instead of something like Google's 8.8.8.8 or Cloudfare's 1.1.1.1 public resolvers.


Forward Authoritative Zone

Now that the resolver is working, you can add a forward zone definition file for your secure.mydomain.com internal domain.

A forward zone file contains all of the name --> IP mappings for a domain name. The BIND9 Documentation describes the details and syntax of a zone file.

All authoritative zone files go in your resolver's /usr/local/etc/namedb/primary directory.

Create a file named /usr/local/etc/namedb/primary/secure.mydomain.com.db and paste the contents:

$ORIGIN secure.mydomain.com.
$TTL 3h
@ SOA ns.secure.mydomain.com. email.address.com. (
        2024070401      ; serial
        1d              ; refresh
        12h             ; retry
        1w              ; expire
        3h              ; TTL
        )

        NS      ns.secure.mydomain.com.


ns              A       192.168.3.5

Save the file and exit the editor.

Add the forward zone file to /usr/local/etc/named/namedb.conf at the end of the file:

// hosted zones
zone "secure.mydomain.com" {
    type primary;
    file "/usr/local/etc/namedb/primary/secure.mydomain.com.db";
};

Restart named to pick up the changes:

/usr/local/etc/rc.d/named reload

Try to resolve the DNS name you just defined in the forward zone:

root@ns:~ # nslookup - 192.168.3.5
> ns.secure.mydomain.net
Server:     192.168.3.5
Address:    192.168.3.5#53

Name:   ns.secure.mydomain.com
Address: 192.168.3.5
> exit

Your resolver is now answering questions about hostnames in the secure.mydomain.com zone.

If you run into trouble, check the syslog for errors about named:

grep named /var/log/messages

Reverse Authoritative Zone

A reverse zone file contains all of the IP --> name mappings for a subnet. APICNET has a guide for reverse zone files that is worth reviewing.

Keep in mind that IP addresses are reversed in DNS zone files. An IP address of 192.168.3.5 would appear in a reverse zone file record as 5.3.168.192.in-addr.arpa..

All authoritative zone files go in your resolver's /usr/local/etc/namedb/primary directory.

Create a file named /usr/local/etc/namedb/primary/3.168.192.in-addr.arpa.db and paste the contents:

$ORIGIN 3.168.192.in-addr.arpa.
$TTL 3h
@ SOA ns.secure.mydomain.com. email.address.com. (
    2024012801  ; serial
    1d          ; refresh
    12h         ; retry
    1w          ; expire
    3h          ; TTL
    )

        NS      ns.secure.mydomain.com.

5   IN  PTR     ns.secure.mydomain.com.

Add the reverse zone file to /usr/local/etc/named/namedb.conf at the end of the file:

// hosted zones
zone "3.168.192.in-addr.arpa." {
    type primary;
    file "/usr/local/etc/namedb/primary/3.168.192.in-addr.arpa.db";
};

Restart named to pick up the changes:

/usr/local/etc/rc.d/named reload

Try to resolve the IP address you just defined a name for in the reverse zone:

root@ns:~ # nslookup - 192.168.3.5
> 192.168.3.5
5.3.168.192.in-addr.arpa    name = ns.secure.mydomain.com.
> exit

Your resolver is now answering questions about IP addresses in the 3.168.192.in-addr.arpa zone.

If you run into trouble, check the syslog for errors about named:

grep named /var/log/messages

Configuring Local Resolver

Now that you have a resolver running on your network, you must tell all your machines to use it. If you don't do this, your systems will not use the resolver you just built, and none of the records you configured in your zones will be resolvable.

Usually, you can edit the /etc/resolv.conf file and change the IP address of the nameserver parameter.

If you are using NetworkManager to manage your IP stack configuration, run nmtui and configure the resolver for your interface(s).


Notes About DNS Zone Files

Important things to remember about DNS zone files:

Terminating Names

Omitting the left-hand side of a resource record in a zone file is shorthand for $ORIGIN.

For example, this data in a zone file:

$ORIGIN secure.mydomain.com.
    IN NS ns.secure.mydomain.com.

would get expanded and parsed as:

$ORIGIN secure.mydomain.com.
secure.mydomain.com.   IN NS ns.secure.mydomain.com.

All names in zone files that are not terminated with a dot (.) will get the $ORIGIN value appended to them. This is a shorthand way to avoid typing in the full domain name for every record.

For example, a record defined in a zone file like this:

$ORIGIN secure.mydomain.com
ns IN A 192.168.3.5

will result in the zone file A record being loaded as:

ns.secure.mydomain.com. IN A 192.168.3.5

Zone File Serial Numbers

Most of the header data in the zone file can be left alone, but you must update the serial number of the zone file every time the zone file is changed.

The usual format of zone file serial numbers is: YYYYMMDDnn.


Reverse Zone Naming

Reverse DNS zones that map IP addresses to names are also called 'in-addr.arpa' zones.

All IP addresses in reverse zones appear in reverse order and must end with .in-addr.arpa..

For example, the IP address 192.168.3.5 appears in reverse zones files as 5.3.168.192.in-addr.arpa..