Kennisbank › Dns › DNS on Linux: How Name Resolution Actually Works
dns starter 28 September 2026

DNS on Linux: How Name Resolution Actually Works

DNS on Linux: How Name Resolution Actually Works You type `pixzo.nl` into a browser and it loads. Behind that single action sits a chain of queries across a

This article walks through what DNS does, how a query travels from your machine to an authoritative server and back, and how to configure and inspect name resolution on a modern Linux system. It is aimed at anyone running a server, debugging a container network, or wondering why a domain move takes hours to propagate.

Requirements

You need a Linux system with `systemd` 245 or newer — that covers Ubuntu 20.04+, Debian 11+, RHEL 8+, and Fedora 32+. Older distributions use `resolvconf` or a hand-written `/etc/resolv.conf`, and the commands below will not all apply.

You also need:

  • Root or `sudo` access, for editing resolver configuration.
  • The `bind-utils` package on RHEL-family systems, or `dnsutils` on Debian-family systems, for `dig` and `nslookup`.
  • Outbound UDP and TCP port 53, or port 853 if you plan to use DNS over TLS.
Install the query tools first if they are missing:

```bash

Debian / Ubuntu

sudo apt update && sudo apt install -y dnsutils

RHEL / Fedora / Rocky

sudo dnf install -y bind-utils ```

How a query travels

Before touching any config, it helps to know what you are configuring.

DNS is a distributed, hierarchical database. There is no central list of every domain and its IP address. Instead the data is spread across root servers, top-level domain servers for `.com`, `.nl`, `.org`, and authoritative name servers that hold the actual records for a specific domain.

When your machine needs to resolve a name, it does not walk that hierarchy itself. It hands the question to a recursive resolver — usually one run by your ISP, or a public one like Cloudflare at `1.1.1.1` or Google at `8.8.8.8`.

The resolver does the walking. It asks a root server, gets pointed to the right TLD server, asks that TLD server, gets pointed to the authoritative name server for the domain, and finally receives the record. Then it caches the answer and returns it to you.

That caching is why DNS feels instant after the first lookup, and also why a domain move is not instant. Every record carries a TTL — a time to live in seconds — and until that TTL expires on every resolver that cached it, some users still get the old address.

The cost of this design is latency on a cold cache and stale answers after a change. The benefit is that no single machine has to hold the entire internet's naming table, which is the only reason any of this scales.

Steps

1. Check what your system currently uses

Start by seeing which resolver your machine talks to.

```bash resolvectl status ```

On systems without `systemd-resolved`, use:

```bash cat /etc/resolv.conf ```

`resolvectl status` shows the per-link DNS servers, the current DNS domain, and whether DNSSEC is active. If `/etc/resolv.conf` is a symlink to `/run/systemd/resolve/stub-resolv.conf`, then `systemd-resolved` is in charge and editing `/etc/resolv.conf` directly will not survive a reboot.

2. Understand the stub resolver

`systemd-resolved` runs a local stub listener on `127.0.0.53:53`. Applications send their queries there, and the stub forwards them to the upstream servers configured for the active link.

This indirection is why `127.0.0.53` shows up in `/etc/resolv.conf` instead of your actual upstream. It also means a broken `systemd-resolved` breaks every name lookup on the box at once, including the ones your package manager needs.

Check that the stub is listening:

```bash ss -lunp | grep 127.0.0.53 ```

If nothing is listening on port 53, `systemd-resolved` is not running and you are resolving some other way.

3. Set upstream DNS servers

Edit the global resolver configuration.

```bash sudo nano /etc/systemd/resolved.conf ```

Set your upstream servers and fallback:

```ini [Resolve] DNS=1.1.1.1 9.9.9.9 FallbackDNS=8.8.8.8 8.8.4.4 DNSSEC=allow-downgrade DNSOverTLS=opportunistic Cache=yes ```

`1.1.1.1` is Cloudflare, `9.9.9.9` is Quad9, which blocks known malicious domains. `FallbackDNS` only kicks in when the primary servers do not answer at all.

`DNSSEC=allow-downgrade` validates signatures when the upstream supports it but does not fail closed if it does not. That is a reasonable default; `yes` is stricter and will break resolution against resolvers that do not speak DNSSEC.

`DNSOverTLS=opportunistic` encrypts the query if the upstream offers it on port 853, and falls back to plain port 53 if not. `yes` forces it and will fail against servers that do not support it.

4. Apply the change

```bash sudo systemctl restart systemd-resolved ```

A restart clears the cache, which is what you want after changing upstream servers. On a busy box this causes a brief burst of cold lookups.

Verify the new servers are picked up:

```bash resolvectl status | grep -A2 "Global" ```

5. Query a name directly

`dig` bypasses the stub and asks a server of your choice, which is how you separate a resolver problem from a network problem.

```bash dig @1.1.1.1 pixzo.nl A ```

The `A` record type returns IPv4 addresses. Use `AAAA` for IPv6, `MX` for mail exchangers, `CNAME` for aliases, and `TXT` for verification strings.

Look at the `ANSWER SECTION` for the record and the `Query time` line for how long it took. A query time under 20 ms means the answer came from cache; several hundred milliseconds means a full recursive walk.

6. Trace the full resolution path

When a name resolves for some people and not others, trace it.

```bash dig +trace pixzo.nl ```

This walks the hierarchy from the root servers down, showing every delegation step. It is the fastest way to see whether a delegation is missing or an authoritative server is unreachable.

`+trace` ignores your configured resolver entirely and does the recursion itself. That is the point — it shows you the raw chain.

7. Inspect records with a specific type

To check mail routing or a verification record:

```bash dig pixzo.nl MX +short dig _dmarc.pixzo.nl TXT +short ```

`+short` strips everything but the answer. Useful in scripts, useless when you need to see the TTL or the authority section.

8. Flush the local cache

After changing a record at your DNS provider, flush the local cache so you are not testing against a stale answer.

```bash sudo resolvectl flush-caches ```

Then confirm the TTL on the record you changed:

```bash dig pixzo.nl A +noall +answer ```

The number in the second column is the remaining TTL in seconds. If it is counting down from a value you set an hour ago, the change has not propagated to that server yet.

Verification

Confirm that resolution works end to end from the machine itself.

```bash resolvectl query pixzo.nl ```

A working setup returns the resolved addresses, the interface the query went out on, and the packet count. If you see `resolve call failed: No appropriate name servers or networks for name found`, the link has no DNS server assigned — check `resolvectl status` for that specific interface.

Then confirm an application-level lookup:

```bash getent hosts pixzo.nl ```

`getent` uses the same path your applications do, including `/etc/nsswitch.conf` and any `mdns` or `llmnr` entries. If `dig` works but `getent` does not, the problem is in NSS configuration, not in DNS.

Common problems

Resolution works with `dig @8.8.8.8` but not with plain `dig`. The stub resolver is not running or not reachable. Check `systemctl status systemd-resolved` and confirm something is listening on `127.0.0.53:53`. A common cause is another service, such as `dnsmasq` or a VPN client, having taken port 53 first.

A domain move is not taking effect. The old record is still cached somewhere with a long TTL. You cannot force other resolvers to drop it; you can only wait for the TTL to expire. Set a low TTL — 300 seconds or less — a day before a planned move, and raise it again afterwards. There is no way to shorten a TTL retroactively.

DNSSEC validation fails and the domain stops resolving. The zone has a broken signature or an expired key. Check with `dig +dnssec pixzo.nl` and look for the `ad` flag in the response, which indicates the answer was validated. If you need the domain to resolve right now and the zone owner is not reachable, `DNSSEC=no` in `resolved.conf` disables validation — a decision with a security cost you should undo once the zone is fixed.

DNS is one of those systems that works silently until it does not, and then it takes everything down with it. The commands above are the ones worth having in your fingers before that happens, not after.

← Terug naar kennisbank
← Terug naar kennisbank