In this tutorial, we’ll look at how the traceroute command-line tool resolves a hostname to its IP address.
2. Resolving IP Address Using getaddrinfo
In Linux, the traceroute command-line tool tracks the route a packet takes to get to a destination. It takes the hostname or IP address of the target host as an argument.
For instance, we can run the traceroute command on google.com:
$ traceroute --icmp google.com traceroute to google.com (18.104.22.168), 30 hops max, 60 byte packets 1 _gateway (10.0.2.2) 0.495 ms 0.496 ms 0.201 ms 2 192.168.100.1 (192.168.100.1) 5.819 ms 5.561 ms 5.283 ms 3 10.31.48.1 (10.31.48.1) 7.706 ms 7.479 ms 7.071 ms 4 * * * 5 22.214.171.124 (126.96.36.199) 7.351 ms 7.931 ms 7.053 ms 6 188.8.131.52 (184.108.40.206) 7.610 ms 6.944 ms 9.775 ms 7 220.127.116.11 (18.104.22.168) 9.535 ms 9.300 ms 9.065 ms 8 22.214.171.124 (126.96.36.199) 8.821 ms 14.983 ms 14.730 ms 9 kul08s12-in-f14.1e100.net (188.8.131.52) 14.482 ms 14.246 ms 14.011 ms
Given the hostname, google.com, the traceroute command performs a DNS lookup to obtain the IP address associated with the hostname. In order to perform the hostname to IP address translation, the traceroute command makes a call to the getaddrinfo function.
2.1. The getaddrinfo Function
The getaddrinfo is a standard Linux library function that translates the hostname and service name into internet addresses. Specifically, it resolves the hostname into the IP address and the service name into the associated port number.
To resolve the service name, getaddrinfo looks up the /etc/services file and does a one-to-one mapping to get the port number associated with the service name. For example, if http is the service name, the function will resolve it to port number 80.
On the other hand, resolving the IP address from the hostname involves a few more steps as compared to the service name translation. To begin the process, it first queries the Name Service Cache Daemon (nscd).
2.2. Checking the Cache With nscd
The nscd is a daemon process that caches frequently requested name service resolutions. It provides caching services for name services such as passwd and hosts. This means, if a hostname has been resolved previously, it would be cached by the nscd to improve the subsequent resolutions for the same hostname.
The getaddrinfo first queries the cache for the IP address associated with the host. If it’s found, getaddrinfo returns the IP address to the caller immediately. Otherwise, the function starts the actual hostname resolution process using files like /etc/hosts and querying the database. But, the getaddrinfo function first consults the Name Service Switch (NSS) to figure out its options.
3. The Name Service Switch (NSS)
Since there could be different ways to perform hostname resolution, the getaddrinfo function consults the Name Service Switch (NSS). The NSS system in Linux refers to the /etc/nsswitch.conf configuration file. This file makes it easy to configure the sources of different name resolution mechanisms. Specifically, we can control the name resolution mechanism for the group, user, host, and many more through this file.
For hostname resolutions, the function reads the value on the hosts directive inside the file:
$ cat /etc/nsswitch.conf | grep hosts hosts: files mdns4_minimal [NOTFOUND=return] dns
Based on the sequence of the values on the hosts directive, the getaddrinfo function will try each method in sequence until it resolves the IP address or until it reaches the last method. In our specific configuration, the function will first attempt to resolve with files, then move on to mdns4_minimal, and finally, with dns until one of them returns a success value.
3.1. The Local DNS /etc/hosts File
With our configuration, we are giving the files method the foremost priority. The files method is referring to the /etc/hosts file that contains a series of static IP address and hostname pairs:
$ cat /etc/hosts 127.0.0.1 localhost 192.168.2.23 internal-device-A
The lookup is done by mapping the given hostname against the list of static IP addresses and hostname pairs in the file. For example, if we run traceroute on internal-device-A, the getaddrinfo will return 192.168.2.23 as the IP address of internal-device-A to traceroute.
3.2. The local TLD Resolver
If the files method fails to resolve the IP address, the next method in line, mdns4_minimal, will be used. mdns4_minimal is a plugin for resolving hostnames with a local top-level domain (TLD). For example, InternalLaptop.local is a hostname with the local TLD.
The extra [NOTFOUND=return] options at the end mean the caller should skip the subsequent methods if the current method cannot resolve the given hostname. This is because the local TLD is specially reserved for determining IP addresses in the same LAN and, therefore, we shouldn’t expect the DNS server to resolve that.
3.3. DNS Server Configuration: the /etc/resolv.conf File
Finally, if none of the preceding methods return a match, the getaddrinfo function will query the DNS server.
Prior to sending a DNS query, the function needs to know the server address of the DNS server. It looks up the DNS server address by reading the /etc/resolv.conf file. This file contains a nameserver directive that points to the IP address of the DNS server:
$ cat /etc/resolv.conf # This file is managed by man:systemd-resolved(8). Do not edit. # # This is a dynamic resolv.conf file for connecting local clients to the # internal DNS stub resolver of systemd-resolved. This file lists all # configured search domains. # # Run "resolvectl status" to see details about the uplink DNS servers # currently in use. # # Third party programs must not access this file directly, but only through the # symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a different way, # replace this symlink by a static file or a different symlink. # # See man:systemd-resolved.service(8) for details about the supported modes of # operation for /etc/resolv.conf. nameserver 127.0.0.53 options edns0 trust-ad
In the resolv.conf file, the nameserver directive specifies the DNS server address. Therefore, the getaddrinfo function will send the DNS query to the 127.0.0.53 IP address.
We can change the DNS server to use by updating this file. Specifically, we can modify the nameserver line to another DNS address, such as 184.108.40.206.
3.4. Modifying the Host Resolution Methods and Priority
To change the priority of the resolution methods, we can rearrange the sequence of the hosts value in the nsswitch.conf file. For instance, we can prioritize the dns resolution method above the files method:
$ cat /etc/nsswitch.conf | grep hosts hosts: dns mdns4_minimal [NOTFOUND=return] files
Additionally, we can also remove some of the resolution methods by taking them out of the hosts directive:
$ cat /etc/nsswitch.conf | grep hosts hosts: dns
The example above causes subsequent hostname resolution to rely on the DNS server alone.
3.5. The Deprecated /etc/host.conf File
In some older documentation, we might come across the /etc/host.conf file. This file was used previously to configure the order of the hostname resolution mechanism, similar to the hosts directive in /etc/nsswitch.conf. It is deprecated in favor of the more generic /etc/nsswitch.conf file.
In this article, we first looked at the traceroute command and getaddrinfo function. We learned that getaddrinfo will first attempt to get the answer from the cache, nscd. Then, we see that if the answer is not found in the cache, the lookup function consults the hosts directive of the nsswitch.conf file. Subsequently, the function then tries each option sequentially until it finds an answer.
Finally, we’ve learned that the /etc/host.conf is a deprecated configuration file that once served a similar function as the nsswitch.conf file.