Thursday 12 March 2020

Implementing a simple DNS service using dnsmasq

In many cases, one would need to have his own DNS service which would resolve local domain names into local IP address, and in the same time, still falls back to a public DNS like google DNS or OpenDNS name servers for external name lookups.

One easy way to implement this on Linux is to use the dnsmasq deamon to implement a local DNS server that fails over to a public one.

First, we need to install dnsmasq on the system and enable it, to do so we run the below commands:

[root@beren ~]#  yum install dnsmasq.x86_64 dnsmasq-utils.x86_64
[root@beren ~]# systemctl enable dnsmasq

[root@beren ~]# systemctl start dnsmasq


To check the if the service is running, we use systemctl status command and would expect to see an output similar to the one below:

[root@beren ~]# systemctl status dnsmasq
● dnsmasq.service - DNS caching server.
   Loaded: loaded (/usr/lib/systemd/system/dnsmasq.service; enabled; vendor preset: disabled)
   Active: active (running) since Thu 2020-03-12 18:21:35 EDT; 12s ago
 Main PID: 3253 (dnsmasq)
    Tasks: 1 (limit: 23977)
   Memory: 716.0K
   CGroup: /system.slice/dnsmasq.service
           └─3253 /usr/sbin/dnsmasq -k

Mar 12 18:21:35 beren systemd[1]: Started DNS caching server..
Mar 12 18:21:35 beren dnsmasq[3253]: started, version 2.79 cachesize 150
Mar 12 18:21:35 beren dnsmasq[3253]: compile time options: IPv6 GNU-getopt DBus no-i18n IDN2 DHCP DHCPv6 no-Lua TFTP no-conntrack ipset auth DNSSEC loop-detect inotify
Mar 12 18:21:35 beren dnsmasq[3253]: reading /etc/resolv.conf
Mar 12 18:21:35 beren dnsmasq[3253]: using nameserver 192.168.178.1#53
Mar 12 18:21:35 beren dnsmasq[3253]: read /etc/hosts - 2 addresses


To configure the now working name service, we need to edit the file /etc/dnsmasq.conf and add the the following configuration:

#Our config starts here, we listen to our local IP address:
listen-address=10.0.2.15

#Domain definition of the name server:
domain=sherif.local

#expand hosts file entries to be part of the domain:
expand-hosts
# Don't use resolv.conf for up stream servers
no-resolv

#Public DNS to fall back to.
server=8.8.8.8

address=/sherif.local/172.16.0.10
address=/beren.sherif.local/172.16.0.1
address=/dns.sherif.local/172.16.0.1
address=/mail.sherif.local/172.16.0.2
# Config end.


Then we need to restart the dnsmasq service for the config to take effect:

[root@beren ~]# systemctl restart dnsmasq

To test the new name service, we can use the nslookup command as below:

[root@beren log]# nslookup
> server 10.0.2.15
Default server: 10.0.2.15
Address: 10.0.2.15#53
> www.google.com
Server:         10.0.2.15
Address:        10.0.2.15#53

Non-authoritative answer:
Name:   www.google.com
Address: 172.217.17.68
Name:   www.google.com
Address: 2a00:1450:400e:80c::2004
> mail.sherif.local
Server:         10.0.2.15
Address:        10.0.2.15#53

Name:   mail.sherif.local
Address: 172.16.0.2
> dns.sherif.local
Server:         10.0.2.15
Address:        10.0.2.15#53

Name:   dns.sherif.local
Address: 172.16.0.1
>


As you can see, the mail server is able to resolve both local and external names successfully.
Last step now is to update our machine resolv.conf to point to the new DNS service which we run locally now.
To do this, we need to change the file /etc/resolv.conf to contain following line:

nameserver 10.0.2.15

Once done, we need to protect the file from Linux network manager service, one way to do this is to make the file immutable, we can use chattr to set the immutable attribute of the file as below:

[root@beren log]# chattr +i /etc/resolv.conf
[root@beren log]# lsattr /etc/resolv.conf
----i-------------- /etc/resolv.conf
[root@beren log]#



This way the networkmanager service will not be able to change our new DNS name server configuration upon system reboot.