Viper - install, step 2/6 - dhcp notes


DHCP server configuration, /etc/dhcp3/dhcpd.conf

DHCP server should support LDAP backend. In Debian, this exists as a package dhcp3-server-ldap.

Then, the dhcp server should be configured simply like this in /etc/dhcp3/dhcpd.conf:
ldap-username "cn=dhcpd,ou=dhcp";
ldap-password "blah"
ldap-port 389;
ldap-base-dn "ou=dhcp";
ldap-method dynamic;
ldap-debug-file "/var/log/dhcp-ldap-startup.log";
ldap-ssl off;

# Standard dhcp options
default-lease-time 36000;
max-lease-time 95000;
authoritative;

Restarting dhcp server

LDAP-enabled DHCP server works by getting configuration pieces from LDAP, forming valid configuration blocks, and sending them to DHCP's standard config parser functions. Therefore, configuration coming from LDAP passes all the same configuration checks as verbatim dhcpd.conf configuration.

So keep an eye on syslog (sudo tail -f /var/log/syslog) and you'll spot all errors there. If basic parsing succeeds and there's no syntactical error in the configuration, DHCP will try to start. /var/log/dhcp-ldap-startup.log will contain the startup configuration in text form, and you can look it up to spot any other errors.

DHCP operation

Thanks to option ldap-method dynamic; in dhcpd.conf, DHCP will query LDAP for every request on the fly. In debug level 256, slapd would report the following about the request:

conn=14 op=35 SRCH base="ou=dhcp" scope=2 deref=0 filter="(&(objectClass=dhcpHost)(dhcpHWAddress=ethernet 00:11:6c:34:ae:8a))"
conn=14 op=35 SEARCH RESULT tag=101 err=0 nentries=1 text=
conn=14 op=36 SRCH base="o=c1.com,ou=clients" scope=2 deref=0 filter="(&(cn=hosts)(objectClass=dhcpGroup))"
conn=14 op=36 SEARCH RESULT tag=101 err=0 nentries=0 text=

From the output, you can see that DHCP asked for subtree (scope=2) search in base ou=dhcp, looking for anything that matches the specified filter "(&(objectClass=dhcpHost)(dhcpHWAddress=ethernet 00:11:6c:34:ae:8a))".

DHCP server issues specific queries and expects to find DHCP data in a specific format (according to logic in the dhcp/ldap patch and visible in dhcp.schema file). But we do not want to keep data in that format, as it is basically a duplication of data that we already keep for a host (MAC address, IP address, network params etc.). We also don't want to keep data ONLY in DHCP format as that makes them unusable for other purposes, and we surely don't want to modify the C code for LDAP support in DHCP.

So, we let DHCP perform LDAP queries as it usually would, under LDAP tree ou=dhcp. ou=dhcp is a suffix configured in slapd.conf, intended specifically to receive requests from the ISC DHCP server. This suffix in our LDAP configuration uses rewrite rules and other magic to transform incoming requests to appropriate form. Another set of rules then operates on the entries found to produce the complete record that will be returned to DHCP. (All of this possible thanks to our Viper backend for slapd).

The appropriate configuration for ou=dhcp in slapd.conf can be found below.

Anyway, there should be only one entry found and returned from the dhcp's HWAddress search, just as seen in the SEARCH RESULT line  above (nentries/number of entries=1). The other query for dhcpGroup is irrelevant and can return no results (nentries=0).

DHCP will receive the data, find it in the format expected, parse it and send to the client, leaving a note about it in syslog:

dhcpd: Sending the following options: 'fixed-address 10.0.1.6;#012option host-name "h6";#012option routers 10.0.1.1;#012option domain-name-servers 192.168.1.254;#012option nis-domain "c1.com";#012option domain-name "c1.com";#012option subnet-mask 255.255.255.0;#012option broadcast-address 10.0.1.255;#012'

LDAP server configuration, suffix ou=dhcp, in /etc/ldap/slapd.conf

As mentioned earlier, ou=dhcp needs to be a suffix configured in slapd.conf and containing rules for query rewriting etc. Without further ado, here's the configuration with inline comments.

(The configuration shown here is just explanatory example, it requires data from a suffix configured before ou=dhcp (which is not shown), and is not guaranteed to be up to date. For a working slapd.conf and all instructions, see ldap.html.)

########################################################################
#
# DHCP     - configure ou=dhcp tree which is intended to be used by
#            the ISC DHCP3 server with LDAP support. The real data is
#            kept under ou=clients, not here, so to produce the correct
#            information expected by DHCP, this suffix sports some dynamic
#            rewriting, substitution and append magic.
#
########################################################################

database           perl
suffix             "ou=dhcp"
perlModulePath     "/root/debconf-backend"
perlModule         "Viper"
directory          "/var/lib/ldap/viper/"
treesuffix         "ou=dhcp"

load               default_opts

reset
# Must-match/Must-not-match regexes that must match and not-match a DN
# respectively to have expandVal overlay run on the entry's attributes.
# This value is a match-all setting, and it is included here because any
# overlay with no config lines is essentially disabled.
expandVal          .   ^$

# Must-match/Must-not-match regexes that must match and not-match a DN
# respectively to have fileVal overlay run on the entry's attributes.
fileVal            .   ^$

# Must-match/Must-not-match regexes that must match and not-match a DN
# respectively to have findVal overlay run on the entry's attributes.
findVal            .   ^$

save               dynamic_opts
reset

# Overlays can accept options, specified directly in overlay calls, or
# here, where both global and per-overlay defaults can be set.
#
# Here we specify default overlay cache time. Caching is used to speed up
# costly overlay evaluations which may happen a significant number of times
# during even a single operation.
# Cache expiry specification is the same as explained in cacheRead, and
# 1o is again overall best setting.
# While cacheRead gives noticeable (but small) speedup, caching overlay
# results here gives enormous performance boost.
overlayConfig      default   cache 1o
#overlayConfig      exp   cache 5m

save               cache_opts

# searchSubst matches a series of input search parameters. If all listed
# parameters match, a rewrite of any search params can be made. The list
# of conditions and the list of rewrites to be made are separated by '->'.
# Note: the following example completely substitutes the search base, it
# moves search from ou=dhcp to ou=clients on the same level, which would
# not be accessible without a rewrite (it's technically a different suffix).
# Also, note that THIS suffix' settings apply to the search, even if the
# search is rewritten to a tree that belongs to another suffix.
# (This property also allows having different views of the same data by
# simply configuring different suffixes with different options, under the
# same base directory).
#
# Solve lack of flexibility in ISC DHCP3 LDAP patch by plainly specifying
# ldap-base-dn "ou=dhcp" in DHCP's config, and then here, rewriting DHCP
# ethernet address lookup to the ou=clients tree under which all clients
# are defined.
searchSubst        base        "^ou=dhcp$"                       \
                   filter      "^\\(&\\(objectClass=dhcpHost\\)\\(dhcpHWAddress=ethernet [\\dabcdef:]+\\)\\)$" \
                   ->                                            \
                   base   .+   ou=clients

# Solve lack of flexibility in ISC DHCP3 LDAP patch by rewriting a search
# in any shared network, tree ou=dhcp, to a proper location,
searchSubst        base        "^ou=\\w+,ou=dhcp$"                \
                   scope       "^1$"                             \
                   filter      "^\\(objectClass=\\*\\)$"         \
                   ->                                            \
                   base   .+   "ou=clients"                      \
                   filter .+   "(&(objectClass=dhcpSubnet)(!(cn=default)))" \
                   scope  .+   2

reset

# entryAppend appends entries with attributes from other entries.
# Match can be made on any attribute/value pair of the original entry
# (in our examples, we match on objectClass and dn).
# Append source can be specified in place (first two examples), or indirectly
# through an attribute in the existing entry (third example).
entryAppend        objectClass "^dhcpHost$"                      \
                   ->                                            \
                   append .+ cn=dhcpHost,ou=objectClasses,ou=defaults

entryAppend        objectClass "^dhcpSubnet$"                    \
                   ->                                            \
                   append .+ cn=dhcpSubnet,ou=objectClasses,ou=defaults

entryAppend        dn          "^cn=default,ou=networks"         \
                   objectClass "^ipNetwork$"                     \
                   ->                                            \
                   attr seeAlso

save               dhcp_opts