Skip to content

DNS Resolution


When you type curl https://example.com, you usually don’t think about DNS at all. You give Linux a hostname, and somehow the system turns that name into an IP address that the networking stack can use.

That translation is the job of DNS, but Linux’s name-resolution process involves more than simply “asking a DNS server.” Local configuration, resolver libraries, /etc/hosts, DNS servers, caching, and the application itself can all affect what happens.

This lesson builds the practical mental model you need to understand DNS on Linux and troubleshoot common resolution failures.

What Problem Does DNS Solve?

Networks communicate using IP addresses, but humans and applications often prefer names.

For example:

example.com

might resolve to an IPv4 address such as:

93.184.216.34

The application can then use that address to establish a connection.

The simplified process is:

Application
    │
    │ "What IP belongs to example.com?"
    ▼
Name resolution
    │
    ▼
IP address
    │
    ▼
Network connection

DNS therefore sits alongside the normal networking path rather than replacing it.

Name
 │
 ▼
DNS resolution
 │
 ▼
IP address
 │
 ▼
Routing
 │
 ▼
Network interface
 │
 ▼
Network

If DNS fails, routing may still be completely healthy. You can have a perfectly working network connection and still be unable to access a service by hostname.

What Is DNS?

DNS stands for Domain Name System. At its simplest, it is a distributed system that maps names to records.

The most familiar record is an address record.

For IPv4:

example.com → 93.184.216.34

For IPv6:

example.com → IPv6 address

DNS can also store other information, including records for mail delivery, aliases, and service discovery.

For Linux administration, the important starting point is:

DNS gives software a way to translate names into network information.

What Happens When Linux Resolves A Name?

Suppose an application wants to connect to:

server.example.com

A simplified flow looks like:

    flowchart LR
    A["Application"] --> R["System Name Resolution"]
    R --> H["Local /etc/hosts"]
    R --> D["Configured DNS Resolver"]
    D --> S["DNS Server"]
    S --> D
    D --> R
    R --> A
  

The exact implementation depends on the system and its configuration, but the important idea is that the application normally asks the operating system’s name-resolution facilities rather than manually constructing DNS packets itself.

The resolver logic then determines how the name should be resolved.

This distinction matters because:

Application
    ≠
DNS server

An application can ask Linux to resolve a name, and Linux can then communicate with a DNS server on the application’s behalf.

Complex View Of DNS Resolution

    sequenceDiagram
    autonumber

    participant C as Client
    participant OS as OS DNS Cache
    participant R as Recursive DNS Resolver
    participant Root as Root DNS Server
    participant TLD as TLD DNS Server
    participant Auth as Authoritative DNS Server

    C->>OS: Resolve example.com
    alt DNS record found in OS cache
        OS-->>C: Return cached IP
    else Cache miss
        OS->>R: DNS Query for example.com

        alt Record found in resolver cache
            R-->>OS: Return cached IP
        else Cache miss
            R->>Root: Query example.com
            Root-->>R: Referral to .com TLD servers

            R->>TLD: Query example.com
            TLD-->>R: Referral to authoritative nameservers

            R->>Auth: Query example.com
            Auth-->>R: Return IP address

            R-->>OS: Return IP address
        end

        OS-->>C: Return IP address
    end

    C->>C: Connect to returned IP
  

/etc/hosts: Local Name Resolution

Before involving a DNS server, Linux can resolve names locally using:

/etc/hosts

Inspect it with:

cat /etc/hosts

A typical file might contain:

127.0.0.1       localhost
127.0.1.1       mymachine
::1             localhost ip6-localhost ip6-loopback

You can also add your own entry:

192.168.1.50    fileserver

Now software that uses the system’s normal hostname-resolution mechanism can resolve:

fileserver

to:

192.168.1.50

without asking an external DNS server.

This is useful for small, controlled mappings.

For example:

192.168.1.50    database
192.168.1.60    webserver
192.168.1.70    fileserver

For a handful of machines, this can be convenient.

For a large environment, maintaining these mappings manually becomes impractical. That’s where DNS becomes important.

Note

/etc/hosts is not a DNS server and it does not contain the entire DNS database. It is simply a local source of hostname-to-address mappings.

Why Does /etc/hosts Matter For Troubleshooting?

It can create a situation that looks like DNS is working when it actually isn’t.

Suppose:

/etc/hosts

192.168.1.50    internal.example

Even if your configured DNS server is unreachable, the system may still resolve:

internal.example

through /etc/hosts.

The opposite can also happen. You may expect DNS to provide an address, but a local /etc/hosts entry can override or otherwise affect the result.

Therefore, when troubleshooting name resolution, don’t immediately assume:

“The DNS server must have this record.”

First check whether the name exists locally.

grep -n "internal.example" /etc/hosts

Where Is DNS Server Configuration?

On many Linux systems, you’ll encounter:

/etc/resolv.conf

Inspect it with:

cat /etc/resolv.conf

You may see something like:

nameserver 192.168.1.1

or:

nameserver 1.1.1.1
nameserver 8.8.8.8

A nameserver entry tells the resolver which DNS server it can query.

Conceptually:

Application
    ↓
Linux resolver
    ↓
/etc/resolv.conf
    ↓
DNS server

However, there is an important operational detail.

Why /etc/resolv.conf May Look Strange

On modern Linux systems, /etc/resolv.conf may be managed by another component rather than being a manually maintained configuration file.

It may be:

  • a regular file
  • a symbolic link
  • generated automatically
  • managed by NetworkManager
  • managed by another resolver service

You can inspect it with:

ls -l /etc/resolv.conf

For example, you might find that it points somewhere else.

This means you should be careful about treating /etc/resolv.conf as the permanent source of DNS configuration.

It is useful to inspect because it often shows the resolver configuration currently visible to applications, but the component managing it may be somewhere else.

This becomes especially relevant when we introduce nmcli later.

The Resolver Is Not The DNS Server

These terms are easy to mix up.

  • DNS server is a broad term for a DNS system that receives DNS queries and provides DNS answers. It may be authoritative, recursive, or caching.
  • DNS resolver is the component that performs DNS lookups on behalf of a client. A resolver can be on the client (a stub resolver) or be a separate recursive resolver operated by an ISP, company, etc.

A simplified picture is:

Linux application
       │
       ▼
Resolver
       │
       │ DNS query
       ▼
DNS server
       │
       │ DNS response
       ▼
Resolver
       │
       ▼
Application

The resolver might query a DNS server such as:

192.168.1.1

or a public resolver such as:

1.1.1.1

The specific DNS server doesn’t change the basic role distinction.

What Does getent hosts Do?

A very useful Linux command for testing the system’s normal name-resolution path is:

getent hosts example.com

You might get:

2606:2800:220:1:248:1893:25c8:1946 example.com

or another address depending on the current DNS response and system configuration.

getent is useful because it asks the system’s configured name-service mechanisms rather than directly testing only one particular DNS tool or protocol.

For an IPv4-focused check, you can use:

getent ahostsv4 example.com

This can be useful when you specifically want to see IPv4 results.

For example:

93.184.216.34   STREAM example.com
93.184.216.34   DGRAM
93.184.216.34   RAW

The exact output varies.

The important idea is:

getent helps test what the system itself can resolve.

That makes it particularly valuable when an application behaves differently from a standalone DNS query tool.

What Does ping Tell You About DNS?

You may already know:

ping example.com

If the command prints something such as:

PING example.com (93.184.216.34) ...

then you know the name was successfully resolved before ping began sending packets.

But this command combines multiple things:

hostname resolution
       ↓
IP address
       ↓
ICMP packets
       ↓
remote host

So if it fails, you don’t immediately know which part failed.

Compare:

getent hosts example.com

with:

ping example.com

The first is much more focused on name resolution.

The second tests resolution plus network reachability.

This distinction is important for debugging.

DNS Queries And IP Connectivity Are Separate

Suppose:

getent hosts example.com

works, but:

ping example.com

fails.

That does not necessarily indicate a DNS problem.

It could mean:

DNS resolution
    ✓

IP connectivity
    ✗

The remote machine might block ICMP, the route might be broken, or another network issue might exist.

The opposite situation is also possible.

Suppose:

ping 93.184.216.34

works, but:

ping example.com

fails.

Now the network path to the IP may be fine while name resolution is broken:

IP connectivity
    ✓

DNS resolution
    ✗

This is one of the most useful distinctions to make when troubleshooting.

How Does DNS Actually Find The Answer?

When your configured DNS resolver doesn’t already know the answer, DNS can involve multiple servers.

A simplified example:

Your Linux machine
       │
       │ query: example.com
       ▼
Recursive DNS resolver
       │
       │ "I need to find this."
       ▼
DNS hierarchy
       │
       ├── Root
       │
       ├── .com
       │
       └── example.com authoritative server
       │
       ▼
Answer
       │
       ▼
Recursive resolver
       │
       ▼
Your Linux machine

You normally don’t interact with all these servers directly.

Your machine generally talks to a configured resolver, and that resolver performs the necessary work.

This is why the DNS server listed in /etc/resolv.conf may not actually be the authoritative server for the domain you’re asking about.

It may be a recursive resolver that finds the answer on your behalf.

Recursive And Authoritative DNS Servers

Two roles are particularly useful to distinguish.

A recursive resolver receives a query from a client and finds the answer, potentially querying other DNS servers.

An authoritative DNS server is responsible for DNS data for a particular domain or zone.

Conceptually:

Linux machine
      │
      ▼
Recursive resolver
      │
      ├── Root
      ├── TLD
      └── Authoritative server
              │
              ▼
           Answer

You don’t need to operate an authoritative DNS server to understand Linux networking, but knowing the distinction prevents a common misconception:

The DNS server configured on my Linux machine does not necessarily “own” every DNS record it answers.

DNS Caching

DNS responses can be cached.

This means that a resolver may already know the answer to:

example.com

without querying another DNS server every time.

DNS records have a TTL, or Time To Live, which indicates how long a response can generally be cached.

Conceptually:

First query
Linux → Resolver → DNS infrastructure
                  ↓
                 answer
                  ↓
                cache

Later query
Linux → Resolver
          ↓
       cached answer

Caching improves performance and reduces unnecessary DNS traffic.

It also explains why DNS changes can appear to take time to become visible. Different resolvers and clients may still have cached answers until their TTLs expire.

A Practical DNS Inspection Exercise

Start with the local configuration:

cat /etc/hosts

Then inspect the resolver configuration:

cat /etc/resolv.conf

Check whether the system can resolve a public name:

getent hosts example.com

Then compare it with an IPv4-specific lookup:

getent ahostsv4 example.com

Finally, check the name through an actual network operation:

curl -I https://example.com

The important thing is not simply that all four commands work.

Notice what each one tests:

/etc/hosts
    ↓
local hostname mappings

/etc/resolv.conf
    ↓
resolver configuration

getent
    ↓
system name-resolution path

curl
    ↓
name resolution + connection + HTTP

If the last command fails, you now have several layers you can investigate instead of simply calling it a “DNS problem.”

What If DNS Resolution Fails?

Imagine:

getent hosts example.com

returns nothing useful.

Start by checking:

cat /etc/hosts

Is there a local entry?

Then:

cat /etc/resolv.conf

Do you have a usable nameserver entry?

Next, consider whether the machine can actually reach that DNS server.

If /etc/resolv.conf says:

nameserver 192.168.1.1

but the machine has no route to 192.168.1.1, DNS cannot work regardless of whether the DNS server itself is healthy.

This gives you another useful dependency chain:

Network interface
      ↓
IP address
      ↓
Route to DNS server
      ↓
DNS query
      ↓
Name resolution

DNS is therefore not completely independent of basic network connectivity.

What If DNS Works But The Application Fails?

Consider:

getent hosts example.com

works.

But:

curl https://example.com

fails.

You have already established that name resolution works through the system’s normal resolver path.

Now the problem may be further down the stack:

DNS
 ✓
 │
 ▼
IP address
 │
 ▼
Routing
 │
 ▼
TCP connection
 │
 ▼
Port 443
 │
 ▼
TLS
 │
 ▼
HTTP

This is why a good troubleshooting process tests one layer at a time.

We’ll make this much more systematic in the Debugging topic.

DNS And IPv6

A hostname can have both IPv4 and IPv6 records.

For example:

example.com
    │
    ├── A     → IPv4 address
    │
    └── AAAA  → IPv6 address

The A record is used for IPv4.

The AAAA record is used for IPv6.

This matters because a system with working IPv4 but broken IPv6 connectivity can sometimes produce confusing application behavior.

You may see an IPv6 address returned successfully, but the actual connection attempt can still fail if the IPv6 path is broken.

You don’t need to disable IPv6 or change resolver behavior simply because you encounter both address families.

The useful troubleshooting habit is to recognize that:

DNS resolution
    ↓
can return multiple address families

and the application or networking stack may then choose how to use them.

Why /etc/resolv.conf Is Not The Whole Story

It is tempting to memorize:

/etc/resolv.conf = DNS

but that is too simplistic.

A better model is:

Application
    ↓
System name-resolution mechanisms
    │
    ├── local sources such as /etc/hosts
    │
    └── configured DNS resolver
             │
             ▼
        DNS server

/etc/resolv.conf is one important part of the configuration visible to the resolver, but on modern Linux systems another service may generate or manage it.

This is particularly relevant when NetworkManager is in use.

Later, in the nmcli topic, you’ll see how NetworkManager can manage network connections and DNS-related configuration instead of requiring you to manually edit files every time the network changes.

DNS Is Not Routing

This distinction deserves one final emphasis.

Suppose:

example.com
    ↓
93.184.216.34

DNS answered the question:

“What address is associated with this name?”

Routing answers a different question:

“Where should Linux send a packet destined for this address?”

So:

DNS
name → address

Routing
address → next hop

You need both for the common hostname-based workflow, but they solve different problems.

A machine can have:

DNS ✓
Routing ✗

or:

DNS ✗
Routing ✓

Treating them as separate layers makes troubleshooting much easier.

A Complete Name-to-Connection Picture

Let’s put everything together:

    flowchart TB
    A["Application<br/>curl / browser / Python"] --> H["Hostname<br/>example.com"]
    H --> R["Linux Name Resolution"]
    R --> HOSTS["/etc/hosts"]
    R --> RES["Configured Resolver"]
    RES --> DNS["DNS Server"]
    DNS --> IP["IP Address"]
    IP --> ROUTE["Routing Table"]
    ROUTE --> IFACE["Network Interface"]
    IFACE --> NET["Network"]
    NET --> SERVER["Remote Server"]
  

This diagram shows why DNS belongs before routing in the normal hostname-based workflow.

The application first needs an address.

Once it has an address, the normal IP networking path takes over.

What You Should Remember

The most useful DNS concepts from this lesson are:

Hostname
    ↓
Name resolution
    ↓
IP address
    ↓
Routing
    ↓
Network connection

And on Linux, the practical pieces you’ll encounter are:

/etc/hosts
    → local hostname mappings

/etc/resolv.conf
    → resolver configuration visible to the system

getent
    → test the system's name-resolution path

DNS server
    → answers DNS queries

The most important troubleshooting distinction is:

Successful DNS resolution does not prove that the destination is reachable, and failed connectivity does not automatically mean DNS is broken.

Test the layers separately.

What’s Next

So far we’ve looked at the conceptual networking pieces: interfaces, addresses, routes, and DNS. The next topic moves closer to actual services running on a Linux machine.

We’ll look at ports and connections, use ss and nc, and build a tiny Python listener so you can see the relationship between a process, a socket, an IP address, and a port.

Last updated on