dnsmasq

Related articles
Domain name resolution
dnsmasq
provides a
DNS server
, a
DHCP server
with support for
DHCPv6
and
PXE
, and a
TFTP server
. It is designed to be lightweight and have a small footprint, suitable for resource constrained routers and firewalls. dnsmasq can also be configured to cache DNS queries for improved DNS lookup speeds to previously visited sites.
Installation
Install
the
dnsmasq
package. Then
start/enable
dnsmasq.service
.
The network will also need to be restarted so the DHCP client can create a new
/etc/resolv.conf
.
Configuration
To configure dnsmasq, edit
/etc/dnsmasq.conf
. The file contains comments explaining the options. For all available options see
dnsmasq(8)
.
Note
dnsmasq's default configuration enables its DNS server. If you do not require it, you need to explicitly disable it by setting
port=0
.
If dnsmasq will not be used as a local DNS resolver, you may also want to
edit
dnsmasq.service
so that it does not pull in
nss-lookup.target
:
/etc/systemd/system/dnsmasq.service.d/no-nss-lookup-target.conf
[Unit]
Wants=
Tip
To check configuration file(s) syntax, execute:
$ dnsmasq --test
DNS server
To set up dnsmasq as a DNS caching daemon on a single computer specify a
listen-address
directive, adding in the localhost IP address:
listen-address=::1,127.0.0.1
To use this computer to listen on its LAN IP address for other computers on the network. It is recommended that you use a static LAN IP in this case. E.g.:
listen-address=::1,127.0.0.1,192.168.1.1
You may alternatively assign a network interface:
interface=enp5s0
Set the number of cached domain names with
cache-size=
size
(the default is
150
):
cache-size=10000
To validate
DNSSEC
load the DNSSEC trust anchors provided by the
dnsmasq
package and set the option
dnssec
:
conf-file=/usr/share/dnsmasq/trust-anchors.conf
dnssec
See
dnsmasq(8)
for more options you might want to use.
DNS addresses file and forwarding
After configuring dnsmasq, you need to add the localhost addresses as the only nameservers in
/etc/resolv.conf
. This causes all queries to be sent to dnsmasq.
Since dnsmasq is a stub resolver not a recursive resolver you must set up forwarding to an external DNS server. This can be done automatically by using
openresolv
or by manually specifying the DNS server address in dnsmasq's configuration.
openresolv
If your network manager supports
resolvconf
, instead of directly altering
/etc/resolv.conf
, you can use
openresolv
to
generate configuration files for dnsmasq
.
Edit
/etc/resolvconf.conf
and add the loopback addresses as name servers, and configure openresolv to write out dnsmasq configuration:
/etc/resolvconf.conf
# Use the local name server
name_servers="::1 127.0.0.1"
resolv_conf_options="trust-ad"

# Write out dnsmasq extended configuration and resolv files
dnsmasq_conf=/etc/dnsmasq-conf.conf
dnsmasq_resolv=/etc/dnsmasq-resolv.conf
Run
resolvconf -u
so that the configuration files get created. If the files do not exist
dnsmasq.service
will fail to start.
Edit dnsmasq's configuration file to use openresolv's generated configuration
[1]
:
# Read configuration generated by openresolv
conf-file=/etc/dnsmasq-conf.conf
resolv-file=/etc/dnsmasq-resolv.conf
Manual forwarding
First you must set localhost addresses as the only nameservers in
/etc/resolv.conf
:
/etc/resolv.conf
nameserver ::1
nameserver 127.0.0.1
options trust-ad
Make sure to protect
/etc/resolv.conf
from modification as described in
Domain name resolution#Overwriting of /etc/resolv.conf
.
This article or section is a candidate for merging with
NetworkManager#Setting custom DNS servers in a connection (nmcli / connection file)
.
Notes:
NetworkManager configuration is out of scope. (Discuss in
Talk:Dnsmasq
)
Alternatively,
NetworkManager
may be configured to automatically generate the
/etc/resolv.conf
file for a specific connection with the following commands:
$ nmcli connection modify 'connection-name' ipv4.dns 127.0.0.1
$ nmcli connection modify 'connection-name' ipv4.dns-options trust-ad
$ nmcli connection modify 'connection-name' ipv4.ignore-auto-dns yes
$ nmcli connection modify 'connection-name' ipv6.dns ::1
$ nmcli connection modify 'connection-name' ipv6.dns-options trust-ad
$ nmcli connection modify 'connection-name' ipv6.ignore-auto-dns yes
Then
restart
NetworkManager.service
.
The upstream DNS server addresses must then be specified in dnsmasq's configuration file as
server=
server_address
. Also add
no-resolv
so dnsmasq does not needlessly read
/etc/resolv.conf
which only contains the localhost addresses of itself.
/etc/dnsmasq.conf
[...]
no-resolv

# Google's nameservers, for example
server=8.8.8.8
server=8.8.4.4
Note
This example uses Google Public DNS. Replace it with a DNS resolver you trust. See
Domain name resolution#Third-party DNS services
.
dnsmasq does not support
encrypted protocols
which are desired when connecting to third-party DNS services. A workaround is to run a separate DNS resolver that supports encrypted DNS and forward dnsmasq's queries to it. See
Stubby#Local DNS cache configuration
for an example.
Now DNS queries will be resolved with dnsmasq, only checking external servers if it cannot answer the query from its cache.
Adding a custom domain
You can assign a domain simply by adding:
address=/router/192.168.1.1
Alternatively, if you continue to use add a custom domain to hosts in your (local) network:
local=/home.arpa/
domain=home.arpa
In this example it is possible to ping a host/device (e.g. defined in your
/etc/hosts
file) as
hostname
.home.arpa
.
Uncomment
expand-hosts
to add the custom domain to hosts entries:
expand-hosts
Without this setting, you will have to add the domain to entries of
/etc/hosts
.
Test
To do a lookup speed test choose a website that has not been visited since dnsmasq has been started (
drill
is part of the
ldns
package):
$ drill archlinux.org | grep "Query time"
Running the command again will use the cached DNS IP and result in a faster lookup time if dnsmasq is setup correctly:
$ drill archlinux.org | grep "Query time"
;; Query time: 18 msec
$ drill archlinux.org | grep "Query time"
;; Query time: 2 msec
To test if DNSSEC validation is working see
DNSSEC#Test the local validating resolver
.
DHCP server
This article or section needs expansion.
Reason:
Add instructions for IPv6 (Discuss in
Talk:Dnsmasq
)
By default dnsmasq has the DHCP functionality turned off, if you want to use it you must turn it on.  Here are the important settings:
# Only listen to routers' LAN NIC.  Doing so opens up tcp/udp port 53 to localhost and udp port 67 to world:
interface=
enp0s0
# dnsmasq will open tcp/udp port 53 and udp port 67 to world to help with dynamic interfaces (assigning dynamic IPs).
# dnsmasq will discard world requests to them, but the paranoid might like to close them and let the kernel handle them.
# You may also need this option if you have other instances of dnsmasq running (eg. because of libvirtd)
bind-interfaces

# Optionally set a domain name
domain=
example.org
# Set default gateway
dhcp-option=3,0.0.0.0

# Set DNS servers to announce
dhcp-option=6,0.0.0.0

# If your dnsmasq server is also doing the routing for your network, you can use option 121 to push a static route out.
# x.x.x.x is the destination LAN, yy is the CIDR notation (usually /24), and z.z.z.z is the host which will do the routing.
dhcp-option=121,
x.x.x.x
/
yy
,
z.z.z.z
,0.0.0.0/0,0.0.0.0

# Dynamic range of IPs to make available to LAN PC and the lease time.
# Ideally set the lease time to 5m only at first to test everything works okay before you set long-lasting records.
# The range of addresses here must lie within the address range assigned to the virtual interface.
dhcp-range=192.168.111.50,192.168.111.100,12h

# Provide IPv6 DHCP leases, the range is constructed using the network interface as prefix
dhcp-range=::f,::ff,constructor:
enp0s0
# If you’d like to have dnsmasq assign static IPs to some clients, bind the LAN computers NIC MAC addresses:
dhcp-host=aa:bb:cc:dd:ee:ff,192.168.111.50
dhcp-host=aa:bb:cc:ff:dd:ee,192.168.111.51
See
dnsmasq(8)
for more options.
Proxy DHCP
In case there is already a DHCP server running on the network and you want to interoperate with it, dnsmasq can be set to behave as a "proxy DHCP", therefore only serving the
#PXE server
specific information to the client. This mode is only available with IPv4. Use the following syntax, providing the existing DHCP server address:
dhcp-range=192.168.0.1,proxy
Test
From a computer that is connected to the one with dnsmasq on it, configure it to use DHCP for automatic IP address assignment, then attempt to log into the network normally.
If you inspect the
/var/lib/misc/dnsmasq.leases
file on the server, you should be able to see the lease.
TFTP server
dnsmasq has built-in
TFTP
server.
To use it, create a root directory for TFTP (e.g.
/srv/tftp
) to put transferable files in.
enable-tftp
tftp-root=/srv/tftp
For increased security it is advised to use dnsmasq's TFTP secure mode. In secure mode only files owned by the
dnsmasq
user will be served over TFTP. You will need to
chown
TFTP root and all files in it to
dnsmasq
user to use this feature.
tftp-secure
See
dnsmasq(8)
for more options.
PXE server
PXE requires a DHCP and a TFTP server; both can be provided by dnsmasq. To setup the PXE server, follow these steps:
Setup the
#TFTP server
and the
#DHCP server
(in full DHCP or proxy mode) in the dnsmasq configuration file,
Copy and configure a PXE compatible boot loader (e.g.
PXELINUX
) in the TFTP root directory,
Enable PXE in the dnsmasq configuration file:
To simply send one file:
dhcp-boot=lpxelinux.0
To send a file depending on client architecture:
pxe-service=x86PC,"PXELINUX (BIOS)",bios/lpxelinux
pxe-service=X86-64_EFI,"PXELINUX (EFI)",efi64/syslinux.efi
Note
File paths are relative to the TFTP root path
If the file has a
.0
suffix, you must exclude the suffix in
pxe-service
options
In case
pxe-service
does not work to identify the architecture (especially for UEFI-based clients), combination of
dhcp-match
and
dhcp-boot
can be used. See
RFC 4578 2.1
for more
client-arch
numbers for use with dhcp boot protocol.
dhcp-match=set:efi-x86_64,option:client-arch,7
dhcp-match=set:efi-x86_64,option:client-arch,9
dhcp-match=set:efi-x86,option:client-arch,6
dhcp-match=set:bios,option:client-arch,0
dhcp-boot=tag:efi-x86_64,efi64/syslinux.efi
dhcp-boot=tag:efi-x86,efi32/syslinux.efi
dhcp-boot=tag:bios,bios/lpxelinux.0
See
dnsmasq(8)
for more options.
The rest is up to the
boot loader
.
Tips and tricks
Prevent OpenDNS redirecting Google queries
To prevent OpenDNS from redirecting all Google queries to their own search server, add to
/etc/dnsmasq.conf
:
server=/www.google.com/
isp-dns-ip
Override addresses
In some cases, such as when operating a captive portal, it can be useful to resolve specific domains names to a hard-coded set of addresses. This is done with the
address
config:
address=/example.com/1.2.3.4
Furthermore, it is possible to return a specific address for all domain names that are not answered from
/etc/hosts
or DHCP by using a special wildcard:
address=/#/1.2.3.4
More than one instance
If we want two or more dnsmasq servers works per interface(s).
Static
To do this statically - one server per interface, use the
interface
and
bind-interfaces
options. This starts a second dnsmasq instance and is only required when running a concurrent nameserver.
To simply co-exist with
libvirtd
for example, add
--bind-dynamic
to the dnsmsaq service start options.
Dynamic
In this case we can exclude per interface and bind any others:
except-interface=lo
bind-dynamic
Note
This is the default in
libvirt
.
Domain blocklisting
To blocklist domains, i.e. answer queries for them with NXDOMAIN, use the
address
option without specifying the IP address:
address=/blocked.example/
address=/anotherblocked.example/
Note
Unlike the
/etc/hosts
file, dnsmasq will block these domains and also all subdomains such as
subdomain.blocked.example
.
Wildcards are also supported. Add a
*
to the start of the pattern:
# blocks both
blocked.example
and
anotherblocked.example
and all their subdomains
address=/*blocked.example/

# blocks subdomains like
mail.google.com
but not
google.com
address=/*.google.com/
Some specific subdomains can be unblocked using
#
as the server address:
# blocks
google.com
and all subdomains except
mail.google.com
.
address=/google.com/
server=/mail.google.com/#
Note
The options
address=/example.com/
and
server=/example.com/
are equivalent. Both will answer queries for them with NXDOMAIN.
The options
address=/example.com/#
and
server=/example.com/#
are not equivalent.
address=/example.com/#
will answer queries for the domain with the NULL address (0.0.0.0 or :: for IPv6).
server=/example.com/#
will send queries for the domain to the standard configured servers.
The patterns
/example.com/
and
/.example.com/
are equivalent. Both will match
example.com
and all its subdomains.
For ease of use place the blocklist in a separate file, e.g.
/etc/dnsmasq.d/blocklist.conf
and load it from
/etc/dnsmasq.conf
with
conf-file=/etc/dnsmasq.d/blocklist.conf
or
conf-dir=/etc/dnsmasq.d/,*.conf
.
Tip
A list of potential sources for the blocklist can be found in
OpenWrt's adblock package's README
.
A hosts file blocklist can be used with the
addn-hosts=hosts.txt
option or it can be converted to a dnsmasq blocklist with this awk command:
awk '/^[^#]/ { print "address=/"$2"/"$1"" }' hosts.txt
.
View cache statistics
Cache statistics can be queried using chaos requests, using the
drill
utility from the
ldns
package:
$ drill misses.bind TXT CH
$ drill hits.bind TXT CH
The output will respectively contain the number of cache misses and hits:
;; ANSWER SECTION:
misses.bind.    0       CH      TXT     "411"
Other options are
cachesize.bind
,
insertions.bind
,
evictions.bind
,
auth.bind
and
servers.bind
.
See also
Caching Nameserver using dnsmasq, and a few other tips and tricks.