# DHCP and DNS Cache ## Install dnsmasq I decided to use [dnsmasq](https://thekelleys.org.uk/dnsmasq/doc.html) since it can fulfull multiple roles as both a DHCP and DNS cache. I'll 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](https://en.wikipedia.org/wiki/MAC_address) and [IP Addresses](https://en.wikipedia.org/wiki/IP_address) 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 binding 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 ```diff # /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 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](https://en.wikipedia.org/wiki/Public_recursive_name_server). ```diff # /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 using those entries too. ```diff # /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_ ```bash # systemctl restart dnsmasq.service ```