Skip to main content

DHCP and DNS Cache

Install dnsmasq

I decided to use dnsmasq since it can fulfull multiple roles as both a DHCP and DNS cache. I first configure it for IPv4 and then later add in the few extra IPv6 lines needed.

Setup DHCP

The following can look complicated but that is just becuase there are a ton of MAC Addresses and IP Addresses mixed throughout. If you look closely you can see that there are only four types of lines.

  1. no-dhcp-interface=eth0,lo prevents DHCP on our loopback address and eth0 which is the interface facing the Internet.

  2. dhcp-range= declares a start and stop address and lease lifetime for each subnet. I am also setting an optional tag for each so I can target them later if I want.

  3. dhcp-option= allows me to set specific DHCP options. The tag: allows me to target addresses matching a specific tag. I am overriding the default DNS servers because I want lan and dmz to use my Pi-hole server and warp should use a public DNS server since any device on that subnet is routed through a VPN tunnel so it doesn't have local network access.

  4. dhcp-host= defines what IP addresses and hostnames get assigned to which network device with a specific MAC address

# /etc/dnsmasq.d/dhcp.conf
+ no-dhcp-interface=eth0,lo
+ 
+ dhcp-range=set:lan,10.0.5.1,10.0.7.254,12h
+ dhcp-range=set:dmz,10.0.8.1,10.0.8.254,12h
+ dhcp-range=set:warp,10.0.9.1,10.0.9.254,5m
+ 
+ dhcp-option=tag:lan,option:dns-server,10.0.1.2
+ dhcp-option=tag:lan,option:dns-server,10.0.1.2
+ dhcp-option=tag:warp,option:dns-server,1.1.1.1,1.0.0.1
+ 
+ # LAN - network infrastructure
+ dhcp-host=aa:af:57:f3:4e:90,10.0.1.2,pihole			# pihole
+ dhcp-host=b4:fb:e4:8f:f9:74,10.0.1.3,unifi-switch-8	# unifi-switch-8
+ 
+ # LAN  - proxmox
+ dhcp-host=e0:d5:5e:63:fe:30,10.0.3.2,blackbox			# blackbox
+ dhcp-host=70:85:c2:fe:4c:b7,10.0.3.3,mini				# mini
+ dhcp-host=6e:91:84:4a:74:f1,10.0.3.4,backup			# backup
+ 
+ # LAN - assigned devices
+ dhcp-host=d0:a6:37:ed:8c:7f,10.0.4.4,silverbook		# silverbook
+ dhcp-host=82:13:00:9c:c7:00,10.0.4.5,thunderbolt		# thunderbolt
+ dhcp-host=34:36:3b:7f:18:1e,10.0.4.8,jess				# jess
+ dhcp-host=96:64:5F:1C:A6:2C,10.0.5.6,refuge			# refuge
+ dhcp-host=7A:BC:46:D1:A3:1B,10.0.5.9,unifi			# unifi
+ 
+ # DMZ - assigned devices
+ dhcp-host=62:59:92:A7:1D:F1,10.0.8.5,bitcoin			# bitcoin
+ dhcp-host=32:cc:fb:a3:1a:57,10.0.8.2,contained		# contained

Setup DNS Caching

Everything here is commented with an explanation of what it does. The only thing slightly interesting is I have two server= parameters pointing to the IPv4/IPv6 loopback addresses which is where Unbound is listening. If Unbound wasn't being used I'd either remove no-resolv and use the system namesevers or change the server= parameters to point to a public recursive name sever.

# /etc/dnsmasq.d/dns.conf
+ # Add the domain to simple names (without a period) in /etc/hosts in the same way as for DHCP-derived names.
+ expand-hosts
+ 
+ # Log the results of DNS queries handled by dnsmasq.
+ log-queries
+ 
+ # Do not listen on the specified interface.
+ except-interface=eth0,lo
+ 
+ # Accept DNS queries only from hosts whose address is on a local subnet, ie a subnet for which an interface exists on the server.
+ local-service
+ 
+ # Dnsmasq binds the address of individual interfaces, allowing multiple dnsmasq instances, but if new interfaces or addresses appear, it automatically listens on those
+ bind-dynamic
+ 
+ # Return answers to DNS queries from /etc/hosts and --interface-name which depend on the interface over which the query was received.
+ localise-queries
+ 
+ # All reverse lookups for private IP ranges (ie 192.168.x.x, etc) which are not found in /etc/hosts or the DHCP leases file are answered with "no such domain"
+ bogus-priv
+ 
+ # Later versions of windows make periodic DNS requests which don't get sensible answers from the public DNS and can cause problems by triggering dial-on-demand links.
+ filterwin2k
+ 
+ # Enable code to detect DNS forwarding loops
+ dns-loop-detect
+ 
+ # Reject (and log) addresses from upstream nameservers which are in the private ranges.
+ stop-dns-rebind
+ 
+ # Exempt 127.0.0.0/8 and ::1 from rebinding checks.
+ rebind-localhost-ok
+ 
+ # Tells dnsmasq to never forward A or AAAA queries for plain names, without dots or domain parts, to upstream nameservers.
+ domain-needed
+ 
+ # Specifies DNS domains for the DHCP server.
+ domain=hermz.io
+ 
+ # Don't read /etc/resolv.conf. Get upstream servers only from the command line or the dnsmasq configuration file.
+ no-resolv
+
+ server=127.0.0.1
+ server=::1

Resolve Static Clients

One problem I ran into was that static clients never use DHCP so the DHCP server doesn't register their hostname with their intended IP address. To work around this limitation I just added those entries to the /etc/hosts file since by default dnsmasq will resolve for those entries too.

# /etc/hosts
+ 10.0.1.1        ember
+ 10.0.1.2        pihol
+ 10.0.1.3        unifi-switch-8
+ 10.0.3.2        blackbox
+ 10.0.3.3        mini
+ 10.0.3.4        backup
+ 10.0.3.5        edge
 
  # --- BEGIN PVE ---

Reboot

Now that dnsmasq is fully configured I just restart it using systemctl

# systemctl restart dnsmasq.service