Run dnsmasq as a local DNS Server (Arch Linux)

DNS with dnsmasq

Dnsmasq is a very handy and easy to install DNS / DHCP server implementation, that uses the local hosts file to determine hostname to IP mappings. I use a local DNS to be able to call my local machines by a memorable domain instead of their IP. Additionally dnsmasq works as an DNS Cache.

Installation of dnsmasq

You can install dnsmasq with the following commands (Arch Linux with installed sudo package):

$> sudo pacman -Syu # Update all packages
$> sudo pacman -S dnsmasq # install dnsmasq

Configuration of dnsmasq

After that you have to configure dnsmasq. This could be done directly in the dnsmasq configuration file (/etc/dnsmasq.conf) or in an own configuration file that is included in the dnsmasq.conf. I decided to use an own file:

$> sudo su - #switch to root user
$> mkdir /etc/dnsmasq.d # create configuration folder
$> cp /etc/dnsmasq.conf /etc/dnsmasq.d/lan.ask-sheldon.com # copy original configuration
$> echo 'conf-dir=/etc/dnsmasq.d,.bak' >> /etc/dnsmasq.conf # loads all confi​_​_guration files in /etc/dnsmasq.d except *.bak files

Now the copied configuration file (lan.ask-sheldon.com) will be interpreted.

Now you have to set the following configurations ($> nano /etc/dnsmasq.d/lan.ask-sheldon.com):

# Never forward plain names (without a dot or domain part)
#domain-needed
# Never forward addresses in the non-routed address spaces.Run a local
bogus-priv

# Add local-only domains here, queries in these domains are answered
# from /etc/hosts or DHCP only.
local=/lan.ask-sheldon.com/

# Or which to listen on by address (remember to include 127.0.0.1 if
# you use this.)
listen-address=127.0.0.1 # => listen for dns calls from the local machine itself
listen-address=192.168.88.1 # => listen for dns calls from the local network

# Set this (and domain: see below) if you want to have a domain
# automatically added to simple names in a hosts-file.
expand-hosts

# Set the domain for dnsmasq. this is optional, but if it is set, it
# does the following things.
# 1) Allows DHCP hosts to have fully qualified domain names, as long
# as the domain part matches this setting.
# 2) Sets the "domain" DHCP option thereby potentially setting the
# domain of all systems configured by DHCP
# 3) Provides the domain part for "expand-hosts"
domain=lan.ask-sheldon.com

I deleted the unchanged lines for clarity and because I have preserve the original dnsmasq.conf.

Now localhost have to be set as the first DNS server for the local machine ($> nano /etc/resolv.conf ):

nameserver 127.0.0.1
nameserver 192.168.88.1 # fritzbox as fallback

The problem is, that different programs can override the resolv.conf, so that all changes are lost. That’s why we have to protect it. In my case the resolv.conf was a symlink to /run/systemd/resolve/resolv.conf.

$> ls -al /etc/resolv.conf 
$> lrwxrwxrwx 1 root root 32 Jul 3 01:56 /etc/resolv.conf -> /run/systemd/resolve/resolv.conf
So I removed the symlink and crated a static file /etc/resolv.conf where I put the lines above again.

Additionally its possible, that the DHCP deamon could change the/etc/resolv.conf . That’s why I added the following line to the end of my dhcpd.conf ($> nano /etc/dhcpcd.conf):

# protect resolv.conf
nohook resolv.conf

To be 100% sure to have the total control about what’s happening with the resolv.conf, I added a write-protection to that file:

$> chattr +i /etc/resolv.conf

Add local domains

Local domains could be defined in the file /etc/hosts now. Afterwards dnsmasq can resolve them.

Example:

# IP            Rechnername                                     Beschreibung
#=====================================================================================
127.0.0.1       localhost dnspi                                 # loopack
::1             localhost ip6-localhost ip6-loopback
fe00::0         ip6-localnet
ff00::0         ip6-mcastprefix
ff02::1         ip6-allnodes
ff02::2         ip6-allrouters

# Fritzbox
192.168.88.1   asgard                                          # Fritzbox home
192.168.99.1   valhalla                                        # Fritzbox parents

# Raspberry Pi's
192.168.88.2   dnspi                                          
192.168.88.2   backup                                          

# IP-Cam
192.168.88.3   cam                                             # IP-Cam Webgui
192.168.88.3   ipcam                                           # IP-Cam Webgui

So you can call dnspi.ask-sheldon.com or just asgard  to call these hosts.

Register and start dnsmasq service

Now after we installed and configured the dnsmasq sever, we have to make sure it will launch after the machine has booted. Therefore we have to enable the service:

$> systemctl enable dnsmasq

Then we have to start the service:  

$> systemctl start dnsmasq

Use the built in DHCP of dnsmasq

I also wanted dnsmasq to manage my local IP-Address assignment. That’s why I use the build in DHCP feature of dnsmasq.

Therefore I added the following lines to my dnsmasq configuration (lan.ask-sheldon.com):

# DHCP settings:
##################################################################

# Uncomment this to enable the integrated DHCP server, you need
# to supply the range of addresses available for lease and optionally
# a lease time. If you have more than one network, you will need to
# repeat this for each network on which you want to supply DHCP
# service.
dhcp-range=192.168.88.20,192.168.88.30, 240h #lease time 10 days

# GATEWAY
# Override the default route supplied by dnsmasq, which assumes the
# router is the same machine as the one running dnsmasq.
dhcp-option=3,192.168.88.1

#dns server address delivered to clients 
dhcp-option=6,192.168.88.2

# Netmask
dhcp-option=1,255.255.255.0

# NTP (Timeserver)
# Set the NTP time server addresses to 192.168.0.4 and 10.10.0.5
dhcp-option=option:ntp-server,192.168.88.1

Attention: I had to switch off the DHCP of my Fritz!Box (Homenet -> Network Settings -> IP-Addresses) before it worked!!!

Testing the dnsmasq service

Afterwards I ran a few test, to check that everything works as expected:

Check if the service is running:

$> journalctl -u dnsmasq

As you can see, you’ll get a log of all actions the dnsmasq did on startup.  At the end of the log it should look like this:

-- Reboot -- 
Sep 13 14:58:46 dnspi systemd[1]: Starting A lightweight DHCP and caching DNS server
... 
Sep 13 14:58:46 dnspi dnsmasq[261]: dnsmasq: syntax check OK. 
Sep 13 14:58:46 dnspi dnsmasq[263]: started, version 2.75 cachesize 150 
Sep 13 14:58:46 dnspi dnsmasq[263]: compile time options: IPv6 GNU-getopt DBus no-i18n no-IDN DHCP DHCPv6 no-Lua TFTP no-conntrack ipset auth DNSSEC loop-detect inotify 
Sep 13 14:58:46 dnspi dnsmasq[263]: DBus support enabled: connected to system bus 
Sep 13 14:58:46 dnspi dnsmasq-dhcp[263]: DHCP, IP range 192.168.88.20 -- 192.168.88.30, lease time 10d 
Sep 13 14:58:46 dnspi dnsmasq[263]: using local addresses only for domain lan.ask-sheldon.com 
Sep 13 14:58:46 dnspi dnsmasq[263]: reading /etc/resolv.conf 
Sep 13 14:58:46 dnspi dnsmasq[263]: using local addresses only for domain lan.ask-sheldon.com 
Sep 13 14:58:46 dnspi dnsmasq[263]: ignoring nameserver 127.0.0.1 - local interface 
Sep 13 14:58:46 dnspi dnsmasq[263]: using nameserver 192.168.88.1#53 
Sep 13 14:58:46 dnspi dnsmasq[263]: read /etc/hosts - 25 addresses 
Sep 13 14:58:46 dnspi systemd[1]: Started A lightweight DHCP and caching DNS server. 

Check if the dnsmasq service listens on the necessary ports of the machine:

$> nestat -nlp

In the resulting list you should see the following lines:

Active Internet connections (only servers)
Proto   Recv-Q   Send-Q   Local Address   Foreign Address   State    PID/Program name
tcp     0        0        0.0.0.0:53      0.0.0.0:*         LISTEN   263/dnsmasq
tcp6    0        0        :::53           :::*              LISTEN   263/dnsmasq
udp     0        0        0.0.0.0:53      0.0.0.0:*                  263/dnsmasq
udp     0        0        0.0.0.0:67      0.0.0.0:*                  263/dnsmasq
udp6    0        0        :::53           :::*                       263/dnsmasq

As you can see the DNS listens on port 53 and the DHCP on port 67 as they should.

Use dig on the local machine to resolve a domain name:

$> dig ask-sheldon.com

Result

; <<>> DiG 9.10.2-P4 <<>> ask-sheldon.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59511
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 3

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;ask-sheldon.com.           IN  A

;; ANSWER SECTION:
ask-sheldon.com.    7200    IN  A   85.13.150.89

;; AUTHORITY SECTION:
ask-sheldon.com.    172800  IN  NS  ns5.kasserver.com.
ask-sheldon.com.    172800  IN  NS  ns6.kasserver.com.

;; ADDITIONAL SECTION:
ns5.kasserver.com.  6753    IN  A   85.13.128.3
ns6.kasserver.com.  6753    IN  A   85.13.159.101

;; Query time: 89 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sun Sep 13 15:32:43 UTC 2015
;; MSG SIZE  rcvd: 138

As you can see the domain is resolved correctly.

Test DHCP:

For this I configured the router (Fritz!Box) in my network to not deal as a DHCP server and my computer to use DHCP to get IP, DNS, etc.
After reboot the machine got an IP address in the defined range.

Watch the actual leases of the DHCP:

$> cat /var/lib/misc/dnsmasq.leases
1442326887 00:12:d7:be:af:e5 192.168.88.24 sheldons-ThinkPad-W520 *

Obviously my computer got a DHCP lease from the machine with the dnsmasq server on it.

 Dig again. But from a remote machine and for a local domain defined in the /etc/hosts file mentioned above. You should get the IP of the target machine in the answer section.

You could also just ping a local domain to see if it is resolved correctly.

Check DNS-Cache:

Call  $> dig ask-sheldon.com | grep "Query time" twice.

This gives you the time it takes the DNS Server to resolve the given domain name. The second call should be significantly shorter.

Further information about dnsmasq under Arch Linux

4 thoughts on “Run dnsmasq as a local DNS Server (Arch Linux)

  1. I follow your instructions and I want to reset all to default as the first cuz my network not working, can u tell me how ?

  2. Hi Bravehart2,

    Quick question, in the first DNS part of config you exposed, about the “domain” and “local“ settings: you set these up to lan.ask-sheldon.com… and later you say you can reach your host using dnspi.ask-sheldon.com…
    How is it not dnspi.LAN.ask-sheldon.com? Is the “lan” part of the domain in the setting the equivalent to a * in the settings syntax so that every hosts which connect to the network gets a full resolution as anyHost.lan.ask-sheldon.com or anyHost.LAN.ask-sheldon.com?

    Cheers and thanks for this post, it enlightened me a lot, hoping for more 😉

Leave a Reply

Your email address will not be published. Required fields are marked *

 

This site uses Akismet to reduce spam. Learn how your comment data is processed.