Archive for the ‘DNS’ Category

How to Deploy Central DNS on Linux with 3 Authoritative Servers and 1 Recursive Cache

Friday, December 19th, 2025

unbound-centrall-dns-deployment-3-linux-authoritative-servers-and-1-caching-DNS

Centralized DNS is one of those services that must be always UP, predictable, and fast. When it isn’t, everything breaks in strange and unpleasant ways.

This article describes a robust central DNS architecture for Linux environments using:

  • 3 authoritative DNS servers
  • 1 dedicated caching resolver
  • Clear separation between authoritative and recursive roles

Architecture Overview

Roles

Server

Role

Purpose

dns-auth-01

Authoritative

Primary (master)

dns-auth-02

Authoritative

Secondary (slave)

dns-auth-03

Authoritative

Secondary (slave)

dns-cache-01

Recursive / Cache

Internal resolution

Why Separate Roles?

Authoritative and recursive DNS have very different workloads:

  • Authoritative DNS: predictable, zone-based, read-only
  • Recursive DNS: bursty, cache-heavy, user-facing

Mixing them increases attack surface, complexity, and failure impact.

Software Choices

Recommended stack:

  • BIND9 or NSD for authoritative servers
  • Unbound for caching/recursive resolver

Reasons:

  • Mature, well-understood behavior
  • Clear separation of responsibilities
  • Excellent Linux support
  • Scriptable and observable

Network Layout

Example internal layout:

10.0.0.10   dns-auth-01 (master)

10.0.0.11   dns-auth-02 (slave)

10.0.0.12   dns-auth-03 (slave)

10.0.0.20   dns-cache-01 (recursive)

All Linux servers point only to dns-cache-01 as their resolver.

Authoritative DNS Configuration

Master Server (dns-auth-01)

Zones are managed only on the master.

Example BIND zone definition:

zone "example.internal" {

    type master;

    file "/etc/bind/zones/example.internal.zone";

    allow-transfer { 10.0.0.11; 10.0.0.12; };

    also-notify { 10.0.0.11; 10.0.0.12; };

};

Key points:

  • Zone transfers restricted by IP
  • NOTIFY enabled for fast propagation
  • No recursion enabled

Disable recursion:

options {

    recursion no;

    allow-query { any; };

};

Slave Servers (dns-auth-02 / dns-auth-03)

Example configuration:

zone "example.internal" {

    type slave;

    masters { 10.0.0.10; };

    file "/var/cache/bind/example.internal.zone";

};

Slaves:

  • Never edited manually
  • Automatically sync zones
  • Serve as HA and load distribution

Caching Resolver (dns-cache-01)

Use Unbound as a dedicated recursive resolver.

Unbound Configuration

Minimal but effective setup:

server:

    interface: 0.0.0.0

    access-control: 10.0.0.0/24 allow

    do-ip6: no

    hide-identity: yes

    hide-version: yes

    prefetch: yes

    cache-min-ttl: 300

    cache-max-ttl: 86400

Forward Internal Zones to Authoritative Servers

forward-zone:

    name: "example.internal"

    forward-addr: 10.0.0.10

    forward-addr: 10.0.0.11

    forward-addr: 10.0.0.12

External Resolution

Either:

  • Use root hints (recommended for independence)
  • Or forward to trusted upstream resolvers

Example:

forward-zone:

    name: "."

    forward-addr: 9.9.9.9

    forward-addr: 1.1.1.1

Client Configuration

All Linux servers use the caching resolver only:

/etc/resolv.conf

nameserver 10.0.0.20

Or via systemd-resolved:

# resolvectl dns eth0 10.0.0.20

Clients never query authoritative servers directly.

High Availability Considerations

Resolver Redundancy

For production environments:

  • Deploy two caching resolvers
  • Use DHCP or systemd-resolved fallback ordering

Example:

nameserver 10.0.0.20

nameserver 10.0.0.21

Zone Management

  • Store zone files in Git
  • Increment SOA serials automatically
  • Deploy via CI/CD or Ansible

DNS changes should be auditable, not ad-hoc.

Security Hardening

Minimum recommendations:

  • No recursion on authoritative servers
  • Firewall restricts TCP/UDP 53
  • TSIG for zone transfers (optional but recommended)
  • Disable version disclosure
  • Monitor query rates

Monitoring & Validation

Useful tools:

  • dig +trace
  • unbound-control stats
  • rndc status
  • Prometheus exporters for BIND/Unbound

DNS that isn’t monitored will fail silently.

Final Thoughts

This setup scales well, is easy to reason about, and avoids the most common DNS mistakes:

  • Mixing recursive and authoritative roles
  • Letting clients query everything directly
  • Overcomplicating zone management

DNS should be boring.
If it’s exciting, something is wrong.

How to prevent /etc/resolv.conf to overwrite on every Linux boot. Make /etc/resolv.conf DNS records permanent forever

Tuesday, February 4th, 2025

how-to-make-prevent-etc-resolv.conf-to-ovewrite-on-every-linux-boot-make-etc-resolv-conf-permanent-forever

Have you recently been seriously bothered, after one of the updates from older to newer Debian / Ubuntu / CentOS or other Linux distributions by the fact /etc/resolv.conf has become a dynamic file that pretty much in the spirit of cloud technologies is being regenerated and ovewritten on each and every system (server) OS update /  reboot and due to that you start getting some wrong inappropriate DNS records /etc/resolv.conf causing you harm to the server infrastructure?

During my set of server infra i have faced that odditty for some years now and i guess every system administrator out there has suffered at a point by having to migrate an older Linux release to a newer one, where something gets messed up with DNS resolving due to that Linux OS new feature of /etc/resolv.conf not being really static any more.

The Dynamic resolv.conf file for glibc resolver is often generated used to be regenerated by resolvconf command and consequentially can be tampered by dhcpd resolved systemd service as well perhaps other mechanism depending on how the different Linux distribution architects make it to behave …

There are more than one ways to stop the annoying /etc/resolv.conf ovewritten behavior

1. Using dhcpd to stop /etc/resolv.conf being overwritten

Using dhcpd either a small null up script can be used or a separate hook script.

The null script would look like this

root@pcfreak:/root# vim /etc/dhcp/dhclient-enter-hooks.d/nodnsupdate

#!/bin/sh
make_resolv_conf() {
    :
}

root@pcfreak:/root# chmod +x /etc/dhcp/dhclient-enter-hooks.d/nodnsupdate

 

This script overrides an internal function called make_resolv_conf() that would normally overwrite resolv.conf and instead does nothing.

On old Ubuntu s and Debian versions this should work.


Alternative method is to use a small hook dhcp script like this:

root@pcfreak:/root# echo 'make_resolv_conf() { :; }' > /etc/dhcp/dhclient-enter-hooks.d/leave_my_resolv_conf_alone
chmod 755 /etc/dhcp/dhclient-enter-hooks.d/leave_my_resolv_conf_alone


Next boot when dhclient runs onreboot or when you manually run sudo ifdown -a ; sudo ifup -a , 
it loads this script nodnsupdate or the hook script and hopefully your manually configured values of /etc/resolv.conf would not mess up your file anymore.

2. Use a chattr and set immutable flag attribute to /etc/resolv.conf to prevent re-boot to ovewrite it

Anyways the universal and simple way "hack" to prevent /etc/resolv.conf many prefer to use instead of dhcp (especially as not everyone is running a dhcp on a server) , to overwrite is to delete the file and make it immutable with chattr (assuming chattr is supported by the filesystem i.e. EXT3 / EXT4 / XFS , you use on the Linux.).

You might need to check the filesystem type, before using chattr.

root@pcfreak:/root# blkid  | awk '{print $1 ,$3, $4}'
/dev/xvda1: TYPE="xfs"
/dev/xvda2: TYPE="LVM2_member"
/dev/mapper/centos-root: TYPE="xfs"
/dev/mapper/centos-swap: TYPE="swap"
/dev/loop0:
/dev/loop1:
/dev/loop2:

 

Normally EXT fs and XFS support it, note that this is not going to be the case with a network filesystem like NFS.

If you have some weird Filesystem type and you try to chattr you will get error like:

chattr: Inappropriate ioctl for device while reading flags on /etc/resolv.conf

To make /etc/resolv.conf file unchangeable on next boot by dhcpd or systemd-resolved

 a systemd service that provides network name resolution to local applications via a D-Bus interface, the resolve NSS service (nss-resolve)
 

root@pcfreak:/root# rm -f /etc/resolv.conf  
{ echo "nameserver 1.1.1.1";
echo "nameserver 1.0.0.1;
echo "search mydomain.com"; } >  /etc/resolv.conf
chattr +i  /etc/resolv.conf
reboot  


Also it is a good think if you don't plan after some update to have unexpected results caused by systemd-resolved doing something strange is to rename to /etc/systemd/resolved.conf.dpkg-bak or completely remove file

/etc/systemd/resolved.conf

To prevent dhcpd to overwrite the server /etc/resolv.conf from something automatically taken from preconfigured central DNS inside the network configurations made from /etc/network/interfaces configurations such as:

        dns-nameservers 127.0.0.1 8.8.8.8 8.8.4.4 207.67.222.222 208.67.220.220


You need to change the DHCP configuration file named dhclient.conf and use the supersede option. 
To so Edit /etc/dhcp/dhclient.conf.

Look for lines like these:

#supersede domain-name "fugue.com home.vix.com";
#prepend domain-name-servers 127.0.0.1;

Remove the preceding “#” comment and use the domain-name and/or domain-name-servers which you want (your DNS FQDN). Save and hopefully the DNS related ovewrite to /etc/resolv.conf would be stopped, e.g. changes inside /etc/resolv.conf mnually done should stay permanent.

Also it is a good practice to disable ddns-update-style direcive inside /etc/dhcp/dhcpd.conf

root@pcfreak:/root# vim /etc/dhcp/dhcpd.conf
##ddns-update-style none;

However on many newer Debian Linux as of 2025 and its .deb based derivative distros, you have to consider the /etc/resolv.conf is a symlink to another file /etc/resolvconf/run/resolv.conf

If that is the case with you then you'll have to set the immutable chattr attribute flag like so

root@pcfreak:~# chattr -V +i /etc/resolvconf/run/resolv.conf
chattr 1.47.0 (5-Feb-2023)
Flags of /etc/resolvconf/run/resolv.conf set as —-i—————–

root@pcfreak:/root# lsattr /etc/resolvconf/run/resolv.conf
—-i—————– /etc/resolvconf/run/resolv.conf

3.  Make /etc/resolv.conf permanent with simple custom a rc.local boot triggered resolv.conf ovewrite from a resolv.conf_actual template file

Consider that due to the increasing complexity of how Linux based OS-es behaves and the fact the Linux is more and more written to fit integration into the Cloud and be as easy as possible to containerize or orchestrate (with lets say docker or some cloud PODs) and other multitude of OS virtualiozation stuff modernities  /etc/resolv.conf might still continue to ovewrite ! 🙂

Thus I've come up with my very own unique and KISS (Keep it Simple Stupid) method to make sure /etc/resolv.conf is kept permanent and ovewritten on every boot for that "hack" trick you only need to have the good old /etc/rc.local enabled – i have written a short article how it can be enabled on newer debian / ubuntu / fedora / centos Linux here.

Prepare your permanent and static /etc/resolv.conf file containing your preferred server DNSes under a file /etc/resolv.conf_actual

Here is an example of one of my /etc/resolv.conf template files that gets ovweritten on each boot.

root@pcfreak:/root# cat /etc/resolv.conf_actual
domain pc-freak.net
search pc-freak.net
#nameserver 192.168.0.1

nameserver 127.0.0.1
nameserver 8.8.8.8
nameserver 8.8.4.4
nameserver 212.39.90.42
nameserver 212.39.90.43
nameserver 208.67.222.222
nameserver 208.67.220.220
options timeout:2 rotate


And in /etc/rc.local place before the exit directive inside the file simple copy over the original /etc/resolv.conf file real location.

Before proceeding to add it to execute /etc/rc.local assure yourself file is being venerated by OS.
 

root@pcfreak:/etc/dhcp# systemctl status rc-local
● rc-local.service – /etc/rc.local Compatibility
     Loaded: loaded (/etc/systemd/system/rc-local.service; enabled; preset: enabled)
    Drop-In: /usr/lib/systemd/system/rc-local.service.d
             └─debian.conf
     Active: active (exited) since Sun 2024-12-08 21:59:01 EET; 1 month 27 days ago
       Docs: man:systemd-rc-local-generator(8)
    Process: 1417 ExecStart=/etc/rc.local start (code=exited, status=0/SUCCESS)
        CPU: 302ms

Notice: journal has been rotated since unit was started, output may be incomplete.

root@pcfreak:/root# vim /etc/rc.local

 

cp -rpf /etc/resolv.conf_actual /etc/resolvconf/run/resolv.conf


NB ! Make sure those line is placed before any exit 0 command in /etc/rc.local otherwise that won''t work

That's it folks 🙂 
Using this simple trick you should be no longer bothered by a mysterious /etc/resolv.conf overwritten on next server reboot or system update (via a puppet / ansible or some other centralized update automation stuff) causing you a service or infrastructure outage.

Enjoy !

Flush DNS on Mac OS X ,Windows and Linux from command line

Wednesday, January 8th, 2025

MAC OSX DNS Configuration | DNSFLEX

 

MAC OS X flush DNS cache


Open macOS /Mac OS X terminal application and type the following command under OS X version 10.5 and above:

# dscacheutil -flushcache

Mac OS X Tiger (v10.4) user, enter:

# lookupd -flushcache

macOS 11 Big Sur or 12 Monterey user, try:

# sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder

 

macOS 10.11 El Capitan, 10.12 Sierra, 10.13 High Sierra, 10.14 Mojave, or 10.15 Catalina user try:

# sudo killall -HUP mDNSResponder

 

On Mac OS X version 10.6 and onwards to dump DNS cached records
 

$ dscacheutil -cachedump -entries

Display your DNS cached records on Windows
 
Implement Windows Server DNS - Training | Microsoft Learn

  DNS cached records are stored to offload the DNS from querying it all the time in order to resolve the questionable site domain IP.

To view most recent cached DNS records on Windows use cmd:
 

c:\Windows\> ipconfig /displaydns

 

Windows IP Configuration

    array805.prod.do.dsp.mp.microsoft.com
    —————————————-
    Record Name . . . . . : array805.prod.do.dsp.mp.microsoft.com
    Record Type . . . . . : 1
    Time To Live  . . . . : 1894
    Data Length . . . . . : 4
    Section . . . . . . . : Answer
    A (Host) Record . . . : 52.143.124.236


    telemetry-incoming.r53-2.services.mozilla.com
    —————————————-
    Record Name . . . . . : telemetry-incoming.r53-2.services.mozilla.com
    Record Type . . . . . : 1
    Time To Live  . . . . : 444
    Data Length . . . . . : 4
    Section . . . . . . . : Answer
    A (Host) Record . . . : 34.120.208.123


    tunnel.googlezip.net
    —————————————-
    Record Name . . . . . : tunnel.googlezip.net
    Record Type . . . . . : 1
    Time To Live  . . . . : 36756
    Data Length . . . . . : 4

Use up/down scroll array to see the cached record you need to view in the DNS cache.
 

Flush DNS Cache on Windows OS

 


Open the terminal (Start > Run > type cmd and press the [Enter] key) and type the following command to flush DNS on Win XP/2000/7/10 etc:

# ipconfig /flushdns

 

How to Flush DNS local cache queries on Linux

How to Flush DNS Cache on Linux | Linux How to Flush DNS Guide

 

If you’re using a Linux distro such as Ubuntu, here’s how to flush the DNS cache:

Open the terminal by pressing Ctrl + Alt + T or searching for “Terminal” in the Activities menu.
Run the following command:
If you are running Ubuntu 20.04 LTS Linux or older Linux distro using systemd-resolve, use: sudo systemd-resolve –flush-caches.
If you are running Ubuntu 22.04 LTS or newer, use: sudo resolvectl flush-caches.
Enter your administrator password when prompted, and the DNS cache will be flushed.

To check the change in the DNS record is real, you can check the DNS cache statistics:

# resolvectl statistics

On older Linux distributions where /etc/resolv.conf nameserver directives are used to set the DNS for the server, to flush the cache
only options is to either flush the server used cache or change the nameserver inside the file.

 

Check the DNS cache records on older Linux distros (requires NSCD daemon)

Assuming the nscd daemon is UP and running (if not you have to install it) to check the cached local DNS records on Linux do

# service nscd status 


Reviewing Your DNS Cache on modern Linux distros

The systemd-resolved daemon reacts to USR1 by writing its cache to the system logs. We can then use the journalctl command to filter out the DNS entries.

We'll use the killall command with USR1 To send the signal to the systemd-resolved daemon. Note that although we're using the killall command, the systemd-resolved daemon continues to run. This isn't a termination signal that we're sending.

$ sudo killall -USR1 systemd-resolved

Now we'll use the journalctl command with the -u (filter by systemd unit) option to extract the log entries that have been generated by systemd-resolved . We'll redirect that output into a text files called "dns.txt."

$ sudo journalctl -u systemd-resolved > dns.txt

Then check the DNS records

$ less dns.txt

 

Then find the cached mappings between domain names and IP addresses in.

How to Flush the dnsmasq Cache on Linux

The dnsmasq application provides a DNS cache and a DHCP server.

dnsmasq is popular among with users who want to run their own DNS server, especially on non-systemd installations.

Flushing the dnsmasq DNS cache is easy. We need to send the SIGHUP signal, which tells the dnsmasq daemon to effectively reinitialize. Doing so clears its DNS cache. To send the signal we use the killall command with the -HUP flag, and the name of the application.

$ sudo killall -HUP dnsmasq

DNS Monitoring: Check and Alert if DNS nameserver resolver of Linux machine is not properly resolving shell script. Monitor if /etc/resolv.conf DNS runs Okay

Thursday, March 14th, 2024

linux-monitor-check-dns-is-resolving-fine

If you happen to have issues occasionally with DNS resolvers and you want to keep up an eye on it and alert if DNS is not properly resolving Domains, because sometimes you seem to have issues due to network disconnects, disturbances (modifications), whatever and you want to have another mean to see whether a DNS was reachable or unreachable for a time, here is a little bash shell script that does the "trick".

Script work mechacnism is pretty straight forward as you can see we check what are the configured nameservers if they properly resolve and if they're properly resolving we write to log everything is okay, otherwise we write to the log DNS is not properly resolvable and send an ALERT email to preconfigured Email address.

Below is the check_dns_resolver.sh script:

 

#!/bin/bash
# Simple script to Monitor DNS set resolvers hosts for availability and trigger alarm  via preset email if any of the nameservers on the host cannot resolve
# Use a configured RESOLVE_HOST to try to resolve it via available configured nameservers in /etc/resolv.conf
# if machines are not reachable send notification email to a preconfigured email
# script returns OK 1 if working correctly or 0 if there is issue with resolving $RESOLVE_HOST on $SELF_HOSTNAME and mail on $ALERT_EMAIL
# output of script is to be kept inside DNS_status.log

ALERT_EMAIL='your.email.address@email-fqdn.com';
log=/var/log/dns_status.log;
TIMEOUT=3; DNS=($(grep -R nameserver /etc/resolv.conf | cut -d ' ' -f2));  

SELF_HOSTNAME=$(hostname –fqdn);
RESOLVE_HOST=$(hostname –fqdn);

for i in ${DNS[@]}; do dns_status=$(timeout $TIMEOUT nslookup $RESOLVE_HOST  $i); 

if [[ “$?” == ‘0’ ]]; then echo "$(date "+%y.%m.%d %T") $RESOLVE_HOST $i on host $SELF_HOST OK 1" | tee -a $log; 
else 
echo "$(date "+%y.%m.%d %T")$RESOLVE_HOST $i on host $SELF_HOST NOT_OK 0" | tee -a $log; 

echo "$(date "+%y.%m.%d %T") $RESOLVE_HOST $i DNS on host $SELF_HOST resolve ERROR" | mail -s "$RESOLVE_HOST /etc/resolv.conf $i DNS on host $SELF_HOST resolve ERROR";

fi

 done

Download check_dns_resolver.sh here set the script to run via a cron job every lets say 5 minutes, for example you can set a cronjob like this:
 

# crontab -u root -e
*/5 * * * *  check_dns_resolver.sh 2>&1 >/dev/null

 

Then Voila, check the log /var/log/dns_status.log if you happen to run inside a service downtime and check its output with the rest of infrastructure componets, network switch equipment, other connected services etc, that should keep you in-line to proof during eventual RCA (Root Cause Analysis) if complete high availability system gets down to proof your managed Linux servers was not the reason for the occuring service unavailability.

A simplified variant of the check_dns_resolver.sh can be easily integrated to do Monitoring with Zabbix userparameter script and DNS Check Template containing few Triggers, Items and Action if I have time some time in the future perhaps, I'll blog a short article on how to configure such DNS zabbix monitoring, the script zabbix variant of the DNS monitor script is like this:

[root@linux-server bin]# cat check_dns_resolver.sh 
#!/bin/bash
TIMEOUT=3; DNS=($(grep -R nameserver /etc/resolv.conf | cut -d ' ' -f2));  for i in ${DNS[@]}; do dns_status=$(timeout $TIMEOUT nslookup $(hostname –fqdn) $i); if [[ “$?” == ‘0’ ]]; then echo "$i OK 1"; else echo "$i NOT OK 0"; fi; done

[root@linux-server bin]#


Hope this article, will help someone to improve his Unix server Infrastucture monitoring.

Enjoy and Cheers !