How does my browser locate the nearest DNS root servers?
Your browser doesn't. Your browser will use the standard system calls for resolving hostnames (usually, I believe, getaddrinfo()
), and these will in turn usually examine the contents of /etc/resolv.conf
to find the configured resolving nameservers, and query them. They will in turn either forward your desktop's OS's query to upstream servers (cacheing any reply) or perform recursive resolution themselves. Note that most steps in the above chain are configurable, so what your browser does in fact will be locally-determined; but the scenario above is typical.
It is the recursive-resolving nameservers in that chain (whether those be your locally-configured authoritative nameservers, or some ISP's servers down the line) that need to know how to find the root servers, and they do it via a pre-configured zonefile for .
(which is usually periodically updated by querying an available root nameserver).
Edit: It doesn't. It'll be implementation-dependent, but afaict in my case (BIND), it just picks one and queries it. As long as it gets an answer in time, it recurses down from there. What makes you think any kind of ranging operation is going on?
In DNS name resolution how do browsers determine the nearest DNS servers available among many DNS servers?
As the other answers indicate, your browser, or other client program does not do this selection. A client program asks for name service resolution by making calls to a library called the resolver.
The resolver determines which servers it should contact to ask a query. It depends on the resolver implementation but usually it consults, in order, a list of recursive resolvers that it has been configured with (either by static configuration or by receiving them through a mechanism such as DHCP.)
In summary then: your (user-level) program asks the resolver for name resolution and the resolver asks the nameservers that have been provided to it via some configuration mechanism.
I am aware that there are 13 root servers but how does my ISP's DNS server know which root DNS server to contact?
This is also implementation dependent. I'm going to describe how it works with BIND, since
- BIND is a very popular nameserver and chances are fairly good that your ISP is using it, and
- Even if your ISP is not using BIND, some alternatives use a similar mechanism for nameserver selection from an NS resource record set.
To begin with, let's talk first about how a recursing nameserver even knows which nameservers to pick from to talk to a specific domain. For each domain that is reachable from the root (".") level of the nameserver, the administrators managing that domain publish, in the containing parent domain, a resource record set of record type NS (i.e. nameserver) to delegate publicly to the nameservers named in the resource record set the responsibility for resolving queries having to do with that domain.
One of the beauties of this system is that it allows distributed hierarchichal delegation for the domain name system and the only domain for which a recursive server requires a priori knowledge is the root level, which the server is configured to know about. It used to be most common to specify the NS RRset for the root through a "hints" file that BIND loaded when it started but for a while now the IP addresses used by the root servers has been pre-defined in BIND. [Digression: You can still override the built-ins by specifying a root hint zone, and in fact the address of d.root-servers.net recently changed and the new location won't be reflected in the built-in list until new versions of BIND are built and distributed that include the new information. At the current time versions which contain the new IP address of the D root servers are in beta.]
Anyway, the key takeaway here is that each domain has associated with it an NS record RRset containing the publicly announced nameservers for that domain. You should try looking at a few yourself. Let's look at the root:
$ dig . ns +edns=0 @f.root-servers.net.
I'm going to just snip out the answer section, which will contain the NS RRset returned in no predictable order (I'm glossing over a bit here -- the order is determined generally by the configuration of the nameserver I'm talking to. Different roots might answer with different orderings but the items being ordered should be the same.)
;; ANSWER SECTION:
. 518400 IN NS h.root-servers.net.
. 518400 IN NS j.root-servers.net.
. 518400 IN NS c.root-servers.net.
. 518400 IN NS l.root-servers.net.
. 518400 IN NS e.root-servers.net.
. 518400 IN NS a.root-servers.net.
. 518400 IN NS f.root-servers.net.
. 518400 IN NS k.root-servers.net.
. 518400 IN NS i.root-servers.net.
. 518400 IN NS d.root-servers.net.
. 518400 IN NS m.root-servers.net.
. 518400 IN NS b.root-servers.net.
. 518400 IN NS g.root-servers.net.
Those are all of the nameservers for the root (".") domain and we can ask any of them questions about the root domain. If we ask them a question about something that's not in the root domain we'll receive either an error or, more likely a referral to another set of nameservers (e.g. "example.com? I don't answer questions about example.com.. Try asking the .com domain nameservers -- they're over there..")
How, then, does BIND know which nameserver from the NS RRset will give it the fastest response?
The answer is: initially it doesn't. But under its default behavior, it learns over time and settles on usually asking the server with the shortest round trip time.
Round Trip Times and the Selection of Candidate Nameservers BIND relies on Round Trip Times (RTTs) to the nameservers in an RRset to choose which nameserver should receive its queries. The first time an NS RRset for a domain is added to the cache, all of the records in the set are assigned a small random round-trip time, on the order of a few milliseconds. After that initial priming, when a query needs to be directed to the nameservers delegated for a given domain, BIND checks its cache and (hopefully) finds the RRset. It chooses the server with the lowest RTT time from the set and makes its query. And when the query is done, BIND updates the RTTs for the NS RRset as follows:
- the RTT of the server which was just queried is set to its actual round trip time.
- All other servers in the RRset have their RTTs reduced by a small fraction (~3-4%, I think..)
Let's see how this works by walking through an example. The first time my recursive resolver encounters the domain example.com, it loads the NS RRset for example.com into its cache. Let's say that the administrators of example.com have announced three nameservers for example.com so the NS RRset looks like:
example.com NS servera.example.com
example.com NS serverb.example.com
example.com NS serverc.example.com
Let's also assume for the sake of this example that it takes your resolver the following amounts of time to receive a response from each of the servers in this set:
servera -- 30 ms
serverb -- 45 ms
serverc -- 50 ms
Now the first time the example.com NS RRset gets loaded, the RTT weights are primed with small random values. So before we have ever asked an example.com nameserver anything, the RTT table might look like this:
servera -- 8 ms
serverb -- 9 ms
serverc -- 7 ms
The first time we query example.com, then, we are going to go to serverc and ask our question. Serverc takes 50 ms to respond, so after our query is done we update our RTT table so that it now reads:
servera -- 7 ms // reduced by a small fraction
serverb -- 8 ms // reduced by a small fraction
serverc -- 50 ms // updated to reflect the actual round trip time.
The next time through we are obviously going to pick servera, as it now has the lowest round trip time. After only a few queries to the example.com domain we should have a pretty decent idea which nameserver gives us the fastest response and we will thereafter prefer that server most of the time.
Why most of the time and not all of the time? And what's up with the bit I mentioned earlier about "All other servers in the RRset have their RTTs reduced by a small fraction"? Well, it turns out that while we want to prefer the fastest server, we don't want to write off the other servers permanently. Maybe server c is the fastest server almost all of the time but at the time we first set its RTT it was anomalously busy. Maybe a server was temporarily out of service, resulting in an incredibly high RTT (after our attempt to query it times out) but we want to start asking it again after it comes back in service. By adjusting the other server values downward each time, sooner or later they're going to creep lower than the average RTT of the server we are preferring. When that happens we'll throw a query in their direction and if the time is better, then great.. Otherwise, we reset its RTT and it goes back to the bottom of our priority list until it creeps back to the front again. The large majority of our queries will go to the fastest server or servers in the set but the outliers get tried periodically to make sure that if conditions have changed that the table gets updated to reflect that and the best server is still being selected on average.
The 13 root nameservers aren't actually 13 servers. Each one is a distributed cluster of servers at various sites around the world, and they are accessed via standard IP routing, just like any other server.
As for which root nameserver the ISP's DNS server chooses to contact, that probably depends on the details of their DNS resolver. Maybe it's completely random, maybe it's weighted, but I couldn't tell you.
Edit: if you meant, how does the ISP find any one of the 13 nameservers, there is a public list of them and their corresponding IP addresses which basically every computer has. From there, it's just a matter of picking one and letting the routers of the internet do the rest.