DHCP & DNS Server with dnsmasq
dnsmasq is a lightweight daemon that provides DHCP, DNS forwarding, and
TFTP services in a single process. It is ideal for small to mid-size
networks -- home labs, development environments, and branch offices. This
guide covers installation, DHCP range and static-lease configuration,
upstream DNS forwarding, local DNS overrides, PXE network booting, and a
brief comparison with ISC dhcpd.
Back to the Networking hub. Related guides: DNS Guide | Network Configuration.
Installing dnsmasq
# Debian / Ubuntu
sudo apt install dnsmasq
# RHEL / Fedora / CentOS
sudo dnf install dnsmasq
# Start and enable
sudo systemctl enable --now dnsmasq
If systemd-resolved is running it may conflict because it binds to port 53
on 127.0.0.53. Either disable it or tell resolved to stop listening:
# Option A: Disable resolved entirely
sudo systemctl disable --now systemd-resolved
sudo rm /etc/resolv.conf
echo "nameserver 127.0.0.1" | sudo tee /etc/resolv.conf
# Option B: Tell resolved not to bind its stub listener
sudo mkdir -p /etc/systemd/resolved.conf.d
cat <<'EOF' | sudo tee /etc/systemd/resolved.conf.d/no-stub.conf
[Resolve]
DNSStubListener=no
EOF
sudo systemctl restart systemd-resolved
Core configuration
The main config file is /etc/dnsmasq.conf. Below is a practical example
covering the most common options:
# /etc/dnsmasq.conf
# Listen only on the LAN interface
interface=eth1
bind-interfaces
# ---- DHCP ----
# Issue addresses from .100 to .200, with a 12-hour lease
dhcp-range=10.0.0.100,10.0.0.200,12h
# Set the default gateway
dhcp-option=option:router,10.0.0.1
# Set DNS servers handed to clients
dhcp-option=option:dns-server,10.0.0.1
# Set the domain name
dhcp-option=option:domain-name,example.lan
domain=example.lan
# ---- Static leases ----
# Tie a MAC address to a fixed IP and hostname
dhcp-host=aa:bb:cc:dd:ee:01,10.0.0.10,fileserver
dhcp-host=aa:bb:cc:dd:ee:02,10.0.0.11,printer
dhcp-host=aa:bb:cc:dd:ee:03,10.0.0.12,nas
# ---- DNS ----
# Upstream DNS servers (forwarding)
server=1.1.1.1
server=8.8.8.8
# Local DNS overrides (respond without forwarding)
address=/git.example.lan/10.0.0.30
address=/wiki.example.lan/10.0.0.31
# Read additional hosts from /etc/hosts
expand-hosts
# Block a domain (returns NXDOMAIN)
address=/ads.example.com/
# ---- Logging ----
log-queries
log-dhcp
log-facility=/var/log/dnsmasq.log
dhcp-range in detail
# Basic range
dhcp-range=10.0.0.100,10.0.0.200,12h
# With a specific netmask
dhcp-range=10.0.0.100,10.0.0.200,255.255.255.0,12h
# Tag-based: give a different range to a VLAN interface
dhcp-range=set:vlan200,172.16.200.100,172.16.200.200,12h
interface=eth1.200
# IPv6 SLAAC + DHCPv6
dhcp-range=::100,::200,constructor:eth1,ra-names,64,12h
dhcp-host (static leases)
# By MAC address
dhcp-host=aa:bb:cc:dd:ee:01,10.0.0.10,fileserver
# Ignore a specific MAC (never give it an address)
dhcp-host=aa:bb:cc:dd:ee:ff,ignore
# Set a per-host lease time
dhcp-host=aa:bb:cc:dd:ee:02,10.0.0.11,printer,infinite
Upstream DNS (server=)
# Forward everything to Cloudflare and Google
server=1.1.1.1
server=8.8.8.8
# Forward a specific domain to an internal DNS server
server=/corp.example.com/10.1.0.53
# Forward reverse lookups for 10.0.0.0/24 to an internal server
server=/0.0.10.in-addr.arpa/10.1.0.53
Local DNS overrides (address=)
# Point a hostname at an IP (any query type returns this)
address=/myapp.dev.local/10.0.0.40
# Wildcard: all subdomains of dev.local resolve to one IP
address=/.dev.local/10.0.0.40
# Block a domain entirely (returns 0.0.0.0 / ::)
address=/ads.doubleclick.net/
PXE network boot (dhcp-boot)
dnsmasq can serve a PXE boot file to network-booting clients:
# Enable the built-in TFTP server
enable-tftp
tftp-root=/srv/tftp
# Tell PXE clients to load pxelinux.0 from TFTP
dhcp-boot=pxelinux.0
# For UEFI clients, match the architecture tag
dhcp-match=set:efi-x86_64,option:client-arch,7
dhcp-boot=tag:efi-x86_64,grubx64.efi
Place the boot files in /srv/tftp:
sudo apt install pxelinux syslinux-common
sudo cp /usr/lib/PXELINUX/pxelinux.0 /srv/tftp/
sudo cp /usr/lib/syslinux/modules/bios/ldlinux.c32 /srv/tftp/
sudo mkdir /srv/tftp/pxelinux.cfg
Reloading and testing
# Check the syntax
dnsmasq --test
# Restart after config changes
sudo systemctl restart dnsmasq
# Watch the log
sudo journalctl -fu dnsmasq
# On a client, release and renew to test DHCP
sudo dhclient -r eth0 && sudo dhclient eth0
# Test DNS resolution through dnsmasq
dig @10.0.0.1 fileserver.example.lan
ISC dhcpd as an alternative
For larger deployments or when you need features like failover pools, ISC
dhcpd is the traditional choice:
sudo apt install isc-dhcp-server
# /etc/dhcp/dhcpd.conf
subnet 10.0.0.0 netmask 255.255.255.0 {
range 10.0.0.100 10.0.0.200;
option routers 10.0.0.1;
option domain-name-servers 10.0.0.1;
option domain-name "example.lan";
default-lease-time 43200;
max-lease-time 86400;
}
host fileserver {
hardware ethernet aa:bb:cc:dd:ee:01;
fixed-address 10.0.0.10;
}
dnsmasq is generally simpler to configure and combines DHCP with DNS in
one service, while ISC dhcpd offers more advanced DHCP features like
failover and conditional classes.