9.15 Resolving Hostnames
One of the final basic tasks in any network configuration is hostname resolution with DNS. You’ve already seen the host resolution tool that translates a name such as www.example.com to an IP address such as 10.23.2.132.
DNS differs from the network elements we’ve looked at so far because it’s in the application layer, entirely in user space. Therefore, it’s technically slightly out of place in this chapter alongside the internet and physical p. 244 layer discussion. However, without proper DNS configuration, your internet connection is practically worthless. No one in their right mind advertises IP addresses (much less IPv6 addresses) for websites and email addresses, because a host’s IP address is subject to change and it’s not easy to remember a bunch of numbers.
Practically all network applications on a Linux system perform DNS lookups. The resolution process typically unfolds like this:
- The application calls a function to look up the IP address behind a hostname. This function is in the system’s shared library, so the application doesn’t need to know the details of how it works or whether the implementation will change.
- When the function in the shared library runs, it acts according to a set of rules (found in /etc/nsswitch.conf; see Section 9.15.4) to determine a plan of action on lookups. For example, the rules usually say that even before going to DNS, check for a manual override in the /etc/hosts file.
- When the function decides to use DNS for the name lookup, it consults an additional configuration file to find a DNS name server. The name server is given as an IP address.
- The function sends a DNS lookup request (over the network) to the name server.
- The name server replies with the IP address for the hostname, and the function returns this IP address to the application.
This is the simplified version. In a typical contemporary system, there are more actors attempting to speed up the transaction or add flexibility. Let’s ignore that for now and look at some of the basic pieces. As with other kinds of network configuration, you probably won’t need to change hostname resolution, but it’s helpful to see how it works.
9.15.1 /etc/hosts
On most systems, you can override hostname lookups with the /etc/hosts file. It usually looks like this:
127.0.0.1 localhost
10.23.2.3 atlantic.aem7.net atlantic
10.23.2.4 pacific.aem7.net pacific
::1 localhost ip6-localhost
You’ll nearly always see the entry (or entries) for localhost here (see Section 9.16). The other entries here illustrate a simple way to add hosts on a local subnet.
In the bad old days, there was one central hosts file that everyone copied to their own machine in order to stay up to date (see RFCs 606, 608, 623, and 625), but as the ARPANET/internet grew, this quickly got out of hand.
9.15.2 resolv.conf
The traditional configuration file for DNS servers is /etc/resolv.conf. When things were simpler, a typical example might have looked like this, where the ISP’s name server addresses are 10.32.45.23 and 10.3.2.3:
search mydomain.example.com example.com
nameserver 10.32.45.23
nameserver 10.3.2.3
The search line defines rules for incomplete hostnames (just the first part of the hostname—for example, myserver instead of myserver.example.com). Here, the resolver library would try to look up host.mydomain.example.com and host.example.com.
Generally, name lookups are no longer this straightforward. Many enhancements and modifications have been made to the DNS configuration.
9.15.3 Caching and Zero-Configuration DNS
There are two main problems with the traditional DNS configuration. First, the local machine does not cache name server replies, so frequent repeated network access may be unnecessarily slow due to name server requests. To solve this problem, many machines (and routers, if acting as name servers) run an intermediate daemon to intercept name server requests and cache the reply, and then use the cached answers if possible. The most common of these daemons is systemd-resolved; you might also see dnsmasq or nscd on your system. You can also set up BIND (the standard Unix name server daemon) as a cache. You can often tell that you’re running a name server caching daemon if you see 127.0.0.53 or 127.0.0.1 either in your /etc/resolv.conf file or listed as the server when you run nslookup -debug host. Take a closer look, though. If you’re running systemd-resolved, you might notice that resolv.conf isn’t even a file in /etc; it’s a link to an automatically generated file in /run.
There’s a lot more to systemd-resolved than meets the eye, as it can combine several name lookup services and expose them differently for each interface. This addresses the second problem with the traditional name server setup: it can be particularly inflexible if you want to be able to look up names on your local network without messing around with a lot of configuration. For example, if you set up a network appliance on your network, you’ll want to be able to call it by name immediately. This is part of the idea behind zero-configuration name service systems such as Multicast DNS (mDNS) and Link-Local Multicast Name Resolution (LLMNR). If a process wants to find a host by name on the local network, it just broadcasts a request over the network; if present, the target host replies with its address. These protocols go beyond hostname resolution by also providing information about available services.
You can check the current DNS settings with the resolvectl status command (note that this might be called systemd-resolve on older systems). You’ll get a list of global settings (typically of little use), and then you’ll see the settings for each individual interface. It’ll look like this:
Link 2 (enp0s31f6)
Current Scopes: DNS
LLMNR setting: yes
MulticastDNS setting: no
DNSSEC setting: no
DNSSEC supported: no
DNS Servers: 8.8.8.8
DNS Domain: ~.
You can see various supported name protocols here, as well as the name server that systemd-resolved consults for a name that it doesn’t know.
We’re not going to go further into DNS or systemd-resolved because it’s such a vast topic. If you want to change your settings, take a look at the resolved.conf(5) manual page and proceed to change /etc/systemd/resolved.conf. However, you’ll probably need to read up on a lot of the systemd-resolved documentation, as well as get familiar with DNS in general from a source such as DNS and BIND, 5th edition, by Cricket Liu and Paul Albitz (O’Reilly, 2006).
9.15.4 /etc/nsswitch.conf
Before we leave the topic of name lookups, there’s one last setting you should be aware of. The /etc/nsswitch.conf file is the traditional interface for controlling several name-related precedence settings on your system, such as user and password information, and it has a host lookup setting. The file on your system should have a line like this:
hosts: files dns
Putting files ahead of dns here ensures that, when looking up hosts, your system checks the /etc/hosts file for host lookup before asking any DNS server, including systemd-resolved. This is usually a good idea (especially for looking up localhost, as discussed next), but your /etc/hosts file should be as short as possible. Don’t put anything in there to boost performance; doing so will burn you later. You can put hosts within a small private LAN in /etc/hosts, but the general rule of thumb is that if a particular host has a DNS entry, it has no place in /etc/hosts. (The /etc/hosts file is also useful for resolving hostnames in the early stages of booting, when the network may not be available.)
All of this works through standard calls in the system library. It can be complicated to remember all of the places that name lookups can happen, but if you ever need to trace something from the bottom up, start with /etc/nsswitch.conf.