DNS Guide
The Domain Name System translates hostnames to IP addresses and back. On
Linux the resolver library reads /etc/resolv.conf to find upstream
nameservers, but modern systems layer systemd-resolved on top for caching
and split-DNS support. This guide covers client-side resolution, the
essential query tools (dig, nslookup, host), running BIND9 as an
authoritative nameserver, and setting up Unbound as a local caching resolver.
Back to the Networking hub. Related guides: Network Configuration | DHCP & DNS Server.
/etc/resolv.conf
The traditional resolver configuration file. It lists up to three nameservers, a search domain, and optional behaviour flags:
# /etc/resolv.conf
nameserver 8.8.8.8
nameserver 8.8.4.4
search example.com internal.example.com
options timeout:2 attempts:3 rotate
When systemd-resolved is active this file is usually a symlink to
/run/systemd/resolve/stub-resolv.conf which points at the local stub
listener 127.0.0.53.
# Check what resolv.conf points to
ls -l /etc/resolv.conf
# See the actual upstream servers resolved is using
resolvectl status
systemd-resolved (resolvectl)
systemd-resolved provides a caching stub resolver, DNSSEC validation, and
per-link DNS settings. It replaced resolvconf on most systemd-based
distributions.
# Show current DNS configuration per interface
resolvectl status
# Query a record through resolved
resolvectl query example.com
# Set DNS for a specific link
resolvectl dns eth0 1.1.1.1 9.9.9.9
# Set the search domain for a link
resolvectl domain eth0 example.com
# Flush the local cache
resolvectl flush-caches
# View cache statistics
resolvectl statistics
dig
dig (Domain Information Groper) is the Swiss-army knife of DNS debugging.
It comes from the bind-utils or dnsutils package.
# Simple A record lookup
dig example.com
# Query a specific record type
dig example.com MX
dig example.com NS
dig example.com AAAA
dig example.com TXT
# Query a specific nameserver
dig @8.8.8.8 example.com A
# Short answer only
dig +short example.com A
# Trace the delegation chain from the root
dig +trace example.com
# Reverse lookup
dig -x 93.184.216.34
# Show all common records
dig example.com ANY +noall +answer
nslookup and host
These simpler tools are useful for quick lookups:
# nslookup
nslookup example.com
nslookup -type=MX example.com
nslookup example.com 8.8.8.8 # use a specific server
# host
host example.com
host -t MX example.com
host 93.184.216.34 # reverse lookup
Running BIND9 as an authoritative nameserver
BIND9 is the most widely deployed DNS server software. Install it and configure a forward zone:
sudo apt install bind9 bind9-utils # Debian / Ubuntu
sudo dnf install bind bind-utils # RHEL / Fedora
named.conf (simplified)
// /etc/bind/named.conf.local
zone "example.lan" {
type master;
file "/etc/bind/db.example.lan";
allow-transfer { 10.0.0.2; }; // secondary NS
};
zone "0.0.10.in-addr.arpa" {
type master;
file "/etc/bind/db.10.0.0";
};
Zone file
; /etc/bind/db.example.lan
$TTL 86400
@ IN SOA ns1.example.lan. admin.example.lan. (
2025040101 ; serial (YYYYMMDDNN)
3600 ; refresh
900 ; retry
1209600 ; expire
86400 ) ; negative-cache TTL
IN NS ns1.example.lan.
IN NS ns2.example.lan.
ns1 IN A 10.0.0.1
ns2 IN A 10.0.0.2
www IN A 10.0.0.10
db IN A 10.0.0.20
# Check the zone file syntax
named-checkzone example.lan /etc/bind/db.example.lan
# Check the main configuration
named-checkconf
# Reload after changes
sudo rndc reload
Unbound as a caching resolver
Unbound is a lightweight, security-oriented caching resolver. It is an excellent choice for a local network resolver that forwards to upstream servers or performs full recursion.
sudo apt install unbound # Debian / Ubuntu
sudo dnf install unbound # RHEL / Fedora
# /etc/unbound/unbound.conf (key excerpts)
server:
interface: 0.0.0.0
access-control: 10.0.0.0/8 allow
access-control: 127.0.0.0/8 allow
do-ip6: no
# Performance tuning
num-threads: 2
msg-cache-size: 64m
rrset-cache-size: 128m
# DNSSEC: auto-trust-anchor-file ships root keys
auto-trust-anchor-file: "/var/lib/unbound/root.key"
# Local records (like /etc/hosts but served via DNS)
local-zone: "example.lan." static
local-data: "gateway.example.lan. A 10.0.0.1"
local-data: "nas.example.lan. A 10.0.0.50"
# Forward to upstream (optional -- remove for full recursion)
forward-zone:
name: "."
forward-addr: 1.1.1.1
forward-addr: 9.9.9.9
# Test the configuration
unbound-checkconf
# Start and enable
sudo systemctl enable --now unbound
# Query through unbound
dig @127.0.0.1 example.com