| |

LFCE 39 ๐Ÿง DNS Server โ€” dnsmasq Basics

โฑ๏ธ Estimated read: 11 min | |

dnsmasq is a lightweight DNS forwarder and DHCP server designed for small networks. It is not a replacement for BIND9’s authoritative zone hosting; it is a different tool with a different purpose. dnsmasq forwards DNS queries to upstream resolvers, caches the responses, and serves local names from /etc/hosts and DHCP leases. It also provides DHCP, TFTP, and PXE boot services in a single small daemon, making it the standard choice for routers, embedded systems, and small office networks where a full BIND9 deployment would be excessive . For the LFCE candidate, dnsmasq represents the “small network” end of the DNS spectrum: simpler to configure than BIND9, but limited to forwarding and local name resolution rather than authoritative zone hosting.

This chapter covers the installation, the basic configuration file, the DNS forwarding and caching behavior, local name resolution through /etc/hosts, and the DHCP integration that makes dnsmasq a combined network services daemon. It also covers the --test validation flag and the common conflict with systemd-resolved.

Key point: dnsmasq is a forwarder and cacher, not an authoritative server. It forwards queries it cannot answer locally to the upstream servers in /etc/resolv.conf (or a custom resolv file), caches the answers, and serves local names from /etc/hosts and DHCP leases. It does not host zone files, does not support zone transfers, and does not implement the full DNS protocol .


Why dnsmasq exists

The small-network problem.

A small office or home network needs DNS and DHCP, but a full BIND9 deployment is overkill. BIND9 requires zone files, SOA records, and careful authoritative configuration. dnsmasq provides the same essential servicesโ€”name resolution, caching, and address assignmentโ€”with a single configuration file and a daemon that fits in a few hundred kilobytes. It is designed to serve a small network, not the public internet .

The caching-forwarder problem.

Every query that a local network sends to a public resolver travels the internet and incurs latency. A local forwarder caches the answers, so repeated queries for the same name are answered instantly from memory. dnsmasq’s cache is in memory, and the default size is 150 entries. For a small network with a limited set of frequently accessed domains, this is sufficient. The cache size can be increased with --cache-size .

The DHCP-DNS integration problem.

When dnsmasq assigns an address via DHCP, it can also register the client’s hostname in its DNS cache. A machine that receives 192.168.1.50 and reports its hostname as laptop becomes reachable as laptop from other machines on the network, without manual DNS configuration. This integration is the reason dnsmasq is commonly used as a combined DNS and DHCP service on small networks .


a. Installation and basic DNS forwarding

The package is available in every major distribution’s repositories. On Debian and Ubuntu, the package is dnsmasq; on RHEL and Fedora, it is also dnsmasq. The service listens on port 53 by default.

# Debian / Ubuntu
sudo apt update
sudo apt install dnsmasq

# RHEL / Fedora
sudo dnf install dnsmasq

# Validate the configuration syntax
dnsmasq --test
# Output: dnsmasq: syntax check OK.

After installation, dnsmasq reads /etc/dnsmasq.conf and, by default, uses the nameservers in /etc/resolv.conf as upstream forwarders. A query for a name not in /etc/hosts is forwarded to the upstream, cached, and returned. This is the default behavior; no configuration is required for a basic forwarding resolver .

# Test the default forwarding behavior
dig @localhost example.com
# The answer is forwarded to the upstream resolver and cached

# Query again; the second query is served from cache
dig @localhost example.com

The configuration file /etc/dnsmasq.conf is heavily commented and documents every option. The interface= directive restricts which interfaces dnsmasq listens on. Without it, dnsmasq listens on all interfaces, which is undesirable on a server with a public-facing NIC .

# /etc/dnsmasq.conf
# Listen only on the internal interface
interface=eth1

# Do not listen on the external interface
except-interface=eth0

The --test flag validates the configuration syntax without starting the daemon. It is the equivalent of named-checkconf for dnsmasq and should be run after every configuration change .


b. Local name resolution and additional hosts files

dnsmasq reads /etc/hosts by default and serves those names to clients. A name added to /etc/hosts becomes resolvable through dnsmasq without any additional configuration. The --no-hosts flag disables this behavior if it is not desired .

# Add a local name to /etc/hosts
echo "192.168.1.50  server.local" | sudo tee -a /etc/hosts

# Reload dnsmasq to pick up the change
sudo systemctl reload dnsmasq

# Test the local name
dig @localhost server.local
# Output: server.local. 0 IN A 192.168.1.50

The TTL for names served from /etc/hosts is zero by default, meaning clients should not cache them. This is controlled by the --local-ttl option. A zero TTL is appropriate for local names that may change, but it means every query hits dnsmasq .

Additional hosts files can be specified with --addn-hosts. This is useful for maintaining a separate file for local names, or for loading a blocklist. A directory can also be specified, in which case all files in the directory are treated as additional hosts files .

# Use an additional hosts file
addn-hosts=/etc/dnsmasq.d/local-hosts

c. DHCP configuration and static leases

dnsmasq’s DHCP server is disabled by default. It is enabled by specifying a dhcp-range. The range defines the pool of addresses that dnsmasq will assign, and the lease time. The syntax is dhcp-range=<interface>,<start>,<end>,<lease-time> .

# /etc/dnsmasq.conf
# Enable DHCP on eth1 with a pool of addresses and a 12-hour lease
dhcp-range=eth1,192.168.1.100,192.168.1.200,12h

# Set the default gateway and DNS server options
dhcp-option=option:router,192.168.1.1
dhcp-option=option:dns-server,192.168.1.10

Static leases bind a specific MAC address to a specific IP address and hostname. The dhcp-host directive takes the MAC, the hostname, and the IP address. The IP address does not have to be within the dynamic range, but it must be on the same subnet as a configured dhcp-range .

# Static lease for a printer
dhcp-host=00:11:22:33:44:55,printer,192.168.1.50

# Static lease with an infinite lease time
dhcp-host=00:11:22:33:44:56,server,192.168.1.51,infinite

The infinite keyword gives the client a lease that never expires. This is appropriate for servers and infrastructure devices that should always have the same address. The static lease is also registered in dnsmasq’s DNS cache, so the hostname is resolvable from other clients on the network .


Complete Example Session

# ============================================
# PART 1: INSTALL DNSMASQ
# ============================================
sudo apt install dnsmasq

# ============================================
# PART 2: VALIDATE THE DEFAULT CONFIGURATION
# ============================================
dnsmasq --test
# Output: dnsmasq: syntax check OK.

# ============================================
# PART 3: RESTRICT LISTENING INTERFACES
# ============================================
sudo tee -a /etc/dnsmasq.conf > /dev/null <<'EOF'
interface=eth1
except-interface=eth0
EOF

# ============================================
# PART 4: ADD A LOCAL NAME
# ============================================
echo "192.168.1.50  server.local" | sudo tee -a /etc/hosts
sudo systemctl reload dnsmasq

# ============================================
# PART 5: TEST FORWARDING AND LOCAL RESOLUTION
# ============================================
dig @localhost example.com
# Forwarded to upstream and cached

dig @localhost server.local
# Served from /etc/hosts

# ============================================
# PART 6: ENABLE DHCP
# ============================================
sudo tee -a /etc/dnsmasq.conf > /dev/null <<'EOF'
dhcp-range=eth1,192.168.1.100,192.168.1.200,12h
dhcp-option=option:router,192.168.1.1
dhcp-option=option:dns-server,192.168.1.10
EOF

# ============================================
# PART 7: ADD A STATIC LEASE
# ============================================
sudo tee -a /etc/dnsmasq.conf > /dev/null <<'EOF'
dhcp-host=00:11:22:33:44:55,printer,192.168.1.50,infinite
EOF

# ============================================
# PART 8: VALIDATE AND RESTART
# ============================================
dnsmasq --test
sudo systemctl restart dnsmasq
sudo systemctl status dnsmasq

# ============================================
# PART 9: VERIFY DHCP IS RUNNING
# ============================================
ss -ulnp | grep :67
# Output shows dnsmasq listening on the DHCP port

# ============================================
# PART 10: CHECK THE CACHE
# ============================================
kill -USR1 $(cat /var/run/dnsmasq.pid)
# The cache statistics are written to syslog
journalctl -u dnsmasq -n 5

The ten parts demonstrate the complete dnsmasq lifecycle: installation, validation, interface restriction, local name resolution, forwarding, DHCP enablement, static leases, restart, verification, and cache inspection. The critical distinction from BIND9 is that dnsmasq has no zone files; local names come from /etc/hosts and DHCP leases, and external names come from upstream forwarders.


Quick Reference

dnsmasq vs BIND9

PropertydnsmasqBIND9
RoleForwarder, cacher, DHCPAuthoritative server, resolver
Zone filesNoYes
Zone transfersNoYes (AXFR/IXFR)
DHCPBuilt-inSeparate service
Local names/etc/hosts and leasesZone files
ConfigurationSingle fileMultiple files
Target networkSmall/embeddedAny scale

Key Configuration Directives

DirectivePurpose
interface=Listen only on this interface
except-interface=Do not listen on this interface
dhcp-range=Enable DHCP with address pool
dhcp-host=Static lease (MAC, hostname, IP)
dhcp-option=DHCP options (router, DNS)
addn-hosts=Additional hosts file
no-hostsDo not read /etc/hosts
cache-size=DNS cache entries (default 150)
server=Upstream DNS server
local=/domain/Answer authoritatively for local domain

Validation and Control

CommandPurpose
dnsmasq --testValidate configuration syntax
systemctl reload dnsmasqReload /etc/hosts changes
systemctl restart dnsmasqApply configuration changes
kill -USR1 <pid>Dump cache statistics to syslog

Best Practices

โœ… Do This:

# Restrict listening to internal interfaces
interface=eth1
except-interface=eth0                                        # โœ…

# Validate before restarting
dnsmasq --test                                               # โœ…

# Use static leases for infrastructure devices
dhcp-host=00:11:22:33:44:55,printer,192.168.1.50,infinite   # โœ…

# Increase cache size for busy networks
cache-size=1000                                              # โœ…

# Reload after /etc/hosts changes
systemctl reload dnsmasq                                     # โœ…

โŒ Don’t Do This:

# Listen on all interfaces on a public server
# No interface= directive means all interfaces               # โŒ

# Use dnsmasq for authoritative zone hosting
# dnsmasq has no zone file support                            # โŒ

# Forget to validate after editing the configuration
systemctl restart dnsmasq    # Syntax error prevents start    # โŒ

# Use a static lease outside the configured subnet
dhcp-host=... ,10.0.0.50    # Must match a dhcp-range subnet # โŒ

# Ignore systemd-resolved conflict on port 53
# Both cannot bind to port 53 simultaneously                  # โŒ

Common Pitfalls

PitfallWhy It HappensFix
dnsmasq fails to startPort 53 occupied by systemd-resolvedDisable or reconfigure systemd-resolved
DHCP not assigning addressesdhcp-range not configuredAdd dhcp-range directive
Local names not resolving/etc/hosts changed but not reloadedsystemctl reload dnsmasq
Static lease not appliedIP not on same subnet as dhcp-rangeVerify subnet match
External queries failUpstream resolvers unreachableCheck /etc/resolv.conf or server= directive
Cache not usedTTL expired or cache size too smallIncrease cache-size

Real-World Examples

1. Basic forwarding resolver

# Default configuration: forwards to /etc/resolv.conf upstreams
dnsmasq --test && systemctl restart dnsmasq

2. Restrict to internal interface

interface=eth1
except-interface=eth0

3. Local name from /etc/hosts

echo "192.168.1.50  server.local" >> /etc/hosts && systemctl reload dnsmasq

4. DHCP range

dhcp-range=eth1,192.168.1.100,192.168.1.200,12h

5. Static lease

dhcp-host=00:11:22:33:44:55,printer,192.168.1.50,infinite

6. DHCP options

dhcp-option=option:router,192.168.1.1
dhcp-option=option:dns-server,192.168.1.10

7. Additional hosts file

addn-hosts=/etc/dnsmasq.d/local-hosts

8. Custom upstream server

server=8.8.8.8

9. Validate configuration

dnsmasq --test

10. Check cache statistics

kill -USR1 $(cat /var/run/dnsmasq.pid) && journalctl -u dnsmasq -n 5

Visual

dnsmasq Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  DNSMASQ COMBINES FORWARDING, CACHING, AND DHCP             โ”‚
โ”‚                                                              โ”‚
โ”‚  Client โ”€โ”€โ–ถ dnsmasq โ”€โ”€โ–ถ Upstream Resolver                    โ”‚
โ”‚              โ”‚                                               โ”‚
โ”‚              โ”œโ”€โ”€ /etc/hosts (local names)                    โ”‚
โ”‚              โ”œโ”€โ”€ DHCP leases (dynamic names)                 โ”‚
โ”‚              โ””โ”€โ”€ Cache (repeated queries)                    โ”‚
โ”‚                                                              โ”‚
โ”‚  No zone files. No authoritative hosting.                    โ”‚
โ”‚  Local names come from /etc/hosts and DHCP.                  โ”‚
โ”‚  External names come from upstream forwarders.               โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

dnsmasq vs BIND9 Roles

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  DIFFERENT TOOLS FOR DIFFERENT SCALES                        โ”‚
โ”‚                                                              โ”‚
โ”‚  BIND9:                                                      โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚ Authoritative zones, zone transfers, DNSSEC            โ”‚  โ”‚
โ”‚  โ”‚ Full DNS protocol implementation                       โ”‚  โ”‚
โ”‚  โ”‚ Complex configuration, multiple files                  โ”‚  โ”‚
โ”‚  โ”‚ Suitable for: public DNS, large networks               โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                                                              โ”‚
โ”‚  dnsmasq:                                                    โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚ Forwarding, caching, DHCP, TFTP                        โ”‚  โ”‚
โ”‚  โ”‚ Local names from /etc/hosts and leases                 โ”‚  โ”‚
โ”‚  โ”‚ Single configuration file                              โ”‚  โ”‚
โ”‚  โ”‚ Suitable for: routers, small networks, labs            โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

DHCP-DNS Integration

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  DHCP LEASES BECOME DNS NAMES                                โ”‚
โ”‚                                                              โ”‚
โ”‚  Client requests DHCP                                         โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  dnsmasq assigns 192.168.1.150 and records hostname "laptop" โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  Other clients query "laptop"                                 โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  dnsmasq returns 192.168.1.150 from the lease cache          โ”‚
โ”‚                                                              โ”‚
โ”‚  No manual DNS configuration required.                       โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
Packagednsmasq
RoleDNS forwarder, cacher, DHCP server
Configuration/etc/dnsmasq.conf
Local names/etc/hosts and DHCP leases
Upstream resolvers/etc/resolv.conf or server=
Cache size150 entries default
DHCP enablementdhcp-range= directive
Static leasedhcp-host= directive
Validationdnsmasq --test
Conflictsystemd-resolved on port 53

Key takeaways:

  • dnsmasq is a forwarder and cacher, not an authoritative server. It does not host zone files, does not support zone transfers, and does not implement the full DNS protocol. It forwards queries to upstream resolvers and caches the answers .
  • Local names come from /etc/hosts and DHCP leases. A name added to /etc/hosts becomes resolvable through dnsmasq after a reload. A DHCP client’s hostname is registered in the DNS cache automatically .
  • DHCP is disabled by default. It is enabled with a dhcp-range directive. Static leases are configured with dhcp-host and can be marked infinite for infrastructure devices .
  • --test validates the configuration. It is the dnsmasq equivalent of named-checkconf and should be run after every change .
  • Interface restriction is a security boundary. Without interface= or except-interface=, dnsmasq listens on all interfaces, including any public-facing NIC .
  • systemd-resolved conflicts with dnsmasq. Both bind to port 53. On systems with systemd-resolved, it must be disabled or reconfigured before dnsmasq can start .

Remember: dnsmasq is the small-network DNS tool. It forwards, caches, and serves local names from /etc/hosts and DHCP leases. It does not host authoritative zones. Configure the interface restriction, validate with --test, and use dhcp-range and dhcp-host for DHCP. The --test flag catches syntax errors before they become outages. For a small network, dnsmasq is simpler and lighter than BIND9. For authoritative zone hosting, BIND9 is the correct tool.


Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!