If you've spent any time configuring user authentication on... Full Story
By Manny Fernandez
April 18, 2026
Deploying Bind9 as DNS Server on Ubuntu Server
In the process of deploying my lab, I needed to set up DNS services for it. I decided to use Bind 9 on my Ubuntu Server. I am going to use infosecmonkey.org as the domain for my lab. The .lab did not work out as I expected before. The idea is to allow anyone to query this server from 10.1.105.0/24, 10.1.106.0/24 and 10.240.0.0/15.
1. Assumptions and Planning
We will assume:
– Ubuntu Server 22.04/24.04, fresh or lightly used.
– Server IP (example): 10.1.106.10 (adjust to your real IP).
– Domain: infosecmonkey.org hosted authoritatively on this box.
– Networks allowed recursion:
– 10.1.106.0/24
– 10.1.105.0/24
– 10.240.0.0/15
Files we will touch (Ubuntu/Debian layout):
– /etc/bind/named.conf.options
– /etc/bind/named.conf.local
– Zone file: /etc/bind/db.infosecmonkey.org
2. Install BIND9 and Base Packages
Run these commands as root or with sudo.
sudo apt update
sudo apt install bind9 bind9-utils bind9-dnsutils -y
Enable and start the service:
sudo systemctl enable bind9
sudo systemctl start bind9
sudo systemctl status bind9
You should see active (running) in the status output.
3. Define ACLs and Recursive Options
We will configure:
– An ACL trusted for your three networks.
– BIND to listen on all interfaces.
– Recursion allowed only for trusted and localhost.
Edit /etc/bind/named.conf.options:
sudo vi /etc/bind/named.conf.options
Replace the entire file contents with this (adjust comments if you like):
acl "trusted" {
127.0.0.1; // localhost
10.1.106.0/24; // allowed subnet
10.1.105.0/24; // allowed subnet
10.240.0.0/15; // allowed subnet
};
options {
directory "/var/cache/bind";
// Listen on all IPv4/IPv6 interfaces
listen-on port 53 { any; };
listen-on-v6 port 53 { any; };
// Allow queries (authoritative + recursive) only from trusted ACL
allow-query { trusted; };
allow-recursion { trusted; };
// Disable zone transfers by default (unless you add slaves later)
allow-transfer { none; };
// Enable recursion
recursion yes;
// DNSSEC validation (recommended on modern BIND/Ubuntu)
dnssec-validation auto;
auth-nxdomain no; // conform to RFC1035
empty-zones-enable yes;
// Some sensible performance/security tuning
max-cache-size 512M;
max-cache-ttl 604800; // 7 days
max-ncache-ttl 3600; // 1 hour
minimal-responses yes;
qname-minimization relaxed;
// Hide software version
version "DNS Server";
// Forwarders (optional) - remove or change if you want pure recursion
// forwarders {
// 1.1.1.1;
// 8.8.8.8;
// };
};
This configuration ensures recursive queries are only served to your specified networks plus localhost.
4. Define the infosecmonkey.org Zone
We now make BIND authoritative for `infosecmonkey.org` by defining a master zone and its zone file.[^1_6][^1_7][^1_2][^1_1]
4.1 Add Zone to named.conf.local
Edit /etc/bind/named.conf.local:
sudo vi /etc/bind/named.conf.local
Append the following block:
zone "infosecmonkey.org" {
type master;
file "/etc/bind/db.infosecmonkey.org";
};
This tells BIND to load the zone data from /etc/bind/db.infosecmonkey.org.
5. Create Zone File for infosecmonkey.org
We will create a basic but functional zone:
– SOA
– NS records
– A record for the nameserver itself
– A couple of sample A records (adjust to your environment).
Create the zone file:
sudo vi /etc/bind/db.infosecmonkey.org
Paste and adjust as needed:
$TTL 86400
@ IN SOA ns1.infosecmonkey.org. admin.infosecmonkey.org. (
2026041701 ; Serial (YYYYMMDDnn)
3600 ; Refresh (1 hour)
1800 ; Retry (30 minutes)
1209600 ; Expire (14 days)
86400 ) ; Minimum TTL (1 day)
; Authoritative name servers
IN NS ns1.infosecmonkey.org.
; Nameserver A record (use your actual IP)
ns1 IN A 10.1.106.10
; Example host records
@ IN A 10.1.106.10
www IN A 10.1.106.10
api IN A 10.1.105.20
vpn IN A 10.240.0.10
Key points:
– Update the serial each time you edit the file (e.g., 2026041702).
– Replace IPs with your real host addresses.
Set proper permissions (usually already fine, but explicit is safe):
sudo chown root:bind /etc/bind/db.infosecmonkey.org
sudo chmod 640 /etc/bind/db.infosecmonkey.org
6. Check Configuration and Reload BIND
Use BIND’s built-in checkers:
sudo named-checkconf
If no output, syntax is OK.
Check the zone file syntax:
sudo named-checkzone infosecmonkey.org /etc/bind/db.infosecmonkey.org
You should see something like:
zone infosecmonkey.org/IN: loaded serial 2026041701
If all is good, reload BIND:
sudo systemctl reload bind9Or restart if you prefer
sudo systemctl restart bind9
7. Allow DNS Through Ubuntu Firewall (ufw)
If you use ufw, allow port 53 (UDP/TCP).
sudo ufw allow 53/tcp
sudo ufw allow 53/udp
sudo ufw reload
Your ACL still restricts who can use recursion; firewall only governs basic reachability.
8. Test Authoritative and Recursive Queries
From a host in 10.1.106.0/24, 10.1.105.0/24, or 10.240.0.0/15, or from the server itself:
8.1 Test Zone Resolution
dig @10.1.106.10 infosecmonkey.org
dig @10.1.106.10 www.infosecmonkey.org
dig @10.1.106.10 ns1.infosecmonkey.org
You should receive NOERROR responses with the configured A records.
8.2 Test Recursion (External Domain)
dig @10.1.106.10 google.com
dig @10.1.106.10 www.cloudflare.com
You should see status: NOERROR and IP addresses in the ANSWER section, plus the ra (recursion available) flag.
8.3 Test Recursion from a Disallowed IP
From a non-allowed subnet (or simulate with a VM on another network) you should see queries refused or timed out:
dig @10.1.106.10 google.com
Expected: status: REFUSED (or similar), indicating ACLs are working.
9. Optional: Logging for Troubleshooting
To get more visibility, you can add logging channels and categories.
Edit /etc/bind/named.conf.local and add before your zone:
logging {
channel default_syslog {
syslog daemon;
severity info;
};
channel query_log {
file "/var/log/named/queries.log" versions 3 size 10m;
severity info;
print-time yes;
`};
category queries { query_log; };
category default { default_syslog; };
};
Create log directory and adjust permissions:
sudo mkdir -p /var/log/named
sudo chown bind:bind /var/log/named
sudo chmod 750 /var/log/named
sudo systemctl restart bind9
You can then tail query logs:
sudo tail -f /var/log/named/queries.log
10. Quick Health Checklist
– systemctl status bind9 shows running.
– named-checkconf and named-checkzone both OK.
– dig for infosecmonkey.org returns your internal IPs.
– dig google.com via your server works from allowed networks and is refused from others
Recent posts
-
-
DNS is one of those technologies that quietly underpins... Full Story
-
BGP issues on FortiGate firewalls usually trace back to... Full Story
-
Every time your laptop talks to your router, a... Full Story
-
If you've spent any time configuring NAT on a... Full Story
-
If you have spent any time configuring firewall policies... Full Story
-
High availability on FortiGate is one of those features... Full Story
-
If you've configured SD-WAN on a FortiGate, you've almost... Full Story
-
FortiLink is the management protocol that turns a FortiSwitch... Full Story
-
FortiSwitches are pretty rock solid from Mean Time Between... Full Story
-
This is a quicky tip. Have you ever gone... Full Story
-
DNS is one of those quiet pieces of internet... Full Story
-
This article is an updated version of the previous... Full Story
-
You will add ns2 as a secondary (slave) BIND9... Full Story
-
In the process of deploying my lab, I needed... Full Story
-
RFC 8805, used to be known as Self-Correcting IP... Full Story
-
Years back, I wrote an article about certificate pinning. ... Full Story
-
FortiGates have the ability to send alerts to Microsoft... Full Story
-
In this post, I am going to walk through... Full Story
-
Troubleshooting VoIP on a FortiGate can feel like trying... Full Story
-
Prior to FortiOS 7.0, there were three commands to... Full Story
-
In this post, I am going to go over... Full Story
-
What we are going to do: We are going... Full Story
-
Choosing between FGCP (FortiGate Clustering Protocol) and FGSP (FortiGate... Full Story
-
Creating a VLAN on macOS (The "Pro" Move) A... Full Story
-
This blog post explores the logic behind how macOS... Full Story
-
Pretty Fly for a Wi-Fi Tell My Wi-Fi Love... Full Story
-
Part of my daily gig is creating BoMs (Bill-of-Materials)... Full Story
-
ICMP introduces several security risks, but careful filtering, rate... Full Story
-
The command diag debug application dhcps -1 enables full... Full Story
-
In the world of FortiOS, execute tac report is... Full Story
-
LLDP; What is it The Link Layer Discovery Protocol... Full Story
-
What it actually does When you run diagnose fdsm... Full Story
-
Monkey Bites are bite-sized, high-impact security insights designed for... Full Story
-
I have run macOS in macOS with Parallels but... Full Story
-
Don't be confused with my other FortiNAC posts where... Full Story
-
This is the third session in a multi-part article... Full Story
-
Today I was configuring key-based authentication on a FortiGate... Full Story
-
Netcat, often called the "Swiss Army knife" of networking,... Full Story
-
At its core, IEEE 802.1X is a network layer... Full Story
-
In case you did not see the previous FortiNAC... Full Story
-
This is our 5th session where we are going... Full Story
-
Now that we have Wireshark installed and somewhat configured,... Full Story
-
The Philosophy of Packet Analysis Troubleshooting isn't about looking... Full Story
-
DISCLAIMER: Please see link above for the official Fortinet... Full Story
-
The underlying assumption that Let’s Encrypt requires you to... Full Story
-
FortiGate ships with thousands of built-in application signatures, but... Full Story