ispconfigdns
This tutorial is for self-hosting your own authoritative DNS server using ISP Config and bind9. The requirements are that you own three IPs, have a domain dedicated just for this with three A records pointing towards three clean Debian installs on each of the VMs. The names would be ns1.server.com, ns2.server.com, and ns3.server.com. Okay, since my data center only just rolled out ipv6 support, I had to disable ipv6 since I could not set ipv6 PTR records at the time of creation:
nano /etc/sysctl.d/00_ipv6_off.conf net.ipv6.conf.all.disable_ipv6 = 1
One of the servers will be primary and the others mirrors of that. For this reason, they will need to use a common mysql database on the primary. Since I did not want to expose mysql publicly, I created a separate NIC on each VM on virsh's default virtual bridge, virbr0. You can also use bridge-utils and just brctl addbr virbr0
but since this was ready to go and did not require me tinkering with my primary interfaces or ifupdown, I just used it.
On virtmanager > Connection Details > Start virbr0 > Auto Start On each VM > open > Add Hardware > NIC > Bridge > virbr0
Of course, you can also do this with pure virsh and xml, but with -X passthrough, it's just so easy to use the GUI and saved a ton of time. Remember, each VM also needs to be publicly accessible as it is an authoritative DNS server, so the bridge above is just the secondary interface with a private subnet. Here's an example of what /etc/network/interfaces
needs to look like inside each of the three VMs:
nano /etc/network/interfaces auto enp1s0 iface enp1s0 inet static address 8.67.82.100 netmask 255.255.255.0 gateway 8.67.82.1 nameservers 8.8.8.8 auto enp7s0 iface enp7s0 inet static address 192.168.122.2 netmask 255.255.255.0 gateway 192.168.122.1 nameservers 8.8.8.8
The next machine would .3, the next one .4. Once you set up all the VMs with the primary and secondary interfaces, make sure each of them can reach the other. You can ping 192.168.122.3
for example from inside the .2 box, and so on. Once they are all reachable, set up the fully qualified hostnames in each.
nano /etc/hosts
The contents being as follows:
127.0.0.1 localhost 127.0.1.1 ns1.haacksnetworking.com ns1 8.67.82.100 ns1.haacksnetworking.com ns1 8.67.82.101 ns2.haacksnetworking.com ns2 8.67.82.102 ns3.haacksnetworking.com ns3
Each VM needs a similar configuration, but the second line would change to ns2.haacksnetworking.com and ns2, and ns3.haacksnetworking.com and ns3 on the other boxes. It's now time to install ISPConfig on the primary box. In my case, I chose to first install a complete configuration and then disabled services manually afterwards. I ran the following official script on ns1.haacksnetworking.com:
wget -O - https://get.ispconfig.org | sh -s
After it completes, make sure to record your admin password and mysql root password securely. It's now time to set up the database on the primary server. It installs roundcube, openVZ, and some other services by default. I later removed all of these after testing and just installed a simple send-only MTA with postfix and nothing else. You should customize to your preference and/or adjust the install script with flags to limit what it brings in. You now want to create users for each of the slave servers:
sudo mysql -u root -p
Then run the following mysql commands for each slave server (.3 and .4) so they can communicate with the primary:
CREATE USER 'root'@'192.168.122.3' IDENTIFIED BY 'securepass';
GRANT ALL PRIVILEGES ON * . * TO 'root'@'192.168.122.3' IDENTIFIED BY 'securepass' WITH GRANT OPTION MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0 ;
CREATE USER 'root'@'192.168.122.4' IDENTIFIED BY 'securepass';
GRANT ALL PRIVILEGES ON * . * TO 'root'@'192.168.122.4' IDENTIFIED BY 'securepass' WITH GRANT OPTION MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0 ;
After that is done, log in to the web panel and add a firewall record with 22,80,443,53,8080,8081
open for tcp and 53
open on udp. Next, we need to manually add a firewall record at the command line to allow mysql to communicate across the local subnet:
ufw allow from 192.168.122.0/24 to any port 3306 proto tcp
Next, set up each of the slave servers ns2 and ns3 by shelling in to them and running this script:
wget -O - https://get.ispconfig.org | sh -s -- --no-web --no-mail --use-php=system --interactive
Make sure to record the mysql and ispconfig database passwords for each securely. Be sure to select expert mode and be sure to use the local address of the primary, 192.168.122.1, not the external for mysql communcations. Use the securepassword you chose while setting up the database above for the primary. Make sure you say “n” to adding the web panel and/or other services not needed for DNS. Next, we need to log in to the web panel of the primary server and go to Settings / ns2.haacksnetworking.com and Settings / ns3.haacksnetworking.com and change the “Is mirror of Server” dropdown to ns1.haacksnetworking.com. Once that's done, we can now set up our zone on ISP Config and the Glue records on the Registrar. To set up your zone, go to DNS / Add new DNS zone with Wizard on the web panel, and enter your domain, the IP of your primary name server, and for the nameservers enter ns1.haacksnetworking.com and ns2.haacksnetworking.com. Enter an email of your choice and select create zone. You need to now add a third NS record for your other name server, and don't forget the trailing “.” as this will cause hours of caching errors. Secondly, make sure to create three corresponding A records for each domain (ns1, ns2, ns3) that point to the IPs of those domains. Once all the zone is added as follows and all records entered properly, check /etc/bind/
and make sure there is no .err
appended to pri.haacksnetworking.com
. If there is, you likely parsed something wrong while entering the records. Adjust and debug until the error goes away when you restart bind9's service. It's now time to set up the Glue records at your Registrar. To do that, go to your Registrar's Name Server settings, and register name servers for the haacksnetworking.com domain. In the settings, point each of those name servers to the IPs you have set up for them. Once those Glue records are setup, you now change the Name Servers from the Registrar's to your own. Give it a good 1-2 hours to cache, and check this site to see if you did everything correctly:
Note everything worked properly at first, and I had to spend some time debugging. Using host and dig can be helpful while debugging:
host ns1.haacksnetworking.com 8.67.82.100 host ns1.haacksnetworking.com dig haacksnetworking.com ns dig haacksnetworking.com ns @8.67.82.100
The commands above check your default dns for the records and/or check the Name Server itself (the one you are setting up now). These commands are particularly helpful in determining whether your name server can return the proper records and/or whether they have already cached to other servers or not. Also, while debugging and re-adding a zone, I did once have to manually remove the “.err” from /etc/bind
and restart bind to get the changes to stick. This is apparently due to a DNSsec glitch in ISPConfig.
Note: This tutorial is fairly advanced and there are lots of omitted smaller steps, days of debugging that are left unreported and so on. Feel free to email or hit me up on Mastodon (see home page of Wiki) if you need help.
— oemb1905 2023/05/21 16:46