I’ve used dnsmasq, running on a Debian Raspberry Pi, for years as my LAN’s combination DHCP and DNS server. It’s got a lot of configuration options, most of whose defaults work fine, is easy to set up, and is fast and so reliable that I almost never pay any attention to it. Exactly what you want network software to be.
But one part of its configuration always confused me. You can set it to always assign the same IP address to a particular MAC address, which is useful for assuring certain devices end up at certain addresses. But, as I recently learned when upgrading to a new Raspberry Pi 3B+, those options in the dnsmasq.conf file don’t take effect until the device being configured accesses the DHCP functions of dnsmasq. It seems like dnsmasq can only resolve device names configured via dnsmasq.conf after a device has pinged the network for DHCP servers. Which was problematic, given that I was transferring DNS functionality on a network with long-running DHCP leases.
I couldn’t find any documentation or advice on how to get around this issue neatly. I knew I could simply load those hard-wired addresses into /etc/hosts on the server running dnsmasq, which would read them when it started up. But having to do both that and also define the MAC-to-name-to-IP-address relationships in dnsmasq.conf seemed inelegantly redundant. Not to mention prone to failure, if the various config files got out of whack.
It’s best to define configuration information only once. But the question was, where?
Fortunately, a thoughtful fellow Debian user over on superuser.com, Holger Böhnke, showed me how to do it, and went even further and explained how all the various pieces fit together. You can read his answer here.
The missing piece, for me, was a file I’d never encountered before, in almost 20 years of running various linux distros: /etc/ethers. It maps MAC addresses on a LAN to either IP addresses or, more useful in my case, device names. Here’s how I set it up on my system:
bc:67:1c:f7:9e:6c portal.localnet 44:94:FC:5D:56:2C wireheadkitchen.localnet 40:16:7e:f4:04:38 wireheadupstairs.localnet 1C:6F:65:39:09:8D colossus.localnet 00:40:ad:96:96:6d sungod.localnet b8:27:eb:44:ea:65 raspberrypi.localnet b8:27:eb:c2:85:7f mycroft.localnet
I wasn’t clear if I needed fully-qualified names, so I included the local domain — localnet, in my case — just to be safe.
The next part of the configuration resides in /etc/hosts, which defines the base name-to-IP-address mappings for my LAN:
127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback ff02::1 ip6-allnodes ff02::2 ip6-allrouters #127.0.1.1 mycroft # make sure the following entries are kept synchronized with what's in # /etc/dnsmasq.d/localnet.conf 10.0.0.2 portal 10.0.0.3 wireheadkitchen 10.0.0.4 raspberrypi 10.0.0.5 mycroft 10.0.0.6 wireheadupstairs 10.0.0.8 colossus 10.0.0.10 sungod
Here’s how I think this all fits together.
dnsmasq reads both /etc/ethers and /etc/hosts when it starts up. It uses the information from both files to figure out, when a device defined in /etc/hosts requests an IP address via DHCP, which IP address to assign. But because the DNS name resolution process also incorporates /etc/hosts, name resolution for devices with fixed IP addresses are successfully resolved, even if the device in question has never asked dnsmasq, in its role as a DHCP server, for an IP address.
This also means you don’t have to define entries linking MAC addresses to IP addresses and device names in the dnsmasq.conf file, which is what I previously was doing with entries like this:
# no longer required in /etc/dnsmasq.conf!! #dhcp-host=44:94:FC:5D:56:2C,wireheadkitchen,10.0.0.3 #dhcp-host=40:16:7e:f4:04:38,wireheadupstairs,10.0.0.6 #dhcp-host=1C:6F:65:39:09:8D,colossus,10.0.0.8 #dhcp-host=00:40:ad:96:96:6d,sungod,10.0.0.10
That eliminates the redundancy issue which concerned me.
Thanx again to Holger for explaining all this in a way I was able to understand!