Caching DNS queries with Unbound
By default on Linux distributions like CentOS, if a process needs to resolve a hostname it will query a remote name server. The IP address of the name server(s) which is queried is controlled by /etc/resolv.conf. While this process is very straightforward, it does mean if the same address is queried multiple times, the system will have to send multiple DNS queries over the network. This post is going to look at configuring Unbound to act as a local DNS cache.
Caching requests
When a process calls a function like getaddrinfo, a query is sent via the network:
Instead of the process making the call directly to the remote name server, traffic can initially be sent to Unbound. Unbound will then forward the request on to a remote server:
However once Unbound received a reply it can cache the response. Subsequent requests can then be answered using the cached answer:
This does add some additional complexity, however the cached responses will avoid network latency and should therefore be quicker:
$ time host example.com 1.1.1.1
Using domain server:
Name: 1.1.1.1
Address: 1.1.1.1#53
Aliases:
example.com has address 93.184.216.34
example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:1946
real 0m0.093s
user 0m0.007s
sys 0m0.008s
$ time host example.com 127.0.0.1
Using domain server:
Name: 127.0.0.1
Address: 127.0.0.1#53
Aliases:
example.com has address 93.184.216.34
example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:1946
real 0m0.018s
user 0m0.012s
sys 0m0.005s
Using a cache for DNS queries is also helpful if the connection to a remote name server is unreliable, as cached requests do not depend on the network.
Setting up Unbound
On CentOS 7 Unbound can be installed using yum
yum install -y unbound bind-utils
Once Unbound is installed, the remote name server(s) to forward DNS queries to can be set with configuration similar to the following:
forward-zone:
name: "."
forward-addr: 1.1.1.1
forward-addr: 1.0.0.1
This configuration will tell Unbound to forward all DNS queries onto
Cloudflare's public DNS servers. The configuration can either
be added to the main configuration file, /etc/unbound/unbound.conf
, or to an
additional config file under /etc/unbound/conf.d/
. You may also want to set
additional options such as cache-max-ttl
. Information on additional options
can be found in the unbound.conf man page.
Once you're happy with the configuration, enable and start the Unbound service:
systemctl enable unbound
systemctl start unbound
If everything goes well you should be able to query the Unbound server:
$ host example.com 127.0.0.1
Using domain server:
Name: 127.0.0.1
Address: 127.0.0.1#53
Aliases:
example.com has address 93.184.216.34
example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:1946
You can also use the unbound-control command to verify Unbound is forwarding queries on to the correct name server(s):
$ unbound-control lookup example.com
The following name servers are used for lookup of example.com.
forwarding request:
Delegation with 0 names, of which 0 can be examined to query further addresses.
It provides 2 IP addresses.
1.1.1.1 rto 147 msec, ttl 144, ping 19 var 32 rtt 147, tA 0, tAAAA 0, tother 0, EDNS 0 probed.
1.0.0.1 rto 194 msec, ttl 144, ping 10 var 46 rtt 194, tA 0, tAAAA 0, tother 0, EDNS 0 probed.
Once you're happy Unbound is functioning correctly, /etc/resolv.conf
can be
updated to point at 127.0.0.1
with configuration similar to the following:
nameserver 127.0.0.1
If /etc/resolv.conf
has been generated by
NetworkManager, it will be overwritten when the network
is restarted. To get around this the NetworkManager configuration can be
updated with commands similar to the following:
nmcli connection modify System\ enp0s3 ipv4.dns 127.0.0.1
nmcli connection modify System\ enp0s3 ipv4.ignore-auto-dns yes
Allowing remote queries
By default Unbound will only accept DNS queries on a local interface. It is however fairly straightforward to allow remote queries, this can be done with the following configuration:
server:
interface: 0.0.0.0
access-control: 10.0.0.0/8 allow
This will tell Unbound to listen on any IPv4 interface, and allow remote
queries from the 10.0.0.0/8
subnet.