On modern systems, /etc/resolv.conf is often a symlink managed by systemd-resolved or NetworkManager. Manual edits will be overwritten. Check the symlink target:
# /etc/resolv.conf -> /run/systemd/resolve/stub-resolv.conf
The Name Service Switch determines the order of lookup mechanisms:
hosts: files dns myhostname
The "hosts' line determines name resolution order:
files — /etc/hosts (checked first)
dns — DNS (resolv.conf nameservers)
myhostname — systemd's nss-myhostname (returns 127.0.0.2 for local hostname)
mdns4 — multicast DNS (Avahi) for .local
mdns4_minimal — same, but only for .local names
resolve — systemd-resolved (nss-resolve)
# DNS-first (traditional)
# Files-first (default on most distributions)
hosts: files mdns4_minimal [NOTFOUND=return] dns myhostname
hosts: resolve [!UNAVAIL=return] files myhostname
# /etc/hosts — static hostname-to-address mapping
# Format: IP_address canonical_hostname [aliases...]
127.0.1.1 myhost.example.com myhost
::1 localhost ip6-localhost ip6-loopback
# Override DNS for specific hosts
10.0.0.50 db-master.internal
10.0.0.51 db-replica.internal
systemd-resolved is a local DNS resolver and cache that integrates with systemd.
# DNS servers (static configuration)
# Fallback DNS servers (used when no per-link DNS is configured)
# DNS-over-TLS mode (no, opportunistic, yes)
# MulticastDNS (yes, no, resolve)
# DNSSEC mode (no, allow, yes)
# systemd-resolved provides a stub resolver at 127.0.0.53
# This is the default on Ubuntu 18.04+ and other distributions
# Query a specific domain
resolvectl query example.com
# Monitor DNS queries in real-time
resolvectl log-level debug
journalctl -u systemd-resolved -f
# Set DNS for a specific interface
resolvectl dns eth0 8.8.8.8 8.8.4.4
# Set search domains for an interface
resolvectl domain eth0 ~example.com
# View per-interface configuration
dnsmasq is a lightweight DNS forwarder, DHCP server, and TFTP server. It is commonly used as a Local DNS cache and for small network management.
domain-needed # refuse queries without dotted part
bogus-priv # refuse private IP responses from public DNS
listen-address=127.0.0.1 # listen only on localhost
listen-address=10.0.0.1 # listen on LAN interface
address=/myapp.local/10.0.0.100
address=/db.internal/10.0.0.50
# Hosts file (additional to /etc/hosts)
addn-hosts=/etc/dnsmasq.hosts
cache-size=1000 # cache up to 1000 entries
min-cache-ttl=300 # minimum TTL 5 minutes
max-cache-ttl=86400 # maximum TTL 24 hours
log-facility=/var/log/dnsmasq.log
systemctl enable --now dnsmasq
# Update resolv.conf to point to dnsmasq
echo "nameserver 127.0.0.1" | sudo tee /etc/resolv.conf
dig example.com @127.0.0.1
# First query: query time ~50ms (upstream)
dig example.com @127.0.0.1
# Second query: query time ~0ms (cached)
sudo systemctl restart dnsmasq
sudo kill -HUP $(pidof dnsmasq)
unbound is a validating, recursive, caching DNS resolver.
access-control: 127.0.0.0/8 allow
access-control: 10.0.0.0/8 allow
# Forward to upstream resolvers
auto-trust-anchor-file: "/var/lib/unbound/root.key"
# Privacy (do not send client IP to upstream)
systemctl enable --now unbound
dig sigfail.verteiltesysteme.net @127.0.0.1
# Should return SERVFAIL (bogus)
dig sigok.verteiltesysteme.net @127.0.0.1
# Should return NOERROR (secure)
BIND9 is the reference DNS server implementation, suitable for authoritative and recursive DNS.
directory "/var/cache/bind";
// Listen on specific interfaces
listen-on { 10.0.0.1; 127.0.0.1; };
// Allow queries from specific networks
allow-query { 10.0.0.0/24; 127.0.0.0/8; };
// Allow recursion (restrict for security)
allow-recursion { 10.0.0.0/24; 127.0.0.0/8; };
// Forwarders (if using as caching resolver)
file "/etc/bind/db.example.com";
allow-transfer { 10.0.0.2; }; # secondary NS IP
zone "0.0.10.in-addr.arpa" {
file "/etc/bind/db.10.0.0";
; /etc/bind/db.example.com
@ IN SOA ns1.example.com. admin.example.com. (
2026040601 ; Serial (YYYYMMDDNN)
86400 ) ; Negative Cache TTL (1 day)
api IN CNAME www.example.com.
; Round-robin for load balancing
; /etc/bind/db.10.0.0 — reverse zone
@ IN SOA ns1.example.com. admin.example.com. (
1 IN PTR ns1.example.com.
2 IN PTR ns2.example.com.
10 IN PTR www.example.com.
50 IN PTR db.example.com.
named-checkzone example.com /etc/bind/db.example.com
named-checkzone 0.0.10.in-addr.arpa /etc/bind/db.10.0.0
named-checkconf /etc/bind/named.conf
# Request a specific hostname
# Request specific IP (not guaranteed)
# ip_address 10.0.0.100/24
# Static configuration (fallback if DHCP fails)
static ip_address=10.0.0.100/24
static domain_name_servers=10.0.0.1 8.8.8.8
# Disable IPv4 on specific interface
# View DHCP configuration
nmcli device show eth0 | grep -i dhcp
nmcli connection show "Wired connection 1"
nmcli connection modify "Wired connection 1" \
ipv4.dhcp-send-hostname yes \
ipv4.dhcp-hostname "myhost"
# Configure static DNS with DHCP
nmcli connection modify "Wired connection 1" \
ipv4.dns "8.8.8.8 8.8.4.4" \
# Request specific hostname
# Send vendor class identifier
# DHCP range (start, end, lease time)
dhcp-range=10.0.0.100,10.0.0.200,12h
dhcp-option=option:router,10.0.0.1
dhcp-option=option:dns-server,10.0.0.1,8.8.8.8
dhcp-option=option:ntp-server,10.0.0.1
dhcp-option=option:domain-search,example.com
# Gateway (alternative to option:router)
# DNS server (alternative to option:dns-server)
dhcp-option=6,10.0.0.1,8.8.8.8
# Fixed IP assignments (by MAC address)
dhcp-host=aa:bb:cc:dd:ee:ff,10.0.0.50,infinite
dhcp-host=11:22:33:44:55:66,server1,10.0.0.51
dhcp-boot=pxelinux.0,pxeserver,10.0.0.1
option domain-name "example.com";
option domain-name-servers ns1.example.com, 8.8.8.8;
default-lease-time 86400;
subnet 10.0.0.0 netmask 255.255.255.0 {
option subnet-mask 255.255.255.0;
option broadcast-address 10.0.0.255;
option domain-name-servers 10.0.0.1, 8.8.8.8;
option ntp-servers 10.0.0.1;
range 10.0.0.100 10.0.0.200;
hardware ethernet aa:bb:cc:dd:ee:ff;
option host-name "server1";
hardware ethernet 11:22:33:44:55:66;
systemctl enable --now isc-dhcp-server
cat /var/lib/dhcp/dhcpd.leases
# Query specific record type
# Query specific DNS server
dig example.com @127.0.0.1
# Reverse DNS (PTR lookup)
# Query with specific options
dig +noall +answer example.com A
dig +noall +comments example.com # show headers
# Batch queries from file
cat << 'EOF' > queries.txt
# Check specific nameserver
dig @ns1.example.com example.com SOA
nslookup example.com 8.8.8.8
# Verbose (show all records)
# Query using systemd-resolved
resolvectl query example.com
resolvectl query example.com A
resolvectl query example.com AAAA
# Monitor DNS transactions
resolvectl log-level debug
journalctl -u systemd-resolved -f
DNS=1.1.1.1#cloudflare-dns.com 8.8.8.8#dns.google
# DNSOverTLS=no — disabled
# DNSOverTLS=opportunistic — use DoT if server supports it
# DNSOverTLS=yes — require DoT, fail if unsupported
forward-tls-upstream: yes
forward-addr: 1.1.1.1@853#cloudflare-dns.com
forward-addr: 8.8.8.8@853#dns.google
Split DNS (split-horizon DNS) returns different responses depending on the client’s source network.
# Internal network sees internal addresses
server=/example.com/10.0.0.1
# External queries go to public DNS
address=/www.example.com/10.0.0.10
address=/api.example.com/10.0.0.11
match-clients { "internal"; };
file "/etc/bind/db.example.com.internal";
file "/etc/bind/db.example.com.external";
Multicast DNS resolves .local hostnames on local networks without a central DNS server.
apt-get install avahi-daemon # Debian/Ubuntu
dnf install avahi # Fedora/RHEL
systemctl enable --now avahi-daemon
# Browse services on the network
avahi-browse -a # all services
avahi-browse -ar # all, resolve addresses
avahi-browse -rt _ssh._tcp # SSH services
avahi-browse -rt _http._tcp # HTTP services
# /etc/avahi/services/myapp.service
<?xml version="1.0" standalone='no'?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
# /etc/avahi/avahi-daemon.conf
# On systems using systemd-resolved, /etc/resolv.conf is a symlink
# lrwxrwxrwx /etc/resolv.conf -> /run/systemd/resolve/stub-resolv.conf
# To make permanent changes, configure systemd-resolved instead:
# /etc/systemd/resolved.conf
# On systems using resolvconf:
# Add: nameserver 8.8.8.8
# After changing DNS records, old values may be cached:
# 1. Local resolver cache
sudo systemctl restart systemd-resolved
sudo systemctl restart dnsmasq
sudo systemctl restart unbound
# Flush in browser settings
sudo systemctl restart nscd
dig +trace example.com @8.8.8.8
# With default ndots=5, "myserver" has fewer than 5 dots
# So the resolver first tries "myserver.example.com" and "myserver.internal.example.com"
# before trying "myserver" as-is
# This causes delays and unnecessary queries
echo "options ndots:1" | sudo tee -a /etc/resolv.conf
ping myserver.example.com # not just "myserver"
# Check current DHCP lease
dhcpcd -T eth0 # test mode, show DHCP exchange
dhcpcd -U eth0 # show current lease
nmcli device disconnect eth0
nmcli device connect eth0
systemctl restart systemd-networkd
# If it returns nothing, check /etc/nsswitch.conf
cat /etc/nsswitch.conf | grep hosts
# Check if the domain search list is correct
# Check if the DNS server has the internal zone
dig @10.0.0.1 db.internal
# Common cause: split DNS misconfiguration
# The internal resolver does not have the zone, or the
# external resolver is being queried instead
This topic covers the core concepts of dns and dhcp on linux, including underlying theory, practical implementation, and key applications.
Key concepts include:
- TCP/IP and the OSI model
- network topologies
- protocols (HTTP, FTP, SMTP)
- encryption and security
- client-server and peer-to-peer
Understanding these concepts thoroughly is essential for both examinations and practical programming, and requires both theoretical knowledge and hands-on practice.
Worked examples demonstrating the application of key concepts are covered in the detailed sub-pages linked above.