dnsmasq is super lightweight compared to ISC’s bind/dhcp servers. On a LAN, you would something that’s flexible and very easy to configure.

A brief description about how dnsmasq works:

Each name available in /etc/hosts on the server, will be available in DNS. For hosts with dynamic IPs, the DHCP daemon that comes with dnsmasq will get their hostname and put it in DNS automatically. By default, only hostnames without a domain is accepted.

Make sure only one DHCP server is listening on the network. If you have more than one DHCP server, each of them should serve a different IP range or subnet, but only hosts that are getting IPs from dnsmasq will be able to register their hostname in DNS.

Here’s my setup:

  • Main router(modem/router combo) provided by my ISP. With an IP of

  • Second Router with a WAN IP of and a LAN IP of

  • DHCP is disabled on the Second Router

The reason I’m adding a Second Router, is because I don’t want to change anything on the Main Router. Devices connected on the main network is unaffected. If you’re trying this as home, I recommend you add another device to your main network and start from there.

Install dnsmasq

I’m on Debian:

apt install dnsmasq

The service is started by default. Stop it:

systemctl stop dnsmasq

Set a Static IP

Set a static IP for your server in /etc/network/interfaces:

auto enp0s3
iface enp0s3 inet static

Basic DNS and DHCP Configuration

The configuration file is /etc/dnsmasq.conf. By default, all lines are commented. You can make a backup if you want, or delete the file and re-create it with touch.

Here’s my configuration:

root@debian:~# cat /etc/dnsmasq.conf
# global options

# upstream name servers
server= # Main Router

# IP range for subnet
# dns server
# router/gateway

I gave the range the name of zone1(could be anything). You typically do this when you have multiple subnets(or in the future). 6 is for DNS and 3 is for the router. A simple DHCP configuration will usually look like this:


Since DHCP is disabled on the second router, dnsmasq won’t communicate with it anymore. From now on, only dnsmasq will answer DHCP requests. All clients connected on the network will get information such as IP address, netmask, router, and DNS. Even though I haven’t specified a netmask, DHCP will send the netmask that is set on the host running dnsmasq.

Verify The Syntax and Allow Required Ports

Verify the syntax with dnsmasq --test:

root@debian:~# dnsmasq --test
dnsmasq: syntax check OK.

Add your loopback address in /etc/resolv.conf:

root@debian:~# cat /etc/resolv.conf

Append your IP in /etc/hosts:

root@debian:~# echo " dns-server" >> /etc/hosts

and start dnsmasq:

root@debian:~# systemctl start dnsmasq.service

Run tests on the dnsmasq server

Query both the dns server and its FQDN with nslookup:

root@debian:~# nslookup dns-server

Name:	dns-server

root@debian:~# nslookup dns-server.local.lan

Name:	dns-server.local.lan

Looks good. Allow UDP port 67 for DHCP, and TCP/UDP port 53 for DNS:

$ ufw allow 53
$ ufw allow 67/udp

View DHCP Leases

Join hosts on the network, and view /var/lib/misc/dnsmasq.leases:

root@debian:~# cat /var/lib/misc/dnsmasq.leases
1635229265 08:00:27:bc:ea:ca alpine 01:00:a0:24:ab:fb:9c
1635228543 20:c9:fakeone:7c:ee:8d MacBook-Pro 01:20:c9:d0:7c:ee:8d

Two hosts connected: alpine and MacBook-Pro.

Configure gethostname() on Linux Clients

If a host is not sending its hostname to DHCP, add the following line in its dhclient.conf:

root@debian:~# cat /etc/dhcp/dhclient.conf | grep hostname
send host-name = gethostname();

Test DNS from a client

On a client or host on the network, query a website with dig to verify which DNS is being queried:

MacBook-Pro:~ kavish$ dig google.com

; <<>> DiG 9.10.6 <<>> google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4512
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

; EDNS: version: 0, flags:; udp: 512
;google.com.			IN	A

google.com.		265	IN	A

;; Query time: 239 msec
;; WHEN: Tue Oct 26 09:27:33 +04 2021
;; MSG SIZE  rcvd: 55

MacBook-Pro:~ kavish$

Look for status: NOERROR, and SERVER: Test the server’s hostname and FQDN:

MacBook-Pro:~ kavish$ dig @dns-server google.com | egrep -i "status|server"
; <<>> DiG 9.10.6 <<>> @dns-server google.com
; (1 server found)
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6296
MacBook-Pro:~ kavish$
MacBook-Pro:~ kavish$ dig @dns-server.local.lan google.com | egrep -i "status|server"
; <<>> DiG 9.10.6 <<>> @dns-server.local.lan google.com
; (1 server found)
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 46472

Verify Automatic DNS from Client Side

I currently have two hosts on the network - alpine and MacBook-Pro. Issue both aping and nslookup from both machines:

## macOS
MacBook-Pro:~ kavish$ nslookup
Address:	name = alpine.local.lan.

MacBook-Pro:~ kavish$
MacBook-Pro:~ kavish$ ping alpine -o
PING alpine.local.lan ( 56 data bytes
64 bytes from icmp_seq=0 ttl=64 time=1.015 ms

--- alpine.local.lan ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 1.015/1.015/1.015/0.000 ms
MacBook-Pro:~ kavish$

## alpine
alpine:~# nslookup	name = MacBook-Pro.local.lan.

alpine:~# ping Macbook-Pro -c 3
PING Macbook-Pro ( 56 data bytes
64 bytes from seq=0 ttl=64 time=1.877 ms
64 bytes from seq=1 ttl=64 time=1.103 ms
64 bytes from seq=2 ttl=64 time=1.169 ms

--- Macbook-Pro ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 1.103/1.383/1.877 ms

No need to modify /etc/hosts on multiple machines.

“Never memorize something that you can look up.”Albert Einstein