I’m using Microsoft Active Directory in my Lab for most of the tasks, like user authentication, DNS services, and DHCP. The windows VM is getting bigger and bigger so I decided to switch to Linux. The goal is, to have my user directory, my DNS zones and DHCP subnets managed in OpenLDAP. This post shows the steps to reach this goal and how to switch from Active Directory to OpenLDAP.
First of all. I’m not an OpenLDAP expert, so everything covered in this post is working for my lab. It is not tuned or optimized.
I use the latest Debian version for my Lab server. For other distributions, the steps might differ. But the concept is still the same.
Install OpenLDAP and Configure the Basics
I assume, that the base OS is installed. I use the latest version as of today:
root@devil:~# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 9 (stretch)"
NAME="Debian GNU/Linux"
VERSION_ID="9"
VERSION="9 (stretch)"
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
To install OpenLDAP I followed the Debian wiki here:
https://wiki.debian.org/LDAP/OpenLDAPSetup
So the first step is to install OpenLDAP on the system:
# apt install slapd ldap-utils ldapscripts
During the installation, the system asks you for the “Administrator Password”. This is the root password for LDAP. So keep it safe and secure.
To create an initial configuration for OpenLDAP use this command:
dpkg-reconfigure -plow slapd
Answer the first question with no:
Omit OpenLDAP server configuration?
Next, the system will grab your DNS name to build the base dn. If the DNS name is not correct, replace the string with the correct DNS name.
You will now be asked for the organization name. It might be the same as the DNS name, but without the .tld part.
You need to enter a new admin password.
Choose MDB as the backend.
As this is a new install, I let the setup remove the database. so the answer is yes, to this question:
Do you want the database to be removed when slapd is purged?
Answer the next question with yes again:
Move old database?
Afterward, the setup creates all the needed files and configurations and you are done. OpenLDAP is installed.
As adviced in the Debian Wiki, I also added the additional indexes to OpenLDAP. Just create a file “indexes.ldif” with the following content:
dn: olcDatabase={1}mdb,cn=config
changetype: modify
replace: olcDbIndex
olcDbIndex: cn pres,sub,eq
-
add: olcDbIndex
olcDbIndex: sn pres,sub,eq
-
add: olcDbIndex
olcDbIndex: uid pres,sub,eq
-
add: olcDbIndex
olcDbIndex: displayName pres,sub,eq
-
add: olcDbIndex
olcDbIndex: default sub
-
add: olcDbIndex
olcDbIndex: uidNumber eq
-
add: olcDbIndex
olcDbIndex: gidNumber eq
-
add: olcDbIndex
olcDbIndex: mail,givenName eq,subinitial
-
add: olcDbIndex
olcDbIndex: dc eq
Make sure, that the database type matches the one you choose during initial setup.
Afterward, you can apply the indexes to OpenLDAP with this command:
# ldapmodify -Y EXTERNAL -H ldapi:/// -f indexes.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "olcDatabase={1}mdb,cn=config"
To check, if the new indexes are applied, use this command:
# ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" -W olcDatabase={1}mdb olcDbIndex
Enter LDAP Password:
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
# extended LDIF
#
# LDAPv3
# base <cn=config> with scope subtree
# filter: olcDatabase={1}mdb
# requesting: olcDbIndex
#
# {1}mdb, config
dn: olcDatabase={1}mdb,cn=config
olcDbIndex: cn pres,sub,eq
olcDbIndex: sn pres,sub,eq
olcDbIndex: uid pres,sub,eq
olcDbIndex: displayName pres,sub,eq
olcDbIndex: default sub
olcDbIndex: uidNumber eq
olcDbIndex: gidNumber eq
olcDbIndex: mail,givenName eq,subinitial
olcDbIndex: dc eq
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1
The system will ask for a password, but as you are on the localhost, you do not need a password.
You can now start to deploy users and groups.
There are plenty of documents on the web, who shows how to structure an LDAP directory. So I will not cover this here, but here are some good links:
- https://www.pks.mpg.de/~mueller/docs/suse10.1/suselinux-manual_en/manual/sec.ldap.tree.html
- https://www.skills-1st.co.uk/papers/ldap-schema-design-feb-2005/ldap-schema-design-feb-2005.html
My structure is as follows, but remember, this is for a lab environment (and for my home use):
On the second level, I have inserted another layer to separate my users and groups from the services like DHCP and DNS.
The first part was the easy one, lets start to integrate DHCP and DNS. It took me several weeks to figure this out.
OpenLDAP: Integrate Bind
My main goal is not performance but easy change. So I wanted to have one database for all and searched for a way to integrate Bind (my DNS server) into my OpenLDAP server. The following part shows how I did it. Bind9 can use OpenLDAP to store data for DNS zones. Other configurations like forwarders are still in the Bind config file.
First of all, you need to install the OpenLDAP extension for Bind:
# apt-get install bind9-dyndb-ldap
If you have Bind already installed, this only adds the extension. If you haven’t, this will also install Bind.
After that, you need to add the Bind schema to your OpenLDAP server. The package includes a schema file here:
/usr/share/doc/bind9-dyndb-ldap/schema.ldif.gz
But this schema file was not working for me, so I changed the schema file to this one:
# cat bind9.schema.ldif
# This schema contains OIDs from Uninett and FreeIPA.
#
# Unninet: http://drift.uninett.no/nett/ip-nett/dnsattributes.schema
# Base OID for DNS records is 1.3.6.1.4.1.2428.20.1,
# see http://drift.uninett.no/nett/ip-nett/oids.html
#
# FreeIPA: http://freeipa.org/
# Base OID for DNS records is 2.16.840.1.113730.3.8.5
# Base OID for DNS objectClasses is 2.16.840.1.113730.3.8.6
#
# If you want to add some record types that are defined by IANA,
# please define it similar to what is done for the existing ones. The
# name should be {TYPE}Record, and OID should be
# 1.3.6.1.4.1.2428.20.1.value. For instance the RR type LOC has value
# 29, so attribute name should be LocRecord (casing shouldn't matter),
# and the OID is 1.3.6.1.4.1.2428.20.1.29. If you follow this, you
# know that it will be compatible with what others use, and one is
# guaranteed that the OIDs are unique.
# The IANA DNS record type values are available from
# .
#
# If you define new attributes, please report them to [email protected]
# to get them added of this schema.
#
# The basic record types like A, CNAME etc are defined in the cosine
# schema and not by UNINETT or FreeIPA. This means that your LDAP server
# should use the old COSINE schema (RFC 1274) plus this one to get
# all the DNS attributes defined.
#
# Alternativelly you can use included excerpt from COSINE schema to get all
# the missing attributes.
#
#
# 389 DS requires following DN
#dn: cn=schema
#
# OpenLDAP 2.4 requires following DN + objectClass + different attribute names
# s/^olcAttributeTypes:/olcAttributeTypes:/
# s/^olcObjectClasses:/olcObjectClasses:/
dn: cn=dns,cn=schema,cn=config
objectClass: olcSchemaConfig
#
#
# COSINE schema
# comment out if your server has COSINE schema installed
#olcAttributeTypes: ( 0.9.2342.19200300.100.1.26
# NAME 'aRecord'
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
# EQUALITY caseIgnoreIA5Match )
#
#olcAttributeTypes: ( 0.9.2342.19200300.100.1.27
# NAME 'mDRecord'
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
# EQUALITY caseIgnoreIA5Match )
#
#olcAttributeTypes: ( 0.9.2342.19200300.100.1.28
# NAME 'mXRecord'
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
# EQUALITY caseIgnoreIA5Match )
#
#olcAttributeTypes: ( 0.9.2342.19200300.100.1.29
# NAME 'nSRecord'
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
# EQUALITY caseIgnoreIA5Match )
# CNAME record was originally defined as multi-value
# but we redefined it as single-value to conform with RFC 2136, section 1.1.5.
#olcAttributeTypes: ( 0.9.2342.19200300.100.1.31
# NAME 'cNAMERecord'
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
# EQUALITY caseIgnoreIA5Match
# SINGLE-VALUE )
#
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.0.0
NAME 'dNSTTL'
DESC 'An integer denoting time to live'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
EQUALITY integerMatch )
#
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.0.2
NAME 'dNSdefaultTTL'
DESC 'An integer denoting default time to live, RFC 2308'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
EQUALITY integerMatch
ORDERING integerOrderingMatch )
#
#
# UNINETT and FreeIPA attributes
# dnsClass attribute is in fact unsupported by bind-dyndb-ldap
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.0.1
NAME 'dNSClass'
DESC 'The class of a resource record'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match )
#
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.1.12
NAME 'pTRRecord'
DESC 'domain name pointer, RFC 1035'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch )
#
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.1.13
NAME 'hInfoRecord'
DESC 'host information, RFC 1035'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch )
#
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.1.14
NAME 'mInfoRecord'
DESC 'mailbox or mail list information, RFC 1035'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch )
#
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.1.16
NAME 'tXTRecord'
DESC 'text string, RFC 1035'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch )
#
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.1.18
NAME 'aFSDBRecord'
DESC 'for AFS Data Base location, RFC 1183'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch )
#
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.1.28
NAME 'aAAARecord'
DESC 'IPv6 address, RFC 1886'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch )
#
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.1.29
NAME 'LocRecord'
DESC 'Location, RFC 1876'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch )
#
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.1.30
NAME 'nXTRecord'
DESC 'non-existant, RFC 2535'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch )
#
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.1.33
NAME 'sRVRecord'
DESC 'service location, RFC 2782'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch )
#
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.1.35
NAME 'nAPTRRecord'
DESC 'Naming Authority Pointer, RFC 2915'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch )
#
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.1.36
NAME 'kXRecord'
DESC 'Key Exchange Delegation, RFC 2230'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch )
#
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.1.37
NAME 'certRecord'
DESC 'certificate, RFC 2538'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch )
#
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.1.38
NAME 'a6Record'
DESC 'A6 Record Type, RFC 2874'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch )
#
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.1.39
NAME 'dNameRecord'
DESC 'Non-Terminal DNS Name Redirection, RFC 6672'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SINGLE-VALUE )
#
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.1.43
NAME 'dSRecord'
DESC 'Delegation Signer, RFC 3658'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch )
#
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.1.44
NAME 'sSHFPRecord'
DESC 'SSH Key Fingerprint, draft-ietf-secsh-dns-05.txt'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch )
#
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.1.51
NAME 'nSEC3PARAMRecord'
DESC 'RFC 5155'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SINGLE-VALUE )
#
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.1.52 NAME 'TLSARecord'
DESC 'DNS-Based Authentication of Named Entities - Transport Layer Security Protocol, RFC 6698'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch )
#
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.1.32769
NAME 'DLVRecord'
DESC 'RFC 4431: DNSSEC Lookaside Validation'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch )
#
# See https://fedorahosted.org/bind-dyndb-ldap/wiki/Design/UnknownRecord
olcAttributeTypes: ( 1.3.6.1.4.1.2428.20.4
NAME 'UnknownRecord'
DESC 'unknown DNS record, RFC 3597'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch )
#
olcAttributeTypes: ( 2.16.840.1.113730.3.8.5.0
NAME 'idnsName'
DESC 'DNS FQDN'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SINGLE-VALUE )
#
olcAttributeTypes: ( 2.16.840.1.113730.3.8.5.1
NAME 'idnsAllowDynUpdate'
DESC 'permit dynamic updates on this zone'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
EQUALITY booleanMatch
SINGLE-VALUE )
#
olcAttributeTypes: ( 2.16.840.1.113730.3.8.5.2
NAME 'idnsZoneActive'
DESC 'define if the zone is considered in use'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
EQUALITY booleanMatch
SINGLE-VALUE )
#
olcAttributeTypes: ( 2.16.840.1.113730.3.8.5.3
NAME 'idnsSOAmName'
DESC 'SOA Name'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SINGLE-VALUE )
#
olcAttributeTypes: ( 2.16.840.1.113730.3.8.5.4
NAME 'idnsSOArName'
DESC 'SOA root Name'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SINGLE-VALUE )
#
olcAttributeTypes: ( 2.16.840.1.113730.3.8.5.5
NAME 'idnsSOAserial'
DESC 'SOA serial number'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.36
EQUALITY numericStringMatch
SINGLE-VALUE )
#
olcAttributeTypes: ( 2.16.840.1.113730.3.8.5.6
NAME 'idnsSOArefresh'
DESC 'SOA refresh value'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.36
EQUALITY numericStringMatch
SINGLE-VALUE )
#
olcAttributeTypes: ( 2.16.840.1.113730.3.8.5.7
NAME 'idnsSOAretry'
DESC 'SOA retry value'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.36
EQUALITY numericStringMatch
SINGLE-VALUE )
#
olcAttributeTypes: ( 2.16.840.1.113730.3.8.5.8
NAME 'idnsSOAexpire'
DESC 'SOA expire value'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.36
EQUALITY numericStringMatch
SINGLE-VALUE )
#
olcAttributeTypes: ( 2.16.840.1.113730.3.8.5.9
NAME 'idnsSOAminimum'
DESC 'SOA minimum value'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.36
EQUALITY numericStringMatch
SINGLE-VALUE )
#
olcAttributeTypes: ( 2.16.840.1.113730.3.8.5.10
NAME 'idnsUpdatePolicy'
DESC 'DNS dynamic updates policy'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SINGLE-VALUE )
#
olcAttributeTypes: ( 2.16.840.1.113730.3.8.5.11
NAME 'idnsAllowQuery'
DESC 'BIND9 allow-query ACL element'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SINGLE-VALUE )
#
olcAttributeTypes: ( 2.16.840.1.113730.3.8.5.12
NAME 'idnsAllowTransfer'
DESC 'BIND9 allow-transfer ACL element'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SINGLE-VALUE )
#
olcAttributeTypes: ( 2.16.840.1.113730.3.8.5.13
NAME 'idnsAllowSyncPTR'
DESC 'permit synchronization of PTR records'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
EQUALITY booleanMatch
SINGLE-VALUE )
#
olcAttributeTypes: ( 2.16.840.1.113730.3.8.5.14
NAME 'idnsForwardPolicy'
DESC 'forward policy: only or first'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SINGLE-VALUE )
#
olcAttributeTypes: ( 2.16.840.1.113730.3.8.5.15
NAME 'idnsForwarders'
DESC 'list of forwarders'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch )
#
olcAttributeTypes: ( 2.16.840.1.113730.3.8.5.18
NAME 'idnsSecInlineSigning'
DESC 'DNSSEC in-line signing'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
EQUALITY booleanMatch
SINGLE-VALUE )
#
olcAttributeTypes: ( 2.16.840.1.113730.3.8.5.31
NAME 'idnsServerId'
DESC 'DNS server identifier'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
EQUALITY caseIgnoreMatch
SINGLE-VALUE )
#
olcAttributeTypes: ( 2.16.840.1.113730.3.8.5.30
NAME 'idnsSubstitutionVariable'
DESC 'User defined variable for DNS plugin'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match )
#
olcAttributeTypes: ( 2.16.840.1.113730.3.8.5.29
NAME 'idnsTemplateAttribute'
DESC 'Template attribute for dynamic attribute generation'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
EQUALITY caseIgnoreIA5Match )
#
olcObjectClasses: ( 2.16.840.1.113730.3.8.6.0
NAME 'idnsRecord'
DESC 'dns Record, usually a host'
SUP top
STRUCTURAL
MUST idnsName
MAY ( cn $ idnsAllowDynUpdate $ DNSTTL $ DNSClass $ ARecord $
AAAARecord $ A6Record $ NSRecord $ CNAMERecord $ PTRRecord $
SRVRecord $ TXTRecord $ MXRecord $ MDRecord $ HINFORecord $
MINFORecord $ AFSDBRecord $ LOCRecord $
NXTRecord $ NAPTRRecord $ KXRecord $ CERTRecord $ DNAMERecord $
DSRecord $ SSHFPRecord $ DLVRecord $ TLSARecord $ UnknownRecord
) )
#
olcObjectClasses: ( 2.16.840.1.113730.3.8.6.1
NAME 'idnsZone'
DESC 'Zone class'
SUP idnsRecord
STRUCTURAL
MUST ( idnsName $ idnsZoneActive $ idnsSOAmName $ idnsSOArName $
idnsSOAserial $ idnsSOArefresh $ idnsSOAretry $ idnsSOAexpire $
idnsSOAminimum
)
MAY ( idnsUpdatePolicy $ idnsAllowQuery $ idnsAllowTransfer $
idnsAllowSyncPTR $ idnsForwardPolicy $ idnsForwarders $
idnsSecInlineSigning $ nSEC3PARAMRecord $ dNSdefaultTTL
) )
#
olcObjectClasses: ( 2.16.840.1.113730.3.8.6.2
NAME 'idnsConfigObject'
DESC 'DNS global config options'
STRUCTURAL
MAY ( idnsForwardPolicy $ idnsForwarders $ idnsAllowSyncPTR ) )
#
olcObjectClasses: ( 2.16.840.1.113730.3.8.6.3
NAME 'idnsForwardZone'
DESC 'Forward Zone class'
SUP top
STRUCTURAL
MUST ( idnsName $ idnsZoneActive )
MAY ( idnsForwarders $ idnsForwardPolicy ) )
#
olcObjectClasses: ( 2.16.840.1.113730.3.8.6.6
NAME 'idnsServerConfigObject'
DESC 'DNS server configuration'
SUP top
STRUCTURAL
MUST ( idnsServerId )
MAY ( idnsSOAmName $ idnsForwarders $ idnsForwardPolicy $
idnsSubstitutionVariable
) )
#
olcObjectClasses: ( 2.16.840.1.113730.3.8.6.5
NAME 'idnsTemplateObject'
DESC 'Template object for dynamic DNS attribute generation'
SUP top
AUXILIARY
MUST ( idnsTemplateAttribute ) )
To add this schema to OpenLDAP I use the following command:
# ldapadd -Y EXTERNAL -H ldapi:/// -f bind9.schema.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry "cn=dns,cn=schema,cn=config"
To check, if the new schema is available just search for it:
# ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b cn=schema,cn=config cn
dn: cn=schema,cn=config
cn: schema
dn: cn={0}core,cn=schema,cn=config
cn: {0}core
dn: cn={1}cosine,cn=schema,cn=config
cn: {1}cosine
dn: cn={2}nis,cn=schema,cn=config
cn: {2}nis
dn: cn={3}inetorgperson,cn=schema,cn=config
cn: {3}inetorgperson
dn: cn={4}samba,cn=schema,cn=config
cn: {4}samba
dn: cn={5}dns,cn=schema,cn=config
cn: {5}dns
The last entry shows, that is it now available.
You can now start to deploy your zones into LDAP. The following page describes the main options:
https://pagure.io/bind-dyndb-ldap
For my first zone, I use the example zone from the package here:
# vi /usr/share/doc/bind9-dyndb-ldap/example.ldif
I modified this to reflect my environment here:
# ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b ou=dns,o=services,dc=flomain,dc=local
dn: ou=dns,o=services,dc=flomain,dc=local
ou: dns
objectClass: organizationalUnit
objectClass: top
dn: idnsName=flomain.local,ou=dns,o=services,dc=flomain,dc=local
idnsSOAmName: devil.flomain.local.
idnsSOArName: devil.flomain.local.
idnsName: flomain.local
objectClass: idnsZone
objectClass: idnsRecord
objectClass: top
idnsSOAexpire: 604800
idnsSOAminimum: 86400
aRecord: 10.104.104.10
idnsSOArefresh: 10800
idnsSOAretry: 900
idnsZoneActive: TRUE
aAAARecord: fd04:57cd:0f5d:f9c6::10
nSRecord: flomain.local.
idnsSOAserial: 1534088762
dn: idnsName=devil,idnsName=flomain.local,ou=dns,o=services,dc=flomain,dc=loca
l
idnsName: devil
objectClass: idnsRecord
objectClass: top
cNAMERecord: flomain.local.
A reverse zone might look like this:
dn: idnsName=100.100.10.in-addr.arpa.,ou=dns,o=services,dc=flomain,dc=local
idnsSOAmName: devil.flomain.local.
idnsSOArefresh: 10800
idnsSOArName: devil.flomain.local.
nSRecord: devil.flomain.local.
idnsSOAretry: 900
idnsZoneActive: TRUE
objectClass: idnsZone
objectClass: idnsRecord
objectClass: top
idnsSOAexpire: 604800
idnsSOAminimum: 86400
idnsSOAserial: 1534092448
idnsName: 100.100.10.in-addr.arpa.
dn: idnsName=haan-router,idnsName=flomain.local,ou=dns,o=services,dc=flomain,d
c=local
aRecord: 10.100.100.1
aAAARecord: fdf0:4d22:9d3e:bcc2::1
idnsName: haan-router
objectClass: idnsRecord
objectClass: top
Now, tell bind to use OpenLDAP as the database. Simply add the following to your configuration:
dynamic-db "my_openldap_db" {
library "ldap.so";
arg "uri ldap://localhost";
arg "base ou=dns,o=services,dc=flomain,dc=local";
arg "auth_method simple";
arg "bind_dn cn=admin,dc=flomain,dc=local";
arg "password Ka02629153";
};
Before you start/restart Bind enable replication on the OpenLDAP server. I use those two LDIF files for this task:
# cat syncrepl.ldif
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: syncprov
root@devil:~/ldap-scripts# ldapmodify -Y EXTERNAL -H ldapi:/// -f syncrepl.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "cn=module{0},cn=config"
and the following to make the new module active:
# cat syncrepl_prov.ldif
dn: olcOverlay=syncprov,olcDatabase={1}mdb,cn=config
changeType: add
objectClass: olcOverlayConfig
objectClass: olcSyncProvConfig
olcOverlay: syncprov
olcSpCheckpoint: 100 10
olcSpSessionLog: 100
root@devil:~/ldap-scripts# ldapmodify -Y EXTERNAL -H ldapi:/// -f syncrepl_prov.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry "olcOverlay=syncprov,olcDatabase={1}mdb,cn=config"
Now, you can use OpenLDAP to store your zones. The cool thing, you can change the entries, without restarting bind. Due to the replication module, bind is aware of any change during runtime.
OpenLDAP: Integrate DHCP Server
For DHCP, I use the ISC-DHCP-Server. This one can also work with OpenLDAP.
To use the OpenLDAP backend for DHCP you install the required package first:
# apt-get install isc-dhcp-server-ldap
Next, you need the schema for DHCP. The package comes with a schema file. But this one is not for the online config in OpenLDAP. You can either convert it manually or use the one I converted:
dn: cn=dhcp,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: dhcp
olcAttributeTypes: {0}( 2.16.840.1.113719.1.203.4.1 NAME 'dhcpPrimaryDN' DES
C 'The DN of the dhcpServer which is the primary server for the configurati
on.' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 S
INGLE-VALUE )
olcAttributeTypes: {1}( 2.16.840.1.113719.1.203.4.2 NAME 'dhcpSecondaryDN' D
ESC 'The DN of dhcpServer(s) which provide backup service for the configura
tion.' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
)
olcAttributeTypes: {2}( 2.16.840.1.113719.1.203.4.3 NAME 'dhcpStatements' DE
SC 'Flexible storage for specific data depending on what object this exists
in. Like conditional statements, server parameters, etc. This allows the s
tandard to evolve without needing to adjust the schema.' EQUALITY caseIgnor
eIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
olcAttributeTypes: {3}( 2.16.840.1.113719.1.203.4.4 NAME 'dhcpRange' DESC 'T
he starting & ending IP Addresses in the range (inclusive), separated by a
hyphen; if the range only contains one address, then just the address can b
e specified with no hyphen. Each range is defined as a separate value.' EQ
UALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
olcAttributeTypes: {4}( 2.16.840.1.113719.1.203.4.5 NAME 'dhcpPermitList' DE
SC 'This attribute contains the permit lists associated with a pool. Each p
ermit list is defined as a separate value.' EQUALITY caseIgnoreIA5Match SYN
TAX 1.3.6.1.4.1.1466.115.121.1.26 )
olcAttributeTypes: {5}( 2.16.840.1.113719.1.203.4.6 NAME 'dhcpNetMask' DESC
'The subnet mask length for the subnet. The mask can be easily computed fr
om this length.' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
SINGLE-VALUE )
olcAttributeTypes: {6}( 2.16.840.1.113719.1.203.4.7 NAME 'dhcpOption' DESC '
Encoded option values to be sent to clients. Each value represents a singl
e option and contains (OptionTag, Length, OptionValue) encoded in the forma
t used by DHCP.' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.12
1.1.26 )
olcAttributeTypes: {7}( 2.16.840.1.113719.1.203.4.8 NAME 'dhcpClassData' DES
C 'Encoded text string or list of bytes expressed in hexadecimal, separated
by colons. Clients match subclasses based on matching the class data with
the results of match or spawn with statements in the class name declaratio
ns.' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGL
E-VALUE )
olcAttributeTypes: {8}( 2.16.840.1.113719.1.203.4.9 NAME 'dhcpOptionsDN' DES
C 'The distinguished name(s) of the dhcpOption objects containing the confi
guration options provided by the server.' EQUALITY distinguishedNameMatch S
YNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
olcAttributeTypes: {9}( 2.16.840.1.113719.1.203.4.10 NAME 'dhcpHostDN' DESC
'the distinguished name(s) of the dhcpHost objects.' EQUALITY distinguished
NameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
olcAttributeTypes: {10}( 2.16.840.1.113719.1.203.4.11 NAME 'dhcpPoolDN' DESC
'The distinguished name(s) of pools.' EQUALITY distinguishedNameMatch SYNT
AX 1.3.6.1.4.1.1466.115.121.1.12 )
olcAttributeTypes: {11}( 2.16.840.1.113719.1.203.4.12 NAME 'dhcpGroupDN' DES
C 'The distinguished name(s) of the groups.' EQUALITY distinguishedNameMa
tch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
olcAttributeTypes: {12}( 2.16.840.1.113719.1.203.4.13 NAME 'dhcpSubnetDN' DE
SC 'The distinguished name(s) of the subnets.' EQUALITY distinguishedNameMa
tch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
olcAttributeTypes: {13}( 2.16.840.1.113719.1.203.4.14 NAME 'dhcpLeaseDN' DES
C 'The distinguished name of a client address.' EQUALITY distinguishedNameM
atch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE )
olcAttributeTypes: {14}( 2.16.840.1.113719.1.203.4.15 NAME 'dhcpLeasesDN' DE
SC 'The distinguished name(s) client addresses.' EQUALITY distinguishedName
Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
olcAttributeTypes: {15}( 2.16.840.1.113719.1.203.4.16 NAME 'dhcpClassesDN' D
ESC 'The distinguished name(s) of a class(es) in a subclass.' EQUALITY dist
inguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
olcAttributeTypes: {16}( 2.16.840.1.113719.1.203.4.17 NAME 'dhcpSubclassesDN
' DESC 'The distinguished name(s) of subclass(es).' EQUALITY distinguishedN
ameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
olcAttributeTypes: {17}( 2.16.840.1.113719.1.203.4.18 NAME 'dhcpSharedNetwor
kDN' DESC 'The distinguished name(s) of sharedNetworks.' EQUALITY distingui
shedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
olcAttributeTypes: {18}( 2.16.840.1.113719.1.203.4.19 NAME 'dhcpServiceDN' D
ESC 'The DN of dhcpService object(s)which contain the configuration informa
tion. Each dhcpServer object has this attribute identifying the DHCP config
uration(s) that the server is associated with.' EQUALITY distinguishedNameM
atch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
olcAttributeTypes: {19}( 2.16.840.1.113719.1.203.4.20 NAME 'dhcpVersion' DES
C 'The version attribute of this object.' EQUALITY caseIgnoreIA5Match SYNTA
X 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
olcAttributeTypes: {20}( 2.16.840.1.113719.1.203.4.21 NAME 'dhcpImplementati
on' DESC 'Description of the DHCP Server implementation e.g. DHCP Servers v
endor.' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SI
NGLE-VALUE )
olcAttributeTypes: {21}( 2.16.840.1.113719.1.203.4.22 NAME 'dhcpAddressState
' DESC 'This stores information about the current binding-status of an addr
ess. For dynamic addresses managed by DHCP, the values should be restricte
d to the following: "FREE", "ACTIVE", "EXPIRED", "RELEASED", "RESET", "ABAN
DONED", "BACKUP". For other addresses, it SHOULD be one of the following:
"UNKNOWN", "RESERVED" (an address that is managed by DHCP that is reserved
for a specific client), "RESERVED-ACTIVE" (same as reserved, but address is
currently in use), "ASSIGNED" (assigned manually or by some other mechanis
m), "UNASSIGNED", "NOTASSIGNABLE".' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.
6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
olcAttributeTypes: {22}( 2.16.840.1.113719.1.203.4.23 NAME 'dhcpExpirationTi
me' DESC 'This is the time the current lease for an address expires.' EQUAL
ITY generalizedTimeMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE-VALUE
)
olcAttributeTypes: {23}( 2.16.840.1.113719.1.203.4.24 NAME 'dhcpStartTimeOfS
tate' DESC 'This is the time of the last state change for a leased address.
' EQUALITY generalizedTimeMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE
-VALUE )
olcAttributeTypes: {24}( 2.16.840.1.113719.1.203.4.25 NAME 'dhcpLastTransact
ionTime' DESC 'This is the last time a valid DHCP packet was received from
the client.' EQUALITY generalizedTimeMatch SYNTAX 1.3.6.1.4.1.1466.115.121.
1.24 SINGLE-VALUE )
olcAttributeTypes: {25}( 2.16.840.1.113719.1.203.4.26 NAME 'dhcpBootpFlag' D
ESC 'This indicates whether the address was assigned via BOOTP.' EQUALITY b
ooleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
olcAttributeTypes: {26}( 2.16.840.1.113719.1.203.4.27 NAME 'dhcpDomainName'
DESC 'This is the name of the domain sent to the client by the server. It
is essentially the same as the value for DHCP option 15 sent to the client,
and represents only the domain - not the full FQDN. To obtain the full FQ
DN assigned to the client you must prepend the "dhcpAssignedHostName" to th
is value with a ".".' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.1
15.121.1.26 SINGLE-VALUE )
olcAttributeTypes: {27}( 2.16.840.1.113719.1.203.4.28 NAME 'dhcpDnsStatus' D
ESC 'This indicates the status of updating DNS resource records on behalf o
f the client by the DHCP server for this address. The value is a 16-bit bi
tmask.' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-V
ALUE )
olcAttributeTypes: {28}( 2.16.840.1.113719.1.203.4.29 NAME 'dhcpRequestedHos
tName' DESC 'This is the hostname that was requested by the client.' EQUALI
TY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
olcAttributeTypes: {29}( 2.16.840.1.113719.1.203.4.30 NAME 'dhcpAssignedHost
Name' DESC 'This is the actual hostname that was assigned to a client. It m
ay not be the name that was requested by the client. The fully qualified d
omain name can be determined by appending the value of "dhcpDomainName" (wi
th a dot separator) to this name.' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6
.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
olcAttributeTypes: {30}( 2.16.840.1.113719.1.203.4.31 NAME 'dhcpReservedForC
lient' DESC 'The distinguished name of a "dhcpClient" that an address is re
served for. This may not be the same as the "dhcpAssignedToClient" attribu
te if the address is being reassigned but the current lease has not yet exp
ired.' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
SINGLE-VALUE )
olcAttributeTypes: {31}( 2.16.840.1.113719.1.203.4.32 NAME 'dhcpAssignedToCl
ient' DESC 'This is the distinguished name of a "dhcpClient" that an addres
s is currently assigned to. This attribute is only present in the class wh
en the address is leased.' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4
.1.1466.115.121.1.12 SINGLE-VALUE )
olcAttributeTypes: {32}( 2.16.840.1.113719.1.203.4.33 NAME 'dhcpRelayAgentIn
fo' DESC 'If the client request was received via a relay agent, this contai
ns information about the relay agent that was available from the DHCP reque
st. This is a hex-encoded option value.' EQUALITY octetStringMatch SYNTAX
1.3.6.1.4.1.1466.115.121.1.40 SINGLE-VALUE )
olcAttributeTypes: {33}( 2.16.840.1.113719.1.203.4.34 NAME 'dhcpHWAddress' D
ESC 'The clients hardware address that requested this IP address.' EQUALITY
caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
olcAttributeTypes: {34}( 2.16.840.1.113719.1.203.4.35 NAME 'dhcpHashBucketAs
signment' DESC 'HashBucketAssignment bit map for the DHCP Server, as define
d in DHC Load Balancing Algorithm [RFC 3074].' EQUALITY octetStringMatch SY
NTAX 1.3.6.1.4.1.1466.115.121.1.40 SINGLE-VALUE )
olcAttributeTypes: {35}( 2.16.840.1.113719.1.203.4.36 NAME 'dhcpDelayedServi
ceParameter' DESC 'Delay in seconds corresponding to Delayed Service Parame
ter configuration, as defined in DHC Load Balancing Algorithm [RFC 3074].
' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
olcAttributeTypes: {36}( 2.16.840.1.113719.1.203.4.37 NAME 'dhcpMaxClientLea
dTime' DESC 'Maximum Client Lead Time configuration in seconds, as defined
in DHCP Failover Protocol [FAILOVR]' EQUALITY integerMatch SYNTAX 1.3.6.1.4
.1.1466.115.121.1.27 SINGLE-VALUE )
olcAttributeTypes: {37}( 2.16.840.1.113719.1.203.4.38 NAME 'dhcpFailOverEndp
ointState' DESC 'Server (Failover Endpoint) state, as defined in DHCP Failo
ver Protocol [FAILOVR]' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466
.115.121.1.26 SINGLE-VALUE )
olcAttributeTypes: {38}( 2.16.840.1.113719.1.203.4.39 NAME 'dhcpErrorLog' DE
SC 'Generic error log attribute that allows logging error conditions within
a dhcpService or a dhcpSubnet, like no IP addresses available for lease.'
EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VAL
UE )
olcAttributeTypes: {39}( 2.16.840.1.113719.1.203.4.40 NAME 'dhcpLocatorDN' D
ESC 'The DN of dhcpLocator object which contain the DNs of all DHCP configu
ration objects. There will be a single dhcpLocator object in the tree with
links to all the DHCP objects in the tree' EQUALITY distinguishedNameMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
olcAttributeTypes: {40}( 2.16.840.1.113719.1.203.4.41 NAME 'dhcpKeyAlgorithm
' DESC 'Algorithm to generate TSIG Key' EQUALITY caseIgnoreIA5Match SYNTAX
1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
olcAttributeTypes: {41}( 2.16.840.1.113719.1.203.4.42 NAME 'dhcpKeySecret' D
ESC 'Secret to generate TSIG Key' EQUALITY octetStringMatch SYNTAX 1.3.6.1.
4.1.1466.115.121.1.40 SINGLE-VALUE )
olcAttributeTypes: {42}( 2.16.840.1.113719.1.203.4.43 NAME 'dhcpDnsZoneServe
r' DESC 'Master server of the DNS Zone' EQUALITY caseIgnoreIA5Match SYNTAX
1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
olcAttributeTypes: {43}( 2.16.840.1.113719.1.203.4.44 NAME 'dhcpKeyDN' DESC
'The DNs of TSIG Key to use in secure dynamic updates. In case of locator o
bject, this will be list of TSIG keys. In case of DHCP Service, Shared Net
work, Subnet and DNS Zone, it will be a single key.' EQUALITY distinguished
NameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
olcAttributeTypes: {44}( 2.16.840.1.113719.1.203.4.45 NAME 'dhcpZoneDN' DESC
'The DNs of DNS Zone. In case of locator object, this will be list of DNS
Zones in the tree. In case of DHCP Service, Shared Network and Subnet, it w
ill be a single DNS Zone.' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4
.1.1466.115.121.1.12 )
olcAttributeTypes: {45}( 2.16.840.1.113719.1.203.4.46 NAME 'dhcpFailOverPrim
aryServer' DESC 'IP address or DNS name of the server playing primary role
in DHC Load Balancing and Fail over.' EQUALITY caseIgnoreIA5Match SYNTAX 1.
3.6.1.4.1.1466.115.121.1.26 )
olcAttributeTypes: {46}( 2.16.840.1.113719.1.203.4.47 NAME 'dhcpFailOverSeco
ndaryServer' DESC 'IP address or DNS name of the server playing secondary r
ole in DHC Load Balancing and Fail over.' EQUALITY caseIgnoreIA5Match SYNTA
X 1.3.6.1.4.1.1466.115.121.1.26 )
olcAttributeTypes: {47}( 2.16.840.1.113719.1.203.4.48 NAME 'dhcpFailOverPrim
aryPort' DESC 'Port on which primary server listens for connections from it
s fail over peer (secondary server)' EQUALITY integerMatch SYNTAX 1.3.6.1.4
.1.1466.115.121.1.27 )
olcAttributeTypes: {48}( 2.16.840.1.113719.1.203.4.49 NAME 'dhcpFailOverSeco
ndaryPort' DESC 'Port on which secondary server listens for connections fro
m its fail over peer (primary server)' EQUALITY integerMatch SYNTAX 1.3.6.1
.4.1.1466.115.121.1.27 )
olcAttributeTypes: {49}( 2.16.840.1.113719.1.203.4.50 NAME 'dhcpFailOverResp
onseDelay' DESC 'Maximum response time in seconds, before Server assumes th
at connection to fail over peer has failed' EQUALITY integerMatch SYNTAX 1.
3.6.1.4.1.1466.115.121.1.27 )
olcAttributeTypes: {50}( 2.16.840.1.113719.1.203.4.51 NAME 'dhcpFailOverUnac
kedUpdates' DESC 'Number of BNDUPD messages that server can send before it
receives BNDACK from its fail over peer' EQUALITY integerMatch SYNTAX 1.3.6
.1.4.1.1466.115.121.1.27 )
olcAttributeTypes: {51}( 2.16.840.1.113719.1.203.4.52 NAME 'dhcpFailOverSpli
t' DESC 'Split between the primary and secondary servers for fail over purp
ose' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
olcAttributeTypes: {52}( 2.16.840.1.113719.1.203.4.53 NAME 'dhcpFailOverLoad
BalanceTime' DESC 'Cutoff time in seconds, after which load balance is disa
bled' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
olcAttributeTypes: {53}( 2.16.840.1.113719.1.203.4.54 NAME 'dhcpFailOverPeer
DN' DESC 'The DNs of Fail over peers. In case of locator object, this will
be list of fail over peers in the tree. In case of Subnet and pool, it will
be a single Fail Over Peer' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1
.4.1.1466.115.121.1.12 )
olcAttributeTypes: {54}( 2.16.840.1.113719.1.203.4.55 NAME 'dhcpServerDN' DE
SC 'List of all DHCP Servers in the tree. Used by dhcpLocatorObject' EQUAL
ITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
olcAttributeTypes: {55}( 2.16.840.1.113719.1.203.4.56 NAME 'dhcpComments' DE
SC 'Generic attribute that allows coments within any DHCP object' EQUALITY
caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
olcAttributeTypes: {56}( 2.16.840.1.113719.1.203.4.57 NAME 'dhcpClientId' DE
SC 'client Identifier.' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466
.115.121.1.26 )
olcAttributeTypes: {57}( 2.16.840.1.113719.1.203.4.58 NAME 'dhcpRange6' DESC
'The starting & ending IP Addresses in the range (inclusive), separated by
a hyphen; if the range only contains one address, then just the address ca
n be specified with no hyphen. Each range is defined as a separate value.'
EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
olcObjectClasses: {0}( 2.16.840.1.113719.1.203.6.1 NAME 'dhcpService' DESC '
Service object that represents the actual DHCP Service configuration. This
is a container object.' SUP top STRUCTURAL MUST cn MAY ( dhcpPrimaryDN $ dh
cpSecondaryDN $ dhcpServerDN $ dhcpSharedNetworkDN $ dhcpSubnetDN $ dhcpGro
upDN $ dhcpHostDN $ dhcpClassesDN $ dhcpOptionsDN $ dhcpZoneDN $ dhcpKeyDN
$ dhcpFailOverPeerDN $ dhcpStatements $ dhcpComments $ dhcpOption ) )
olcObjectClasses: {1}( 2.16.840.1.113719.1.203.6.2 NAME 'dhcpSharedNetwork'
DESC 'This stores configuration information for a shared network.' SUP top
STRUCTURAL MUST cn MAY ( dhcpSubnetDN $ dhcpPoolDN $ dhcpOptionsDN $ dhcpZo
neDN $ dhcpStatements $ dhcpComments $ dhcpOption ) X-NDS_CONTAINMENT 'dhcp
Service' )
olcObjectClasses: {2}( 2.16.840.1.113719.1.203.6.3 NAME 'dhcpSubnet' DESC 'T
his class defines a subnet. This is a container object.' SUP top STRUCTURAL
MUST ( cn $ dhcpNetMask ) MAY ( dhcpRange $ dhcpPoolDN $ dhcpGroupDN $ dhc
pHostDN $ dhcpClassesDN $ dhcpLeasesDN $ dhcpOptionsDN $ dhcpZoneDN $ dhcpK
eyDN $ dhcpFailOverPeerDN $ dhcpStatements $ dhcpComments $ dhcpOption ) X-
NDS_CONTAINMENT ( 'dhcpService' 'dhcpSharedNetwork' ) )
olcObjectClasses: {3}( 2.16.840.1.113719.1.203.6.4 NAME 'dhcpPool' DESC 'Thi
s stores configuration information about a pool.' SUP top STRUCTURAL MUST (
cn $ dhcpRange ) MAY ( dhcpClassesDN $ dhcpPermitList $ dhcpLeasesDN $ dhc
pOptionsDN $ dhcpZoneDN $ dhcpKeyDN $ dhcpStatements $ dhcpComments $ dhcpO
ption ) X-NDS_CONTAINMENT ( 'dhcpSubnet' 'dhcpSharedNetwork' ) )
olcObjectClasses: {4}( 2.16.840.1.113719.1.203.6.5 NAME 'dhcpGroup' DESC 'Gr
oup object that lists host DNs and parameters. This is a container object.'
SUP top STRUCTURAL MUST cn MAY ( dhcpHostDN $ dhcpOptionsDN $ dhcpStatemen
ts $ dhcpComments $ dhcpOption ) X-NDS_CONTAINMENT ( 'dhcpSubnet' 'dhcpServ
ice' ) )
olcObjectClasses: {5}( 2.16.840.1.113719.1.203.6.6 NAME 'dhcpHost' DESC 'Thi
s represents information about a particular client' SUP top STRUCTURAL MUST
cn MAY ( dhcpLeaseDN $ dhcpHWAddress $ dhcpOptionsDN $ dhcpStatements $ dh
cpComments $ dhcpOption $ dhcpClientId ) X-NDS_CONTAINMENT ( 'dhcpService'
'dhcpSubnet' 'dhcpGroup' ) )
olcObjectClasses: {6}( 2.16.840.1.113719.1.203.6.7 NAME 'dhcpClass' DESC 'Re
presents information about a collection of related clients.' SUP top STRUCT
URAL MUST cn MAY ( dhcpSubClassesDN $ dhcpOptionsDN $ dhcpStatements $ dhcp
Comments $ dhcpOption ) X-NDS_CONTAINMENT ( 'dhcpService' 'dhcpSubnet' ) )
olcObjectClasses: {7}( 2.16.840.1.113719.1.203.6.8 NAME 'dhcpSubClass' DESC
'Represents information about a collection of related classes.' SUP top STR
UCTURAL MUST cn MAY ( dhcpClassData $ dhcpOptionsDN $ dhcpStatements $ dhcp
Comments $ dhcpOption ) X-NDS_CONTAINMENT 'dhcpClass' )
olcObjectClasses: {8}( 2.16.840.1.113719.1.203.6.9 NAME 'dhcpOptions' DESC '
Represents information about a collection of options defined.' SUP top AUXI
LIARY MUST cn MAY ( dhcpOption $ dhcpComments ) X-NDS_CONTAINMENT ( 'dhcpSe
rvice' 'dhcpSharedNetwork' 'dhcpSubnet' 'dhcpPool' 'dhcpGroup' 'dhcpHost' '
dhcpClass' ) )
olcObjectClasses: {9}( 2.16.840.1.113719.1.203.6.10 NAME 'dhcpLeases' DESC '
This class represents an IP Address, which may or may not have been leased.
' SUP top STRUCTURAL MUST ( cn $ dhcpAddressState ) MAY ( dhcpExpirationTim
e $ dhcpStartTimeOfState $ dhcpLastTransactionTime $ dhcpBootpFlag $ dhcpDo
mainName $ dhcpDnsStatus $ dhcpRequestedHostName $ dhcpAssignedHostName $ d
hcpReservedForClient $ dhcpAssignedToClient $ dhcpRelayAgentInfo $ dhcpHWAd
dress ) X-NDS_CONTAINMENT ( 'dhcpService' 'dhcpSubnet' 'dhcpPool' ) )
olcObjectClasses: {10}( 2.16.840.1.113719.1.203.6.11 NAME 'dhcpLog' DESC 'Th
is is the object that holds past information about the IP address. The cn i
s the time/date stamp when the address was assigned or released, the addres
s state at the time, if the address was assigned or released.' SUP top STRU
CTURAL MUST cn MAY ( dhcpAddressState $ dhcpExpirationTime $ dhcpStartTimeO
fState $ dhcpLastTransactionTime $ dhcpBootpFlag $ dhcpDomainName $ dhcpDns
Status $ dhcpRequestedHostName $ dhcpAssignedHostName $ dhcpReservedForClie
nt $ dhcpAssignedToClient $ dhcpRelayAgentInfo $ dhcpHWAddress $ dhcpErrorL
og ) X-NDS_CONTAINMENT ( 'dhcpLeases' 'dhcpPool' 'dhcpSubnet' 'dhcpSharedNe
twork' 'dhcpService' ) )
olcObjectClasses: {11}( 2.16.840.1.113719.1.203.6.12 NAME 'dhcpServer' DESC
'DHCP Server Object' SUP top STRUCTURAL MUST cn MAY ( dhcpServiceDN $ dhcpL
ocatorDN $ dhcpVersion $ dhcpImplementation $ dhcpHashBucketAssignment $ dh
cpDelayedServiceParameter $ dhcpMaxClientLeadTime $ dhcpFailOverEndpointSta
te $ dhcpStatements $ dhcpComments $ dhcpOption ) X-NDS_CONTAINMENT ( 'orga
nization' 'organizationalunit' 'domain' ) )
olcObjectClasses: {12}( 2.16.840.1.113719.1.203.6.13 NAME 'dhcpTSigKey' DESC
'TSIG key for secure dynamic updates' SUP top STRUCTURAL MUST ( cn $ dhcpK
eyAlgorithm $ dhcpKeySecret ) MAY dhcpComments X-NDS_CONTAINMENT ( 'dhcpSer
vice' 'dhcpSharedNetwork' 'dhcpSubnet' ) )
olcObjectClasses: {13}( 2.16.840.1.113719.1.203.6.14 NAME 'dhcpDnsZone' DESC
'DNS Zone for updating leases' SUP top STRUCTURAL MUST ( cn $ dhcpDnsZoneS
erver ) MAY ( dhcpKeyDN $ dhcpComments ) X-NDS_CONTAINMENT ( 'dhcpService'
'dhcpSharedNetwork' 'dhcpSubnet' ) )
olcObjectClasses: {14}( 2.16.840.1.113719.1.203.6.15 NAME 'dhcpFailOverPeer'
DESC 'This class defines the Fail over peer' SUP top STRUCTURAL MUST ( cn
$ dhcpFailOverPrimaryServer $ dhcpFailOverSecondaryServer $ dhcpFailoverPri
maryPort $ dhcpFailOverSecondaryPort ) MAY ( dhcpFailOverResponseDelay $ dh
cpFailOverUnackedUpdates $ dhcpMaxClientLeadTime $ dhcpFailOverSplit $ dhcp
HashBucketAssignment $ dhcpFailOverLoadBalanceTime $ dhcpComments ) X-NDS_C
ONTAINMENT ( 'dhcpService' 'dhcpSharedNetwork' 'dhcpSubnet' ) )
olcObjectClasses: {15}( 2.16.840.1.113719.1.203.6.16 NAME 'dhcpLocator' DESC
'Locator object for DHCP configuration in the tree. There will be a single
dhcpLocator object in the tree with links to all the DHCP objects in the t
ree' SUP top STRUCTURAL MUST cn MAY ( dhcpServiceDN $ dhcpServerDN $ dhcpSh
aredNetworkDN $ dhcpSubnetDN $ dhcpPoolDN $ dhcpGroupDN $ dhcpHostDN $ dhcp
ClassesDN $ dhcpKeyDN $ dhcpZoneDN $ dhcpFailOverPeerDN $ dhcpOption $ dhcp
Comments ) X-NDS_CONTAINMENT ( 'organization' 'organizationalunit' 'domain'
) )
olcObjectClasses: {16}( 2.16.840.1.113719.1.203.6.17 NAME 'dhcpSubnet6' DESC
'This class defines an IPv6 subnet. This is a container object.' SUP top S
TRUCTURAL MUST cn MAY ( dhcpRange6 $ dhcpPoolDN $ dhcpGroupDN $ dhcpHostDN
$ dhcpClassesDN $ dhcpLeasesDN $ dhcpOptionsDN $ dhcpZoneDN $ dhcpKeyDN $ d
hcpFailOverPeerDN $ dhcpStatements $ dhcpComments $ dhcpOption $ dhcpPermit
List ) X-NDS_CONTAINMENT ( 'dhcpService' 'dhcpSharedNetwork' ) )
olcObjectClasses: {17}( 2.16.840.1.113719.1.203.6.18 NAME 'dhcpPool6' DESC '
This stores configuration information about an IPv6 pool.' SUP top STRUCTUR
AL MUST ( cn $ dhcpRange6 ) MAY ( dhcpClassesDN $ dhcpPermitList $ dhcpLeas
esDN $ dhcpOptionsDN $ dhcpZoneDN $ dhcpKeyDN $ dhcpStatements $ dhcpCommen
ts $ dhcpOption ) X-NDS_CONTAINMENT ( 'dhcpSubnet6' 'dhcpSharedNetwork' ) )
The above one is converted from the schema, which comes with Debian. Import the schema to OpenLDAP:
# ldapadd -Y EXTERNAL -H ldapi:/// -f dhcp_schema.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry "cn=dhcp,cn=schema,cn=config"
To check, if the schema is there, use this command:
# ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b cn=schema,cn=config cn
dn: cn=schema,cn=config
cn: schema
dn: cn={0}core,cn=schema,cn=config
cn: {0}core
dn: cn={1}cosine,cn=schema,cn=config
cn: {1}cosine
dn: cn={2}nis,cn=schema,cn=config
cn: {2}nis
dn: cn={3}inetorgperson,cn=schema,cn=config
cn: {3}inetorgperson
dn: cn={4}samba,cn=schema,cn=config
cn: {4}samba
dn: cn={5}dns,cn=schema,cn=config
cn: {5}dns
dn: cn={6}dhcp,cn=schema,cn=config
cn: {6}dhcp
The last entry is the new DHCP schema.
We can now start to populate the objects to OpenLDAP. My entry point is again below “o=services,dc=flomain,dc=local”. Here I create a new ou dhcp:
# ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b ou=dhcp,o=services,dc=flomain,dc=local
dn: ou=dhcp,o=services,dc=flomain,dc=local
ou: dhcp
objectClass: organizationalUnit
objectClass: top
All the DHCP related stuff will go into this branch. Let’s start with the DHCP server configuration:
# ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b ou=dhcp,o=services,dc=flomain,dc=local
dn: ou=dhcp,o=services,dc=flomain,dc=local
ou: dhcp
objectClass: organizationalUnit
objectClass: top
dn: cn=server,ou=dhcp,o=services,dc=flomain,dc=local
cn: server
objectClass: dhcpServer
objectClass: top
We need to modify this entry later. The cn for the “dhcpServer” object is the name of the server. If you have multiple, make them unique.
Next step, is to create the service:
# ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b ou=dhcp,o=services,dc=flomain,dc=local
dn: ou=dhcp,o=services,dc=flomain,dc=local
ou: dhcp
objectClass: organizationalUnit
objectClass: top
dn: cn=config,ou=dhcp,o=services,dc=flomain,dc=local
cn: config
objectClass: dhcpService
objectClass: top
objectClass: dhcpOptions
dhcpPrimaryDN: cn=server,ou=dhcp,o=services,dc=flomain,dc=local
dhcpStatements: default-lease-time 691200
dhcpStatements: max-lease-time 1382400
dhcpStatements: ddns-update-style none
dhcpStatements: authoritative
dhcpOption: domain-name "flomain.local"
dhcpOption: domain-name-servers 10.104.104.10
I think the “dhcpStatements” and “dhcpOption” values are well known to people, who have configured the DHCP server with a config file already.
Now, we need to bind the server to this services as well:
# ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b cn=server,ou=dhcp,o=services,dc=flomain,dc=local
dn: cn=server,ou=dhcp,o=services,dc=flomain,dc=local
cn: server
objectClass: dhcpServer
objectClass: top
dhcpServiceDN: cn=config,ou=dhcp,o=services,dc=flomain,dc=local
The attribute “dhcpServiceDN” is new.
We can now start to populate the subnets. First, we start with the one for the local interface. This one is just there to let the server start without issues, but will not serve IP addresses:
# ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b cn=config,ou=dhcp,o=services,dc=flomain,dc=local
dn: cn=config,ou=dhcp,o=services,dc=flomain,dc=local
cn: config
objectClass: dhcpService
objectClass: top
objectClass: dhcpOptions
dhcpPrimaryDN: cn=server,ou=dhcp,o=services,dc=flomain,dc=local
dhcpStatements: default-lease-time 691200
dhcpStatements: max-lease-time 1382400
dhcpStatements: ddns-update-style none
dhcpStatements: authoritative
dhcpOption: domain-name "flomain.local"
dhcpOption: domain-name-servers 10.104.104.10
dn: cn=10.104.104.0,cn=config,ou=dhcp,o=services,dc=flomain,dc=local
dhcpNetMask: 24
cn: 10.104.104.0
objectClass: dhcpSubnet
objectClass: top
I include the service object as well, as this, together with the subnets creates the whole config. I add 2 other subnets as well, which I need for my network to work properly. One for my users and one for my Aruba Campus AP’s. This one also includes the option 43 for those AP’s, to find the Aruba Controller. Below is my full config in OpenLDAP for DHCP:
# ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b cn=config,ou=dhcp,o=services,dc=flomain,dc=local
dn: cn=config,ou=dhcp,o=services,dc=flomain,dc=local
cn: config
objectClass: dhcpService
objectClass: top
objectClass: dhcpOptions
dhcpPrimaryDN: cn=server,ou=dhcp,o=services,dc=flomain,dc=local
dhcpStatements: default-lease-time 691200
dhcpStatements: max-lease-time 1382400
dhcpStatements: ddns-update-style none
dhcpStatements: authoritative
dhcpOption: domain-name "flomain.local"
dhcpOption: domain-name-servers 10.104.104.10
dhcpOption: master code 43 = ip-address
dn: cn=192.168.2.0,cn=config,ou=dhcp,o=services,dc=flomain,dc=local
dhcpOption: routers 192.168.2.1
dhcpOption: subnet-mask 255.255.255.0
dhcpOption: domain-search "flomain.local"
dhcpOption: domain-name "flomain.local"
dhcpOption: domain-name-servers 10.104.104.10
dhcpNetMask: 24
cn: 192.168.2.0
objectClass: dhcpSubnet
objectClass: top
dhcpRange: 192.168.2.2 192.168.2.254
dhcpComments: VLAN 1 range, will be removed in the future
dn: cn=10.104.104.0,cn=config,ou=dhcp,o=services,dc=flomain,dc=local
dhcpNetMask: 24
cn: 10.104.104.0
objectClass: dhcpSubnet
objectClass: top
dhcpComments: Local Subnet to let the DHCP start
dn: cn=10.106.106.0,cn=config,ou=dhcp,o=services,dc=flomain,dc=local
dhcpOption: subnet-mask 255.255.255.0
dhcpOption: domain-search "flomain.local"
dhcpOption: domain-name "flomain.local"
dhcpOption: domain-name-servers 10.104.104.10
dhcpOption: routers 10.106.106.1
dhcpComments: VLAN 106, CAP Management
dhcpNetMask: 24
cn: 10.106.106.0
objectClass: dhcpSubnet
objectClass: top
dhcpRange: 10.106.106.10 10.106.106.200
dn: cn=ArubaAP-Class,cn=config,ou=dhcp,o=services,dc=flomain,dc=local
dhcpStatements: match option vendor-class-identifier
dhcpComments: Aruba AP DHCP Class for Option 43
cn: ArubaAP-Class
objectClass: dhcpClass
objectClass: top
dn: cn=ArubaAP,cn=10.106.106.0,cn=config,ou=dhcp,o=services,dc=flomain,dc=loca
l
dhcpOption: vendor-class-identifier "ArubaAP"
dhcpOption: master 10.100.100.50
cn: ArubaAP
objectClass: dhcpSubClass
objectClass: top
dhcpClassData: ArubaAP-Class
Below is my config for the dhcpd daemon:
#dhcpd.conf
#
# LDAP config
ldap-server "localhost";
ldap-port 389;
# We do an anonymous bind
# ldap-username "cn=directorymanagerloginname";
# ldap-password "mypassword";
ldap-base-dn "ou=dhcp,o=services,dc=flomain,dc=local";
ldap-method static;
ldap-debug-file "/var/log/dhcp-ldap-startup.log";
ldap-dhcp-server-cn "server";
Restart the daemon and check the LDAP debug file:
# cat /var/log/dhcp-ldap-startup.log
default-lease-time 691200;
max-lease-time 1382400;
ddns-update-style none;
authoritative;
option domain-name "flomain.local";
option domain-name-servers 10.104.104.10;
option master code 43 = ip-address;
class "ArubaAP-Class" {
match option vendor-class-identifier;
}
subnet 192.168.2.0 netmask 255.255.255.0 {
range 192.168.2.2 192.168.2.254;
option routers 192.168.2.1;
option subnet-mask 255.255.255.0;
option domain-search "flomain.local";
option domain-name "flomain.local";
option domain-name-servers 10.104.104.10;
}
subnet 10.104.104.0 netmask 255.255.255.0 {
}
subnet 10.106.106.0 netmask 255.255.255.0 {
range 10.106.106.10 10.106.106.200;
option subnet-mask 255.255.255.0;
option domain-search "flomain.local";
option domain-name "flomain.local";
option domain-name-servers 10.104.104.10;
option routers 10.106.106.1;
subclass "ArubaAP-Class" "ArubaAP" {
option vendor-class-identifier "ArubaAP";
option master 10.100.100.50;
}
}
If this is the config you expect, you have done a great job.
If you change something in OpenLDAP, you need to restart the DHCP server, to read the new options.
OpenLDAP: Update Bind from DHCP
This part describes the configuration to update dynamic IP leases from the DHCP server to the DNS server.
First, you should create a key, which is used for the secure communication between the DHCP server and the DNS server. I use the “dnssec-keygen” tool. The “-a” defines the algorithm, “-b” the key size and “-n” the nametype. For dynamic dns updates, this value needs to be host, followed by the hostname:
# dnssec-keygen -a HMAC-SHA512 -b 512 -n HOST test.flomain.local.
Ktest.flomain.local.+165+51489
This creates two files in the current directory:
# ls -l Ktest.flomain.local.+165+51489.*
-rw-r--r-- 1 root root 127 Aug 20 20:35 Ktest.flomain.local.+165+51489.key
-rw------- 1 root root 232 Aug 20 20:35 Ktest.flomain.local.+165+51489.private
The secret key is in both of them:
# cat Ktest.flomain.local.+165+51489.private
Private-key-format: v1.3
Algorithm: 165 (HMAC_SHA512)
Key: D19nAcL6JLhVoNldTvcZ7B3Ni77Yc4hkhG59kNi0chz8owyeYEFl53S62YAgDh5yeKJ0SAB+fZ9OtyRIkAmsGw==
Bits: AAA=
Created: 20180820183533
Publish: 20180820183533
Activate: 20180820183533
root@devil:~# cat Ktest.flomain.local.+165+51489.key
test.flomain.local. IN KEY 512 3 165 D19nAcL6JLhVoNldTvcZ7B3Ni77Yc4hkhG59kNi0chz8owyeYEFl53S6 2YAgDh5yeKJ0SAB+fZ9OtyRIkAmsGw==
The line with “key” is the secret key. Copy this in this file:
cat /etc/bind/rndc.key
key "test.flomain.local" {
algorithm hmac-sha512;
secret "D19nAcL6JLhVoNldTvcZ7B3Ni77Yc4hkhG59kNi0chz8owyeYEFl53S62YAgDh5yeKJ0SAB+fZ9OtyRIkAmsGw==";
};
The string in quotes is used to reference the secret. This should be the same value as after the “-n HOST” part form the command above.
Now, include the key in the bind configuration and configure the key usage for updates:
# cat /etc/bind/named.conf.local
//
// Do any local configuration here
//
// Consider adding the 1918 zones here, if they are not used in your
// organization
//include "/etc/bind/zones.rfc1918";
dynamic-db "my_openldap_db" {
library "ldap.so";
arg "uri ldap://localhost";
arg "base ou=dns,o=services,dc=flomain,dc=local";
arg "auth_method simple";
arg "bind_dn cn=admin,dc=flomain,dc=local";
arg "password Ka02629153";
};
include "/etc/bind/rndc.key";
The last line includes the key file. Now, add the following line to the “named.conf.options” file in the “options” section:
allow-update { key test.flomain.local; };
You need to do this globally, as the bind schema for OpenLDAP does not allow this kind of configuration in the zone. Normally, you would have this option in the zone section of your config.
Now, update the zone object in OpenLDAP to look like this:
# ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b idnsName=flomain.local,ou=dns,o=services,dc=flomain,dc=local
dn: idnsName=flomain.local,ou=dns,o=services,dc=flomain,dc=local
idnsSOAmName: devil.flomain.local.
idnsSOArName: devil.flomain.local.
idnsName: flomain.local
objectClass: idnsZone
objectClass: idnsRecord
objectClass: top
idnsSOAexpire: 604800
idnsSOAminimum: 86400
aRecord: 10.104.104.10
idnsSOArefresh: 10800
idnsSOAretry: 900
idnsZoneActive: TRUE
aAAARecord: fd04:57cd:0f5d:f9c6::10
nSRecord: flomain.local.
idnsSOAserial: 1534151701
idnsAllowDynUpdate: TRUE
idnsUpdatePolicy: grant test.flomain.local zonesub ANY;
idnsAllowSyncPTR: TRUE
The important parts are the last 3 ones:
idnsAllowDynUpdate: TRUE
idnsUpdatePolicy: grant test.flomain.local zonesub ANY;
idnsAllowSyncPTR: TRUE
The first one allows dynamic updates for that zone, the second one specifies the policy and the last one enables the reverse lookup creation.
Do this for all zones with dynamic updates. Afterward, the DNS part is done.
Now let’s do the DHCP part.
Change the DHCP service object to look like this:
dn: cn=config,ou=dhcp,o=services,dc=flomain,dc=local
cn: config
objectClass: dhcpService
objectClass: top
objectClass: dhcpOptions
dhcpPrimaryDN: cn=server,ou=dhcp,o=services,dc=flomain,dc=local
dhcpStatements: default-lease-time 691200
dhcpStatements: max-lease-time 1382400
dhcpStatements: authoritative
dhcpStatements: ddns-update-style interim
dhcpStatements: update-static-leases on
dhcpOption: domain-name "flomain.local"
dhcpOption: domain-name-servers 10.104.104.10
dhcpOption: master code 43 = ip-address
The following two lines are important:
dhcpStatements: ddns-update-style interim
dhcpStatements: update-static-leases on
Next, you need to create a “dhcpTSigKey” object. This object holds the key, generated with “dnssec-keygen” tool:
dn: cn=test.flomain.local,cn=config,ou=dhcp,o=services,dc=flomain,dc=local
dhcpKeyAlgorithm: hmac-sha512
objectClass: dhcpTSigKey
objectClass: top
cn: test.flomain.local
dhcpKeySecret:D19nAcL6JLhVoNldTvcZ7B3Ni77Yc4hkhG59kNi0chz8owyeYEFl53S62YAgDh5yeKJ0SAB+fZ9OtyRIkAmsGw==
The last step is to create a DNS zone:
dn: cn=flomain.local.,cn=config,ou=dhcp,o=services,dc=flomain,dc=local
cn: flomain.local.
objectClass: dhcpDnsZone
objectClass: top
dhcpDnsZoneServer: 127.0.0.1
dhcpKeyDN: cn=test.flomain.local,cn=config,ou=dhcp,o=services,dc=flomain,dc=l
ocal
This “dhcpDnsZone” object references the “dhcpTSigKey” object. And whenever an IP for this zone gets an update, this update is sent to the DNS server as well.
You can see a successful update in the Bind logs:
0-Aug-2018 21:17:25.883 update: info: client 127.0.0.1#54490/key test.flomain.local: updating zone 'flomain.local/IN': adding an RR at 'Netatmo-Personal-Weather-Station.flomain.local' A 192.168.2.108
20-Aug-2018 21:17:25.885 update: info: client 127.0.0.1#54490/key test.flomain.local: updating zone 'flomain.local/IN': adding an RR at 'Netatmo-Personal-Weather-Station.flomain.local' TXT "0031f4153610e090a639d5c80be22fc76f"
20-Aug-2018 21:17:25.971 notify: info: zone flomain.local/IN: sending notifies (serial 1534792646)
20-Aug-2018 21:17:25.972 notify: info: zone 2.168.192.in-addr.arpa/IN: sending notifies (serial 1534792645)
20-Aug-2018 21:17:25.972 notify: info: client 10.104.104.10#46481: received notify for zone 'flomain.local'
20-Aug-2018 21:17:26.472 notify: info: client fd04:57cd:f5d:f9c6::10#58608: received notify for zone 'flomain.local'
20-Aug-2018 21:17:30.971 notify: info: zone flomain.local/IN: sending notifies (serial 1534792646)
20-Aug-2018 21:17:30.972 notify: info: client 10.104.104.10#59458: received notify for zone 'flomain.local'
20-Aug-2018 21:17:31.471 notify: info: client fd04:57cd:f5d:f9c6::10#50364: received notify for zone 'flomain.local'
20-Aug-2018 21:17:34.865 update: info: client 127.0.0.1#54490/key test.flomain.local: updating zone 'flomain.local/IN': deleting an RR at Netatmo-Personal-Weather-Station.flomain.local A
20-Aug-2018 21:17:34.906 notify: info: zone 2.168.192.in-addr.arpa/IN: sending notifies (serial 1534792654)
20-Aug-2018 21:17:34.907 update: info: client 127.0.0.1#54490/key test.flomain.local: updating zone 'flomain.local/IN': deleting an RR at Netatmo-Personal-Weather-Station.flomain.local TXT
20-Aug-2018 21:17:35.971 notify: info: zone flomain.local/IN: sending notifies (serial 1534792648)
20-Aug-2018 21:17:35.971 notify: info: client 10.104.104.10#58622: received notify for zone 'flomain.local'
20-Aug-2018 21:17:36.471 notify: info: client fd04:57cd:f5d:f9c6::10#57899: received notify for zone 'flomain.local'
This is an update for the Zone flomain.local. The client is my weather station, which comes online for a very short time, so you see the first entries, where the station is added to the DNS zone, and seconds later, after the station sends the DHCP release, the entry is removed again. Due to the pointer sync, the reverse zone is updated as well.
That’s it. The last important point for me is to enable monitoring with Munin.
OpenLDAP: Monitoring with Munin
To start monitoring with OpenLDAP and online config, you need to load the monitoring module first.
Check for the next free sequence number:
# ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=module{0},cn=config
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
# extended LDIF
#
# LDAPv3
# base <cn=module{0},cn=config> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#
# module{0}, config
dn: cn=module{0},cn=config
objectClass: olcModuleList
cn: module{0}
olcModulePath: /usr/lib/ldap
olcModuleLoad: {0}back_mdb
olcModuleLoad: {1}syncprov
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1
In my case it is {2}, as {1} is already used by the “syncprov” module. So, create the following file:
# cat monitoring.ldif
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: {2}back_monitor
Replace the {2} with your sequence number and execute the LDIF file:
# ldapmodify -Y EXTERNAL -H ldapi:/// -f monitoring.ldif
Afterward, create a new user for monitoring purposes. The first step is to create a password for that user:
s# slappasswd -s secret_password
{SSHA}GkbsH9EDpeydBvGqAvWEgwxkoPXZjW73
Using this password create the following file:
# cat monitoring-user.ldif
dn: cn=monitor,dc=flomain,dc=local
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: monitor
description: LDAP monitor
userPassword:{SSHA}GkbsH9EDpeydBvGqAvWEgwxkoPXZjW73
Add the new user to LDAP:
# ldapadd -x -D cn=admin,dc=flomain,dc=local -w secre_password_from_admin -f monitoring-user.ldif
adding new entry "cn=monitor,dc=flomain,dc=local"
Afterward, add the monitoring database by creating this file:
# cat monitor-database.ldif
dn: olcDatabase={2}Monitor,cn=config
objectClass: olcDatabaseConfig
objectClass: olcMonitorConfig
olcDatabase: {2}Monitor
olcAccess: {0}to dn.subtree="cn=Monitor" by dn.base="cn=monitor,dc=flomain,dc=local" read by * none
And add the database to OpenLDAP:
# ldapadd -Y EXTERNAL -H ldapi:/// -f monitor-database.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry "olcDatabase={2}Monitor,cn=config"
I assume Munin is already up and running. to make sure you have all the needed libraries, run this command:
# apt-get install munin-node libnet-ldap-perl
and add the following lines to your munin config (/etc/munin/plugin-conf.d/munin-node):
[slapd_*]
env.server 127.0.0.1
env.binddn cn=monitor,dc=flomain,dc=local
env.bindpw secret_password
The last step is to change into the plugins directory and create the needed symlinks:
# cd /etc/munin/plugins/
root@devil:/etc/munin/plugins# ln -s /usr/share/munin/plugins/slapd_ slapd_statistics_bytes
root@devil:/etc/munin/plugins# ln -s /usr/share/munin/plugins/slapd_ slapd_statistics_pdu
root@devil:/etc/munin/plugins# ln -s /usr/share/munin/plugins/slapd_ slapd_statistics_referrals
root@devil:/etc/munin/plugins# ln -s /usr/share/munin/plugins/slapd_ slapd_operations_diff
root@devil:/etc/munin/plugins# ln -s /usr/share/munin/plugins/slapd_ slapd_statistics_entries
root@devil:/etc/munin/plugins# ln -s /usr/share/munin/plugins/slapd_ slapd_connections
root@devil:/etc/munin/plugins# ln -s /usr/share/munin/plugins/slapd_ slapd_waiters
root@devil:/etc/munin/plugins# ln -s /usr/share/munin/plugins/slapd_ slapd_operations
Now, restart munin and wait for the result:
# /etc/init.d/munin-node restart
As you can see above, the OpenLDAP server in my LAB is not heavily used
How do you manage your services in your LAB, like user database, DNS and DHCP?
If you find this post interesting, leave me a comment and share it with your friends. If you don’t like the post, leave me a comment and share it with your enemy. But whatever you do, leave me a comment, now.
A very complete solution. Thank you very much!
Hi Frank,
thanks for the feedback. Really appreciated:)
BR
Florian
Hi Florian,
I am not having any luck, I m getting stuck at the zone creation. with the following error:
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry “cn=dns, dc=bunker, dc=telensa, dc=com”
ldap_add: Invalid syntax (21)
additional info: objectClass: value #0 invalid per syntax
it seems to be down to line 3
objectClass: nsContainer
do you have any suggestion?
The install is on debian 10, but I have test it on 9 as well
Peder.
your solution is very interesting, I have been looking for several days to make my arubaAP work with my Dhcp – LDAP server. Is your confusion giving you full satisfaction?
the dhcp-eval part is poorly documented to work with ldap …
I am looking to write the ldif file for this configuration:
subnet 192.168.1.0 netmask 255.255.255.0 {
subnet-mask option 255.255.255.0;
range dynamic-bootp 192.168.1.10 192.168.1.254;
default-lease-time 21600;
max-lease-time 43200;
option domain-name-servers 192.168.1.1;
# option routers x.x.x.x;
class “UEFI” {
match if substring (vendor-class-identifier option, 0, 20) = “PXEClient: Arch: 00006”;
filename “ipxe.efi”;
}
class “Legacy” {
match if substring (vendor-class-identifier option, 0, 20) = “PXEClient: Arch: 00000”;
filename “undionly.kkpxe”;
}
}
thank you for you help?
wow, thats a long time ago 🙂
I’m running now windows server again, not because I’m happy with the windows server, but most of the customers use windows server and I just need to know how it works.
but I have found the following post here:
There is a description of the Perl script, which will convert your dhcpd.conf to a ldif file. Maybe this is what you are looking for.
BR
Florian
Hi Florian,
It is a pity I did not find your page until I was in the end phase. I have been trying to get bind-dyndb-ldap running for 3 days straight! The obstacles were schema.ldif, syncprov and updatepolicy. I did manage to get schema.ldif and syncprov going but got stuck with updatepolicy. The server would state “key ddns_update: updating zone ‘example.com/IN’: update failed: rejected by secure update (REFUSED) “.
Thanks to your page, I now have a fully working setup. Besides the doc on pagure.io, I did not find any documentation for bind-dyndb-ldap which describes each idns* values. This made me make some wrong assumption (e.g. idnsSOAmName, I thought mName = Mail Name). The server did perform well for DNS but did not work for reverse lookup.
Thank you for your detailed description. I have added your site to my bookmarks.
Greetings from Switzerland
Hi joanandk,
thanks for the feedback.
Yeah, this was a hard one for me as well. It took me several weeks to get everything working. There is nearly no documentation out there and you need to find out most of it the hard way. Good to see that I was not the only one 😉
BR
Florian
Hello Florián, I have a couple of questions. The first would be if in the part of integrating dhcp it is necessary to install only isc-dhcp-server-ldap or also isc-dhcp-server. And the second question would be that when you show the configuration of the dhcp daemon you are showing the file /etc/dhcp/dhcpd.conf, are the lines that appear in the photo the only ones that the file should contain? Thank you very much for the guide.
Hi Jorge,
Thanks for your comment.
I only installed “isc-dhcp-server-ldap” and let the system keep track of additional packages to install to satisfy the requirements of the “isc-dhcp-server-ldap” package.
The config file is complete. Nothing else is required. The real configuration will be created after you start the service.
BR
Florian