Welcome back to Linux Networking Mastery! In Part 1 we covered the basics of the network stack and inspection tools. Part 2 taught us how to manage interfaces and assign IPs persistently using modern tools like Netplan, NetworkManager (nmcli), and systemd-networkd. Part 3 dove into routing: manipulating tables, static/policy routes, network namespaces, and building a simple router.
Now we turn to name resolution—the process that turns human-friendly hostnames (like google.com) into IP addresses. This is critical for almost every network task beyond raw IP connectivity.
We'll explore how Linux resolves names, the role of key files and services, configuring DNS servers (including modern systemd-resolved), setting up local caching, and troubleshooting common issues with practical tools.
How Linux Resolves Hostnames: The NSSwitch Layer
Linux uses the Name Service Switch (NSS) to decide where to look for name information. The relevant line in /etc/nsswitch.conf is usually:
hosts: files dns myhostname resolve [!UNAVAIL=return]
Order matters:
files→ checks/etc/hostsfirst (static mappings)dns→ queries DNS servers (traditional via glibc resolver)myhostname→ local hostname resolutionresolve→ uses systemd-resolved (if enabled and nss-resolve is configured)
On many modern distributions (Ubuntu 18.04+, Fedora 33+, recent Debian), systemd-resolved is the default local resolver, and /etc/resolv.conf points to 127.0.0.53 (the stub listener). This provides caching, per-interface DNS, DNSSEC support, and split-DNS capabilities.
Check your setup:
cat /etc/nsswitch.conf | grep hosts
ls -l /etc/resolv.conf # Often a symlink to ../run/systemd/resolve/stub-resolv.conf
Configuring Basic DNS: /etc/resolv.conf (Legacy/Direct)
Historically, you edited /etc/resolv.conf directly:
nameserver 8.8.8.8
nameserver 1.1.1.1
search example.local
But on systems with systemd-resolved, NetworkManager, or Netplan, this file is managed dynamically—manual edits are overwritten on reboot or network change.
Best practice: configure via your network manager instead.
Modern DNS with systemd-resolved (Default on Many Distros)
systemd-resolved runs as a daemon, listens on 127.0.0.53:53 (stub), caches responses, supports DNS-over-TLS (DoT), and handles per-link DNS from DHCP or manual config.
Status and current config:
systemctl status systemd-resolved
resolvectl status
Global override (affects all links unless overridden):
Edit drop-in file (preferred over editing main conf):
sudo mkdir -p /etc/systemd/resolved.conf.d
sudo nano /etc/systemd/resolved.conf.d/10-custom.conf
Example content:
[Resolve]
DNS=1.1.1.1 1.0.0.1 # Cloudflare
FallbackDNS=8.8.8.8 8.8.4.4
DNSOverTLS=yes
Domains=~.
Apply:
sudo systemctl restart systemd-resolved
Per-interface DNS comes from your network config (see below).
DNS Configuration via Network Managers (Persistent)
Netplan (Ubuntu/Debian family):
In your YAML file (e.g., /etc/netplan/01-netcfg.yaml):
network:
version: 2
ethernets:
enp0s3:
dhcp4: yes
nameservers:
addresses: [1.1.1.1, 8.8.8.8]
search: [example.local]
Apply:
sudo netplan apply
NetworkManager (Fedora/RHEL, many desktops):
Via nmcli:
sudo nmcli con mod "System enp0s3" ipv4.dns "1.1.1.1 8.8.8.8"
sudo nmcli con mod "System enp0s3" ipv4.dns-search "example.local"
sudo nmcli con up "System enp0s3"
Or edit connection file in /etc/NetworkManager/system-connections/.
systemd-networkd:
In .network file:
[Network]
DNS=1.1.1.1 8.8.8.8
Domains=example.local
Local DNS Caching: dnsmasq or unbound
For faster resolution and reduced external queries, run a local cache.
dnsmasq (lightweight, often bundled with NetworkManager):
- Disable systemd-resolved stub if conflicting (set
DNSStubListener=noin resolved.conf.d drop-in) - Configure
/etc/dnsmasq.confor use NetworkManager integration - Common on older Ubuntu setups or routers
unbound (more feature-rich, recursive resolver, DNSSEC validation):
Install:
sudo apt install unbound # Debian/Ubuntu
sudo dnf install unbound # Fedora/RHEL
Basic config in /etc/unbound/unbound.conf:
server:
interface: 127.0.0.1
do-ip6: no
harden-dnssec-stripped: yes
Point resolved or resolv.conf to 127.0.0.1.
Many prefer systemd-resolved's built-in caching today unless needing advanced recursion or DoH.
Troubleshooting DNS Issues
Essential tools:
resolvectl status/resolvectl query google.com(systemd-resolved specific)dig google.com @1.1.1.1(test specific server; installdnsutils/bind-utils)nslookup google.comhost google.comping -c 3 google.com(quick connectivity + resolution check)
Common problems & fixes:
- Slow resolution → enable local caching
- Wrong DNS from DHCP → override in network config
- 127.0.0.53 not responding →
sudo systemctl restart systemd-resolved - Split-DNS (VPN) issues → check
resolvectl domainand routing domains (~.)
Hands-On Exercises
- View current resolution setup:
resolvectl statusorcat /etc/resolv.conf - Set global Cloudflare DNS via systemd-resolved drop-in; restart service and test with
dig. - Override DNS for one interface via Netplan/nmcli/systemd-networkd; verify per-link settings.
- Test resolution failure: temporarily set invalid DNS, observe symptoms, fix.
Tip: Use public resolvers like Cloudflare (1.1.1.1), Quad9 (9.9.9.9), or Google (8.8.8.8) for reliability.
What's Next?
In Part 5, we'll secure our networks with firewalls: moving from legacy iptables to modern nftables, using front-ends like firewalld (RHEL/Fedora) and ufw (Ubuntu), and writing practical rules for common services.