Debian (Stretch / Buster) DNS Configuration
This guide is intended to get you up and running with a fairly minimal set up configurations. Able to provide forward and reverse caching DNS lookups using BIND9.
A note of warning
This guide is only intended for those that plan to use these servers within their own networks running behind a NAT router. Or with the service only available on the internal interfaces. This configure is not intended for WAN (Wide Area Network) interfaces.
Installation¶
apt update && apt upgrade
apt install bind9 dnsutils
This will update the server so that we have the latest patched modules and libraries and then install Bind9.
Configuration¶
Some Assumptions¶
Whilst assumptions are the mother of all hiccups. I will make a few.
- You have not set up Bind previously.
- Your network address space is 192.168.11.0/24
- You have chosen two servers for your DNS services.
- 192.168.11.10 (Primary)
- 192.168.11.20 (Secondary)
- Please change these in your setting to match your own network.
Usful Tools and Commands¶
dig
nslookup
(alternative to dig)named-checkconf
named-checkzone
systemd-resolve --status
Important files¶
/etc/default/bind9
/etc/bind/*
/etc/default/bind9
# run resolvconf?
RESOLVCONF=no
# startup options for the server
OPTIONS="-u bind"
Disable IP6
You can disable IP6 by adding "-4" between the quotation marks for OPTIONS
This file is where we can set additional options which are passed to bind on startup. We can specify if our network is IP4 only and if we want to run the service chrooted. I will not go into that here. I am assuming that the DNS server will only be used internally behind a NAT router and not exposed to the internet. Thus additional security is not required.
/etc/bind/¶
named.conf
This is the main configuration file.
We can break this into multiple files which can be included in named.conf by using the include directive.
Working with configuration files¶
Let's start by creating a file that will contain our ACLs (Access Control List) and add the following contents.
cd /etc/bind/
named.conf.acl¶
Create a file called named.conf.acl
Then add the following contents.
acl "internal" {
192.168.11.0/24; # Local Area Network.
127.0.0.1; # Localhost
};
This will be used to allow DNS to make external lookups for the address ranges specified. This is very important if your DNS server is exposed on the internet. Not really needed if it is not exposed. But let's follow some best practices.
named.conf¶
Next we want to add this to our named.conf file. Let's add this to the top of the file.
include "/etc/bind/named.conf.acl";
named.conf will now load this information as part of its configuration.
The named.conf file should now look something like this:
// This is the primary configuration file for the BIND DNS server named.
//
// Please read /usr/share/doc/bind9/README.Debian.gz for information on the
// structure of BIND configuration files in Debian, *BEFORE* you customize
// this configuration file.
//
// If you are just adding zones, please do that in /etc/bind/named.conf.local
include "/etc/bind/named.conf.acl";
include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.local";
include "/etc/bind/named.conf.default-zones";
There is no more work to be done with the named.conf file. So we will not be looking at it again. You can and probably should check that the configuration file has no problems by using this command.
named-checkconf
This will report errors and their line numbers if they exist.
named.conf.options¶
named.conf.options
Let's turn to the options file. The default version will look something like this:
options {
directory "/var/cache/bind";
// If there is a firewall between you and nameservers you want
// to talk to, you may need to fix the firewall to allow multiple
// ports to talk. See http://www.kb.cert.org/vuls/id/800113
// If your ISP provided one or more IP addresses for stable
// nameservers, you probably want to use them as forwarders.
// Uncomment the following block, and insert the addresses replacing
// the all-0s placeholder.
// forwarders {
// 0.0.0.0;
// };
...
...
};
Lets add some options just below the directory option:
recursion yes;
allow-recursion { internal; };
listen-on { 127.0.0.1; 192.168.11.10; };
allow-transfer { none; };
What do these options mean?
- Enable recursion so that the server can make lookups for us.
- Limit the addresses that can do recursive lookups to the addresses we specified using the internal ACL. A pretty standard security measure.
- Listen for and answer DNS queries that come in. Limited to the internal loopback address and the main interface address. If you do not want to restrict the listen-on interfaces, use a value of any;. The use of any is not recommended. And should certainly not be used if any of your interfaces are internet facing!
- Don't allow zone transfers to secondary DNS servers. This can and will be adjust on a zone by zone basis later if you configure a secondary name server for your network.
Next look at the forwarder portion. This is were we can tell the DNS server who it should go and ask to make lookups on its behalf if it doesn't already know the answer. Either because it is not the authoritative server or does not have a cache record. This would generally be your ISP's name servers. But you are free to use others. Such as 8.8.8.8 and other public DNS servers. Though using a name server that is not local or part of your normal service is generally frowned upon and could also result in slow lookups.
The primary benefit of using forwarders is that hopefully someone else has already made the same DNS lookup using that server. The server will probably therefore already have a cached answer. This results in a faster lookup. Though it is not required for operations as the name server is able to query the root servers. Though this is going the long way around when a cached answer is probably only a single server away.
Let's remove the // characters which are comment markers and add some addresses.
forwarders {
8.8.8.8;
x.x.x.x;
};
Save the file and again use the named-checkconf command to make sure no errors have been introduced.
Warning
You might hit an issue during testing. You might find that lookups work without any forwarders set, but fail with them set.
If you want to use forwarders. The work around here is as follows:
Reference: ServerFault Link
Update the dnssec-validation line.
Replace auto with no
The other option is to not use forwarders and let your server query the root name servers as needed.
At this point you basically have a caching server configuration. It might be a good idea to test that it's working. Let's start bind.
systemctl enable bind9
systemctl start bind9
At the moment the server itself doesn't know to use the newly configured bind service. But we can cheat here. And actually this is useful trick when you are testing DNS related issues. We can use the dig command.
dig www.google.com @localhost
Using @
The @localhost is saying we want to specifically send our DNS query to the localhost without using the /etc/resolv.conf file.
Which should give you output similar to the text below. This will probably be a little different on your own system.
; <<>> DiG 9.10.3-P4-Raspbian <<>> www.google.com @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18246
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 13, ADDITIONAL: 27
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.google.com. IN A
;; ANSWER SECTION:
www.google.com. 86 IN A 172.217.24.132
;; AUTHORITY SECTION:
. 411182 IN NS b.root-servers.net.
. 411182 IN NS h.root-servers.net.
. 411182 IN NS g.root-servers.net.
. 411182 IN NS l.root-servers.net.
. 411182 IN NS j.root-servers.net.
. 411182 IN NS f.root-servers.net.
. 411182 IN NS e.root-servers.net.
. 411182 IN NS k.root-servers.net.
. 411182 IN NS a.root-servers.net.
. 411182 IN NS i.root-servers.net.
. 411182 IN NS d.root-servers.net.
. 411182 IN NS m.root-servers.net.
. 411182 IN NS c.root-servers.net.
;; ADDITIONAL SECTION:
a.root-servers.net. 335582 IN A 198.41.0.4
a.root-servers.net. 335424 IN AAAA 2001:503:ba3e::2:30
b.root-servers.net. 336203 IN A 199.9.14.201
b.root-servers.net. 335567 IN AAAA 2001:500:200::b
c.root-servers.net. 335601 IN A 192.33.4.12
c.root-servers.net. 335299 IN AAAA 2001:500:2::c
d.root-servers.net. 343081 IN A 199.7.91.13
d.root-servers.net. 343973 IN AAAA 2001:500:2d::d
e.root-servers.net. 336987 IN A 192.203.230.10
e.root-servers.net. 336987 IN AAAA 2001:500:a8::e
f.root-servers.net. 335460 IN A 192.5.5.241
f.root-servers.net. 335895 IN AAAA 2001:500:2f::f
g.root-servers.net. 336203 IN A 192.112.36.4
g.root-servers.net. 335863 IN AAAA 2001:500:12::d0d
h.root-servers.net. 335567 IN A 198.97.190.53
h.root-servers.net. 335785 IN AAAA 2001:500:1::53
i.root-servers.net. 335363 IN A 192.36.148.17
i.root-servers.net. 335424 IN AAAA 2001:7fe::53
j.root-servers.net. 335298 IN A 192.58.128.30
j.root-servers.net. 335785 IN AAAA 2001:503:c27::2:30
k.root-servers.net. 335460 IN A 193.0.14.129
k.root-servers.net. 335567 IN AAAA 2001:7fd::1
l.root-servers.net. 335601 IN A 199.7.83.42
l.root-servers.net. 335443 IN AAAA 2001:500:9f::42
m.root-servers.net. 343973 IN A 202.12.27.33
m.root-servers.net. 343835 IN AAAA 2001:dc3::35
;; Query time: 33 msec
;; SERVER: ::1#53(::1)
;; WHEN: Sat Nov 21 23:37:26 JST 2020
;; MSG SIZE rcvd: 842
Now we have a working caching name server. Time to make the server use it for its own DNS lookups.
Modifying /etc/resolv.conf¶
There seems to be a few ways to do this.
-
Edit the file manually. An acceptable option if you are setting your network statically.
-
Change the name server information at the source. The DHCP server that provides it.
-
Modify /etc/dhcpcd.conf if you are assigning host addresses and name servers using dhcp.
Note
Option 2 is probably the best. Though it will not be a good choice for your name servers themselves. The name servers need to list their own interfaces first in the resolv.conf file
Options 1 or 3 are good for the name servers you will be configuring.
The dhcpcd approach¶
If you do not have a /etc/dhcpcd.conf you can install and configure it using:
apt install dhcpcd
systemctl enable dhcpcd
systemctl start dhcpcd
Open /etc/dhcpcd.conf
You should find something like this. But it will be different based on your own network address space and other details.
# Example static IP configuration:
#interface eth0
#static ip_address=192.168.0.10/24
#static ip6_address=fd51:42f8:caae:d92e::ff/64
#static routers=192.168.0.1
#static domain_name_servers=192.168.0.1 8.8.8.8 fd51:42f8:caae:d92e::1
The new information should look similar to this.
# Example static IP configuration:
interface eth0
#static ip_address=192.168.0.10/24
#static ip6_address=fd51:42f8:caae:d92e::ff/64
#static routers=192.168.0.1
#static domain_name_servers=192.168.0.1 8.8.8.8 fd51:42f8:caae:d92e::1
static domain_name_servers=192.168.11.10 192.168.11.20
static domain_search=example.com
- Uncomment your interface line
- Uncomment your static domain_name_servers and list the IP Addresses of your name servers.
- Optionally add your domain_search. This will allow you to access machines using the single host name.
Restart the dhcpcd service
systemctl restart dhcpcd
Your /etc/resolv.conf should now reflect these changes but retain some of its original settings. You will need to make changes on all machines in your network to use the new primary, and secondary name server once they are running.
You now should have a functioning caching name server.
Time to get Authoritative¶
Having a caching name server is nice. But it's not really that useful. The real benefit comes from controlling your own domain within your network. As well as being able to provide reverse DNS entries.
What are reverse DNS entries¶
We have all probably watched a police drama where they use a reverse lookup on a phone number to get a name or address. It's basically the same.
dig -x 192.168.11.1
Response:
...
...
;; ANSWER SECTION:
1.11.168.192.in-addr.arpa. 86400 IN PTR router.example.com.
..
..
Slow initial network connections?
Have you ever noticed that sometimes initial connections to hosts can be slow? This is often caused by a failed reverse DNS lookup.
The other benefit, is that reverse DNS is another way to document your network. Sure a spreadsheet is useful.
But sometimes a simple dig -x will give you the information you need provided you keep your zone files up to date.
Setting a Reverse Zone file¶
Creating the reverse zone file¶
Let's copy the db.empty to a new file called db.192.168.11
cp db.empty db.192.168.11
Original file:
; BIND reverse data file for empty rfc1918 zone
;
; DO NOT EDIT THIS FILE - it is used for multiple zones.
; Instead, copy it, edit named.conf, and use that copy.
;
$TTL 86400
@ IN SOA localhost. root.localhost. (
1 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
86400 ) ; Negative Cache TTL
;
@ IN NS localhost.
Let's delete the first 5 lines. We don't need these comments. Next we are going to edit the "localhost. root.localhost." portion and replace localhost. with ns1.example.com. and root.localhost. with root.example.com.
The line should now look like:
@ IN SOA ns1.example.com. root.example.com. (
What does this mean?
We are saying that ns1.example.com is the SOA (Start Of Authority) for this zone record. And the contact email address for this zone is root@example.com. This may not be important for a purely internally hosted service, but it's good knowledge to have.
An important point.
Always update the serial number when you edit any zone files. If you forget to do this. The zone data will not propagate to the name servers correctly. The general format that has been used for the serial number is in the form of: 'YEARMONTHDATESEQUENCE'. Assume todays date was 20201122 the Serial would be 2020112201. If you edit the zone file on that date. If you edit it a second time on the same day, then increment the sequence. The serial would now be 2020112202.
Edit the serial to match your actual date. Try and keep everything nicely lined up.
Zone file format
The file uses tab spacing.
After editing you want to have something that looks like the following:
$TTL 86400
@ IN SOA ns1.example.com. root.example.com. (
2020112201 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
86400 ) ; Negative Cache TTL
;
; Name servers
IN NS ns1.example.com.
IN NS ns2.example.com.
1 IN PTR router.example.com.
..
..
35 IN PTR hassio.example.com.
40 IN PTR printer.example.com.
Reverse records end with a .
These lines end with a .(period / full stop). This tells DNS not to append to the record.
Add any other records that you want to have in your reverse DNS records.
Make the server aware of our new reverse zone file¶
Next lets make DNS aware of this db.192.168.11 file.
For simplicity edit the zones.rfc1918 file and add these lines:
zone "11.168.192.in-addr.arpa" {
type master;
file "/etc/bind/db.192.168.11";
};
just above the line shown here.
zone "168.192.in-addr.arpa" { type master; file "/etc/bind/db.empty"; };
Setting a forward zone record¶
Next we want to add our more standard forward lookups.
Creating db.example.com¶
Again copy the db.empty to a file called db.example.com. Make the same basic edits for the SOA line and serial. Then add your host records.
Here is the example.
$TTL 604800
@ IN SOA ns1.example.com. root.example.com. (
2020112201 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
IN NS ns1.example.com.
IN NS ns2.example.com.
ns1.example.com. IN A 192.168.11.10
ns2.example.com. IN A 192.168.11.20
hassio.example.com. IN A 192.168.11.35
printer.example.com. IN A 192.168.11.40
; External Servers/Services
blog.example.com. IN CNAME ghs.google.com.
bogus.example.com. IN A 203.X.X.X
Warning
The big gotcha that follows.
The pickle in this pie is going to be if you use the same domain for your internal network and anything that you have hosted outside on the internet. You need to duplicate these entries in your new zone file.
Let's say you are using Google's Blogger to host a site.
https://blog.example.com
Out side your own network this resolves to 172.217.175.83 for example
We need to duplicate this sort of entry in our new zone file. If you were looking carefully you might have noticed the entry above under External Servers/Services
Adding the zone file to the DNS Server¶
Add this db file to named.conf.local just below:
//
// Do any local configuration here
//
zone "example.com" {
type master;
file "/etc/bind/db.example.com";
//allow-transfer { 192.168.11.20; };
};
Since there is no secondary DNS server yet. We can leave the allow-transfer as a comment. Uncomment this after you have a secondary server configured.
You can again use named-checkconf to check for issues. Then restart the bind9 with
systemctl reload bind9
You should now be able to use dig or nslookup to find hosts on your network.
You now have a fully functioning primary cache and authoritative DNS server.
The next step would be to set up your secondary DNS server to provide redundancy. You could also setup a third or fourth.
Do keep in mind this is only accessible from within your home network. And does not work when you are connected to external networks. So it does not affect any of your existing externally hosted services.
Add a Secondary Name Server¶
This will involve using the same steps to set up a caching server that we did when setting up NS1. So I will list these commands in quick succession.
Update and install packages¶
apt update && apt upgrade
apt install bind9 dnsutils
Create named.conf.acl¶
Create the named.conf.acl file in /etc/bind/ and add your acl data
acl "internal" {
192.168.11.0/24;
127.0.0.1;
::1;
};
Get the named.conf.acl included into named.conf by adding the following to named.conf near the top.
include "/etc/bind/named.conf.acl";
Update named.conf.options¶
Edit named.conf.options as we did previously. But replace .10 with .20 to match the servers IP address.
options {
directory "/var/cache/bind";
recursion yes;
allow-recursion { internal; };
listen-on { 127.0.0.1; 192.168.11.20; };
allow-transfer { none; };
listen-on
Make sure you use the internal interface of the secondary server.
Update your forwarders¶
forwarders {
8.8.8.8;
xx.xx.xx.xx;
};
And add the following if you are using forwarders.
//dnssec-validation auto;
dnssec-validation no;
Update named.conf.local¶
Edit the named.conf.local to include zones.rfc1918
// Consider adding the 1918 zones here, if they are not used in your
// organization
include "/etc/bind/zones.rfc1918";
But don't do anything more at this stage. This should result in a working cache server.
Enable and start Bind9¶
systemctl enable bind9
systemctl start bind9
Feel free to test using:
nslookup @localhost www.google.com
Update /etc/resolv.conf using dhcpcd option¶
Install dhcpcd if missing¶
apt install dhcpcd
systemctl enable dhcpcd
systemctl start dhcpcd
Edit /etc/dhcpcd.conf¶
The new information should look similar to this.
# Example static IP configuration:
interface eth0
#static ip_address=192.168.0.10/24
#static ip6_address=fd51:42f8:caae:d92e::ff/64
#static routers=192.168.0.1
#static domain_name_servers=192.168.0.1 8.8.8.8 fd51:42f8:caae:d92e::1
static domain_name_servers=192.168.11.20 192.168.11.10
static domain_search=example.com
Change in the order of IP addresses for name servers
Please notice that we have reversed the order of the domain_name_servers on this server. On NS1 we have .10 then .20 on NS2 we have changed to .20 then .10
Restart dhcpcd¶
systemctl restart dhcpcd
Share zone data with the secondary¶
Warning
These next steps should be done on the primary name server.
On your primary server let's edit the named.conf.options file and add the following:
notify yes;
also-notify { 192.168.11.20; };
This means that when ever we edit our zone files on the primary name server, the secondary will be notified and will pull the updated zone information without waiting for the zones TTL (Time To Live) to expire.
We will now edit the previously created zone files, and add zone transfer ability.
Edit zones.rfc1918 and add the allow-transfer line.
zone "11.168.192.in-addr.arpa" {
type master;
file "/etc/bind/db.192.168.11";
allow-transfer { 192.168.11.20; };
};
Add the same allow-transfer line to any other zone files you have created.
Check the configuration and reload.
systemctl reload bind9
restart vs reload vs rndc reload
What is the difference between a restart and a reload?
restart kills the bind process and then restarts it. This clears memory and the cache.
reload on the other hand just has bind9 refresh the data from its files while maintaining other cached data.
rndc is provided by bind and is another option instead of using systemctl
Secondary server named.conf.local¶
Steps done on secondary name server
These steps are to be done on the secondary name serve only.
We can now turn our attention to the secondary name server and configure it to get zone data from the primary which will make it authoritative for our zones.
In this case we just need to update the named.conf.local file so that the server knows about the zones. Add the following configuration.
//
// Do any local configuration here
//
zone "example.com" {
type slave;
file "db..example.com";
masters { 192.168.11.10; };
};
zone "11.168.192.in-addr.arpa" {
type slave;
file "db.192.168.11";
masters { 192.168.11.10; };
};
This basically says that for the zone file we are a secondary (slave) and that the source of all truth is our primary server.
You can reload bind9
systemctl reload bind9
or
rndc reload
That should conclude getting the name servers up and running and answering queries.
You still need to configure your network equipment to use these new servers.