1 Title: What are they searching for - PowerDNS and ISC DHCP in LDAP
2 Tags: english, debian, debian edu, nuug, ldap
6 <a href="http://people.skolelinux.org/pere/blog/Time_for_new__LDAP_schemas_replacing_RFC_2307_.html">followup</a>
8 <a href="http://people.skolelinux.org/pere/blog/Idea_for_a_change_to_LDAP_schemas_allowing_DNS_and_DHCP_info_to_be_combined_into_one_object.html">previous
10 <a href="http://people.skolelinux.org/pere/blog/Combining_PowerDNS_and_ISC_DHCP_LDAP_objects.html">merging
11 all</a> the computer related LDAP objects in Debian Edu.</p>
13 <p>As a step to try to see if it possible to merge the DNS and DHCP
14 LDAP objects, I have had a look at how the packages pdns-backend-ldap
15 and dhcp3-server-ldap in Debian use the LDAP server. The two
16 implementations are quite different in how they use LDAP.</p>
18 To get this information, I started slapd with debugging enabled and
19 dumped the debug output to a file to get the LDAP searches performed
20 on a Debian Edu main-server. Here is a summary.
22 <p><strong>powerdns</strong></p>
24 <a href="http://www.linuxnetworks.de/doc/index.php/PowerDNS_LDAP_Backend">Clues
25 on how to</a> set up PowerDNS to use a LDAP backend is available on
28 <p>PowerDNS have two modes of operation using LDAP as its backend.
29 One "strict" mode where the forward and reverse DNS lookups are done
30 using the same LDAP objects, and a "tree" mode where the forward and
31 reverse entries are in two different subtrees in LDAP with a structure
32 based on the DNS names, as in tjener.intern and
33 2.2.0.10.in-addr.arpa.</p>
35 <p>In tree mode, the server is set up to use a LDAP subtree as its
36 base, and uses a "base" scoped search for the DNS name by adding
37 "dc=tjener,dc=intern," to the base with a filter for
38 "(associateddomain=tjener.intern)" for the forward entry and
39 "dc=2,dc=2,dc=0,dc=10,dc=in-addr,dc=arpa," with a filter for
40 "(associateddomain=2.2.0.10.in-addr.arpa)" for the reverse entry. For
41 forward entries, it is looking for attributes named dnsttl, arecord,
42 nsrecord, cnamerecord, soarecord, ptrrecord, hinforecord, mxrecord,
43 txtrecord, rprecord, afsdbrecord, keyrecord, aaaarecord, locrecord,
44 srvrecord, naptrrecord, kxrecord, certrecord, dsrecord, sshfprecord,
45 ipseckeyrecord, rrsigrecord, nsecrecord, dnskeyrecord, dhcidrecord,
46 spfrecord and modifytimestamp. For reverse entries it is looking for
47 the attributes dnsttl, arecord, nsrecord, cnamerecord, soarecord,
48 ptrrecord, hinforecord, mxrecord, txtrecord, rprecord, aaaarecord,
49 locrecord, srvrecord, naptrrecord and modifytimestamp. The equivalent
50 ldapsearch commands could look like this:</p>
54 -b dc=tjener,dc=intern,ou=hosts,dc=skole,dc=skolelinux,dc=no \
55 -s base -x '(associateddomain=tjener.intern)' dNSTTL aRecord nSRecord \
56 cNAMERecord sOARecord pTRRecord hInfoRecord mXRecord tXTRecord \
57 rPRecord aFSDBRecord KeyRecord aAAARecord lOCRecord sRVRecord \
58 nAPTRRecord kXRecord certRecord dSRecord sSHFPRecord iPSecKeyRecord \
59 rRSIGRecord nSECRecord dNSKeyRecord dHCIDRecord sPFRecord modifyTimestamp
62 -b dc=2,dc=2,dc=0,dc=10,dc=in-addr,dc=arpa,ou=hosts,dc=skole,dc=skolelinux,dc=no \
63 -s base -x '(associateddomain=2.2.0.10.in-addr.arpa)'
64 dnsttl, arecord, nsrecord, cnamerecord soarecord ptrrecord \
65 hinforecord mxrecord txtrecord rprecord aaaarecord locrecord \
66 srvrecord naptrrecord modifytimestamp
69 <p>In Debian Edu/Lenny, the PowerDNS tree mode is used with
70 ou=hosts,dc=skole,dc=skolelinux,dc=no as the base, and these are two
71 example LDAP objects used there. In addition to these objects, the
72 parent objects all th way up to ou=hosts,dc=skole,dc=skolelinux,dc=no
76 dn: dc=tjener,dc=intern,ou=hosts,dc=skole,dc=skolelinux,dc=no
78 objectclass: dnsdomain
79 objectclass: domainrelatedobject
82 associateddomain: tjener.intern
84 dn: dc=2,dc=2,dc=0,dc=10,dc=in-addr,dc=arpa,ou=hosts,dc=skole,dc=skolelinux,dc=no
86 objectclass: dnsdomain2
87 objectclass: domainrelatedobject
89 ptrrecord: tjener.intern
90 associateddomain: 2.2.0.10.in-addr.arpa
93 <p>In strict mode, the server behaves differently. When looking for
94 forward DNS entries, it is doing a "subtree" scoped search with the
95 same base as in the tree mode for a object with filter
96 "(associateddomain=tjener.intern)" and requests the attributes dnsttl,
97 arecord, nsrecord, cnamerecord, soarecord, ptrrecord, hinforecord,
98 mxrecord, txtrecord, rprecord, aaaarecord, locrecord, srvrecord,
99 naptrrecord and modifytimestamp. For reverse entires it also do a
100 subtree scoped search but this time the filter is "(arecord=10.0.2.2)"
101 and the requested attributes are associateddomain, dnsttl and
102 modifytimestamp. In short, in strict mode the objects with ptrrecord
103 go away, and the arecord attribute in the forward object is used
106 <p>The forward and reverse searches can be simulated using ldapsearch
110 ldapsearch -h ldap -b ou=hosts,dc=skole,dc=skolelinux,dc=no -s sub -x \
111 '(associateddomain=tjener.intern)' dNSTTL aRecord nSRecord \
112 cNAMERecord sOARecord pTRRecord hInfoRecord mXRecord tXTRecord \
113 rPRecord aFSDBRecord KeyRecord aAAARecord lOCRecord sRVRecord \
114 nAPTRRecord kXRecord certRecord dSRecord sSHFPRecord iPSecKeyRecord \
115 rRSIGRecord nSECRecord dNSKeyRecord dHCIDRecord sPFRecord modifyTimestamp
117 ldapsearch -h ldap -b ou=hosts,dc=skole,dc=skolelinux,dc=no -s sub -x \
118 '(arecord=10.0.2.2)' associateddomain dnsttl modifytimestamp
121 <p>In addition to the forward and reverse searches , there is also a
122 search for SOA records, which behave similar to the forward and
125 <p>A thing to note with the PowerDNS behaviour is that it do not
126 specify any objectclass names, and instead look for the attributes it
127 need to generate a DNS reply. This make it able to work with any
128 objectclass that provide the needed attributes.</p>
130 <p>The attributes are normally provided in the cosine (RFC 1274) and
131 dnsdomain2 schemas. The latter is used for reverse entries like
132 ptrrecord and recent DNS additions like aaaarecord and srvrecord.</p>
134 <p>In Debian Edu, we have created DNS objects using the object classes
135 dcobject (for dc), dnsdomain or dnsdomain2 (structural, for the DNS
136 attributes) and domainrelatedobject (for associatedDomain). The use
137 of structural object classes make it impossible to combine these
138 classes with the object classes used by DHCP.</p>
140 <p>There are other schemas that could be used too, for example the
141 dnszone structural object class used by Gosa and bind-sdb for the DNS
142 attributes combined with the domainrelatedobject object class, but in
143 this case some unused attributes would have to be included as well
144 (zonename and relativedomainname).</p>
146 <p>My proposal for Debian Edu would be to switch PowerDNS to strict
147 mode and not use any of the existing objectclasses (dnsdomain,
148 dnsdomain2 and dnszone) when one want to combine the DNS information
149 with DHCP information, and instead create a auxiliary object class
150 defined something like this (using the attributes defined for
151 dnsdomain and dnsdomain2 or dnszone):</p>
154 objectclass ( some-oid NAME 'dnsDomainAux'
157 MAY ( ARecord $ MDRecord $ MXRecord $ NSRecord $ SOARecord $ CNAMERecord $
158 DNSTTL $ DNSClass $ PTRRecord $ HINFORecord $ MINFORecord $
159 TXTRecord $ SIGRecord $ KEYRecord $ AAAARecord $ LOCRecord $
160 NXTRecord $ SRVRecord $ NAPTRRecord $ KXRecord $ CERTRecord $
161 A6Record $ DNAMERecord
165 <p>This will allow any object to become a DNS entry when combined with
166 the domainrelatedobject object class, and allow any entity to include
167 all the attributes PowerDNS wants. I've sent an email to the PowerDNS
168 developers asking for their view on this schema and if they are
169 interested in providing such schema with PowerDNS, and I hope my
170 message will be accepted into their mailing list soon.</p>
172 <p><strong>ISC dhcp</strong></p>
174 <p>The DHCP server searches for specific objectclass and requests all
175 the object attributes, and then uses the attributes it want. This
176 make it harder to figure out exactly what attributes are used, but
177 thanks to the working example in Debian Edu I can at least get an idea
178 what is needed without having to read the source code.</p>
180 <p>In the DHCP server configuration, the LDAP base to use and the
181 search filter to use to locate the correct dhcpServer entity is
182 stored. These are the relevant entries from
183 /etc/dhcp3/dhcpd.conf:</p>
186 ldap-base-dn "dc=skole,dc=skolelinux,dc=no";
187 ldap-dhcp-server-cn "dhcp";
190 <p>The DHCP server uses this information to nest all the DHCP
191 configuration it need. The cn "dhcp" is located using the given LDAP
192 base and the filter "(&(objectClass=dhcpServer)(cn=dhcp))". The
193 search result is this entry:</p>
196 dn: cn=dhcp,dc=skole,dc=skolelinux,dc=no
199 objectClass: dhcpServer
200 dhcpServiceDN: cn=DHCP Config,dc=skole,dc=skolelinux,dc=no
203 <p>The content of the dhcpServiceDN attribute is next used to locate the
204 subtree with DHCP configuration. The DHCP configuration subtree base
205 is located using a base scope search with base "cn=DHCP
206 Config,dc=skole,dc=skolelinux,dc=no" and filter
207 "(&(objectClass=dhcpService)(|(dhcpPrimaryDN=cn=dhcp,dc=skole,dc=skolelinux,dc=no)(dhcpSecondaryDN=cn=dhcp,dc=skole,dc=skolelinux,dc=no)))".
208 The search result is this entry:</p>
211 dn: cn=DHCP Config,dc=skole,dc=skolelinux,dc=no
214 objectClass: dhcpService
215 objectClass: dhcpOptions
216 dhcpPrimaryDN: cn=dhcp, dc=skole,dc=skolelinux,dc=no
217 dhcpStatements: ddns-update-style none
218 dhcpStatements: authoritative
219 dhcpOption: smtp-server code 69 = array of ip-address
220 dhcpOption: www-server code 72 = array of ip-address
221 dhcpOption: wpad-url code 252 = text
224 <p>Next, the entire subtree is processed, one level at the time. When
225 all the DHCP configuration is loaded, it is ready to receive requests.
226 The subtree in Debian Edu contain objects with object classes
227 top/dhcpService/dhcpOptions, top/dhcpSharedNetwork/dhcpOptions,
228 top/dhcpSubnet, top/dhcpGroup and top/dhcpHost. These provide options
229 and information about netmasks, dynamic range etc. Leaving out the
230 details here because it is not relevant for the focus of my
231 investigation, which is to see if it is possible to merge dns and dhcp
232 related computer objects.</p>
234 <p>When a DHCP request come in, LDAP is searched for the MAC address
235 of the client (00:00:00:00:00:00 in this example), using a subtree
236 scoped search with "cn=DHCP Config,dc=skole,dc=skolelinux,dc=no" as
237 the base and "(&(objectClass=dhcpHost)(dhcpHWAddress=ethernet
238 00:00:00:00:00:00))" as the filter. This is what a host object look
242 dn: cn=hostname,cn=group1,cn=THINCLIENTS,cn=DHCP Config,dc=skole,dc=skolelinux,dc=no
245 objectClass: dhcpHost
246 dhcpHWAddress: ethernet 00:00:00:00:00:00
247 dhcpStatements: fixed-address hostname
250 <p>There is less flexiblity in the way LDAP searches are done here.
251 The object classes need to have fixed names, and the configuration
252 need to be stored in a fairly specific LDAP structure. On the
253 positive side, the invidiual dhcpHost entires can be anywhere without
254 the DN pointed to by the dhcpServer entries. The latter should make
255 it possible to group all host entries in a subtree next to the
256 configuration entries, and this subtree can also be shared with the
257 DNS server if the schema proposed above is combined with the dhcpHost
258 structural object class.
260 <p><strong>Conclusion</strong></p>
262 <p>The PowerDNS implementation seem to be very flexible when it come
263 to which LDAP schemas to use. While its "tree" mode is rigid when it
264 come to the the LDAP structure, the "strict" mode is very flexible,
265 allowing DNS objects to be stored anywhere under the base cn specified
266 in the configuration.</p>
268 <p>The DHCP implementation on the other hand is very inflexible, both
269 regarding which LDAP schemas to use and which LDAP structure to use.
270 I guess one could implement ones own schema, as long as the
271 objectclasses and attributes have the names used, but this do not
272 really help when the DHCP subtree need to have a fairly fixed
275 <p>Based on the observed behaviour, I suspect a LDAP structure like
276 this might work for Debian Edu:</p>
280 cn=machine-info (dhcpService) - dhcpServiceDN points here
282 cn=dhcp-internal (dhcpSharedNetwork/dhcpOptions)
283 cn=10.0.2.0 (dhcpSubnet)
284 cn=group1 (dhcpGroup/dhcpOptions)
285 cn=dhcp-thinclients (dhcpSharedNetwork/dhcpOptions)
286 cn=192.168.0.0 (dhcpSubnet)
287 cn=group1 (dhcpGroup/dhcpOptions)
288 ou=machines - PowerDNS base points here
289 cn=hostname (dhcpHost/domainrelatedobject/dnsDomainAux)
292 <P>This is not tested yet. If the DHCP server require the dhcpHost
293 entries to be in the dhcpGroup subtrees, the entries can be stored
294 there instead of a common machines subtree, and the PowerDNS base
295 would have to be moved one level up to the machine-info subtree.</p>
297 <p>The combined object under the machines subtree would look something
301 dn: dc=hostname,ou=machines,cn=machine-info,dc=skole,dc=skolelinux,dc=no
304 objectClass: dhcpHost
305 objectclass: domainrelatedobject
306 objectclass: dnsDomainAux
307 associateddomain: hostname.intern
309 dhcpHWAddress: ethernet 00:00:00:00:00:00
310 dhcpStatements: fixed-address hostname.intern
313 </p>One could even add the LTSP configuration associated with a given
314 machine, as long as the required attributes are available in a
315 auxiliary object class.</p>