1. What is a stub resolver? #
First of all, let’s shed some light on what a stub resolver is.
Whenever someone begins talking about hostname resolution issues or nameserver changes, the first thing most people think of is the /etc/resolv.conf
configuration file. Indeed, /etc/resolv.conf
is a core and fundamental part of the local resolver system, and we will discuss it in detail later in this series, including how it’s managed on modern GNU/Linux distributions with systemd
. However, it’s far from being the only component involved in converting a hostname string into a list of IP addresses. Often, other lesser-known parts of the system may cause unpredictable behaviors and have their own unique features and limitations.
At its core, a stub resolver is a “simple” DNS client designed primarily to send DNS requests to a recursive name server. Rather than starting with system configuration files, I’d like to begin our journey from the perspective of an application.
As you might expect, when any application (whether it’s a client or server, CLI or desktop, web or native) needs to resolve a domain name to IP addresses, it must query a DNS server. Typically, all programming languages include functions or classes in their standard libraries to facilitate such requests. These components, known as stub resolvers, read various system configuration files, decide which record types to request (A
and/or AAAA
), make the DNS queries, and sort and format the returned IP addresses for the caller.
Historically, in UNIX and POSIX environments where the C
language has been foundational, the basic function for domain name resolution was gethostbyname()
, which was later deprecated and replaced by getaddrinfo()
.
So, let’s begin here with a bottom-up approach, starting with the gethostbyname()
function and its successor, getaddrinfo()
, from the libc
specification.