newspaint

Documenting Problems That Were Difficult To Find The Answer To

Using Dnsmasq as Caching Nameserver on Ubuntu Xenial

Setting up dnsmasq as a caching nameserver locally on Ubuntu Xenial (16.04.6 LTS) can speed up the Internet experience as, by default, Linux queries a nameserver every time a domain name is connected to – and this usually involves the round-trip time to the configured nameserver. It is so much quicker to have a response locally if it is cached.

First, install dnsmasq:

$ sudo apt-get install dnsmasq
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
  dns-root-data dnsmasq-base libnetfilter-conntrack3
The following NEW packages will be installed:
  dns-root-data dnsmasq dnsmasq-base libnetfilter-conntrack3
0 upgraded, 4 newly installed, 0 to remove and 7 not upgraded.
Need to get 353 kB of archives.
After this operation, 972 kB of additional disk space will be used.
Do you want to continue? [Y/n] y

You may also want the lookup tool “dig” to test the dnsmasq install:

$ sudo apt-get install dnsutils
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
  bind9-host libbind9-140 libdns162 libisc160 libisccc140 libisccfg140
  liblwres141
Suggested packages:
  rblcheck
The following NEW packages will be installed:
  bind9-host dnsutils libbind9-140 libdns162 libisc160 libisccc140
  libisccfg140 liblwres141
0 upgraded, 8 newly installed, 0 to remove and 7 not upgraded.
Need to get 1,338 kB of archives.
After this operation, 6,059 kB of additional disk space will be used.
Do you want to continue? [Y/n] y

Once dnsmasq has been installed create a custom cache configuration in the /etc/dnsmasq.d/ subdirectory:

# http://www.thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html

# Listen on the given IP address(es).
listen-address=127.0.0.1,::1

# Listen on <port> instead of the standard DNS port (53).
port=53

# Force dnsmasq to really bind only the interfaces it is listening on.
bind-interfaces

# Log the results of DNS queries handled by dnsmasq.
# Enable a full cache dump on receipt of SIGUSR1.
# If the argument "extra" is supplied, ie --log-queries=extra then the
# log has extra information at the start of each line. This consists of
# a serial number which ties together the log lines associated with an
# individual query, and the IP address of the requestor.
log-queries

# If the facility given contains at least one '/' character, it is
# taken to be a filename, and dnsmasq logs to the given file, instead
# of syslog. If the facility is '-' then dnsmasq logs to stderr.
log-facility=/var/log/dnsmasq.log

# Tells dnsmasq to never forward A or AAAA queries for plain names,
# without dots or domain parts, to upstream nameservers. If the name is
# not known from /etc/hosts or DHCP then a "not found" answer is
# returned.
domain-needed

# All reverse lookups for private IP ranges (ie 192.168.x.x, etc) which
# are not found in /etc/hosts or the DHCP leases file are answered with
# "no such domain" rather than being forwarded upstream.
bogus-priv

# Don't read the hostnames in /etc/hosts.
#no-hosts

# Set the maximum number of concurrent DNS queries.
dns-forward-max=150

# Set the size of dnsmasq's cache.
# Setting the cache size to zero disables caching.
cache-size=250

# Disable negative caching.
#no-negcache

# This option gives a default value for time-to-live (in seconds) which
# dnsmasq uses to cache negative replies even in the absence of an SOA
# record.
neg-ttl=120

# Read the IP addresses of the upstream nameservers from <file>,
# instead of /etc/resolv.conf.
resolv-file=/etc/resolv.dnsmasq

# Don't poll /etc/resolv.conf for changes.
#no-poll

# Specify time-to-live for information from /etc/hosts.
local-ttl=15

# Set a maximum TTL value for entries in the cache.
max-cache-ttl=300

# Setting this flag forces dnsmasq to try each query with each server
# strictly in the order they appear in /etc/resolv.conf
#strict-order

Next, create a custom resolv.conf file for dnsmasq to use:

# Google secondary DNS
nameserver 8.8.4.4

# Cloudflare secondary DNS
nameserver 1.0.0.1

We’re not finished! If we want to use our own resolv.conf file then we have to modify the defaults file for dnsmasq:

IGNORE_RESOLVCONF=yes

Alright, now we’re ready to start dnsmasq. Well it might already be running:

$ sudo systemctl status dnsmasq
* dnsmasq.service - dnsmasq - A lightweight DHCP and caching DNS server
   Loaded: loaded (/lib/systemd/system/dnsmasq.service; enabled; vendor preset: enabled)
  Drop-In: /run/systemd/generator/dnsmasq.service.d
           `-50-dnsmasq-$named.conf, 50-insserv.conf-$named.conf
   Active: active (running) since Mon 2019-08-26 06:13:09 UTC; 1h 4min ago
  Process: 7170 ExecStop=/etc/init.d/dnsmasq systemd-stop-resolvconf (code=exited, status=0/SUCCESS)
  Process: 7224 ExecStartPost=/etc/init.d/dnsmasq systemd-start-resolvconf (code=exited, status=0/SUCCESS)
  Process: 7212 ExecStart=/etc/init.d/dnsmasq systemd-exec (code=exited, status=0/SUCCESS)
  Process: 7209 ExecStartPre=/usr/sbin/dnsmasq --test (code=exited, status=0/SUCCESS)
 Main PID: 7223 (dnsmasq)
   CGroup: /system.slice/dnsmasq.service
           `-7223 /usr/sbin/dnsmasq -x /var/run/dnsmasq/dnsmasq.pid -u dnsmasq -7 /etc/dnsmasq.d,.dpkg-dist,.dpkg-old,.dpkg-new --local-service

Aug 26 06:13:08 myhost systemd[1]: Starting dnsmasq - A lightweight DHCP and caching DNS server...
Aug 26 06:13:08 myhost dnsmasq[7209]: dnsmasq: syntax check OK.
Aug 26 06:13:09 myhost systemd[1]: Started dnsmasq - A lightweight DHCP and caching DNS server.

Either way, start or restart the dnsmasq daemon:

$ sudo systemctl stop dnsmasq
$ sudo systemctl start dnsmasq

We can view the dnsmasq log:

$ cat /var/log/dnsmasq.log
Aug 26 07:21:10 dnsmasq[8118]: started, version 2.75 cachesize 250
Aug 26 07:21:10 dnsmasq[8118]: compile time options: IPv6 GNU-getopt DBus i18n IDN DHCP DHCPv6 no-Lua TFTP conntrack ipset auth DNSSEC loop-detect inotify
Aug 26 07:21:10 dnsmasq[8118]: reading /etc/resolv.dnsmasq
Aug 26 07:21:10 dnsmasq[8118]: using nameserver 8.8.4.4#53
Aug 26 07:21:10 dnsmasq[8118]: using nameserver 1.0.0.1#53
Aug 26 07:21:10 dnsmasq[8118]: read /etc/hosts - 4 addresses

How about testing with a looking?

$ dig @localhost -p 53 www.wikipedia.org
; <> DiG 9.10.3-P4-Ubuntu <> @localhost -p 53 www.wikipedia.org
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 29520
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1452
;; QUESTION SECTION:
;www.wikipedia.org.             IN      A

;; ANSWER SECTION:
www.wikipedia.org.      9864    IN      CNAME   dyna.wikimedia.org.
dyna.wikimedia.org.     266     IN      A       91.198.174.192

;; Query time: 7 msec
;; SERVER: ::1#53(::1)
;; WHEN: Mon Aug 26 07:24:27 UTC 2019
;; MSG SIZE  rcvd: 91

$ tail /var/log/dnsmasq.log
Aug 26 07:24:27 dnsmasq[8118]: query[A] www.wikipedia.org from ::1
Aug 26 07:24:27 dnsmasq[8118]: forwarded www.wikipedia.org to 8.8.4.4
Aug 26 07:24:27 dnsmasq[8118]: forwarded www.wikipedia.org to 1.0.0.1
Aug 26 07:24:27 dnsmasq[8118]: reply www.wikipedia.org is 
Aug 26 07:24:27 dnsmasq[8118]: reply dyna.wikimedia.org is 91.198.174.192

Looks to be working. Interestingly, by default, dnsmasq queries all name servers simultaneously, at first, to determine which is responding the quickest, and will then tend to just query that one for a while, until it tries all the name servers again.

A few more things to finish up. Let’s tell Linux to use localhost to do DNS lookups in future:

# The primary network interface
auto ens5
iface ens5 inet static
        # dns-* options are implemented by the resolvconf package, if installed
        dns-nameservers 127.0.0.1

And to make the change by hand until the next reboot you can edit /etc/resolv.conf directly to use 127.0.0.1 as the only nameserver.

You may want to also add a logrotate configuration:

/var/log/dnsmasq.log {
        size 20M
        rotate 50
        compress
        missingok
        notifempty
        create 644 dnsmasq root
        prerotate
                if systemctl status dnsmasq >/dev/null; then
                        systemctl stop dnsmasq >/dev/null;
                        touch /tmp/logrotate-dnsmasq-stopped.tmp;
                fi
        endscript
        postrotate
                if [ -e /tmp/logrotate-dnsmasq-stopped.tmp ]; then
                        rm /tmp/logrotate-dnsmasq-stopped.tmp;
                        systemctl start dnsmasq >/dev/null;
                fi
        endscript
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: