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.
# 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: Starting A lightweight DHCP and caching DNS server ... Sep 13 14:58:46 dnspi dnsmasq: dnsmasq: syntax check OK. Sep 13 14:58:46 dnspi dnsmasq: started, version 2.75 cachesize 150 Sep 13 14:58:46 dnspi dnsmasq: 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: DBus support enabled: connected to system bus Sep 13 14:58:46 dnspi dnsmasq-dhcp: DHCP, IP range 192.168.88.20 -- 192.168.88.30, lease time 10d Sep 13 14:58:46 dnspi dnsmasq: using local addresses only for domain lan.ask-sheldon.com Sep 13 14:58:46 dnspi dnsmasq: reading /etc/resolv.conf Sep 13 14:58:46 dnspi dnsmasq: using local addresses only for domain lan.ask-sheldon.com Sep 13 14:58:46 dnspi dnsmasq: ignoring nameserver 127.0.0.1 - local interface Sep 13 14:58:46 dnspi dnsmasq: using nameserver 192.168.88.1#53 Sep 13 14:58:46 dnspi dnsmasq: read /etc/hosts - 25 addresses Sep 13 14:58:46 dnspi systemd: 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
; <<>> 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 126.96.36.199 ;; 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 188.8.131.52 ns6.kasserver.com. 6753 IN A 184.108.40.206 ;; 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.
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.
$> 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.