Bind 9: Setting Up a DNS Record

Bind 9: Setting Up a DNS Record

Understanding Bind9 Config Files

named.conf

  • This is a file which reference all other configuration files in BIND9

named.conf.options

  • Your global configuration for Bind9 DNS server
  • Configure server defaults, acls, dns forwarding

named.conf.local

  • Contains your zone (domains) your Bind9 DNS server is authorised to resolve
  • Specific to your local (home-lab) network

db.<domain>

  • These are the zone files/ DNS records.
  • You configure your A, CNAME, NS, etc. records in this file

Now that we know the basics lets add a DNS record.

Step 1: Check if your DNS server is accessible

To do this I use two commands. One tells me if I can reach the server and the second one tells me what is the routing to reach the server

ping 192.<>.<>.70

# You should see some output like below
PING 192.<>.<>.<> (192.<>.<>.<> ): 56 data bytes
64 bytes from 192.<>.<>.<> : icmp_seq=0 ttl=63 time=4.145 ms
64 bytes from 192.<>.<>.<> : icmp_seq=1 ttl=63 time=3.333 ms
64 bytes from 192.<>.<>.<> : icmp_seq=2 ttl=63 time=2.750 ms
        
traceroute 192.<>.<>.70 

# You should see some output like below
traceroute to 192.<>.<>.<>  (192.<>.<>.<> ), 64 hops max, 40 byte packets
 1  192.<>.<>.1  (192.<>.<>.<> )  8.457 ms  3.254 ms  2.937 ms
 2  192.<>.<>.70  (192.<>.<>.<> )  4.095 ms  4.459 ms  4.005 ms
        

Step 2: Update the named.conf.options file to include your DNS server defaults and ACLs’

In my name.conf.options, I will set up an ACL (Access Control List) for some additional security. ACL is a security feature which defines who is allowed to do what on your DNS server.

Think of it like a bouncer at a VIP club. Bouncer has a list of who can enter. If you are on the list, you get in. All others are turned away. ACLs does the same thing. In this case, I am making sure only devices in my network can DNS quarries to my Bind9 server.

sudo nano /etc/bind/named.conf.options

# Add a config similar to below 
# Define trusted networks
# MUST be at the TOP before options block
# Include all of your Subnets/ VLANs here
acl "trusted" {
    192.<>.<>.0/24;
    192.<>.<>.0/24;
    192.<>.<>.0/24;
    [localhost](<http://localhost>);
    localnets;
};

# These are your options/settings
options {
    directory "/var/cache/bind";
    recursion yes; # Allow to resolve external domains like google.com
    allow-query { trusted; }; # Setting to trusted means only accessible by ips from the acls
    allow-query-cache { trusted; }; # Setting to trusted means only accessible by ips from the acls
    allow-recursion { trusted; }; # Setting to trusted means only accessible by ips from the acls
    forwarders { 
        1.1.1.1;
        8.8.8.8;
    };
    dnssec-validation no;
    listen-on { any; };
    listen-on-v6 { any; };
    allow-transfer { none; };   # Prevent zone transfers
};
        

Verify there are no syntax errors

sudo named-checkconf /etc/bind/named.conf.options
        

Step 3: Create a local zone

# Lets create a dir to keep all zone files 
sudo mkdir -p /etc/bind/zones

# Create zone file 
sudo nano /etc/bind/named.conf.local

# Add the following to your named.conf.local 
# Makesure to replace the <domain-name>
zone "<domain-name>" {
    type master;                                # This server is authoritative
    file "/etc/bind/zones/db.<domain-name>";       # Path to zone file
    allow-query { trusted; };                   # Only trusted networks
    allow-update { none; };                     # Prevent dynamic updates
    allow-transfer { none; };                   # No zone transfers
};
        

Step 4: Create your forwarding zone

This file contains the DNZ records

sudo nano /etc/bind/zones/db.<domain-name>

# Add the following config
$TTL    604800
@       IN      SOA     ns1.<domain-name>. admin.<domain-name>. (
                              2025110901    ; Serial (YYYYMMDDNN format)
                              604800        ; Refresh (1 week)
                              86400         ; Retry (1 day)
                              2419200       ; Expire (4 weeks)
                              604800 )      ; Negative Cache TTL (1 week)
;
; Name servers
@       IN      NS      ns1.<domain-name>.

; A records - hostname to IP mappings
ns1             IN      A       192.<>.<>.70        ; DNS server itself
homeassistant   IN      A       192.<>.<>.177       ; Home Assistant
homeassist      IN      A       192.<>.<>.177       ; Shorter name

; CNAME records - aliases
ha              IN      CNAME   homeassistant.<domain-name>.
        

Step 5: Validate if there are no configuration issues

# Check main configuration
sudo named-checkconf

# Check forward zone
sudo named-checkzone <domain-name> /etc/bind/zones/db.<domain-name>
        

You should see an output like this

zone <domain-name>/IN: loaded serial 2025110901
OK
        

Note: Every time you make a change to /etc/bind/zones/db.<domain-name> remember to update the serial

Step 6: If no errors restart Bind9 service

sudo systemctl restart named
sudo systemctl status named

# You should see this as an output if everything is good
named.service - BIND Domain Name Server
   Loaded: loaded
   Active: active (running)
        

Step 7: Test domain names are resolved within Bind9

dig @192.<>.<>.70 homeassistant.home.local
dig @192.<>.<>.70 homeassist.home.local
dig @192.<>.<>.70 ha.home.local

# You should see an output like this 
; <<>> DiG 9.20.15-1+ubuntu24.04.1+deb.sury.org+1-Ubuntu <<>> @192.<>.<>.70 ha.<domain-name>
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 42115
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: ab91426908e2e1ea01000000691016b4e3ce1b1ba65445b1 (good)
;; QUESTION SECTION:
;ha.labconsulting.net.		IN	A

;; ANSWER SECTION:
ha.<domain-name>.	604800	IN	CNAME	homeassistant.<domain-name>.
homeassistant.<domain-name>. 604800	IN A	192.<>.<>.177

;; Query time: 0 msec
;; SERVER: 192.<>.<>.70#53(192.<>.<>.70) (UDP)
;; WHEN: Sun Nov 09 04:21:08 UTC 2025
;; MSG SIZE  rcvd: 121
        

Step 8: Update your routers domain resolver settings

Typically this is set to auto. If that is the case then change it to manual and add your Bind9 server ip address and at least one other knows DNS resolver like 1.1.1.1 (CloudFlare)

Article content

Note: For anyone who is using UnitFi CloudGateways, you will also need to add a policy to forward your local domain queries to be forwarded to the Bind9 server. Without this policy, UniFi CloudGateway does not seem to pass the query to Bind9. I spent few hours troubleshooting this

Article content

Step 9: Test from your device.

# Run this command in your terminal
dig @192.<>.<>.70 homeassistant.<domain-name>

# You should see a result similar to below

; <<>> DiG 9.10.6 <<>> @192.<>.<>.70 homeassistant.<domain-name>
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 23301
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;homeassistant.<domain-name>. IN	A

;; ANSWER SECTION:
homeassistant.l<domain-name>. 746 IN	A	192.<>.<>.177

;; Query time: 4 msec
;; SERVER: 192.168.4.70#53(192.168.4.70)
;; WHEN: Sun Nov 09 15:30:07 AEDT 2025
;; MSG SIZE  rcvd: 107
        

Test from your browser

Article content

Note: At the time of writing I have trouble getting Safari to resolve this domain. However, it works with Chrome.

What is Next

As you can see, this connection is not secure. In my next blog I will address how we can add TLS verification and if time permits how to set up a reverse proxy service like nginx proxy manager.

To view or add a comment, sign in

More articles by Basitha Gamage

Others also viewed

Explore content categories