Logo

dnsmasq: lightweight DHCP + DNS for LAN

dnsmasq: lightweight DHCP + DNS for LAN

dnsmasq does DHCP, DNS forwarding, TFTP, and local cache in one 200 KB binary. Essential for OpenWrt routers, modest enterprise LANs, PXE provisioning, and labs.

dnsmasq: lightweight DHCP + DNS for LAN

dnsmasq does DHCP, DNS forwarding, TFTP, and local cache in one 200 KB binary. Essential for OpenWrt routers, modest enterprise LANs, PXE provisioning, and labs.

Introduction

dnsmasq:

  • IPv4 + IPv6 DHCP server (DHCPv6, SLAAC)
  • DNS forwarder + cache (not authoritative)
  • Integrated TFTP support (PXE)
  • Automatic LAN hostname resolution
  • Ultra-simple config (one file)
  • Available on Linux, BSD, OpenWrt

Use cases:

  • Router/firewall (often integrated, e.g. OpenWrt, pfSense)
  • Small office/lab/datacenter LAN
  • PXE boot
  • Simple DHCP with static reservations

Note: dnsmasq is not an authoritative DNS server. For that, see BIND9 or NSD.

Prerequisites

  • Linux VPS / server Debian / Ubuntu
  • Root access
  • Dedicated LAN interface (not in same broadcast as your public VPS!)

Step 1: Installation

sudo apt update
sudo apt install -y dnsmasq dnsmasq-utils
dnsmasq --version

⚠️ On Ubuntu, systemd-resolved already listens on 53:

sudo systemctl disable --now systemd-resolved
sudo unlink /etc/resolv.conf
echo "nameserver 1.1.1.1" | sudo tee /etc/resolv.conf

Step 2: Base config

sudo nano /etc/dnsmasq.d/lan.conf
interface=ens4
bind-interfaces

except-interface=ens3

domain-needed
bogus-priv
no-resolv

server=9.9.9.9
server=1.1.1.1

cache-size=10000
no-negcache

log-queries
log-dhcp

Step 3: DHCP

dhcp-range=192.168.50.100,192.168.50.200,12h

dhcp-option=option:router,192.168.50.1
dhcp-option=option:dns-server,192.168.50.1
dhcp-option=option:domain-name,example.lan
dhcp-option=option:netbios-ns,192.168.50.1

dhcp-leasefile=/var/lib/misc/dnsmasq.leases

Step 4: Static reservations

dhcp-host=AA:BB:CC:DD:EE:01,192.168.50.10,web01
dhcp-host=AA:BB:CC:DD:EE:02,192.168.50.11,db01
dhcp-host=AA:BB:CC:DD:EE:03,192.168.50.12,proxy01,infinite

infinite = infinite lease.

Step 5: Local domain

local=/example.lan/
domain=example.lan
expand-hosts

If a DHCP client is named laptop-alice, you can ping laptop-alice.example.lan.

Step 6: Start and test

sudo systemctl restart dnsmasq
sudo systemctl status dnsmasq
sudo journalctl -u dnsmasq -f

On LAN client:

sudo dhclient -r eth0 && sudo dhclient eth0
sudo cat /var/lib/misc/dnsmasq.leases

Step 7: Host mappings

For manual DNS entries (non-DHCP):

address=/internal-app/192.168.50.50
address=/grafana.example.lan/192.168.50.51

Or use standard /etc/hosts (dnsmasq reads it automatically):

192.168.50.50 internal-app internal-app.example.lan
192.168.50.51 grafana.example.lan

Step 8: TFTP / PXE Boot

For PXE (see tutorial 28):

enable-tftp
tftp-root=/srv/tftp
dhcp-boot=pxelinux.0

Very useful: dnsmasq does DHCP + TFTP + DNS in one shot, perfect for a lab.

Step 9: Advanced DHCP options

# Force Pi-hole DNS for all DHCP clients
dhcp-option=option:dns-server,192.168.50.2

# NTP
dhcp-option=option:ntp-server,192.168.50.1

# Tag by MAC or IP
dhcp-host=set:office,192.168.50.20-192.168.50.49

# Tag by vendor class
dhcp-vendorclass=set:windows,MSFT

# Windows-specific
dhcp-option=tag:windows,option:netbios-ns,192.168.50.1

Step 10: IPv6 DHCP (SLAAC + DHCPv6)

dhcp-range=fd12:3456::,ra-only,infinite
dhcp-range=fd12:3456::100,fd12:3456::200,64,12h

ra-param=ens4
enable-ra

Step 11: Logs and stats

sudo killall -SIGUSR1 dnsmasq
sudo journalctl -u dnsmasq | tail -20

Shows:

  • Cache size, hits, misses
  • Active DHCP leases
  • Top queries

For Prometheus: dnsmasq_exporter.

Step 12: DNS resolver only mode (no DHCP)

For a fast local DNS cache:

no-dhcp-interface=ens3,ens4

interface=lo
bind-interfaces

no-resolv
server=1.1.1.1
server=9.9.9.9

cache-size=10000

/etc/resolv.conf:

nameserver 127.0.0.1

Local DNS is very fast thanks to cache.

Troubleshooting

"dnsmasq: failed to create listening socket"

Port 53 already taken:

sudo ss -tunlp | grep :53

Often systemd-resolved. Disable it.

Clients don't get DHCP lease

Check:

  • Correct interface in interface=...
  • No firewall blocking (UDP 67, 68)
  • Network isolated (no conflicting DHCP)
sudo tcpdump -i ens4 port 67 or port 68

Slow resolution / cache not used

sudo killall -SIGUSR1 dnsmasq
sudo journalctl -u dnsmasq | grep cache

If cache-size=0, increase. If no-cache active, remove.

"no such file" on leasefile

sudo touch /var/lib/misc/dnsmasq.leases
sudo chown dnsmasq:dnsmasq /var/lib/misc/dnsmasq.leases

Conflict with another DHCP

Two DHCP responses on LAN = conflict. Kill the other server.

Useful commands

sudo systemctl status dnsmasq
sudo systemctl restart dnsmasq

sudo dnsmasq --test

sudo killall -SIGUSR1 dnsmasq
sudo journalctl -u dnsmasq | tail -30

sudo cat /var/lib/misc/dnsmasq.leases
# Format: timestamp_expire MAC IP hostname client-id

sudo dhcpdump -i ens4

dig @192.168.50.1 google.com
nslookup web01.example.lan 192.168.50.1

Conclusion

dnsmasq is the all-in-one tool for simple LANs:

  • DHCP + DNS + TFTP in one binary
  • Very light (RAM, CPU)
  • One-file configuration
  • Auto LAN hostname resolution

Limits:

  • Not authoritative DNS (for public domain serving, use BIND9/NSD/PowerDNS)
  • Not for large infrastructure (use ISC DHCP / Kea)

Going further:

  • Combine with Unbound or Pi-hole for resolver layer
  • For enterprise DHCP, look at ISC Kea (successor to ISC DHCP)
  • For DDNS, use nsupdate or Knot DNS

Resources

Join our Discord community server

For any questions, suggestions, or just to chat with the community, join us on Discord!

900+Members