Troubleshooters.Com®, Linux Library and Unbound and NSD Present:
Unbound, an Easy, Fast and Small DNS Resolver
Copyright © 2018 by Steve Litt
See the Troubleshooters.Com Bookstore.
CONTENTS
Recursive resolvers, when queried for a Fully Qualified Domain Name, keep querying various authoritative nameservers in descendent zones, starting at the highest level and descending, until either the IP address of the resource is found, or until all descendent authoritative nameservers have been queried without a find, at which time an error is returned.
One algorithm is worth a thousand words, so let's walk through looking up domain name my.fsu.edu, which is known to exist. We'll use ourselves and the nslookup program to simulate a recursive resolver, to find the IP address of my.fsu.edu. Start by querying one of the root nameservers (c.root-servers.net) for authoritative nameservers of the .edu top level domain:
[slitt@mydesk ~]$ nslookup -query=ns edu. c.root-servers.net
Server: c.root-servers.net
Address: 192.33.4.12#53
Non-authoritative answer:
*** Can't find edu.: No answer
Authoritative answers can be found from:
edu nameserver = g.edu-servers.net.
edu nameserver = a.edu-servers.net.
edu nameserver = d.edu-servers.net.
edu nameserver = l.edu-servers.net.
edu nameserver = f.edu-servers.net.
edu nameserver = c.edu-servers.net.
a.edu-servers.net internet address = 192.5.6.30
c.edu-servers.net internet address = 192.26.92.30
d.edu-servers.net internet address = 192.31.80.30
f.edu-servers.net internet address = 192.35.51.30
g.edu-servers.net internet address = 192.42.93.30
l.edu-servers.net internet address = 192.41.162.30
g.edu-servers.net has AAAA address 2001:503:cc2c::2:36
OK, now, in the "Authoritative answers can be found from" section, we have a list of authoritative nameservers that are authoritative over the edu. top level domain. Let's use one of them (c.edu-servers.net) to look up any authoritative nameservers for fsu.edu:
[slitt@mydesk ~]$ nslookup -query=ns fsu.edu. c.edu-servers.net.
Server: c.edu-servers.net.
Address: 192.26.92.30#53
Non-authoritative answer:
*** Can't find fsu.edu.: No answer
Authoritative answers can be found from:
fsu.edu nameserver = dns2.fsu.edu.
fsu.edu nameserver = nsx.lbl.gov.
fsu.edu nameserver = dns1.fsu.edu.
fsu.edu nameserver = trantor.umd.edu.
fsu.edu nameserver = dnsa.fsu.edu.
dns2.fsu.edu internet address = 128.186.8.8
dns1.fsu.edu internet address = 128.186.6.103
trantor.umd.edu internet address = 128.8.10.14
dnsa.fsu.edu internet address = 192.12.121.44
[slitt@mydesk ~]$
Well cool! Once again, pay attention to the authoritative nameservers in the "Authoritative answers can be found from" section. Now we have a list of five authoritative nameservers authoritative over the fsu.edu domain, presumably hosted and maintained by FSU (Florida State University). Only four of them have IP addresses, so let's arbitrarily pick one of the ones with an IP address. Let's pick dns2.fsu.edu. and do a lookup. But wait. This lookup must be different, because our goal is to find the IP address of my.fsu.edu, not any authoritative nameservers for my.fsu.edu. So we'll remove the -query=ns option, but otherwise do the same thing, on the authoritative nameserver authoritative over the fsu.edu domain:
[slitt@mydesk ~]$ nslookup my.fsu.edu. dns2.fsu.edu. Server: dns2.fsu.edu. Address: 128.186.8.8#53 Name: my.fsu.edu Address: 146.201.111.85 [slitt@mydesk ~]$
The query told us (on 9/17/2018) that the IP address of my.fsu.edu is 146.201.111.85.
We've just imitated a recursive DNS Resolver (defined in Glossary section. Start at the very highest level, and keep querying for authoritative nameservers, and query the next lower level on each subsequent authoritative nameserver. Just like you did above.
A few comments. I'm sure a real recursive resolver isn't this simplistic. I'm sure they have better ways of picking an authoritative nameserver from a list than rolling dice like we did. Perhaps, to enhance accuracy via redundancy, they ask more than one of the authoritative nameservers.
Note:
The following paragraph is for computer programmers only. If you're not a computer programmer, then to avoid confusion, please skip the following paragraph.
And let's talk about the name "recursive". The algorithm we used in this section was pure iterative, not recursive. We could have done it recursively, because you can always substitute recursion for iteration and vice versa (with a stack). I have no idea whether recursive authoritative nameservers and/or recursive resolvers use iterative or recursive algorithms, but one thing's for sure. You start at the top with a query, then use that query's result to run exactly the same query (with the next lower level tacked on) on the returned authoritative nameserver, and keep going until your query includes all levels. This description is definitely recursive.
A bit of advice. When dealing with any DNS topic, forget the word "iterative" ever existed, and simply say "Non-Recursive", perhaps with a few extra words of explanation. The word "iterative", in the context of DNS, has too many conflicting definitions across the Internet to be useful.
The terminology used for DNS has been rendered ineffective by years of progress and an effect like "the whispering game" where a line of 20 kids consecutively whispers something in the next kid's ear, and by the time it reaches the other end it's materially changed. There is no way of specifying a DNS setup, using only terminology, because of these terminology problems.
So what this section does is to establish its own definitions, to be used only in this document, that can be consistently applied and understood. To the best of my ability, I've also made these definitions as consistent as possible with current DNS jargon and terminology, and the document at https://tools.ietf.org/html/draft-ietf-dnsop-terminology-bis-14, a draft hoping to soon become an RFC that represents the current best attempt at DNS terminology.
Point of Information:
Some of this document's terminology departs from keywords in config files. This is because the config file keywords were made by programmers or committee members, decades ago, with more pressing priorities than making an absolutely unambiguous grammar. By far this glossary's top priority, on the other hand, is to make as close to an absolutely unambiguous grammar as possible.
Please understand that the fact that a term matches a conf file keyword in no way de-legitimizes anything in this glossary.
Please remember, the terminology in this glossary is not to be used outside this document.
The following is a list of terms covered in this section:
DNS System Definitions
Let's start with definitions of the entire DNS system...
IP Address
An IP Address is a number that uniquely specifies a computer or an alias representing a program running on that computer. Certain ranges of possible IP addresses, which are not supposed to be used worldwide, are called Private IP Addresses. IP Addresses can be expressed in IPV4 or IPV6 notation.
IPV4
In the IPV4 system, each IP address is a 32 bit number. An IPV4 address is represented by four 8 bit numbers, each separated by a dot (period). Each 8 bit number is represented by a decimal number between 0 and 255. The following are IPV4 numbers:
IPV4 seemed like a good idea, but once everyone began using the Internet, we pretty much exhausted our supply of 32 bit IPV4's and had to turn to IPV6...
IPV6
In the IPV6 system, each IP address is a 128 bit number. That 128 bit number is represented by 8 groups of 16 bits each, written in hexidecimal, with the groups separated by colons (:). That's enough bits to make more than 1028 IP addresses for every one of the 13 billion humans that can supposedly exist on earth assuming perfect farming, ideal resource allocation, and no war. I know in the world of computers we always rue the day when we say "that should be enough", but unless we're deliberately wasteful of IPV6 addresses, they should last us awhile.
Because I have no IPV6 facilities available to me in order to tech edit this document in IPV6, this will be the last mention of IPV6 in this document. However, everything in this document applies equally well to IPV6, assuming all hardware and software queried for DNS is IPV6 compatible.
Private IP Addresses
Three chunks of IP addresses are declared "private", meaning they should never appear on the public Internet. These chunks are used for Local Area Networks (LANs) separate from the Internet, connected only by a router that routes the private addresses to public ones. Here are the private address blocks:
If you're unfamiliar with how the preceding notation works, please refer to Troubleshooters.Com CIDR Calculator.
DNS
Stands for Domain Name Service. It's a worldwide, distributed, hierarchical translator from Domain Name to IP address and vice versa. If you don't understand the "distributed" or "hierarchical" part, that's OK, they'll become clear later in this document.
Domain Name
The following are domain names:
All the preceding domain names are Fully Qualified Domain Names (FQDN), because they contain all levels, from the root's dot on the right, to the lowest level's name on the left. If the preceding did not have dots on the right, this section would still define them as FQDNs because the dot is implied. For the purposes of this document, the word "Domain Name" means FQDN. If we were to discuss a relative domain name, "my" for instance, in this document it would be referred to as a Relative Domain Name. Once again, in this document, Domain Name means FQDN, with or without the trailing dot.
Domain Name Space
The entirety of the worldwide, distributed, hierarchical database of domain name/IP address pairs. The entire database is constructed as a tree of nodes.
Usual and Customary Architecture
This definition appears nowhere but here: It's my definition: You'll never see it anywhere else. The usual and customary use of DNS is to have each domain level take charge of authoritative DNS on all computers on its level. For instance, the authoritative nameserver of personal.home.lan directly yields DNS data over every computer directly within the personal.home.lan zone, but not within music.personal.home.lan zone.
As a contrast, unusual and non-customary architecture occurs when an authoritative nameserver for the personal.home.lan zone is authoritative for both the personal.home.lan and music.personal.home.lan zones.
All DNS architecture in this document is Usual and Customary unless otherwise stated. Creating the definition of Usual and Customary makes other definitions much easier.
Node
One atomic chunk of the DNS Namespace. Imagine the following domain name:
house.music.personal.home.lan.
In the preceding, each of the following is a node:
A given node does not include its children or descendants.
The preceding definition is valid only for Usual and Customary architectures.
Zone
A Zone is a group of computers with one common set of authoritative data. For practical purposes, "zone" and "node" are almost synonymous.
Child Zone
Easy definition: personal.home.lan is the child zone of home.lan. Technically, this term is about who has authority over whom, but in Usual and Customary architectures, the preceding definition produces the right answer every time.
Descendent Zone
If zone B is the child of zone A then B is a descendant zone of A. Both house.music.personal.home.lan and personal.home.lan are descendent zones of home.lan.
Parent Zone
Easy definition: home.lan is the parent zone of personal.home.lan. Technically, this term is about who has authority over whom, but in Usual and Customary architectures, the preceding definition produces the right answer every time.
Ancestor Zone
If zone A is the parent of zone B then A is a ancestor zone of B. Both personal.home.lan and home.lan are ancestor zones of music.personal.home.lan.
Bogus Term: Domain
No definition. Use "Domain Name" if you mean Domain Name, or "Zone" if you mean Zone.
Subdomain
personal.home.lan is a subdomain of home.lan.
Clients, Resolvers and Authoritative Nameservers
Of all the words used in the DNS world, "client", "resolver", and "nameserver" are the most multiply defined, ambiguous, and leading to the most misunderstanding.
WARNING!
This document never uses the word "nameserver" without the word "authoritative" in front of it. In this document, a program that takes a domain name and returns an IP address is either a resolver or an authoritative nameserver.
Let's start with a couple basic DNS transaction:
In the preceding diagram, the DNS Client asks the Resolver for the IP address of a domain, and then the Resolver asks an Authoritative Nameserver, which returns the answer to the Resolver, which returns the answer to the DNS client.
In the preceding, the resolver on computer A queries a resolver on computer B, and then computer B's resolver queries the appropriate authoritative nameserver. The answer is returned through both the resolvers to the DNS client. Note that all queries and responses are in the form of RRs.
RR, or Resource Record
An RR (which appears to stand for "Resource Record" but is usually used as an abbreviation) is a known and defined data structure in which all DNS queries and answers are packaged. The specification of RRs is such that they can be different sizes and carry completely different types of data, but still fall within the specification.
Query RRs contain a RD (Recursive Desired) bit, and responses contain both an RR bit and an RA (Recursion Available) bit.
Beyond the preceding details, RR architecture is beyond the scope of this document. If you're curious and want further info, see section 3.2 of RFC-1035 for the down and dirty details.
DNS Client
The DNS Client is a user program. It could be an email client, or a web browser, or an internet streaming client. It could also be a diagnostic program like dig or nslookup, both of which are really user programs because their interface is optimized for a human user. DNS client programs are usually designed to interface with humans.
Authoritative Nameserver
The Authoritative Nameserver is a program especially made to hold and disburse translations between Domain Name and IP address and vice versa, for a particular zone. It's basically a translation table that takes questions in DNS query format (RRs). We'll refine on this definition later, but for the time being assume it cannot report on anything not written into its database.
There are two kinds of Authoritative Nameservers: Recursive and non-recursive. If ns1.home.lan, which is the authoritative nameserver for zone home.lan, has the smarts to return an address for music.personal.home.lan, if asked to do so, then ns1.home.lan is a recursive nameserver. If, however, when asked specifically to search recursively, ns1.home.lan replies "I don't know, why don't you ask ns1.personal.home.lan, that's zone personal.home.lan's authoritative nameserver," then ns1.home.lan is non-recursive.
Recursive Authoritative Nameserver
In the preceding definition we mentioned "when asked specifically to search recursively", that "ask" is in the form of the query RR's RD (Recursion Desired) bit. Responses contain RA (REcursion Available) bits saying whether the authoritative nameserver is capable of descending through its child zones.
A recursive authoritative nameserver, when queried with the RD bit set, responds by setting the RA bit, and then queries in its descendant zones until an answer is obtained, and that answer becomes becomes part of the authoritative nameserver's returned answer.
Non-Recursive Authoritative Nameserver
An non-recursive authoritative nameserver not recursive. It is not capable, or configured to be not capable, of querying its descendant zones to return an answer.
Bogus Term: Iterative Authoritative Nameserver
It is forbidden, in this document, to use this term. The Authoritative Nameserver is either Recursive or it's not. There's no need for the term "iterative authoritative nameserver", and in fact it has multiple non-compatible definitions across the Internet.
Resolver
The Resolver is a computer program whose only purpose is answering DNS queries, namely, converting a domain name to an IP address or vice versa. However, Resolvers aren't (for the purposes of this document) Authoritative Nameservers. Instead, they do their conversions by querying authoritative nameservers, or querying another Resolver.
Most resolvers cache results, so that if a second request for a domain comes in before the TTL (Time To Live) from the last result expires, it fills the request from cache, eliminating the need to send requests over the wire, and bother other computers with the question. Note that cache is a property of a resolver, not a type of resolver. Hence one should never use the always-misleading term "caching DNS server".
There are two types of resolvers: Recursive and Non-Recursive.
Recursive Resolver
A recursive resolver is a resolver that is smart enough to start at the root servers, get the IP address of the authoritative nameserver(s) of the .edu Top Level Domain, then ask that authoritative nameserver the IP address of the authoritative nameserver(s) of fsu.edu, then ask that authoritative nameserver(s) the IP address of my.fsu.edu. This would be necessary if the RD bit isn't set, or if the authoritative nameservers queried are not Recursive Authoritative Nameservers.
The various "Public DNS Servers", such as Google's 8.8.8.8 and 8.8.4.4, or Cloudflare's 1.1.1.1, are really recursive resolvers with caching capabilities.
Non-Recursive Resolver
A resolver that can't do recursion. Such a resolver can do only two things:
Bogus Term: Iterative Resolver
It is forbidden, in this document, to use this term. The Resolver is either Recursive or it's not, within the definitions given previously. There's no need for the term "iterative resolver", and in fact it has multiple non-compatible definitions across the Internet.
Bogus Term: Caching DNS Server or Caching Server
Caching is an attribute of resolvers, not a type of resolver. These terms are never used in this document, and in my opinion should never be used at all. These terms cause nothing but confusion.
Non-helpful Term: Forwarding Resolver
You see this term used in various places including RFCs. I could speculate about what it means, but the fact is that it's unneeded. If a resolver wants to send some or all of its queries to a different resolver, that situation doesn't really require a new term. This term, along with the even less helpful "Forwarding DNS Server", are never used in this document.
Primary and Secondary DNS Servers
These are valid terms but are beyond the scope of this document. If you're curious, good definitions can be found at Section 6 of https://tools.ietf.org/html/draft-ietf-dnsop-terminology-bis-14.
AXFR
A type of data transfer certain authoritative nameservers can do. AXFR is way beyond the scope of this document. Read RFCs 1034, 1035 and 5936 if you really want to know.
Other Definitions
Glue Record
A glue record is a special RR, possessed by the authoritative nameserver over a parent zone, containing the IP address of the authoritative nameserver(s) for its child zone. The following paragraph illustrates why this is necessary:
Imagine there were no glue records, and the authoritative nameserver for the edu. domain knows only that the authoritative nameserver for fsu.edu. has authoritative nameservers at dns1.fsu.edu., dns2.fsu.edu., and dnsa.fsu.edu. Hey, that's wonderful, but how do you get IP address for those three servers in order to look up my.fsu.edu? You can't. It's a buried shovel. If only you could reach those authoritative nameservers for fsu.edu, you could look up the authoritative nameservers for fsu.edu. Ugh!
So the parent zone is also given "glue reecords" with the IP addresses of the child's IP addresses, to go along with the child zone's authoritative nameservers in domain name form. The buried shovel is dug up, and everything can be looked up.
Unbound is the new kid on the block when it comes to Resolvers for DNS. More and more people are using it. It's not bloaty or complicated like Bind's resolver part, and it's not as tricky as djbdns' dnscache program. Unbound is a recursive resolver that can be used to send queries to authoritative nameservers or to another resolver. Either way, it maintains a cache for lightning quick repeated lookups. Unbound's cache resides entirely in RAM, so it's lightning fast. Later in this document you'll find out how to down and up your resolver without losing that cache.
Unbound is capable of passing queries to authoritative nameservers, such as Bind and NSD, anywhere on the Internet. Unbound can also imitate authority over local LAN hosts via its local-zone, local-data, and local-data-ptr commands in the server section of its configuration file. In other words, instead of querying an authoritative nameserver on the Unbound resolver's domain, Unbound can can specify domain name to IP and IP to domain name lookups, on the Unbound resolver's domain. This can be a great simplification for doing authoritative DNS on a small LAN, especially if such DNS resolution doesn't need to be visible outside the LAN. Note that this use of Unbound is not Usual and Customary Architecture.
Unbound is fast becoming the go-to DNS resolver, replacing Bind's resolver, so it's very likely your Linux distribution will have an excellently crafted Unbound package. If not, you'll need to compile, but let's assume you have a package.
All configuration, including authoritative DNS definitions, is done in the unbound.conf file, which is typically in the /etc/unbound directory. You need to be user root to edit it.
And then there's the resolv.conf issue...
The makers of Unbound have chosen /usr/local/etc/unbound/ as the directory in which to put the unbound.conf config file and all the key files and other accessory files, including root.hints.
However, different distros use different paths for that directory. My distro happens to use /etc/unbound as the path to that directory. As you read this document, please be sure to change that directory to suit your installation's needs.
The /etc/resolv.conf file tells your computer which DNS resolver(s) to ask for a domain name to IP address translation. It should be pretty simple. But noooooo.
Back in the 1990's, when Linux was new and everybody was getting big salary increases, Linux laptops were rare. Most Linux computers had static IP addresses. /etc/resolv.conf was a configuration file: Nothing more, nothing less.
Roll forward to the early to mid 00's, when flip-phones became all the rage, a lot of folks had Linux laptops, phrases like "wardriving" and "road warrior" began referring to folks who brought their laptops everywhere, but public DNS resolvers were unheard of. Your laptop learned what resolver to query via DHCP, and Linux started containing software that would automagically change your /etc/resolv.conf when your DHCP changed. /etc/resolv.conf was no longer a config file: It was an intermediate file. This presented problems, but we were all happy that we could walk from the office to Starbucks and keep connected, via different "hotspots", all the way back and forth.
Which brings us to today (I'm writing this in September 2018). Nobody under 89 has a flip-phone, and we can choose from a wide range of public DNS resolvers, most more reliable and faster than the ones your ISP gives you. This is the twenty-tens, and having the computer change its own /etc/resolv.conf is an unnecessity straight out of a time when Dick Cheney was relevant.
Life can be simpler now. Just put the IP addresses of a couple or a few public DNS resolvers into your /etc/resolv.conf, or run your own resolver right on your laptop. Your choice. Either way, the last thing you need is some program changing your /etc/resolv.conf. And yet programs still do. Queue up the Backstreet Boys on your CD player.
So the cognizant computer user prevents software from changing /etc/resolv.conf. Shifting quicksand /etc/resolv.conf files don't belong in 2018, and must be eliminated, by any means necessary.
The "right" way to keep /etc/resolv.conf static is to adjust a conf file, depending on which software you have overseeing your /etc/resolv.conf. I suggest starting with Rick Moen's Suggestions and see how they work for you.
I have no time for defeating "features" that should have been removed about the time of Barack Obama's first inauguration, so I just use the following shellscript, which I call replaceresolv.sh:
#!/bin/sh resolv=/etc/resolv.conf chattr -i $resolv chmod 644 $resolv cp /etc/$1 $resolv chmod 444 $resolv chattr +i $resolv cat $resolv
I can edit a separate file, and have that file replace /etc/resolv.conf quicker than the resolv.conf manager software, whatever it might be, can sneak in a change. And by setting the i attribute, I deny the resolv.conf manager software the possibility of setting the file.
In summary, what I want in my /etc/resolv.conf is one of the following two:
Finally, just to round things out, here's a brief list of the most memorable public DNS resolver IP addresses:
The many other public DNS resolvers can be found at https://www.lifewire.com/free-and-public-dns-servers-2626062.
I just made the point that it's easy to find a public DNS resolver. I made that point to show that modifying /etc/resolv.conf is no longer necessary: At the very least we can use a public resolver.
Using a public facing resolver like 8.8.8.8 is much better than letting DHCP change your resolver at a whim, but what's even better than using a public facing DNS resolver is having your own resolver right on your computer. As you accumulate more and more domains in your cache, more and more domain queries are answered within one to two hundredths of a second. This is especially true if your cache is persistent between the ups and downs of your resolver, and between powerups and powerdowns.
Unbound's cache vanishes when Unbound terminates, unfortunately. This can be a problem on a laptop, where you might be turning your computer on and off several times an hour. The real problem is that one access to a "cloud based" website could pull in hundreds of URLs, every one of which needs its domain resolved to an IP address. To illustrate this point, after I restarted Unbound, when I dumped cache to STDOUT, the wc command reported five lines. After I accessed ford.com with a Chromium browser, that number jumped to 4270. Without a cache, web browsing is slow, especially on sites that assemble themselves from hundreds of web resources. They perform all this domain resolution on your dime. Having your DNS cache primed with the most common web resources and your favorite websites and the resources they pull in is a must, to avoid frustration when bringing the computer up and down.
There's a way, with unbound-control, to write the cache to disk and then after it restarts push the disk version of cache back into the running instance of Unbound. According to Unbound's documentation, you should load cache from the disk only for experimentation and troubleshooting, not production. Also, enabling unbound-control is non-trivial.
So here's a better way I found out. I dumped my cache to a file, picked out the most important (to me) domains, and made a shellscript to perform a nslookup on each of them. Actually, for some of the bigger websites that I browse often (rather than the ones that supply tiny parts of "cloud-based" websites), I perform the command elinks --dump on each, to pull in urls of their various web resources. My shellscript takes about two minutes to run, and starting from a new cache of 5 lines, fills it with about 5200 more.
My shellscript can be run, in the background, by the init system's startup of Unbound. The init system runs my shellscript in the background, then launches Unbound, and because my shellscript starts with a 2 second sleep, Unbound is definitely functional when my shellscript begins. Thus, my shellscript is running in parallel with everything else, before the computer is even ready for the user to use. The only caveat is that the init system must make a working network (not dns, just network) a prerequisite dependency to running Unbound, so DNS calls don't fail due to no network. Fortunately, this process dependency is trivial with runit, s6, daemontools, and daemontools-encore. It's fairly easy with systemd. With sysvinit and OpenRC it's just a matter of adding a small loop to Unbound's init script.
The true beauty of my shellscript is it does only good and causes no harm. It doesn't materially slow the boot because it runs parallel to everything else, and most of the time it takes is taken in the Internet's DNS system, not on my computer. It consumes almost no resources.
But what if you have to browse the web before my shellscript finishes? This is common at conventions where the previous speaker runs overtime, and hasn't removed his computer from the audio and vidio until two minutes after you were supposed to start. No problem, you can browse the web while my shellscript is still running. Unbound is a resolver built to handle hundreds or thousands of requests almost simultaneously, so it won't break a sweat. And once my shellscript has done even half its stuff, browsing is pretty fast.
The primecache.sh shellscript is just a normal foreground shellscript. The following is the runit init system's run script for Unbound with primecache.sh:
#!/bin/sh if ping -4 -c1 8.8.8.8 > /dev/null; then (/etc/unbound/primecache.sh &) exec unbound -dp else sleep 1 fi
If the Internet isn't yet functional, as indicated by a ping to 8.8.8.8, this run script waits 1 second and tries again. When the Internet is up, it runs (via something like doublefork) primecache.sh in the background and then execs into unbound. The -dp option stands for "debug and don't go into the background" (-d), and "don't maintain a PID file" (-p). You use these for modern init systems and process supervisors such as runit, s6, daemontools-encore, and probably systemd. For sysvinit and OpenRC you'd drop both those options because you want Unbound to background itself.
The parentheses around /etc/unbound/primecache.sh & do something like doubleforking, so that this process, which is run in the background, doesn't leave a zombie behind.
The preceding run script is for the runit init system. Run scripts for s6, daemontools and daemontools-encore are almost the same. I'm sure systemd has some way of doing this. With sysvinit and OpenRC, you'll probably need to add a short loop to their init scripts, with the loop repeatedly checking the network, and if the network is solid, doubleforking primecache.sh, and then running Unbound in daemonizing mode (no -dp argument).
My primecache.sh cache-priming shellscript can be seen in Appendix A of this document.
As mentioned previously, some websites must resolve hundreds of URLs to achieve their design goals. A cached Unbound DNS lookup should take 0.02 seconds. Successful uncached Unbound DNS lookups are typically between 0.5 and 3 seconds. Unsuccessful lookups depend on the timeout value of the command asking for the IP address, but 1 second isn't unreasonable. If your /etc/resolv.conf contains a bogus IP address above the IP address for Unbound, your web browsing will seem annoyingly slow, because each of those lookups requires a timeout time before Unbound takes care of business. Fortunately, I think that most resolvers stop consulting a /etc/resolv.conf IP address after several failures, but browsing will still feel like swimming in alake of mollassas.
So if you're going to use Unbound, make sure its IP address is at the top of /etc/resolv.conf. Personally, I make sure /etc/resolv.conf contains only Unbound's IP address, because if my domain resolution fails, I want it to fail hard so I know to fix it. I want my web work to feel like I'm on a line with 20Mbps capacity, not the 500Kbps from a decade ago. And if I don't have time to fix it, I can substitute 1.1.1.1
The folks from Unbound make it very easy for us, because if you run
unbound -dp -c empty.conf from the command prompt, it will resolve at 127.0.0.1. So do the following:
The unbound-checkconf program checks your configuration file. Run it from your /etc/unbound directory so it does not error out on a key file (if you've enabled remote control).
Run this program every time you change the config file. Fix any errors. This saves a lot of troubleshooting.
Always remember, after every change to /etc/unbound/unbound.conf, always run the unbound-checkconf program, before restarting Unbound.
The following config file assumes the following:
Your first task is to download the list of root servers from the Internet into a file called /etc/unbound/root.hints. After making sure directory /etc/unbound exists, either of the following commands does that:
curl -o /etc/unbound/root.hints \ https://www.internic.net/domain/named.cache
or:
wget -O /etc/unbound/root.hints \ https://www.internic.net/domain/named.cache
Now create the following /etc/unbound/unbound.conf:
### BE SURE to use unbound-checkconf ### before enabling a changed conf file! #FORWARD-ZONE SECTION!!!!!!!!!!!!!!!! # The following is how you query google DNS instead of root servers # I chose to query the root servers and commented it out. #forward-zone: #name: "." #forward-addr: 8.8.8.8 #forward-addr: 8.8.4.4 #SERVER SECTION!!!!!!!!!!!!!!!!!!!!!! server: use-syslog: yes # Use 192.168.47.102 so whole LAN can use it ip-address: 192.168.47.102 # Guard against future default changes: no systemd ever! use-systemd: no # Speed UDP so-reuseport: yes # use all CPU cores, I have 1 CPU with 2 cores num-threads: 2 # power of 2 close to num-threads msg-cache-slabs: 2 rrset-cache-slabs: 2 infra-cache-slabs: 2 key-cache-slabs: 2 # more cache memory, rrset=msg*2 rrset-cache-size: 100m msg-cache-size: 50m # more outgoing connections # depends on number of cores: 1024/cores - 50 outgoing-range: 450 # Larger socket buffer. # OS may need config, so I don't use it #so-rcvbuf: 4m #so-sndbuf: 4m # Faster UDP with multithreading (only on Linux). so-reuseport: yes # ROOT HINTS STUFF TO FIND ROOT DNS SERVERS # /etc/unbound/root.hints refreshed by following command # Update every six months # No (default) or old root-hints make slow lookups # curl -o /etc/unbound/root.hints \ # https://www.internic.net/domain/named.cache root-hints: /etc/unbound/root.hints # Other stuff, see # https://www.tecmint.com/setup-dns-cache-server-in-centos-7/ # Enable dig command with allow_snoop #access-control: 0.0.0.0/0 allow_snoop #access-control: 0.0.0.0/0 deny access-control: 192.168.47.0/24 allow access-control: 127.0.0.0/8 allow
A few words about the preceding /etc/unbound/unbound.conf. You're going to change all instances of 192.168.47.0 and 192.168.47.102 to whatever subnet and alias IP address is right for your computer. Don't worry about the commented out forward zone: If that becomes necessary you can deal with it then. The rest of the file is the server section. The reason 192.168.47.102 was used instead of 127.0.0.1 is so any computer on your subnet can query this resolver. If this isn't necessary, like if you're simply giving a laptop its own resolver, then 127.0.0.1 is simpler and more secure.
If you'll be using this with systemd, you can say use-systemd: yes, but make sure you declare it, because I have a feeling they'll change the default from "no" to "yes" unless the current backlash against systemd continues to grow.
Everything past use-systemd until the root hints part is designed to improve performance. Please read the optimization page at https://nlnetlabs.nl/documentation/unbound/howto-optimise/.
For security, I set Unbound to respond only to subnets 192.168.47.0/24 and 127.0.0.0/8. If it doesn't work, you can set it to 0.0.0.0/0 for the full Internet range, or even allow_snoop on that range.
Remember downloading /etc/unbound/root.hints? Notice the line in the preceding config file saying:
root-hints: /etc/unbound/root.hints
The preceding is what lets Unbound use the Internet-wide DNS system's Root Servers. The root-hints string is an Unbound config reserved word, but the filename could be any name. Note that you could remove this line and Unbound would still work. Poorly. You want to use this list of root servers, and you want to re-download it every six months or more frequently.
Be sure to check your config file:
When you're done downloading the Root Server list and creating /etc/unbound/unbound.conf, start or restart Unbound, and you should be able to resolve almost any address on the Internet, at address 192.168.47.102.
Enabling remote control is somewhat difficult, but you can do it. Remote control isn't necessary, but it sure is a handy troubleshooting tool.
Your first task is to create the proper keys. Do that with the following commands:
After performing the preceding commands, the following files should exist in /etc/unbound:
These files are essential to using Remote Control. Next, add the following Remote control section to the file. Don't put it inside another section like the server section.
#REMOTE-CONTROL SECTION!!!!!!!!!!!!!! # Enable use of unbound-control # Remote control is very, very useful # Use judgment re security # Use doublequotes on filenames, unbound should read them # from /etc/unbound # Create keys and certs by running unbound-control-setup remote-control: control-enable: yes control-use-cert: yes server-key-file: "unbound_server.key" server-cert-file: "unbound_server.pem" control-key-file: "unbound_control.key" control-cert-file: "unbound_control.pem"
Still inside the /etc/unbound directory, perform the unbound-checkconf command. Fix any errors.
Now stop and start your Unbound service. How you do that depends on your init system. On my runit-initted system, sv stop unbound; sv stop unbound is sufficient. You've guaranteed that Unbound is working on your latest config edits. Now perform the following commands:
If everything is OK, you'll be presented with a short list of properties of the daemon. Otherwise, troubleshoot.
Don't use unbound-control stop or unbound-control start. If you need to turn your daemon off or on, do it with your init system.
You can reload cache and reread the conf file with:
unbound-control reload.
This doesn't stop and start the daemon, so its PID remains the same. If you reload this way, you'll probably want to prime the cache by running shellscript primecache.sh described in the Preserving Cache Between Starts subsection and rendered Appendix A.
A spectacular troubleshooting tool is the following:
unbound-control dump_cache | wc
The preceding shows how developed your cache has become. With number of lines under 1000, you'll doubtlessly have some browsing degradation. With numbers above 5000, browsing will be a pleasant experience.
Well, not exactly authoritative in the usual meaning. Not Usual and Customary as defined in this document's Glossary section. And certainly not the kind of authoritative you'd want to put out on the Internet. But Unbound can associate computers on your LAN with IP addresses, without the aid of a local authoritative nameserver. The results can be served out on your LAN. Once again, if you want the IP addresses of local computers on the Internet at large, use a separate authoritative nameserver. But if you're only serving it out to your LAN, that can be done by Unbound alone. The rest of this section tells how to do it.
It's pretty simple. Add the following inside the server section of /etc/unbound/unbound.conf
### AUTH DNS on subnet, no separate AUTH srvr needed local-zone: "cxm." static local-data: "littlinks.cxm. IN A 192.168.47.189" local-data-ptr: "192.168.47.189 littlinks.cxm" local-data: "shazam.cxm. IN A 192.168.47.222" local-data-ptr: "192.168.47.222 shazam.cxm" local-zone: "domain.cxm." static local-data: "backup.domain.cxm. IN A 192.168.47.97" local-data-ptr: "192.168.47.97 backup.domain.cxm" local-data: "mydesk.domain.cxm. IN A 192.168.47.189" local-data-ptr: "192.168.47.189 mydesk.domain.cxm" local-data: "wincli.domain.cxm. IN A 192.168.47.5" local-data-ptr: "192.168.47.5 wincli.domain.cxm" local-data: "firewall.domain.cxm. IN A 192.168.47.206" local-data-ptr: "192.168.47.206 firewall.domain.cxm" local-data: "wifi.domain.cxm. IN A 192.168.47.207" local-data-ptr: "192.168.47.207 wifi.domain.cxm" local-data: "printer.domain.cxm. IN A 192.168.47.208" local-data-ptr: "192.168.47.208 printer.domain.cxm"
Next, run unbound-checkconf on it, and if it passes, restart Unbound. You should now be able to use command nslookup wincli.domain.cxm 192.168.47.102 to look up the IP address of wincli.domain.cxm, from anywhere on the subnet.
A Key Detail
It's rare that a resolver would or should refer queries directly to an authoritative nameserver. In most cases it's best for it to check its cache and if not there, start drilling down from the root DNS nameservers. The following two situations call for a resolver to refer to a specific authoritative nameserver:
Let's say you have a local domain, called home.lan, that has its own authoritative nameserver. A real authoritative nameserver, not just a few domain definitions grafted on to a resolver. An authoritative nameserver that can't look up any DNS, just define it. Let's say the home.lan authoritative nameserver is at 192.168.47.189. This section shows how to direct queries for anything on domain home.lan to that nameserver at 192.168.47.189:
Add the following to the very bottom of /etc/unbound.conf:
local-zone: "168.192.in-addr.arpa." nodefault #FANTASTIC MAGIC! stub-zone: name: "home.lan" stub-addr: 192.168.47.189 stub-zone: name: "47.168.192.in-addr.arpa." stub-addr: 192.168.47.189
BE SURE not to accidentally put the preceding in the middle of the server section. Be sure to use unbound-checkconf after the edit and before running Unbound.
The preceding snippet has two stub-zone references: One for your pure-authoritative DNS nameserver's forward DNS resolution, and one for its reverse DNS resolution. The local-zone reference is necessary to enable IP addresses in 192.168.47.0/24 to be referred to an auth nameserver: Otherwise Unbound would just return with an NXDOMAIN error. The zone overrides the default to return NXDOMAIN, enabling these addresses to get resolved by the reverse DNS at 192.168.47.189.
If you're curious why the local zone references 168.192.in-addr.arpa. instead of 47.168.192.in-addr.arpa, well, so am I. After all, you're using only 192.168.47.0/24, not the whole 192.168.0.0/16, so why does the local zone mention 168.192.in-addr.arpa instead of 47.168.192.in-addr.arpa? The short answer is that 47.168.192.in-addr.arpa doesn't work: It gives you the same NXDOMAIN error you'd get without it. So why does Unbound demand the larger range?
Truth be told, I don't know. My core competency isn't understanding all the RFCs. All I can say is RFC-1918 tells us that address blocks 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16 are intended to be private IP address blocks. RFC-6761 goes on to tell us that the following are, as RFC-6761 phrases it, "Special Use Domain Names":
Nowhere in the preceding list is 47.168.192.in-addr.arpa. For the local zone, Unbound makes you use one of the RFC-6761 Special Use Domain Names in order for Unbound to enable a purely authoritative nameserver to reverse-resolve an IP address in the subject private IP range. Note, however, that this is not true of the stub address. Take a few minutes to really let this sink in.
The reason I spent so much time on this detail is that it is, at least in my opinion, unexpected behavior, so it can cost a lot of troubleshooting time if not pre-warned.
#!/bin/sh display_and_grab(){ #echo Looking up $1 nslookup $1 > /dev/null 2>&1 } webbrowse(){ #echo Browsing $1 elinks --dump $1 > /dev/null 2>&1 } sleep 2 #echo startnow webbrowse troubleshooters.com webbrowse walmart.com webbrowse nhc.noaa.gov webbrowse cnn.com webbrowse flhurricane.com webbrowse futurequest.com webbrowse bluehost.com webbrowse gm.com webbrowse buick.com webbrowse ford.com webbrowse chevy.com webbrowse jeep.com webbrowse chrysler.com webbrowse ebay.com display_and_grab a.root-servers.net display_and_grab b.root-servers.net display_and_grab c.root-servers.net display_and_grab d.root-servers.net display_and_grab e.root-servers.net display_and_grab f.root-servers.net display_and_grab g.root-servers.net display_and_grab h.root-servers.net display_and_grab i.root-servers.net display_and_grab j.root-servers.net display_and_grab k.root-servers.net display_and_grab l.root-servers.net display_and_grab m.root-servers.net display_and_grab mail.a3b3.com display_and_grab 1and1.com display_and_grab pop.earthlink.net display_and_grab earthlink.net display_and_grab dns1.rr.com display_and_grab rr.com display_and_grab brighthouse.com display_and_grab resolute-3.com display_and_grab a3.verisigndns.com display_and_grab dns1.registrar-servers.com display_and_grab 1and1.com display_and_grab ns1.google.com display_and_grab ns2.google.com display_and_grab ns3.google.com display_and_grab ns4.google.com display_and_grab google.com display_and_grab rr.com display_and_grab googleapis.com display_and_grab free.org display_and_grab ns0.free.org display_and_grab ns1.free.org display_and_grab cloudflare.com display_and_grab ns.cloudflare.com display_and_grab ns1.cloudflare.net display_and_grab ns2.cloudflare.net display_and_grab ns3.cloudflare.net display_and_grab ns4.cloudflare.net display_and_grab dnsnode.net display_and_grab org display_and_grab net display_and_grab linuxmafia.com display_and_grab gitlab.com display_and_grab archlinux.org display_and_grab akamai.net display_and_grab akam.net display_and_grab akadns.org display_and_grab yahoo.com display_and_grab ultradns.net display_and_grab ultradns.org display_and_grab googleadservices.com display_and_grab dotster.com display_and_grab ns1.dotster.com display_and_grab ns2.dotster.com display_and_grab nasa.gov display_and_grab ns1.nasa.gov display_and_grab ns2.nasa.gov display_and_grab ns2.nasa.gov display_and_grab ns3.nasa.gov display_and_grab doubleverify.com display_and_grab amazon-adsystem.com display_and_grab disqus.com display_and_grab whois.com display_and_grab registrar-servers.com display_and_grab awsdns.com display_and_grab awsdns.net display_and_grab viglink.com display_and_grab msft.net display_and_grab windows.net display_and_grab whois.com display_and_grab yahoodns.net display_and_grab tv display_and_grab digital display_and_grab futurequest.net display_and_grab ns1.futurequest.net display_and_grab ns2.futurequest.net display_and_grab ns3.futurequest.net display_and_grab salesforce.com display_and_grab doubleclick.net
### BE SURE to use unbound-checkconf ### before enabling a changed conf file! #FORWARD-ZONE SECTION!!!!!!!!!!!!!!!! # The following is how you query google DNS instead of root servers # I chose to query the root servers and commented it out. #forward-zone: #name: "." #forward-addr: 8.8.8.8 #forward-addr: 8.8.4.4 #REMOTE-CONTROL SECTION!!!!!!!!!!!!!! # Enable use of unbound-control # Remote control is very, very useful # Use judgement re security # Use doublequotes on filenames, unbound should read them # from /etc/unbound # Create keys and certs by running unbound-control-setup remote-control: control-enable: yes control-use-cert: yes server-key-file: "unbound_server.key" server-cert-file: "unbound_server.pem" control-key-file: "unbound_control.key" control-cert-file: "unbound_control.pem" #SERVER SECTION!!!!!!!!!!!!!!!!!!!!!! server: use-syslog: yes # Use 192.168.47.189 so whole WAN can use it ip-address: 192.168.47.102 # Guard against future default changes: no systemd ever! use-systemd: no # Speed UDP so-reuseport: yes # use all CPU cores, I have 1 CPU with 2 cores num-threads: 2 # power of 2 close to num-threads msg-cache-slabs: 2 rrset-cache-slabs: 2 infra-cache-slabs: 2 key-cache-slabs: 2 # more cache memory, rrset=msg*2 rrset-cache-size: 100m msg-cache-size: 50m # more outgoing connections # depends on number of cores: 1024/cores - 50 outgoing-range: 450 # Larger socket buffer. # OS may need config, so I don't use it #so-rcvbuf: 4m #so-sndbuf: 4m # Faster UDP with multithreading (only on Linux). so-reuseport: yes # ROOT HINTS STUFF TO FIND ROOT DNS SERVERS # /etc/unbound/root.hints refreshed by following command # Update every six months # No (default) or old root-hints make slow lookups # curl -o /etc/unbound/root.hints \ # https://www.internic.net/domain/named.cache root-hints: /etc/unbound/root.hints ### AUTH DNS on subnet, no separate AUTH srvr needed local-zone: "cxm." static local-data: "littlinks.cxm. IN A 192.168.47.189" local-data-ptr: "192.168.47.189 littlinks.cxm" local-data: "shazam.cxm. IN A 192.168.47.222" local-data-ptr: "192.168.47.222 shazam.cxm" local-zone: "domain.cxm." static local-data: "backup.domain.cxm. IN A 192.168.47.97" local-data-ptr: "192.168.47.97 backup.domain.cxm" local-data: "mydesk.domain.cxm. IN A 192.168.47.189" local-data-ptr: "192.168.47.189 mydesk.domain.cxm" local-data: "wincli.domain.cxm. IN A 192.168.47.5" local-data-ptr: "192.168.47.5 wincli.domain.cxm" local-data: "firewall.domain.cxm. IN A 192.168.47.206" local-data-ptr: "192.168.47.206 firewall.domain.cxm" local-data: "wifi.domain.cxm. IN A 192.168.47.207" local-data-ptr: "192.168.47.207 wifi.domain.cxm" local-data: "printer.domain.cxm. IN A 192.168.47.13" local-data-ptr: "192.168.47.13 printer.domain.cxm" # Other stuff, see # https://www.tecmint.com/setup-dns-cache-server-in-centos-7/ # Enable dig command with allow_snoop #access-control: 0.0.0.0/0 allow_snoop access-control: 0.0.0.0/0 deny # access-control: 192.168.47.236/30 allow access-control: 192.168.47.0/24 allow access-control: 127.0.0.0/8 allow forward-zone: name: "home.lan" forward-addr: 192.168.47.189
[ Training | Troubleshooters.Com | Email Steve Litt ]