LDAP to DNS gateway

ldap2dns is a program to create DNS (Domain Name Service) records directly from a LDAP directory. It can and should be be used to replace the secondary name-server by a second primary one.
ldap2dns reduces all kind of administration overhead: No more flat file editing, no more zone file editing. After having installed ldap2dns, the administrator only has to access the LDAP directory.
Optionally she can add access control for each zone, create a GUI and add all other kind of zone and resource record information without interfering with the DNS server.
ldap2dns is designed to write ASCII data files used by tinydns from the djbdns package, but also may be used to write .db-files used by named as found in the BIND package.

1. Introduction

Often it is desirable to store DNS information in a database rather than in flat text files. This can greatly help to reduce administration overhead since associate information such as billing contact, account management, etc. can be stored and processed inside the same database. Also due to the nature of DNS, information must be stored redundantly on two or more hosts. The classical data replication through zone transfer is unreliable, insecure and difficult to administer.
To solve this problem some proprietary attempts have been proposed to store DNS information in relational databases. The nature of DNS, however, is hierarchical and such should the database be. Using a relational database to store DNS information is undesirable, because it becomes difficult to store free form information. Within a hierachical data scheme, the administrator might define more than one IP-address for each canonical name. To implement such a feature in a relational database without breaking the normalization rules, one would have to add another table.
One of the most widely spread hierarchical database protocols is LDAP. ldap2dns retrieves DNS information stored in an LDAP directory service and generates a file suitable for name-servers.
Actually the most widely spread name-servers named and tinydns are supported. ldap2dns specially has been designed to work with tinydns and is the favored name server daemon for the author of this program. ldap2dns can also generate files suitable for named version 8, but this feature is not well supported. There is a RFC for a format description how to store DNS information in LDAP. This paper a draft RFC which expired in February 1999, looks as if it has been specially designed to be used by named. This scheme does not have strict attribute-value-pair mapping, making it difficult to be used by user interfaces. It also lacks of an implementation (or I have never heard of any).
Since tinydns is going another descriptive way. Therefore I implemented a similar object-scheme more suitable for tinydns. Two object-classes have been defined. DNSzone stores all the information to define a DNS zone, such as the SOA (Start Of Authority), serial numbers etc. DNSrrset is used to store the information for a single resource record, such as the domain name, IP-addresses, class and type.
Here are the tables:

DNSzone

This object-class represents a DNS zone. It is the container for all the resource records within a zone. Zones can be primary or secondary. If used in conjunction with tinydns zones are always primary. Secondary zones don't make sense anyway! In addition to being a container, the zone object has attributes related to the management of the zone. These include the zone's SOA information. Each zone-object can have none to many children of class DNSrrset.
ATTRIBUTEVALUEComment
objectclassDNSzonerequired
cncommon namerequired
DNSzonenameName of the zonerequired, multivalued
DNSserialSerial number of SOAoptional
DNSrefreshRefresh time of SOAoptional, only used for zone transfers
DNSretryRetry time of SOAoptional, only used for zone transfers
DNSexpireExpire time of SOAoptional, only used for zone transfers
DNSminimumMinimum time to liveoptional, only used for zone transfers
DNSadminmailboxHostmaster's contact addressoptional
DNSzonemasterPrimary nameserver for this zoneoptional
DNStypeSOAmust be SOA
DNSclassINmust be IN
DNSttltime to liveoptional, only used with tinydns
DNStimestamptimestampoptional, only used with tinydns

DNSrrset

The Resource Record Set represents all of the resource records for a given host name within a zone. It must be a child of a DNSzone object.
ATTRIBUTEVALUEComment
objectclassDNSrrsetrequired
cncommon namerequired
DNSdomainnameName of this recordoptional, relative to zonename
DNSipaddrIP addressoptional, mutivalued
DNScnameCanonical nameoptional, without ending dot relative to zonename
DNSpreferenceintegeroptional, only used for MX records
DNStypeA, CNAME, NS, MX, PTR or TXTmust be any valid record type
DNSclassINmust be IN
DNSttltime to liveoptional, only used with tinydns
DNStimestamptimestampoptional, only used with tinydns

2. Installation

3. Running ldap2dns

If You are a tinydns user, run ldap2dns in /services/tinydns/root.
If You are an openldap user, the command line switches are the same as for ldapsearch or ldapadd.
$ ldap2dns -D "binddn" [ -w passwd ] -b "searchbase" -o data -e "cd /var/tinydns/root && /usr/bin/tinydns-data"
This generates a data file which is converted into a data.cdb by tinydns-data as soon as ldap2dns detects a modification in the LDAP directory. The password is required if You restrict read queries to authenticated users only. Test with
$ dnsq any corp.local ipaddr
Replace ipaddr with whatever You configured tinydns to listen to.

If You are a BIND user, run ldap2dns in /var/named with

$ ldap2dns -D "binddn" -w passwd -b "searchbase" -o db -e "kill -HUP `cat /var/run/named-pid`"
Do not forget to add You primary definition to Your named.boot file. Your named should be restarted automatically as soon as ldap2dns detects a modification in the LDAP directory. If bind is not restarted, do so with
# kill -HUP PID
Now run
$ nslookup - localhost
> ns1.corp.local
Note that nslookup only works with tinydns if Your nameserver resolves its IP-address backwards.

4. Running ldap2dnsd

ldap2dnsd is a hard link onto ldap2dns. If invoked, the program starts as backgound-daemon and contineously checks for modifications in the LDAP directory. If the the daemon sees a modification in the DNSserial numbers it updates the data or .db files, depending what kind of output was configured. This check is done about once a minute.
The command-line options for ldap2dnsd are the same as for ldap2dns. Use the -u option to modify the update intervall. You may also use -u on ldap2dns to start as a foreground daemon. This is useful if You want to run ldap2dns from daemontools. To do this run ldap2tinydns-conf in /service/tinydns and link /service/ldap2dns onto /service/tinydns/ldap2dns.
# ln -s /service/tinydns/ldap2dns /service/ldap2dns
After a few seconds daemontools starts ldap2dns which itself generates data files whenever a modification is commited into the LDAP directory.

ldap2dns and ldap2dnsd recognize the following options:

-D binddn specify the distinguished name to bind to the LDAP directory
-w bindpasswd use bindpasswd as the password for simple authentication
-b searchbase use searchbase as the starting point for the search instead of the default
-o Generate a "data" file to be processed by tinydns-data. 
-o db	For each zone generate a ".db" file to be used by named.
-L[filename] print output in LDIF format for reimport. If no filename is specified output goes to stdout. 
-h host specify the hostname of LDAP directory. Default is localhost.
-p port portnumber to connect to LDAP directory. Defaults is 389
-v run in verbose mode
-vv even more verbose
-V print version and exit
-u numsecs update DNS data every numsecs.
ldap2dns and ldap2dnsd recognizes the following environement variables:
TINYDNSDIR: Specifies the directory where ldap2dns writes its data file.
LDAP2DNS_UPDATE: Specifies the update intervall as the -u command line option would.
LDAP2DNS_OUTPUT: Specifies the default output, as the -o command line option would.

ldap2dns and ldap2dnsd use the following parameters from /etc/ldap.conf if not specified on the command line: BASE: The LDAP search base.
HOST: The LDAP server.
PORT: The LDAP port.

5. Importing DNS data from Your named

A perl-script import.pl is contained in this package. Edit the first lines of the script to conform to Your configuration. If You have installed the Perl packages Net::LDAP and Net::DNS skip the following lines, otherwise do
# perl -MCPAN -e 'shell'
(...snip...)
> install Net::DNS
> install Net::LDAP
Now check that Your nameserver allows zone transfers to your host and run the import script:
$ echo 'primary mydomain.org ' | ./import.pl
for a single domain or
# cat named.boot | ./import.pl
to populate Your LDAP directory.

6. Coming soon

A browser-based administration toolkit, which connects directly to the LDAP-directory service. Here is a screenshot

7. To Do

8. Copyright and disclaimer

This program is licensed under the GPL version 2 or at Your choice any later version.
It is maintained by Jacob Rief. If you run ldap2dns on a productive nameserver, please mail me and tell me on what OS and with which nameserver you do so.