Tuesday, September 18, 2012

Caching Nameserver using dnsmasq


BIND vs dnsmasq

BIND is the flagship of DNS servers with large deployments around the globe. I have used BIND for many years as a caching nameserver, even on my desktop, until I realized it is overkill to use BIND this way. There are lighter solutions, even all-in-one software like dnsmasq, that seem to be more suitable for setting up local DNS caching.

System preparation

So, let’s get started with the system preparation before going into the details of the dnsmasq configuration.
First of all, we need to install dnsmasq:
yum install dnsmasq
dnsmasq, when run as root, is designed to drop privileges and run as an unprivileged user. By default, this user is nobody. We use a dedicated system user to run dnsmasq.
Run the following commands as root to create such an unprivileged system user and group named dnsmasq:
groupadd -r dnsmasq
useradd -r -g dnsmasq dnsmasq
The above should be enough.

Configuration

All dnsmasq configuration options go into /etc/dnsmasq.conf. Here we write this file from scratch, so if you need to keep a copy of the original that ships with your distribution, do so with:
cp /etc/dnsmasq.conf /etc/dnsmasq.conf.orig
Now, let’s get started with adding our own dnsmasq configuration in /etc/dnsmasq.conf.
First of all, we set some options regarding the basic server operation like the interface and port on which it should bind, the unprivileged user that should run the service and a PID file:
listen-address=127.0.0.1
port=53
bind-interfaces
user=dnsmasq
group=dnsmasq
pid-file=/var/run/dnsmasq.pid
The bind-interfaces directive instructs dnsmasq to bind only to the network interface specified in the listen-address directive.
Next comes logging.
By default, dnsmasq sends its log messages to the DAEMON syslog facility (LOCAL0 when operating in debug mode). We go with the defaults here, but keep in mind that a separate log file can be set as it is shown in the configuration snippet below (currently commented out):
#log-facility=/var/log/dnsmasq.log
#log-queries
Logging to file requires some extra configuration for proper log rotation. For more information, please read Appendix II.
Finally, we set the options that configure dnsmasq’s name resolution and caching operations.
The following directives prevent dnsmasq from forwarding plain names (without any dots) or addresses in the non-routed address space to the parent nameservers.
domain-needed
bogus-priv
The no-hosts directive also instructs dnsmasq not to read any hostnames from /etc/hosts. In most systems, /etc/hosts is queried before a DNS service is used by the system for name lookups. So, all plain name to private IP mappings should normally be added in /etc/hosts. If this is not what you want, then take a look at the expand-hosts and domain directives.
no-hosts
Set the maximum number of concurrent DNS queries. The default value is 150. Adjust to your needs.
dns-forward-max=150
Set the size of the dnsmasq cache. The default is to keep 150 hostnames. By setting the cache size to 0 disables the feature (this is not what we really want). Again, adjust this value according to your needs.
cache-size=1000
The following directive controls whether negative caching should be enabled or not. Negative caching allows dnsmasq to remember “no such domain” answers from the parent nameservers, so it does not query for the same non-existent hostnames again and again. This is probably useful for spam filters or MTA services. By default, negative caching is enabled. To disable, un-comment the following directive.
#no-negcache
The neg-ttl directive sets a default TTL value to add to negative replies from the parent nameservers, in case these replies do not contain TTL information. If neg-ttl is not set and a negative reply from a parent DNS server does not contain TTL information, then dnsmasq will not cache the reply. Here we set the default TTL to 3600 seconds. Again, adjust to your specific needs.
neg-ttl=3600
Here we use a separate file where dnsmasq reads the IPs of the parent nameservers from. The syntax is the same as in /etc/resolv.conf. We do this to facilitate the manipulation of the parent nameservers that should be used by dnsmasq by using, for example, an external script. The filename we use here is resolv.dnsmasq, but this can be changed to your liking. We also set the no-poll directive here to prevent dnsmasq from polling the ‘resolv’ file for changes.
resolv-file=/etc/resolv.dnsmasq
no-poll
A full configuration file containing all the above configuration, which can can be used as a drop-in replacement of the default /etc/dnsmasq.conf, can be found in Appendix I.

Upstream Nameservers

We have used a separate file to store the IPs of the parent nameservers; that is/etc/resolv.dnsmasq. Using the same syntax as in /etc/resolv.conf add the nameserver IP addresses in resolv.dnsmasq. For example:
nameserver 192.168.0.252
nameserver 192.168.0.253
nameserver 192.168.0.254
Note that we still need to make a change in /etc/resolv.conf before the system starts using dnsmasq for domain name lookups. Read on…

Starting dnsmasq

In order to start dnsmasq, run as root:
/etc/init.d/dnsmasq start
Check the syslog or the dnsmasq logfile (if used) for any error messages.
If everything seems to be OK, set the dnsmasq service to start on boot:
chkconfig dnsmasq on
This command might be Red-Hat specific, so consult your distribution’s documentation about how to set services to start on boot.

Switch name resolution to dnsmasq

What we have done so far is set up the dnsmasq service. For hostnames that do not exist in/etc/hosts the system still uses the nameserver inside /etc/resolv.conf for name resolution.
To start using dnsmasq, edit /etc/resolv.conf, remove all nameservers and add only the IP of our dnsmasq service:
nameserver 127.0.0.1
From now on, the system will use dnsmasq for domain name resolution. You can un-comment thelog-queries option in order to confirm the dnsmasq operation.

Appendix I – Full configuration file

This is the complete configuration file containing the configuration that has been discussed in this article. Note that it can be used as is to replace the default /etc/dnsmasq.conf.
#
# Configuration file for dnsmasq acting as a caching nameserver.
#
# Format is one option per line, legal options are the same
# as the long options legal on the command line. See
# "/usr/sbin/dnsmasq --help" or "man 8 dnsmasq" for details.
#
# Updated versions of this configuration file may be available at:
#
# http://www.g-loaded.eu/2010/09/18/caching-nameserver-using-dnsmasq/
#

#
# Basic server configuration
#

listen-address=127.0.0.1
port=53
bind-interfaces
user=dnsmasq
group=dnsmasq
pid-file=/var/run/dnsmasq.pid

#
# Logging
#

#log-facility=/var/log/dnsmasq.log
#log-queries

#
# Name resolution options
#

domain-needed
bogus-priv
no-hosts
dns-forward-max=150
cache-size=1000
#no-negcache
neg-ttl=3600
resolv-file=/etc/resolv.dnsmasq
no-poll
This file is meant to be used both on servers and desktops.

Appendix II – Logging to file

Before dnsmasq starts logging to file it is required to set the path to the logfile in the log-facility option inside /etc/dnsmasq.conf.
log-facility=/var/log/dnsmasq.log
To ensure proper rotation of the log file you should use the following logrotate configuration:
/var/log/dnsmasq.log {
monthly
missingok
notifempty
delaycompress
sharedscripts
postrotate
[ ! -f /var/run/dnsmasq.pid ] || kill -USR2 `cat /var/run/dnsmasq.pid`
endscript
create 0640 dnsmasq dnsmasq
}

0 comments: