DNS Server bind mit Zonen in LDAP via bind-dlz
Das Thema beschäftigt mich schon länger. Wie kann ich meine DNS-Verwaltung im LDAP abbilden? Dazu gibt es grundsätzlich mehrere Möglichkeiten, wie ich herausfand.
Eine Lösung ist einen anderen DNS-Server als bind zu benutzen, welcher ein LDAP-Backend hat. Hier seien powerDNS und ldapdns genannt. Ersterer hat mir einen zu komerziellen Hauch, Letzterer macht einen zu schmalen Eindruck.
Ich bleibe also bei bind9. Es gibt ein LDAP-sdb-Backend für bind9, welches allerdings das patchen von bind9 verlangt. Die Beispiele des alten Maintainers und das LDAP-Schema sind recht nett. Auf eine weitere Möglichkeit wies mich Jan-Piet Mens hin. Bind DLZ (dynamic loadable zones) ist eine API, die verschiedenste Datenquellen für bind9 ermöglicht. Neben der orginalen Berkley DB kann der Treiber auch Mysql, PostgreSQL und LDAP. Das DLZ-Schema ist eine wenig gewöhnungsbedürftig, funktioniert aber.
Nach der Installation von bind9 auf ubuntu hardy per apt-get stellte ich fest, dass dort keine dlz-zones einkompiliert sind. Also eben apt-get source gemacht und in debian/rules die ./configure optionen eingetragen. Das sah dann so aus:
apt-get source bind9
cd bind9-9.4.2
vi debian/rules
–enable-ipv6 \
–with-dlz-ldap=yes
Später stellte sich noch heraus, dass die ldap 2.4.7 API sich verändert hat. Der sogenannte %-Bug kann dann gleich mit erledigt werden. Dafür in die Datei contrib/dlz/drivers/sdlz_helper.c um Zeile 168 das % ind ein $ verändern. Dank an Jen-Piet Mens für die schnelle Hilfe. In den nächsten Ubuntu-Versionen sollte das nicht mehr vorkommen - der Bug 227344 wurde beseitigt.
Nun das neue .deb Paket zusammenbauen und installieren.
dpkg-buildpackage
dpkg -i ../bind9_9.4.2-10_i386.deb
Nun kann bind in seiner Konfiguration LDAP-Zonen verarbeiten. Dazu hab ich lediglich das Beispiel für meine Zwecke angepasst. Auf Zeilenumbrüche reagiert der dlz-Treiber recht eigensinnig. Deshalb immer prüfen, ob die Anzahl der Parameter aka Zeilen wirklich stimmt. Man beachte den Unterschied von % und $ im Vergleich zum dlz-LDAP-Beispiel. Die leeren Zeilen und die Einrückungen müssen natürlich entfernt werden.
dlz “ldap zone” {
database “ldap 1
v3 simple {cn=admin,<ldap-bind-dn>} {<secret>} {}
ldap:///dlzZoneName=$zone$,ou=dns,<ldap-bind-dn>???objectclass=dlzZone
ldap:///dlzHostName=$record$,dlzZoneName=$zone$,ou=dns,<ldap-bind-dn>?
dlzTTL,dlzType,dlzPreference,dlzData,dlzIPAddr,
dlzPrimaryNS,dlzAdminEmail,dlzSerial,dlzRefresh,dlzRetry,dlzExpire,
dlzMinimum?sub?(&(objectclass=dlzAbstractRecord)(!(dlzType=soa)))ldap:///dlzHostName=@,dlzZoneName=$zone$,ou=dns,<ldap-bind-dn>?
dlzTTL,dlzType,dlzData,dlzPrimaryNS,
dlzAdminEmail,dlzSerial,dlzRefresh,dlzRetry,dlzExpire,
dlzMinimum?sub?(&(objectclass=dlzAbstractRecord)(dlzType=soa))ldap:///dlzZoneName=$zone$,ou=dns,<ldap-bind-dn>?
dlzTTL,dlzType,dlzHostName,dlzPreference,dlzData,
dlzIPAddr,dlzPrimaryNS,dlzAdminEmail,dlzSerial,dlzRefresh,dlzRetry,
dlzExpire,dlzMinimum?sub?(&(objectclass=dlzAbstractRecord)(!(dlzType=soa)))ldap:///dlzZoneName=$zone$,ou=dns,<ldap-bind-dn>??sub?
(&(objectclass=dlzXFR)(dlzIPAddr=$client$))”;
};
Nach dem Neustart von bind sollte im Log das erfolgreiche Laden der Zone vermerkt sein
named[14557]: Loading ‘ldap zone’ using driver ldap
Sollte das nicht der Fall sein, dann sind mit 99,9% die Leerzeichen, Zeilenumbrüche oder Verbindungsdaten falsch.
Nun braucht der LDAP-Server noch das DLZ-Schema ein ein paar Einträge. Als minimal gilt folgendes LDIF:
dn: ou=dns,<ldap-bind-dn>
objectClass: organizationalUnit
objectClass: top
ou: dnsdn: dlzZoneName=zone.intern,ou=dns,<ldap-bind-dn>
objectClass: dlzZone
objectClass: top
dlzZoneName: zone.interndn: dlzHostName=@,dlzZoneName=zone.intern,ou=dns,<ldap-bind-dn>
objectClass: dlzHost
objectClass: top
dlzHostName: @dn: dlzRecordID=1,dlzHostName=@,dlzZoneName=zone.intern,ou=dns,<ldap-bind-dn>
dlzTTL: 10
dlzExpire: 604800
dlzRefresh: 2800
dlzMinimum: 86400
dlzAdminEmail: it.zone.de.
objectClass: dlzSOARecord
objectClass: dlzAbstractRecord
objectClass: top
dlzRecordID: 1
dlzSerial: 2008022801
dlzType: soa
dlzHostName: @
dlzRetry: 7200dn: dlzRecordID=2,dlzHostName=@,dlzZoneName=zone.intern,ou=dns,<ldap-bind-dn>
dlzRecordID: 2
objectClass: dlzNSRecord
objectClass: dlzGenericRecord
objectClass: dlzAbstractRecord
objectClass: top
dlzTTL: 10
dlzType: ns
dlzHostName: @
dlzData: pridns.zone.intern.dn: dlzHostName=pridns,dlzZoneName=zone.intern,ou=dns,<ldap-bind-dn>
objectClass: dlzHost
objectClass: top
dlzHostName: pridnsdn: dlzRecordID=1,dlzHostName=pridns,dlzZoneName=zone.intern,ou=dns,<ldap-bind-dn>
dlzIPAddr: 192.168.1.1
dlzRecordID: 1
objectClass: dlzARecord
objectClass: dlzAbstractRecord
objectClass: top
dlzTTL: 3600
dlzType: A
dlzHostName: pridns
Wenn alles gut geht, dann sollte der Nameserver nun funktionieren. Beim testen mit host sollte die IP 192.168.1.1 zurückkommen.
host pridns.zone.intern localhost
Et Voilà - der bind am LDAP ist fertig.