Setting up a Local Zone Record
July 5, 2021
January - March 2021
WARNING: If you are looking for an authoritative DNS tutorial, STOP READING. This isn't it.
Required Reading: Wireguard tutorial
A local zone record allows you to give unique, consistent names to network resources, shape the traffic of outbound DNS requests, and is an excellent way to migrate between private namespaces if you decide to expand your network. We will be using the sample namespaces from the Wireguard tutorial in all examples. If some steps appear to be missing, this is intentional. REMEMBER - because you enabled recursion, this zone file tutorial is for local resolution only. Start an SSH session or open the command prompt on your Wireguard endpoint, and switch to the /etc/bind folder using the cd command. Use the ls command to see what is inside. You will likely see template files for forward zones, which translate a human readable domain name into an IP address, and a reverse zone, which translates IP addresses back into hostnames. These files, when finished, should compliment each other. We will not be using ACLs due to the technical nature of Wireguard automatically enumerating packets. But you should add those values to your /etc/hosts.allow file instead.
Before we work on the zone files, we need to tell bind9 where we plan to keep them by creating a forward and reverse zone entry in /etc/bind/named.conf.local. Transfers are not needed as we are only resolving local addresses that do not directly face the internet. Comments are your best friend. Use a crapton of them for yourself and others who might need to troubleshoot your code in the future. Start them with (//). See the following example file for information.
Open the file that resembles the IP namespace you chose. Since I chose namespace B in the Wireguard tutorial, we will pick the file that resembles db.0.16.172 and open it in Nano. Then hit CTRL + O to save it as a different file. We will choose db.79.16.172 for the name. Make sure yours resembles the 3rd, 2nd and 1st octets of your private IPs. This will be your reverse zone file, and should resemble this when done. In production, DO NOT use .txt as an extension.
Now we are going to open a sample forward DNS file. This file's name format should resemble the domain you plan to use. Because this is a local service, do not use an internet TLD. We will choose 'forward.wireguard.lan.db' as our database name and populate it with entries that resemble the hosts on our network. As you combed over the example file in the previous paragraph, you might have noticed the serial number entry. This is a mandatory entry. Any empty field that appears red in Nano MUST be filled or the file will fail to execute. You can use YYYYMMDD format or incremental numbers - the choice is yours. This becomes useful when you are debugging DNS problems later as you will be told which serial is causing the issues in the logs. Here is an example file of the forward rules. Adjust for your server needs. If you need to disable entries, use a semicolon (;) at the beginning of the line you want to disable.
Finally, before we continue, we need to check the syntax of our files to make sure they work as intended. If you restart bind9 and there is incorrec syntax, name resolution will stop for the whole network will stop until you fix it. These commands require elevation. This will NOT affect your current SSH session, so do not exit if the process fails. Use the named-checkconf command to check for general syntax errors. If any exist, you will be told which line. Then, run the named-checkzone command in the following syntax:
named-checkzone wireguard.lan /etc/bind/forward.wireguard.lan.db
named-checkzone wireguard.lan /etc/bind/db.79.16.172
If nothing is wrong, it should state the loaded serial and say OK in the next line break.
Now we start with the block zone, which will punt any domain you want into your very own sinkhole. You do not need to give it a name, but if you do, open /etc/hosts in a privileged nano session and add the following line (adjust for your own domain names):
Next, we are going to create a shell script file that organizes a hosts file created by Dan Pollock. I have a harshly modified version of this file in a folder location only visible to the local network. To prevent others from circumventing your blocks, please add an .htaccess file that denys IPs first and allows them second, and list local network addresses or CIDRs (like 172.16.79.0/27) to retain access. The shell script is here, modified for the example. You will need to change the URL to where it points on your site. Again, save it as an .sh file. You will need to make it executable and this will require elevation. Type the following command:
chmod +x /etc/bind/make-block-list.sh
We are not done yet. We still need to create a zone for these blocked domains. So reopen /etc/bind/named.conf.local and add these lines to the end of the file we modified earlier:
And now, we create a new zone file. See this one for an example. I used a date serial in this case due to personal record keeping requirements, but you can use number increments if you want. Now run the script we created earlier. You can run a script by recalling its FULL path, or a preceding "sh" iteration if it is in the same folder as the terminal. If you followed the advice I left in the comments, things should be OK. Because I removed the pipes, you will need to reload rndc manually as a privileged user:
Proper Output should be server reload successful.
If you run into issues, like Port 953 being refused, you will need to modify some file permissions. Navigate to /etc/bind and type the following commands:
chown root:bind rndc.key
chmod 640 rndc.key
The top command changes ownership of the mentioned file to the name resolver, which is its own user in most distros.
The bottom command adjusts permissions that enable read and write access to the owner, read only access to the group, and no permissions for others to the file mentioned.
Please run the script again.
WARNING: Any domain you include in the file will fail to resolve not only on the endpoint, but any client that uses the same DNS resolver. This applies to any services besides HTTP. There's one final step: If you want your devices, INCLUDING your endpoint, to prefer your DNS resolver on startup, you will need to edit /etc/resolvconf/resolv.conf.d/head and add the following lines:
Now, when your droplet or clients restart, they will look for this server first. Don't worry - your ISP will still append their IP if you decide not to use your VPN for the day.
Advanced Reading - Separating Logs
By default, all bind9 activity is lumped in /var/log/syslog. We can change this behavior by asking bind9 to save a separate file. First, we create the directories we wish to store the files in. Enter the following commands, one line at a time:
chown -R bind:bind /var/log/bind
chmod -R 775 /var/log/bind
The first line creates the directory we will store logs in. The second line assigns ownership to the named process, which has its own user on Debian systems. The final line gives bind9 read, write, and excute permissions for itself and its group, and read/execute privileges for everyone else.
Next, we open /etc/bind/named.conf and add the following text to the end of it:
We must then create this file and add the following text. Afterwards, we create a logrotate file with the following text to control the size of the log. Save it to /etc/logrotate.d/bind. If you miss this step, bind9 will delete older entries from the same log to keep it small anyway. Check the syntax of logrotate scripts by entering the following command:
logrotate -d /etc/logrotate.d/bind
Finally, we MUST edit the apparmor directive to allow logs to be written to this directory, otherwise restarts will fail. Open /etc/apparmor.d/usr.sbin.named and add the following lines after line 23 (add carriage returns if needed):
The first line allows logs from bind to be written to the directory, while the second logs allows bind9 to write to the directory itself. Failure to include this step on App Armor enabled systems will lead to irreconcilable permissions issues. Proceed to restart both bind9 and apparmor by entering the following:
systemctl restart apparmor
systemctl restart bind9
You should now have separate logs for DNS in /var/log/bind.
© 2021 Mass Transit Honchkrow, IT-Dan, OITIBS, AskUbuntu, DigitalOcean | Last modified Sunday, 05-Dec-2021 15:00:43 EST