Setting up a DNS (dnsmasq) server for your home network

First a what this post is and is not. It covers only using dnsmasq.

Who this post is for

It is is primarily for people that have a lot of VMs running in their
home network and are finding the time needed to keep /etc/hosts files
up to date on multiple machines.

It is is for people that want a simple home network dns resolver
as the solution rather than investigate deployment tools that could push out
hosts files to dozens of VMs/servers.

it is for people who used to have dnsmasq working and then it suddenly all
broke a few years ago.
(which is a read the docs, the way short names were handled by default completely
changed, which is good because now all clients across all OSs can expect the
same responses).

And the biggee; it is for people who have tried to set it up but have issues
with short names not resolving, SERVFAIL requests coming back, or just a
general mess as a result
. This post covers off the things that are probably
breaking in the way you have set it up.

And see the very last section on why you would want to, you may not want to bother.

Who this post is not for

it is definately not for people that want to assign known ip-addresses
to the many devices that may connect to their home network via wireless connections…
as of course they get the info for wireless connections from your wireless router which
is outside the scope of this.

That includes things like laptops that may have both a cabled static address plus a wireless
dhcp address to your network active at the sametime, the wireless connection will really
mess things up as the dhcp settings happily take precedence over you static ones.

So on to DNSMASQ itself

As I am sure you are aware dnsmasq builds it entries by reading the /etc/hosts
file in the machine it is running on (by default, you can provide other files if you wish).
That should be simple should it not ?, if your hosts file works it should also work in dnsmasq right ?.

Of course not, your hosts files are probably populated with a mix of short names and FQDNs
making it impossible for a remote client to know what format to use.

If you are reading this post because you may have issues with short names not
resolving for some machines, sometimes long names do and sometimes they do not, or
generally strange and what appears inconsistent behaviour then read on.

The key thing is that using dnsmasq to privide DNS lookup services for
your home network is that everything in your home network should be in the
same domain
.

So the issues you experience could be caused by

  • you have not configured your domain in dnsmasq
  • your servers were installed using defaults like localdomain or
    if built using dhcp before assigning a static address will be in your
    routers domain (Home, D-Link etc) instead of your home domain
  • you have made life over complicated by having both short named and FQDN names
    in the hosts file used by dnsmasq

STEP1 – configure DNSMASQ properly

First step: in any /etc/hosts file on servers running dnsmasq only have the
short names of the servers (ie: do not have entries like myserver1.myhomenet.org;
you would only have a entry for myserver1). If you have a FQDN in there you
are doing it all wrong.

Second Step: in /etc/dnsmasq.conf search for the line “#local=/localnet/” and
change it to your domain, for example “local=/myhomenet.org/” uncommented of course).

The effect of this change is that dnsmasq will append myhomenet.org to all the short
names read from the hosts file it uses (short name being anything without a trailing
dot and data). You may wonder why this is going to help if you want to lookup a short
name; read on as it is the clients fault
.
Remember to change the example myhomenet.org to your domain of course.

Third step:
In dnsmasq.conf uncomment “domain-needed” and “bogus-priv”. You do not want
short name queries forwarded to the internet;
and we will be correcting client queries later.

Fourth step:
In dnsmasq.conf uncomment “strict-order”

On your dnsmasq DNS server(s) you should have configured them to first lookup
their own ip-address (have your local dnsmasq server ip as the first nameserver as it
should be the first queried by tools like nslookup if run on your dnsmasq host;
or you will find client queries work but quesries on the dnsmasq host itself do not, so you
must also tell this dnsmasq server it can resolve names using itself),

if you do not have strict-order plus your dnsmasq server first
nameservers will
be selected from the list in resolv.conf in random
(or round robin) order
and you will end up with some queries being sent
to DNS servers that know nothing about your local domain (if step3 was not done
to the internet to resolve), and queries will randonly fail.

For those of you who may have got to playing with this in the past and got
frustrated by some queries made on the dnsmasq host itself working and some not,
omitting strict-order
is probably why, it would have been occasionally querying the upstream server
instead of itself (for queries from things like “nslookup”, tools that do
not use dns but would have used the /etc/hosts file will still have worked
masking any issue… assuming your nsswitch.conf has files as the first entry
which I think you should have in a home network, even if a clients host file
has nothing but localhost in it there is always going to be an exception.

Slightly of topic, “dig” and “nslookup” work in different ways, if “dig”
is working and “nslookup” is not you have a config error in your DNS setup.

That is it for the dnsmasq config but I bet it is still not working :-).
We have to move onto the clients.

Random tip: if your DNS search list (/etc/resolv.conf) on the server running
dnsmasq does not contain
the ip of the machine running yor dnsmasq instance and the interface it listens
on is managed by NetworkManager
the example below may help (eth0 is the
primary interface on my server and .181 is the server ip… I lock it down to
server ip, if you do not do that 127.0.0.1 may work as the first entry).
The last nameserver (.1) is my router, so with strict order it it cannot find
a server locally it will hunt the internet dns servers for it via the router
with whatver ISP defaults were set on that.

nmcli conn modify eth0 ipv4.dns 192.168.1.181,192.168.1.1
systemctl restart NetworkManager

STEP2 – configure your clients, thats the real problem

We have dnsmasq setup correctly, why are queries for short names still failing ?.
Because the clients are misconfigured of course.

Now I do not now how many servers or VMs you have setup, but if you
have accepted all the default prompts you probably have localdomain as a domain.
If you installed a VM using DHCP and later changed it to a static address it probably
still has the domain name assigned by the DHCP sever (or your router).

Guess what, that is not going to work. There are two things you can do,
manually edit /etc/resolv.conf on each server after every reboot or fix
each client server.

Do it properly, fix each client server and for future installs use the
correct domain name instead of the defaults.

You may see in some of your client /etc/resolv.conf files entries like “search localdomain” or “domain localdomain” (or on some of my VMs built from DHCP before changing to static things like Home or D-Link).

That is obviously a problem that will prevent name lookups working… (well part of it as discussed later).

When a DNS lookup is performed on a short name the client will
append to any short name (a hostname without a dot) the domain/search value from
resolv.conf to the query to make a FQDN to be looked up.

Now if you had a search value in /etc/resolv.conf on the client as used in the dnsmasq
steps as “myhomenet.org” then the short name query would work as the client will
append the correct domain part and find a match in dnsmasq which has also now been
configured to add the domain name to short names.

But if you have left install defaults like localdomain still lying around
on clients that will never work (unless of course all your servers are setup for
localdomain and you set that as the home network domain in dnsmasq).

So, first fix the server running dnsmasq, a unique client setup

This is what you want on the server running dnsmasq, not for clients in general.
The main difference is that the server(s) running dnsmasq must only reference themselves and
upstream DNS resolvers, never any other dnsmasq servers you may be running for the same
domain or you will be an an endless loop as they refer to each other as they try and
resolve a mistyped host name.

The assumption in the examples is that the interface name is eth0 and your dns server
ip address is 192.168.1.181 with the next upstream server an internet (or router) dns server.
The next upstream server is required as in many cases you will want to resolve
hostnames/URLs out in the big wide world also.

RHEL has pretty much dropped /etc/sysconfig/network-scripts and you must use
NetworkManager; NetworkManager is on most Debian servers as well although you
can still use the older network/interfaces.d files there

NetworkManager: Assuming eth0 is your interface name and we use the example myhomenet.org.

nmcli conn modify eth0 ipv4.dns-search myhomenet.org
nmcli conn modify eth0 ipv4.dns 192.168.1.181,192.168.1.1
systemctl restart NetworkManager   # applies changes to resolv.conf, no connection drop

For debian static manual interfaces in /etc/network/interfaces.d

auto eth0
iface eth0 inet static
      address 192.168.1.181
      netmask 255.255.0.0
      gateway 192.168.1.1
      dns-nameserver 192.168.1.181
      dns-nameserver 192.168.1.1
      dns-search myhomenet.org
      dns-domain myhomenet.org

When the dnsmasq server is correct, update/correct all your clients

It goes without saying that to avoid doing this often, always use the correct domain name
and dns list when building a new VM or server so it will never need to be done on those.

It is important to note a few things here about clients in general that do not run
any copies of dnsmasq themselves.

  1. they can refer to multiple dnsmasq servers on your home network so they can
    resolve names if one is down
  2. while you can also include an upstream DNS server that will probably stop
    things working correctly again, you should only search your home network dnsmasq servers

The second point above is an important one, you will remember we configured dnsmasq
to use strict order to always check the home network dnsmasq instance first.

Guess what, clients also are unlikely to use a strict order.
Depending upon what version of operating system you are running lookup operations
by the client are quite likely to round-robin through the nameserver list rather
than use strict order so can
quite easily query the upstream server instead of your dnsmasq server;
this is something else that can cause dns lookups of servers in your home network
to sometimes work and sometimes not
.

The solution I use is to have two dnsmasq servers so one is always available,
all clients only use those two for all name resolution (yes, including external)
and no client has any internet dns resolver address configured relying on the
dnsmasq server instead.

As the dnsmasq servers are configured with an upsteam dns then any external
host name they are unable to resolve themselves (ie: google.com) the dnsmasq servers
will query the external DNS and resturn the correct ip-address for the name to the client
requesting it. The client does not need an external dns entry and not having one
avioids lookup problems if a client round-robins through name servers.

Remember this is just for the dns name resolution, once the client has the ip-address
it will cache it and all traffic is from the client direct to the ip-address (unless you go
through a proxy of course).

Based on the examples for dnsmasq above with a single server providing dnsmasq,
and letting that dnsmasq server query any upstream dns resolvers on behalf of the client(s)
then a client configuration would be based on the above examples as below.
If you have a second dnsmasq servers just add it to the dns ip list,
as long as the two dnsmasq servers do not reference each other in any way to avoid
the endless lokkup loop situation.

# NetworkManager
nmcli conn modify eth0 ipv4.dns-search myhomenet.org
nmcli conn modify eth0 ipv4.dns 192.168.1.181
systemctl restart NetworkManager   # applies changes to resolv.conf, no connection drop

For debian static manual interfaces in /etc/network/interfaces.d

# Debian /etc/network/interfaces.d files (xxx is the client ipaddr)
auto eth0
iface eth0 inet static
      address 192.168.1.xxx
      netmask 255.255.0.0
      gateway 192.168.1.1
      dns-nameserver 192.168.1.181
      dns-search myhomenet.org
      dns-domain myhomenet.org

Congradulations,it now of course works

You can lookup your internal servers from any client by either short or FQDN names
using yout home network domain without
any issue; and internet names are still resolvable for all your clients.

Troubleshooting

  • “dig” works but “nslookup” does not. You have misconfigured it
  • to check a nameserver “nslookup hostnametolookup dnsserveripaddr”,
    if querying the dns server explicity by dnsserveripaddr returns the
    results expected there is nothing wrong with it, the issue is your nameserver search order

You could of course manually edit /etc/resolv.conf to correct search and nameserver
entries for testing, those changes would be lost pretty quickly.

For search this may be an option for testing.
(Ref: https://man7.org/linux/man-pages/man5/resolv.conf.5.html)
The search keyword of a system’s resolv.conf file can be
overridden on a per-process basis by setting the environment
variable LOCALDOMAIN to a space-separated list of search domains.

That depends on the client inplementing it of course.

The big question of course is why you would want to

So why would you want to run a home network DNS server ?.

The main reasons for needing a DNS server for your home network would be
that you have a lot of servers or VMs and trying to keep their hosts files
all syncronised is becoming too much effort; you want to be able to just
edit a single file and all your servers be able to use it.

This would only be an issue if you did not have any sort of deployment
infrastructure like ansible/chef/puppet that could deploy a “template”
hosts file to all your servers from a single source file; and yes I do
mean template file not a static hosts file sas each hosts file would have to
be correctly set with the ip and hostname of the server it is being deployed to
as so many things depend on that.

Now suppose you did run two dnsmasq servers, without a deployment tool
to push a central edited hosts file to both servers and restart dnsmasq
you are already editing two hosts files for every change now. Still a lot
less than the effort of doing so on every server but they could also get out
of sync if manual edits on each are required.

You should (if you have enough headroom for another small VM on a different
physical server) run two copies; if you followed the post I have made here you
will have all your clients now doing internat name resolution via your dnsmasq
servers upstream queries so if you have a single dns server and it stops
you have lost name resolution to not only your servers but to the internet
(which is not an issue, you just edit /etc/resolv.conf to insert a nameserver
line for your router or maybe one of googles nameservers to get internet access
back for that client so you can at least watch youtube while your dnsmasq server reboots).

Using something like puppet-ce or ansible would let you deploy a ‘source’
hosts file to both dnsmaqs servers so you only need to edit the file in one place,
however you could also go wild and use them to deploy the hsosts file to all
your servers negating the need for a home network dns server at all… the drawback with
the later of course being that anyone that can see your /etc/hosts file would then
know every machine in your network; best to have it on as few machines as possible.

Deployment tools have a learning curve you may not be interested in, so for
a home network dns setup I would say just run two dnsmasq servers and on only
those two servers have a rsync job that runs occasionally to check for an
updated hosts file on whatever server you want to make edits to it on. Or if you
only want to run one then there is only one file to edit so no syncing needed at all.

Once you get above 4-5 VMs manually keeping /etc/hosts files up-to-date
on each becomes a nightmare. A home network DNS resolver (or two) becomes
essential.

Hopefully this long winded post has got you past any issues you were having
with setting on up using dnsmasq.

One last note: if the changes above do not result in network or NetworkManager startup correctly setting /etc/resolv.conf then… it could simply be you do not have NetworkManager/resolved or similar service installed that updates it; in which case simply vi/nano the resolv.conf file and set the values you want. That took me ages to work out when a new VM refused to correctly set resolv.conf, until a check on the last modified time showed nothing was updating it on a reboot at all. So a new first step, see if the file is being updated on boot and if not just manually edit it.

About mark

At work, been working on Tandems for around 30yrs (programming + sysadmin), plus AIX and Solaris sysadmin also thrown in during the last 20yrs; also about 5yrs on MVS (mainly operations and automation but also smp/e work). At home I have been using linux for decades. Programming background is commercially in TAL/COBOL/SCOBOL/C(Tandem); 370 assembler(MVS); C, perl and shell scripting in *nix; and Microsoft Macro Assembler(windows).
This entry was posted in Unix. Bookmark the permalink.