How do I set up my own DNS on my LAN, with delegation of public domains?
I want to have a local DNS server on my home LAN, say at 192.168.1.123
. All of my machines will use 192.168.1.123
as their only DNS server when connected to my home network.
By default, my DNS server will process requests by checking them with a public DNS service on the internet. I am planning to also add caching to this (eg. dnsmasq) and use a secure DNS query method (eg. dnscrypt). These will only be set up on one machine (the DNS server) so by pointing all other clients (laptops, phones) to the server I will avoid having to configure dnsmasq and dnscrypt on each one.
My DNS server will also have its own configuration file with some arbitrary domain-IP mappings (or perhaps I can just use /etc/hosts
on that machine). When processing a DNS query, the server will first check that file and if it finds a match, return that. If not, it will then try the public DNS servers on the internet. I am planning to use this to assign user-friendly domains to various machines in my LAN, such as printers, so that I don't have to type in their IP address every time. I can also use this to assign non-functional IPs to real domains that I don't want to resolve (like ad servers).
I have access to a regular Linux server on the network which is always on. I would prefer to set up the DNS service on this server, because it's easier to maintain.
I also have an open source firmware running on my router (OpenWRT). I'd prefer not to set up DNS there because the hardware and software is more limited than the server, but it's an option.
What is a practical way to set up a local DNS service like I describe?
1 answer
What you describe is a typical mixed authoritative/recursive resolver setup. Such a DNS server setup will respond from its own data about zones for which it has explicit configuration, and will perform recursive resolution for any other names on behalf of clients.
Exactly how to set it up depends on the DNS server software you're running; for example, BIND
is going to be different from dnsmasq
is going to be different from Unbound
. The general approach, however, is the same. (It's also worth noting that no proper DNS server will see host names listed in /etc/hosts
.)
First, set up your choice of DNS server software in a "recursive resolver" configuration. For example, with BIND, you'll likely want to add something like allow-recursion { 192.168.1.0/24; };
to the options {}
block of your named.conf
. Take care to not enable recursion for hosts that should not be allowed to use your DNS resolver for recursive queries.
Second, choose a zone in which to group your local hosts, and add that. If you don't know what zone name to choose, I strongly recommend home.arpa
(RFC 8375). Again, with BIND as an example, add to named.conf
outside of the options {}
block a zone
block:
zone "home.arpa" {
type master;
allow-transfer { none; };
file "home.arpa.db";
};
Then create a home.arpa.db
file which lists the hosts in question. The simplest incarnation of this can be something similar to:
@ SOA ns . 1 300 300 2592000 30
@ NS ns
ns A 192.168.1.123 ; the IP address of your DNS server machine
phone A 192.168.1.99
desktop A 192.168.1.33
printer A 192.168.1.44
laptop A 192.168.1.55
; ... and so on ...
If you are only running a single DNS server for the zone, the only number in the SOA
record that really matters is the last one, which is the negative response time-to-live (expressed in seconds); it controls how long "no such host" responses are cached by caching downstream resolvers. The first number in the SOA
record (the 1
) is the zone serial number; increment it when you make changes to the zone data.
Once you have the DNS zone set up, perform whatever magic is required to make your DNS server software (re)load it. Again BIND as an example, this might be rndc reload
. Check your system logs to ensure that no errors are reported.
You can then experiment a little with dig
to check that things are working properly (+norec
means "no recursion"; +short
causes printing only of the relevant portion of the response, in this case an IPv4 address since we ask for A
records):
$ dig @192.168.1.123 phone.home.arpa a +short +norec
192.168.1.99
$ dig @192.168.1.123 linux.codidact.com a +short
...
$
This can be expanded upon to allow for example dynamic updates, but if you are contemplating using /etc/hosts
, the above will get you much the same results.
0 comment threads