mirror of
				https://github.com/bklang/ldap2dns.git
				synced 2025-10-30 23:53:12 -04:00 
			
		
		
		
	
		
			
	
	
		
			428 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			428 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|  |                               LDAP to DNS gateway | ||
|  | 
 | ||
|  | ldap2dns is a program to read DNS (Domain Name Service) records from an LDAP | ||
|  | directory and format them into flat files suitable for TinyDNS (or Bind). | ||
|  | 
 | ||
|  | 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 modify the data stored in the LDAP directory. | ||
|  | 
 | ||
|  | Optionally access control can be configured for each zone, GUIs can be more | ||
|  | easily implemented, and add all other kind of zone and resource record | ||
|  | information can be managed 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 zone db files used by named as found in | ||
|  | the BIND package. | ||
|  | 
 | ||
|  | ldap2dns is known to compile and run under Linux and Solaris using GCC or Sun | ||
|  | Studio C Compiler. | ||
|  | 
 | ||
|  | 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. | ||
|  | 
 | ||
|  | The two most-widely-used domain name service daemons, named and tinydns are | ||
|  | supported. | ||
|  | 
 | ||
|  | ldap2dns specifically 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 (and possibly version 9), 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 the original author implemented | ||
|  | a similar object-scheme more suitable for tinydns. | ||
|  | 
 | ||
|  | Installation | ||
|  | 
 | ||
|  |   * Install an LDAP server such as openldap. Other LDAP implementations may | ||
|  |     work but have not been tested. If you are building from source you will | ||
|  |     need to also install the development libraries and include files. On most | ||
|  |     package based systems these would be the -devel packages (example: | ||
|  |     openldap-devel). | ||
|  |   * Install djbdns or BIND. Configuring the nameserver to automatically start | ||
|  |     and work in your environment is beyond the scope of this document. | ||
|  |   * Install ldap2dns | ||
|  |     From RPM: | ||
|  | 
 | ||
|  |     $ sudo rpm -Uhv ldap2dns.rpm | ||
|  | 
 | ||
|  |     Replace "ldap2dns.rpm" with the file you have downloaded. | ||
|  |     Now that you have it installed, skip to Usage to continue. | ||
|  | 
 | ||
|  |     To build ldap2dns from source: | ||
|  |     Unpack the package and build it: | ||
|  | 
 | ||
|  |     $ gzcat ldap2dns.tar.gz | tar x | ||
|  |     $ cd ldap2dns-version | ||
|  |     $ make | ||
|  |     $ sudo make install | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | Configuration | ||
|  | 
 | ||
|  |   * Copy the file ldap2dns.schema into the directory /etc/openldap/schema. Add | ||
|  |     the following line to Your slapd.conf file: | ||
|  | 
 | ||
|  |     include         /etc/openldap/schema/ldap2dns.schema | ||
|  | 
 | ||
|  |     Now restart your LDAP server. | ||
|  | 
 | ||
|  | Note: If you are running OpenLDAP 2.0 or earlier look for appropriate schema | ||
|  | files for your version in the deprecated/ subdirectory. These files are known | ||
|  | to work as of ldap2dns 0.3.5 but are no longer supported for future feature | ||
|  | updates. | ||
|  | 
 | ||
|  | 
 | ||
|  |   * 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. | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | Schema Documentation | ||
|  | 
 | ||
|  | 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   must be any valid record type | ||
|  |                or TXT | ||
|  | DNSclass       IN                      must be IN | ||
|  | DNSttl         time to live            optional, only used with tinydns | ||
|  | DNStimestamp   timestamp               optional, only used with tinydns | ||
|  | DNSsrvpriority SRV Priority            optional, defaults to 0 for SRV records | ||
|  | DNSsrvweight   SRV Weight              optional, defaults to 0 for SRV records | ||
|  | DNSsrvport     SRV Port                Required for SRV records | ||
|  | 
 | ||
|  | 
 | ||
|  |   * 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 | ||
|  |   * DNSsrvpriority: Integer representing the relative priority of this DNS SRV | ||
|  |     record. See menandmice.com for more information about DNS SRV records. | ||
|  |   * DNSsrvweight: DNS SRV record weight field. Integer | ||
|  |   * DNSsrvport: DNS SRV record port number. Integer | ||
|  | 
 | ||
|  | 
 | ||
|  | Usage: Running ldap2dns | ||
|  | 
 | ||
|  | ldap2dns and ldap2dnsd recognize the following options: | ||
|  | 
 | ||
|  | -D binddn specify the distinguished name to bind to the LDAP directory | ||
|  | -w bindpasswd use bindpasswd as password for simple authentication | ||
|  | -b searchbase use searchbase as starting point for search instead default | ||
|  | -o data generate a "data" file to be processed by tinydns-data | ||
|  | -o db for each zone generate a "<zonename>.db" file to be used by named | ||
|  | -L[filename] print output in LDIF format to [filename] or stdout for reimport | ||
|  | -h host specify the hostname of LDAP directory. Default is localhost | ||
|  | -p port portnumber to connect to LDAP directory. Defaults is 389 | ||
|  | -H ldapURI URI for LDAP server (examples: ldap://hostname or ldaps://hostname:636) | ||
|  | -v run in verbose mode | ||
|  | -vv even more verbose | ||
|  | -V print version and exit | ||
|  | -u numsecs update DNS data every numsecs. | ||
|  | -t timeout timeout for LDAP searches, in seconds | ||
|  | -M reclimit Limit LDAP results to reclimit number of records. | ||
|  | 
 | ||
|  | ldap2dns and ldap2dnsd recognize the following environment 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. | ||
|  | 
 | ||
|  | 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.conf 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. | ||
|  | 
 | ||
|  | Usage: Running ldap2dnsd | ||
|  | 
 | ||
|  | When ldap2dns is invoked as ldap2dnsd, the program starts as backgound-daemon | ||
|  | and continuously 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 and is configurable. | ||
|  | The command-line options for ldap2dnsd are the same as for ldap2dns. Use the -u | ||
|  | option to modify the update interval. You may also use -u on ldap2dns to start | ||
|  | as a foreground daemon. This is useful if You want to run ldap2dns from | ||
|  | daemontools. | ||
|  | 
 | ||
|  | These instructions assume you will be running ldap2dns under daemontoolsb> and | ||
|  | that tinydns is also running under daemontools. These instructions also assume | ||
|  | you are using Dan Bernstein's standard directory locations. Make sure you | ||
|  | change the below examples to match your environment. | ||
|  | 
 | ||
|  | Start by creating the a non-root user to run your ldap2dns and associated | ||
|  | logging mechanism: | ||
|  | 
 | ||
|  | # groupadd -r ldap2dns | ||
|  | # useradd -r -d /dev/null -s /bin/false -c "ldap2dns Daemon" \ | ||
|  |  -g ldap2dns ldap2dns | ||
|  | # groupadd -r l2dnslog | ||
|  | # useradd -r -d /dev/null -s /bin/false -c "ldap2dns Logger" \ | ||
|  |  -g l2dnslog l2dnslog | ||
|  | 
 | ||
|  | 
 | ||
|  | Next configure the ldap2dns area to be managed by daemontools. Typically this | ||
|  | is /etc/ldap2dns | ||
|  | 
 | ||
|  | # cd /etc | ||
|  | # ldap2tinydns-conf ldap2dns l2dnslog /etc/ldap2dns /etc/tinydns/root | ||
|  | 
 | ||
|  | The syntax is close to tinydns-conf except that you will also need to specify | ||
|  | the path to the root directory for tinydns. This is the directory that holds | ||
|  | the data file. | ||
|  | 
 | ||
|  | Next edit the file /etc/ldap2dns/run and optionally the environment variables | ||
|  | in /etc/ldap2dns/env as necessary for your environment. This may include | ||
|  | configuring a base DN, a bind DN, a password, and an interval. | ||
|  | 
 | ||
|  | When everything is ready configured properly create a symlink from /etc/ | ||
|  | ldap2dns into /service. This action will cause daemontools to launch ldap2dns. | ||
|  | 
 | ||
|  | # ln -s /etc/ldap2dns /service/ldap2dns | ||
|  | 
 | ||
|  | After a few seconds daemontools starts ldap2dnsd which itself generates data | ||
|  | files whenever a modification is commited into the LDAP directory. | ||
|  | 
 | ||
|  | Importing DNS data from an existing AXFR capable (BIND) name server | ||
|  | 
 | ||
|  | 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. | ||
|  | 
 | ||
|  | Importing DNS data from an existing TinyDNS name server | ||
|  | 
 | ||
|  | Use the supplied data2ldap.pl in the scripts/ directory | ||
|  | 
 | ||
|  | $ data2ldap.pl data data.ldif ou=DNS,dc=example,dc=com | ||
|  | 
 | ||
|  | More to come... | ||
|  | 
 | ||
|  | 
 | ||
|  | Roadmap | ||
|  | 
 | ||
|  | A browser-based administration toolkit, which connects directly to the | ||
|  | LDAP-directory service. | ||
|  | 
 | ||
|  | To Do | ||
|  | 
 | ||
|  |   * Write a man page. | ||
|  |   * named.conf should be created automatically. | ||
|  | 
 | ||
|  | Copyright and Disclaimer | ||
|  | 
 | ||
|  | This program is Copyright 1999-2004 Jacob Rief and 2005-2006 Ben Klang | ||
|  | This program is licensed under the GPL version 2 | ||
|  | 
 | ||
|  | ldap2dns was originally written by Jacob Rief (jacob.rief@tiscover.com). It is | ||
|  | now maintained by Ben Klang (bklang@alkaloid.net). If you run ldap2dns on a | ||
|  | production nameserver, please send the maintainer an email and mention on what | ||
|  | OS and with which nameserver you do so. | ||
|  | 
 | ||
|  | Disclaimer: The author and all contributors disclaim any kind of warranty or | ||
|  | liability or suitability for any purpose. By running this software you agree | ||
|  | that you are a competent systems administrator and will bear the responsibility | ||
|  | for your actions. | ||
|  | 
 | ||
|  | Download | ||
|  | 
 | ||
|  | Latest Release: ldap2dns version 0.4.1 | ||
|  | 
 | ||
|  | Released October 19, 2006 | ||
|  | ChangeLog | ||
|  | 
 | ||
|  | 
 | ||
|  | Developer Access: | ||
|  | 
 | ||
|  | The bleeding edge of ldap2dns is in the Alkaloid Networks subversion repository | ||
|  | found at https://svn.alkaloid.net/gpl/ldap2dns/trunk. | ||
|  | 
 | ||
|  | Following the Subversion standard, releases are kept in /gpl/ldap2dns/tags and | ||
|  | branches are in /gpl/ldap2dns/branches. | ||
|  | 
 |