Running A MySQL-Based DNS Server: MyDNS

Want to support HowtoForge? Become a subscriber!
 
Submitted by falko (Contact Author) (Forums) on Mon, 2006-01-02 15:47. :: MyDNS | DNS

This is a "copy & paste" HowTo! The easiest way to follow this tutorial is to use a command line client/SSH client (like PuTTY for Windows) and simply copy and paste the commands (except where you have to provide own information like IP addresses, hostnames, passwords,...). This helps to avoid typos.

Running A MySQL-Based DNS Server: MyDNS

Version 1.0
Author: Falko Timme <ft [at] falkotimme [dot] com>
Last edited: 01/02/2006

In this tutorial I will describe how to install and configure MyDNS, a DNS server that uses a MySQL database as backend instead of configuration files like, for example, Bind or djbdns. This has the advantage that you can easily use web-based frontends to administrate your DNS records. You could even write your own frontend, e.g. using PHP, to interact with the MyDNS database. MyDNS simply reads the records from the database, and it does not have to be restarted/reloaded when DNS records change or zones are created/edited/deleted! This is a major advantage.

I will also show how to set up a secondary DNS server, but I will not use normal zone transfers to get the records from the primary to the secondary DNS server; instead, I will use MySQL database replication. I will simply replicate the data from the primary to the secondary server.

There are multiple web frontends to MyDNS. Of course, you can use phpMyAdmin for the MyDNS administration, or you can use the web frontend that comes with MyDNS (which is not for beginners because it lacks the field descriptions), or you can use MyDNSConfig, a tool written by myself. I will show how to install each of them.

All in all, MyDNS makes a very good impression on me, and I think that the future belongs to services that use a database as backend instead of configuration files.

I have used a Debian Sarge system for this setup. However, most of the steps described here should also apply to other distributions like Fedora, SuSE, Mandriva, etc.

I want to say first that this is not the only way of setting up such a system. There are many ways of achieving this goal but this is the way I take. I do not issue any guarantee that this will work for you!

1 Install MySQL And MyDNS

First, make sure you have a working basic Debian installation, as described on http://www.howtoforge.com/perfect_setup_debian_sarge and http://www.howtoforge.com/perfect_setup_debian_sarge_p2 (please refer to the respective "Perfect Setup" document on HowtoForge if you use another distribution).

Then install MySQL:

apt-get install mysql-server mysql-client libmysqlclient12-dev phpmyadmin

You will be asled a few questions:

Enable suExec? <-- Yes
Which web server would you like to reconfigure automatically? <-- apache, apache2
Do you want me to restart apache now? <-- Yes

Set a root MySQL password like this:

mysqladmin -u root password yourrootsqlpassword

The MyDNS installation is easy. Just follow these steps:

cd /tmp/
wget http://mydns.bboy.net/download/mydns-1.0.0.tar.gz
tar xvfz mydns-1.0.0.tar.gz
cd mydns-1.0.0/
./configure
make
make install

Now we have to create the MyDNS database (called mydns) and a MyDNS database user (also called mydns, with mydns_password as password):

mysql -u root -p
Enter password:

Now, on the MySQL shell, we create the mydns database and the user mydns:

CREATE DATABASE mydns;
GRANT SELECT, INSERT, UPDATE, DELETE ON mydns.* TO 'mydns'@'localhost' IDENTIFIED BY 'mydns_password';
GRANT SELECT, INSERT, UPDATE, DELETE ON mydns.* TO 'mydns'@'localhost.localdomain' IDENTIFIED BY 'mydns_password';
FLUSH PRIVILEGES;
quit;

Back on the normal shell, we create the tables in the mydns database:

mydns --create-tables | mysql -u root -p mydns
Enter password:

If you see errors like these:

mydns[14287]: error loading gid for group `nobody'
mydns[14287]: using gid 65534 from user `nobody'

do not worry, you can forget about them.

Next we add two more columns to the soa table of the mydns database:

mysql -u root -p
Enter password:
ALTER TABLE mydns.soa ADD COLUMN active ENUM('Y','N') NOT NULL;
ALTER TABLE mydns.soa ADD INDEX (active);
ALTER TABLE mydns.soa ADD COLUMN xfer CHAR(255) NOT NULL;
quit;

With the active column, you can simply enable/disable zones later on, and the xfer column can be used for zone transfers (which we do not need because we will use MySQL database replication to get the data to the secondary DNS server, but I mention it for completeness) (if you want to use zone transfers instead of database replication, then the xfer column should contain one or more IP addresses separated by commas. These IP addresses will be allowed to transfer the zone.).

Now we create the MyDNS configuration file /etc/mydns.conf by running this command:

cd /tmp/mydns-1.0.0/
make conf

Then we edit /etc/mydns.conf so that it looks like this:

##
## /etc/mydns.conf
## Fri Oct 21 16:36:32 2005
## For more information, see mydns.conf(5).
##


# DATABASE INFORMATION

db-host = localhost # SQL server hostname
db-user = mydns # SQL server username
db-password = mydns_password # SQL server password
database = mydns # MyDNS database name


# GENERAL OPTIONS

user = nobody # Run with the permissions of this user
group = nogroup # Run with the permissions of this group
listen = * # Listen on these addresses ('*' for all)


# CACHE OPTIONS

zone-cache-size = 1024 # Maximum number of elements stored in the zone cache
zone-cache-expire = 60 # Number of seconds after which cached zones expires
reply-cache-size = 1024 # Maximum number of elements stored in the reply cache
reply-cache-expire = 30 # Number of seconds after which cached replies expire


# ESOTERICA

log = LOG_DAEMON # Facility to use for program output (LOG_*/stdout/stderr)
pidfile = /var/run/mydns.pid # Path to PID file
timeout = 120 # Number of seconds after which queries time out
multicpu = 1 # Number of CPUs installed on your system
allow-axfr = no # Should AXFR be enabled?
allow-tcp = yes # Should TCP be enabled?
ignore-minimum = no # Ignore minimum TTL for zone?
soa-table = soa # Name of table containing SOA records
rr-table = rr # Name of table containing RR data

Make sure to fill in the correct database details, and also take care about the group. On Debian, nobody's group is nogroup, which is different from the default value in /etc/mydns.conf (also nobody), so make sure you change this! Also set allow-tcp to yes.

Now we create the MyDNS init script /etc/init.d/mydns:

#! /bin/sh
#
# mydns Start the MyDNS server
#
# Author: Falko Timme <ft@falkotimme.com>.
#

set -e

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
NAME=mydns
DAEMON=/usr/local/sbin/$NAME
DESC="DNS server"

SCRIPTNAME=/etc/init.d/$NAME

# Gracefully exit if the package has been removed.
test -x $DAEMON || exit 0

case "$1" in
start)
echo -n "Starting $DESC: $NAME"
$DAEMON --background
echo "."
;;
stop)
echo "Stopping $DESC: $NAME."
kill -9 `pidof $NAME` &> /dev/null
;;
restart)
echo "Restarting $DESC: $NAME."
$0 stop && sleep 1
$0 start
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart}" >&2
exit 1
;;
esac

exit 0

Then we make it executable and start MyDNS:

chmod 755 /etc/init.d/mydns
/etc/init.d/mydns start

If you want that MyDNS is started automatically during the system boot, you have to create the necessary system bootup links. On Debian, you do it like this:

update-rc.d mydns defaults 21 22

On Fedora or RedHat, you would run this:

chkconfig --levels 235 mydns on


Please do not use the comment function to ask for help! If you need help, please use our forum.
Comments will be published after administrator approval.
Submitted by Anonymous (not registered) on Sun, 2009-02-01 16:57.
It goes to show how bad BIND's config file management really is--that--someone would write, from scratch, a DNS server using mysql to manage the records. Amazing.

Submitted by sysAdmin (not registered) on Tue, 2010-07-20 20:33.
I've Found a great DNS scanner that can locate any DNS server at your network (multi-subnet) it can also test if the DNS is answering anyones requests or not.
you can get it here: http://www.softpedia.com/get/Internet/Other-Internet-Related/DNS-Locator.shtml
Submitted by Anonymous (not registered) on Sun, 2008-11-09 23:20.

I would love to see how this could be used in conjuction with an existing server setup so that it would be a secondary only to what is already being used on that server. 

For example I have a VPS that I rent and I would like to be able to use MyDNS as a secondary resource so that current setup of LXAdmin would not be affected but I could still use this for certain domains or subdomains that I would like to be able to work as my own dynamic dns service on my own server.

Submitted by berlinerkindl (registered user) on Wed, 2007-09-12 11:09.

The occurs from an incompatability with PHP5. Easily resolved with either:

vi +2475 /var/www/admin.php *hit enter

*this will open admin.php at line 2475, now you need to edit each instance of $this to $_this

between line 2475 and 2485 

if you arn't familiar with vi, you may find it easier to use nano (please note that ^ represents the CTRL key on your keyboard, I am using it here as it is what you will see in the editor)

nano /var/www/admin.php *hit enter

^\ *hit enter

Search (to replace): $this *hit enter

Replace with: $_this *hit enter

Replace this instance?: A *hit enter

^x *hit enter 

Save modified buffer (ANSWERING "No" WILL DESTROY CHANGES) ?  Y *hit enter

File Name to Write: /var/www/admin.php *hit enter 

That's it, in the end that section should look like the following:


/**************************************************************************************************
   RR_TYPE_OPTIONS
   Returns a list of resource record types.
**************************************************************************************************/
function _rr_type_option($type, $_this) {
    return "<OPTION" . (!strcasecmp($type, $_this) ? " selected" : "") . ">$_this";
}
function rr_type_options($type)
{
   global $db_valid_types;

   reset($db_valid_types);
   $rv = '';
   foreach ($db_valid_types as $_this)
      $rv .= _rr_type_option($type, $_this);
   return $rv;
}
/*--- rr_type_options() -------------------------------------------------------------------------*/

 

Submitted by Anonymous (not registered) on Sat, 2006-04-15 23:32.

Article states:

MyDNS simply reads the records from the database, an

t does not have to be restarted/reloaded

when DNS records change or zones are created/edited/deleted! This is a major advantage.

Only old BIND deployments would run this way. BIND has supported dynamic updates for quite some time. Mine never goes down (well practically speaking). All of our changes to the BIND DATABASE are made dynamically.

I emphasize database, because BIND is a database... whether you want to look at that way or not. I'm not against a DNS sitting on top of a database of some other kind, but I certainly don't like tools where the data is replicated out of a sql database and into BIND... just speaking out loud. Again, serving up out of a sql database is fine... just want to point out that BIND has/is a database and you don't have to restart it to make record changes or additions (with a few exceptions.. but not 99% of what would be changed normally).

Submitted by Azuretek (not registered) on Fri, 2008-10-10 17:42.

Just wanted to clarify, you do have to reload the bind configuration for record changes to take effect. The benefit of running MyDNS is that you can replicate changes and backup your data the same way you would do it for any other database driven application.

Reloading bind is usually accomplished by using "rndc" which is kind of like an API connector that can be used to control bind. Issuing the command "rndc reload" will apply your record updates.