openldap_centos7_tls
Table of Contents
CentOS 7 - OpenLDAP 2.4 provider (master)
This page describes the installation of an OpenLDAP server with TLS.
Points of departure:
- TLS only, RSA SHA256 / 4096 bit subject alternative name (SAN) certificate.
- Self signed CA / certificates.
- LDAP v3 only.
- Require forward secrecy.
- Minimum SSF 256 (recommended by manual).
- No anonymous binds.
- Users can only change own password, nothing else (cannot alter UID/GID etc).
- Users cannot see password hashes.
- Use the default repo packages (note: uses MozNSS instead of OpenSSL).
- SELinux enabled.
- iptables enabled.
Italic text is quoted from the OpenLDAP Admin guide.
Generate self signed CA and server certificates
- If your LDAP server is multhomed, has multiple FQDNs, you need to generate TLS SAN (subject alt name) certificates. Use the certuil -8 option.
- Create the certificate database directory, if it does not already exisist:
# mkdir /etc/openldap/certs
- Generate a secure password:
# pwgen -sy 32 1 > /etc/openldap/certs/password
- Create a new empty database, if it does not already exists:
# certutil -d /etc/openldap/certs -N -f /etc/openldap/certs/password
- Create a temporary random seed:
# head -c 1024 /dev/urandom > /tmp/noise.txt
- Create a self signed CA, valid for 10 years:
# certutil -S -n LDAP-CA -t "C,C,C" -x \ -f /etc/openldap/certs/password \ -d /etc/openldap/certs \ -z /tmp/noise.txt \ -s "CN=LDAP-CA,OU=IT,O=Company,L=City,ST=State,C=NL" \ -v 120 \ -Z SHA256 \ -g 4096
- Create a certificate and sign with CA, valid for 3 years:
# certutil -S -n 'OpenLDAP Server' -t ",," \ -c LDAP-CA \ -f /etc/openldap/certs/password \ -d /etc/openldap/certs \ -z /tmp/noise.txt \ -s "CN=OpenLDAP Server,OU=IT,O=Company,L=City,ST=State,C=NL" \ -8 "ldap.domain.tld,ldap.mgmt.domain.tld-example!" \ -v 36 \ -Z SHA256 \ -g 4096
- Trust the CA certificate:
# certutil -M -n "LDAP-CA" -t TCu,Cu,Cu -d /etc/openldap/certs
- Modify rights so that LDAP can read the NSS database:
# chmod 440 /etc/openldap/certs/password # chown ldap. /etc/openldap/certs/*
Verify
- List all certificates:
# certutil -L -d /etc/openldap/certs/
- List all private keys in the database:
# certutil -K -d /etc/openldap/certs/ -f /etc/openldap/certs/password
- View certificate:
# certutil -L -d /etc/openldap/certs/ -n LDAP-CA
- Verify certificate:
# certutil -V -d /etc/openldap/certs -n "OpenLDAP Server" -u C certutil: certificate is valid
Open firewall port
- Open port 636:
# firewall-cmd --permanent --zone public --add-service=ldaps success # firewall-cmd --reload success
Install and configure OpenLDAP
- Install required packages:
# yum install openldap-clients openldap-servers openldap pam_ldap nss-pam-ldapd pam_krb5 sssd migrationtools openldap-devel
- Activate LDAPS (TLS), change ldap to ldaps, only start LDAPS and LDAPI (IPC socket). And run slapd with user and group ldap:
# vi /etc/sysconfig/slapd SLAPD_URLS="ldapi:/// ldaps:///" # Any custom options SLAPD_OPTIONS="-g ldap"
- Modify /etc/openldap/ldap.conf:
# vi /etc/openldap/ldap.conf BASE dc=<domain>,dc=<tld> URI ldaps://<FQDN> TLS_CACERTDIR /etc/openldap/certs TLS_REQCERT demand
- Use the DB config example. You can configure the DB_LOG_AUTOREMOVE directive in DB_CONFIG, but If the log files are removed automatically, recovery after a catastrophic failure is likely to be impossible.:
# install -m 644 -o ldap -g ldap /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
- Start OpenLDAP:
slaptest -u systemctl start slapd systemctl enable slapd
- Add required schema's:
core.schema OpenLDAP core (required) cosine.schema Cosine and Internet X.500 (useful) inetorgperson.schema InetOrgPerson (useful) nis.schema Network Information Services (FYI) ## already exists: # ldapadd -Q -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/core.ldif # ldapadd -Q -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif # ldapadd -Q -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif # ldapadd -Q -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/nis.ldif
- Generate an LDAP root password, you need this hash in the next steps:
# slappasswd New password: <password> Re-enter new password: <password> {SSHA}<hash>
- Export variables used in next steps:
# export MYHASH="{SSHA}your-hash" # export MYDOMAIN=your-domain # export MYTLD=your-tld
- olcDatabase={0}config: Add a root password, and modify the olcAccess in order to (at least) require a password using simple authentication
# ldapmodify -Q -Y EXTERNAL -H ldapi:/// <<EOF dn: olcDatabase={0}config,cn=config changetype: modify add: olcRootPW olcRootPW: ${MYHASH} - replace: olcAccess olcAccess: {0}to * by dn.base="cn=Manager,dc=${MYDOMAIN},dc=${MYTLD}" manage by * none EOF
- olcDatabase={1}monitor: Change the monitor ACL:
# ldapmodify -H ldapi:/// -x -D "cn=config" -W <<EOF dn: olcDatabase={1}monitor,cn=config changetype: modify replace: olcAccess olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" read by dn.base="cn=Manager,dc=${MYDOMAIN},dc=${MYTLD}" read by * none EOF
- olcDatabase={2}hdb: Change the standard DN suffix and root password
# ldapmodify -H ldapi:/// -x -D "cn=config" -W <<EOF dn: olcDatabase={2}hdb,cn=config changetype: modify replace: olcSuffix olcSuffix: dc=${MYDOMAIN},dc=${MYTLD} - replace: olcRootDN olcRootDN: cn=Manager,dc=${MYDOMAIN},dc=${MYTLD} - add: olcRootPW olcRootPW: ${MYHASH} EOF
- olcDatabase={2}hdb: configure indexing:
# ldapmodify -H ldapi:/// -x -D "cn=config" -W <<EOF dn: olcDatabase={2}hdb,cn=config changetype: modify replace: olcDbIndex olcDbIndex: objectClass eq,pres olcDbIndex: ou,cn,mail,surname,givenname eq,pres,sub olcDbIndex: uid,memberUid,gidNumber eq - EOF
- Modify the configration so that users can change their own passwords, but cannot view others':
# ldapmodify -H ldapi:/// -x -D "cn=config" -W <<EOF dn: olcDatabase={2}hdb,cn=config changetype: modify replace: olcAccess olcAccess: {0}to attrs=userPassword,shadowLastChange by dn.exact="cn=Manager,dc=${MYDOMAIN},dc=${MYTLD}" write by self =xw by anonymous auth by * none olcAccess: {1}to * by dn.exact="cn=Manager,dc=${MYDOMAIN},dc=${MYTLD}" write by self read by users read by * none EOF
- Modify the TLS configuration:
# ldapmodify -H ldapi:/// -x -D "cn=config" -W <<EOF dn: cn=config changetype: modify replace: olcTLSCipherSuite olcTLSCipherSuite: HIGH - replace: olcTLSProtocolMin olcTLSProtocolMin: 3.1 - replace: olcDisallows olcDisallows: bind_anon - replace: olcIdleTimeout olcIdleTimeout: 120 EOF
- olcDatabase={-1}frontend: Due to a bug i was not able to perform this step… I had to manually edit the olcDatabase={-1}frontend.ldif file and set olcDatabase to “olcDatabase: {-1}frontend”.
- Set global options: Some backend types, such as frontend and monitor use a hard-coded suffix which may not be overridden in the configuration. Access controls defined in the frontend are appended to all other databases' controls. Configure password and require LDAPv3:
# ldapmodify -H ldapi:/// -x -D "cn=config" -W <<EOF dn: olcDatabase={-1}frontend,cn=config changetype: modify add: olcPasswordHash olcPasswordHash: ${MYHASH} - add: olcRequires olcRequires: LDAPv3 authc EOF
- Accept only TLS:
# ldapmodify -H ldaps://<FQDN> -x -D "cn=config" -W <<EOF dn: cn=config changetype: modify add: olcSecurity olcSecurity: tls=1 EOF
Test server config, restart and test connectivity
- Restart slapd:
# slaptest -u # systemctl restart slapd
- Test connection and verify certificate. Export ca certificate for testing with openssl:
# certutil -L -d /etc/openldap/certs -n "LDAP-CA" -a > /tmp/ca.crt # openssl s_client -connect localhost:636 -showcerts -CAfile /tmp/ca.crt ... Verify return code: 0 (ok) # ldapwhoami -H ldaps://<FQDN> -x -D "cn=Manager,dc=<domain>,dc=<tld>" -W # ldapsearch -H ldaps://<FQDN> -x -D "cn=Manager,dc=<domain>,dc=<tld>" -W # ldapsearch -H ldap://<FQDN> -x -D "cn=Manager,dc=<domain>,dc=<tld>" -W ldap_bind: Confidentiality required (13) additional info: TLS confidentiality required or: ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1) # openssl s_client -connect localhost:636 2>&1 | openssl x509 -text | grep DNS
Create basic structure
- Load the basic structure:
# ldapadd -H ldaps://<FQDN> -x -W -D "cn=Manager,dc=<domain>,dc=<tld>" -f base.ldif dn: ,dc=<domain>,dc=<tld> dc: <domain> objectClass: top objectClass: domain dn: ou=people,dc=<domain>,dc=<tld> ou: people objectClass: top objectClass: organizationalUnit dn: ou=groups,dc=<domain>,dc=<tld> ou: groups objectClass: top objectClass: organizationalUnit dn: ou=hosts,dc=<domain>,dc=<tld> ou: hosts objectClass: top objectClass: organizationalUnit
User management
Verify cipher suites / analyse network traffic
- nmap test cipher suites:
# nmap --script ssl-enum-ciphers -p 636 ldap.server.tld Starting Nmap 6.40 ( http://nmap.org ) at 2015-09-07 20:54 CEST Nmap scan report for ldap.server.tld () Host is up (0.00025s latency). PORT STATE SERVICE 636/tcp open ldapssl | ssl-enum-ciphers: | TLSv1.2: | ciphers: | TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA - strong | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - strong | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - strong | TLS_RSA_WITH_3DES_EDE_CBC_SHA - strong | TLS_RSA_WITH_AES_128_CBC_SHA - strong | TLS_RSA_WITH_AES_256_CBC_SHA - strong | TLS_RSA_WITH_CAMELLIA_128_CBC_SHA - strong | TLS_RSA_WITH_CAMELLIA_256_CBC_SHA - strong | compressors: | NULL |_ least strength: strong MAC Address: (QEMU Virtual NIC) Nmap done: 1 IP address (1 host up) scanned in 0.17 seconds
- tshark:
tshark -f "tcp port 636" -i any
openldap_centos7_tls.txt · Last modified: 2021/10/09 15:14 by 127.0.0.1