                              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.

   ATTRIBUTE       VALUE                        Comment                       
   objectclass     DNSzone                      required                      
   cn              common name                  required                      
   DNSzonename     Name of the zone             required, multivalued         
   DNSserial       Serial number of SOA         optional                      
   DNSrefresh      Refresh time of SOA          optional, only used for zone  
                                                transfers                     
   DNSretry        Retry time of SOA            optional, only used for zone  
                                                transfers                     
   DNSexpire       Expire time of SOA           optional, only used for zone  
                                                transfers                     
   DNSminimum      Minimum time to live         optional, only used for zone  
                                                transfers                     
   DNSadminmailbox Hostmaster's contact address optional                      
   DNSzonemaster   Primary nameserver for this  optional                      
                   zone                         
   DNStype         SOA                          must be SOA                   
   DNSclass        IN                           must be IN                    
   DNSttl          time to live                 optional, only used with      
                                                tinydns                       
   DNStimestamp    timestamp                    optional, only used with      
                                                tinydns                       

     * DNSzonename: This field is required to describe the zone's domain
       name, for instance myorg.com. More than one DNSzonename my be
       specified for a DNSzone so that the same host is accessable with
       different zonenames.
     * DNSserial: This is the serial number as used for BIND's zone
       transfers. Here it is used to inform ldap2dns that it has to rebuild
       its data-file. Without increasing the serial number ldap2dns will
       ignore all modifications until it is restarted.
     * DNSrefresh, DNSretry, DNSexpire, DNSminimum: You may safly ignore
       these numbers if You don't do zone-transfers. Since Your secondary
       nameserver will connect to the LDAP server the same way Your primary
       does, You don't need zone-transfers anyway.
     * DNSzonemaster: Here you specify the canonical name of your primary
       nameserver.
     * DNSadminmailbox: This is the contact address of Your
       DNS-administrator. The first dot is converted to a @.
     * DNStype: Must be SOA (Start Of Authority)
     * DNSclass: Must be IN (Internet, or do still use Chaosnet?)
     * DNSttl: This is the time-to-live value as used by tinydns. If TTL is
       nonzero (or omitted), the timestamp is a starting time from whereon
       this zone's information is valid. If TTL is zero, the timestamp is an
       ending time (``time to die'').
     * DNStimestamp: This is the timestamp as used by tinydns. It represents
       a string as external TAI64 timestamp, printed as 16 lowercase
       hexadecimal characters

    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.

   ATTRIBUTE     VALUE                    Comment                             
   objectclass   DNSrrset                 required                            
   cn            common name              required                            
   DNSdomainname Name of this record      optional, relative to zonename      
   DNSipaddr     IP address               optional, mutivalued                
   DNScname      Canonical name           optional, without ending dot        
                                          relative to zonename                
   DNSpreference integer                  optional, only used for MX records  
   DNStype       A, CNAME, NS, MX, PTR or must be any valid record type       
                 TXT                      
   DNSclass      IN                       must be IN                          
   DNSttl        time to live             optional, only used with tinydns    
   DNStimestamp  timestamp                optional, only used with tinydns    

     * DNSrrset: This object-class must be a direct child of DNSzone. Its dn
       should be specified as

 cn=domainname,cn=zonename,...

     * DNSdomainname This is the partial domain-name, ie. the part in front
       of the zone-name.
     * DNSipaddr: This specifies the IP-address in dotted format. It can be
       used for DNSrrset's of type A, NS, MX or PTR. DNSipaddr is multivalued
       to specifiy more than one IP-address for a service. If used in
       DNSrrset's with DNStype = PTR it overrides the old-fashioned form used
       in DNSdomainname such as 13.178.23.in-addr.arpa for reverse lookups.
     * DNScname: Whenever there is a mapping of a domain-name to a canonical
       name, use this attribute. DNScname may be used for DNSrrset's with
       DNStype CNAME, NS, MX, PTR or TXT. If the last character of a CNAME is
       a dot its name is considered absolute. If it does not contain a dot,
       its name is prepended to the zone-name.
     * DNSpreference: This number is the mail-exchange preference as used by
       BIND.
     * DNStype: This must be A, CNAME, NS, MX, PTR or TXT. It specifies the
       DNSrrset type.
     * DNSclass: Must be IN
     * DNSttl: This is the time-to-live value as used by tinydns. If TTL is
       non-zero (or omitted), the time-stamp is a starting time from where-on
       this zone's information is valid. If TTL is zero, the timestamp is an
       ending time (``time to die'').
     * DNStimestamp: This is the timestamp as used by tinydns. It represents
       a string as external TAI64 time-stamp, printed as 16 lowercase
       hexadecimal characters

  2. Installation

     * Install an LDAP server such as openldap. Other LDAP implementations
       may work but have not been tested. Also install the development
       libraries and include files.
     * Install djbdns or if you really have to, go with BIND.
       I suggest to install tinydns included in the djbdns package, because
       it is safer, but You may have reasons why You want to use BIND.
     * Install ldap2dns
       Unpack the package and build it:

 gzcat ldap2dns.tar.gz | tar x
 cd ldap2dns-version
 make
 make install

       If you run ldap2dns togther with tinydns, go into /var/tinydns and run
       ldap2tinydns-conf.
     * Add the extra object-classes to the slapd.conf file. If You are using
       openldap-1.2.x:
       copy the files dns.oc.conf and dns.ac.conf into the directory
       /etc/openldap or appropriate and add the following two lines to Your
       slapd.conf file:

 include         /etc/openldap/dns.at.conf
 include         /etc/openldap/dns.oc.conf

       or, if You are using openldap-2.0.x:
       copy the file dns.schema into the directory /etc/openldap/schema or
       appropriate and add the following line to Your slapd.conf file:

 include         /etc/openldap/schema/dns.schema

       Now restart your LDAP server.

     * Start to populate your LDAP server with DNS information. As a first
       test do

 $ ldapadd -D "binddn" -w password < example.ldif

       Replace 'myorg' and 'binddn' with whatever is appropriate on Your
       system. Start a search and see if something was added

 $ ldapsearch -D "binddn" "objectclass=dnsrrset"

     * Test ldap2dns

 $ ./ldap2dns -D "binddn" [ -b "searchbase" ] [ -w passwd ] -o data -o db -L

       This should create a 'data' file, a 'corp.local.db' file and should
       print the DNS content.
       Note: The data file is text data which can be processed with
       tinydns-data. corp.local.db is the file as used by named. If You are
       using bind, You also have to adopt the file /etc/named.conf and You
       have to restart named.

  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

     * Write a man page.
     * named.conf should be created automatically.

  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.
