Secure OpenLDAP with TLS, MTLS, STARTTLS in Rocky Linux


Rocky Linux, OpenLDAP

In this tutorial we will learn how to secure OpenLDAP server with either TLS, Optional/Mandatory MTLS or STARTTLS. Now since we don't have a third party signed certificate so we will generate our own set of server and client certificates and use them with our OpenLDAP server and client.

 

Compare TLS Vs Mandatory MTLS Vs Optional MTLS Vs STARTTLS

TLS (Transport Layer Security)

Flow:

  1. Client Hello: The client sends a message to the server indicating it wants to establish a secure session.
  2. Server Hello: The server responds, providing its chosen cipher suite and its digital certificate.
  3. Key Exchange: The client and server exchange cryptographic keys.
  4. Client Finished: The client sends a message to indicate it has completed its part of the handshake.
  5. Server Finished: The server responds, completing the handshake.

Validation:

  • Server Validation: The client validates the server's certificate against a trusted CA.
  • Client Validation: Not required unless configured for mutual authentication.

 

Optional MTLS (Mutual TLS)

Flow:

  1. Client Hello: The client initiates the handshake.
  2. Server Hello: The server responds with its certificate and may request a client certificate.
  3. Client Certificate (optional): The client sends its certificate if requested.
  4. Key Exchange: Both parties exchange cryptographic keys.
  5. Finished Messages: Both client and server send finished messages to complete the handshake.

Validation:

  • Server Validation: The client validates the server's certificate.
  • Client Validation: The server attempts to validate the client's certificate if presented but does not abort if the client certificate is not provided.

 

Mandatory MTLS (Mutual TLS)

Flow:

  1. Client Hello: The client starts the secure session.
  2. Server Hello: The server responds with its certificate and requests the client's certificate.
  3. Client Certificate: The client must provide its certificate.
  4. Key Exchange: Both parties perform the key exchange.
  5. Finished Messages: Both client and server complete the handshake with finished messages.

Validation:

  • Server Validation: The client validates the server's certificate.
  • Client Validation: The server validates the client's certificate.

 

STARTTLS

Flow:

  1. Plaintext Connection: The client establishes a non-secure connection to the server.
  2. STARTTLS Command: The client sends the STARTTLS command to upgrade the connection to a secure one.
  3. TLS Handshake: The client and server perform the TLS handshake steps, including key exchange and certificate validation.
  4. Key Exchange: Both parties exchange cryptographic keys.
  5. Secure Connection: The connection is now secure, and communication can proceed encrypted.

Validation:

  • Server Validation: The client validates the server's certificate.
  • Client Validation: Can be optional or mandatory, depending on server configuration.

Now that you know little bit about different security mode and how they differ from each other, so you can plan to enable the respective security for your environment.

 

Generate Required Certificates

If you already have the required certificates then you can skip this step. In a nutshell you basically have to perform the following steps:

You can also refer The Only OpenSSL CheatSheet You Will Need! for more information.

I will store all my certs inside /certs:

mkdir /certs

Generate CA private key:

openssl genrsa -out /certs/ca.key 4096

Generate CA certificate

openssl req -new -x509 -days 3650 -key /certs/ca.key -out /certs/ca.crt
Secure OpenLDAP with TLS, MTLS, STARTTLS in Rocky Linux

Here is a shell script which will generate both server and client certificates inside /certs. The script is very basic and I have not added too many checks, if you intend to use it then I would recommend you to modify the individual fields such as CSR, SAN Fields based on your environment.

You can add multiple DNS and IP Addresses using DNS.1, DNS.2, DNS.3,... and IP.1, IP.2, IP.3 and so on. These fields should contain the FQDN/Hostname and IP of your LDAP server which will be used by clients for communication. For example in my case I am planning to use server.example.com to communication with LDAP server and the same has been updated to /etc/hosts.

For client certificate the SAN Field is not required so we are not passing any custom extension or configuration.

#!/bin/bash

# Define directories and filenames
CERT_DIR="/certs"
CA_KEY="${CERT_DIR}/ca.key"
CA_CERT="${CERT_DIR}/ca.crt"
CLIENT_KEY="${CERT_DIR}/client.key"
CLIENT_CSR="${CERT_DIR}/client.csr"
CLIENT_CERT="${CERT_DIR}/client.crt"
SERVER_KEY="${CERT_DIR}/server.key"
SERVER_CSR="${CERT_DIR}/server.csr"
SERVER_CERT="${CERT_DIR}/server.crt"

# Create the certs directory if it doesn't exist
[[ ! -d $CERT_DIR ]] && mkdir -p $CERT_DIR

# Generate server private key and CSR
openssl req -new -sha512 -nodes -out $SERVER_CSR -newkey rsa:4096 -keyout $SERVER_KEY -subj "/C=IN/ST=KARNATAKA/L=BENGALURU/O=GoLinuxCloud/OU=Admin/CN=ldap-server"

# Define OpenSSL configuration file for server extensions
SERVER_EXT_CONF="${CERT_DIR}/server_ext.cnf"
cat > $SERVER_EXT_CONF << EOF
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = @alt_names
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer

[ alt_names ]
DNS.1 = server.example.com
IP.1 = 10.10.1.17
EOF

# Generate server certificate with the correct extensions
openssl x509 -req -in $SERVER_CSR -CA $CA_CERT -CAkey $CA_KEY -CAcreateserial -out $SERVER_CERT -days 3650 -sha512 -extfile $SERVER_EXT_CONF -extensions v3_req

# Generate client private key and CSR
openssl req -new -sha512 -nodes -out $CLIENT_CSR -newkey rsa:4096 -keyout $CLIENT_KEY -subj "/C=IN/ST=KARNATAKA/L=BENGALURU/O=GoLinuxCloud/OU=Admin/CN=ldap-client"

# Generate client certificate
openssl x509 -req -in $CLIENT_CSR -CA $CA_CERT -CAkey $CA_KEY -CAcreateserial -out $CLIENT_CERT -days 3650 -sha512

echo "Certificates generated successfully."

Verify if SAN field is properly updated on server certificate:

openssl x509  -noout -text -in /certs/server.crt | grep -A 2 "X509v3 Subject Alternative Name"
Secure OpenLDAP with TLS, MTLS, STARTTLS in Rocky Linux

The script will generate both server and client certificate. You can copy the client certificates to your openldap client.

Since I am using same VM as master and client so I will copy all certificates inside /etc/openldap/certs.

sudo cp /certs/* /etc/openldap/certs/
sudo chown -R ldap:ldap /etc/openldap/certs/
sudo chmod 600 /etc/openldap/certs/*
Secure OpenLDAP with TLS, MTLS, STARTTLS in Rocky Linux

You can also choose to only copy certificate and key file as the CSR, ca.key, server_ext.cnf files are not required for securing LDAP server.

 

Configure Certificates on OpenLDAP Server

Configure your openldap server to consume the server certificates. Create an LDIF file (e.g., enable_tls.ldif) with the following content:

dn: cn=config
changetype: modify
replace: olcTLSCertificateFile
olcTLSCertificateFile: /etc/openldap/certs/server.crt
-
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/openldap/certs/server.key
-
replace: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/openldap/certs/ca.crt

Apply the configuration:

sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f enable_tls.ldif
Secure OpenLDAP with TLS, MTLS, STARTTLS in Rocky Linux

Verify the changes:

sudo ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=config olcTLSCACertificateFile olcTLSCertificateFile olcTLSCertificateKeyFile
Secure OpenLDAP with TLS, MTLS, STARTTLS in Rocky Linux

 

Enable LDAPS on OpenLDAP Server

In Rocky Linux by default LDAP runs on both port 389 and 636. You can verify if slapd is running with LDAPS support or not using below command:

systemctl status slapd
Secure OpenLDAP with TLS, MTLS, STARTTLS in Rocky Linux

Also check if LDAP server is listening on port 636 or not:

ss -ntlp | grep :636
Secure OpenLDAP with TLS, MTLS, STARTTLS in Rocky Linux

If in case in your environment if slapd is not configured to use ldaps then you can edit /usr/lib/systemd/system/slapd.service. Look for the ExecStart line and modify it to include the desired port

ExecStart=/usr/sbin/slapd -u ldap -h "ldap:/// ldaps:/// ldapi:///"

After editing the slapd.service file, reload the systemd configuration to apply the changes:

sudo systemctl daemon-reload

Restart the OpenLDAP service to apply the changes:

sudo systemctl restart slapd

Verify that OpenLDAP is now listening on the new ports using netstat or ss:

sudo netstat -tulnp | grep slapd

OR

sudo ss -tulnp | grep slapd

 

Configure Firewall and SELinux

Ensure that your firewall allows traffic on port 389 and 636, which is the default port for LDAP and LDAPS respectively.

Verify if firewalld is running:

sudo systemctl status firewalld

If it is not running, you can start it with:

sudo systemctl start firewalld

Open port 389 and 636 to allow LDAP and LDAPS traffic. You can use the following command:

sudo firewall-cmd --permanent --add-port=389/tcp
sudo firewall-cmd --permanent --add-port=636/tcp

Apply the changes by reloading the firewall rules:

sudo firewall-cmd --reload

Ensure that the rule has been added correctly:

sudo firewall-cmd --list-all

If SELinux is enabled, make sure it is configured to allow OpenLDAP to use the certificates and the LDAPS port.

sudo setsebool -P allow_ldap_tls=on
sudo semanage port -a -t ldap_port_t -p tcp 636
sudo semanage port -a -t ldap_port_t -p tcp 389

To verify that the ports have been correctly added, you can use the following command:

sudo semanage port -l | grep ldap

 

Understanding olcTLSVerifyClient and olcSecurity

Based on the type of security we will configure OpenLDAP server with two options olcTLSVerifyClient and olcSecurity to control the OpenLDAP security.

The olcSecurity attribute in OpenLDAP is used to configure security-related policies for the LDAP server. Specifically, it can be used to enforce various levels of security on the LDAP connections, such as requiring encryption or stronger authentication mechanisms.

  • tls=0: No security required.
  • tls=1: Requires the use of TLS for all operations.
  • ssf=128: Security Strength Factor of 128 bits required.
  • transport=256: Requires a transport layer with a security strength factor of 256 bits.

The olcTLSVerifyClient directive in OpenLDAP specifies the level of client certificate verification required during a TLS (SSL) handshake. Here's what the different settings mean:

  • demand (or hard): The server requires the client to provide a certificate. If the client does not provide a certificate or the certificate is not valid, the connection is aborted.
  • never: The server never asks the client for a certificate.
  • allow: The server asks the client for a certificate, but the client may choose not to provide one. If a certificate is provided, it will be checked.
  • try: The server asks the client for a certificate, but if the client does not provide one, the server proceeds with the connection anyway. If a certificate is provided, it will be checked.

We will be using these options in the next sections to configure OpenLDAP with TLS, MTLS or STARTTLS.

 

Secure OpenLDAP Server with TLS

For TLS communication we don't need any additional config on the OpenLDAP server. Simply adding the certificates is enough.

Configure your client to use the CA certificate for any LDAP communication. Add the following for client configuration (/etc/openldap/ldap.conf):

TLS_CACERT /etc/openldap/certs/ca.crt

Test the LDAP client connection with TLS/SSL:

ldapsearch -H ldaps://server.example.com -b "dc=example,dc=com" -D "cn=admin,dc=example,dc=com" -W

 

Secure OpenLDAP with Optional MTLS

On OpenLDAP server, create an LDIF file (e.g., optional_mtls.ldif) with the following content:

dn: cn=config
changetype: modify
replace: olcTLSVerifyClient
olcTLSVerifyClient: allow

Apply the changes using the ldapmodify command:

sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f optional_mtls.ldif

Restart the OpenLDAP service to apply the changes:

sudo systemctl restart slapd

On OpenLDAP Client, edit the LDAP client configuration file /etc/openldap/ldap.conf to include the TLS settings:

TLS_CACERT /etc/openldap/certs/ca.crt
TLS_CERT /etc/openldap/certs/client.crt
TLS_KEY /etc/openldap/certs/client.key
TLS_REQCERT allow

Use ldapsearch to test the connection with optional MTLS. The server will request the client certificate, but it will not be mandatory:

sudo ldapsearch -H ldaps://server.example.com -x -D "cn=admin,dc=example,dc=com" -W -b "dc=example,dc=com"
Secure OpenLDAP with TLS, MTLS, STARTTLS in Rocky Linux

 

Secure OpenLDAP with Mandatory MTLS

On OpenLDAP server, create an LDIF file (e.g., mandatory_mtls.ldif) with the following content:

dn: cn=config
changetype: modify
replace: olcTLSVerifyClient
olcTLSVerifyClient: demand

Apply the changes using the ldapmodify command:

sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f mandatory_mtls.ldif
Secure OpenLDAP with TLS, MTLS, STARTTLS in Rocky Linux

Restart the OpenLDAP service to apply the changes:

sudo systemctl restart slapd

On OpenLDAP Client, edit the LDAP client configuration file /etc/openldap/ldap.conf to include the TLS settings:

TLS_CACERT /etc/openldap/certs/ca.crt
TLS_CERT /etc/openldap/certs/client.crt
TLS_KEY /etc/openldap/certs/client.key
TLS_REQCERT demand

In some cases we also have to set the environment variable on the LDAP client:

export LDAPTLS_CACERT=/etc/openldap/certs/ca.crt
export LDAPTLS_CERT=/etc/openldap/certs/client.crt
export LDAPTLS_KEY=/etc/openldap/certs/client.key

Use ldapsearch to test the connection with optional MTLS. The server will request the client certificate, but it will not be mandatory:

sudo ldapsearch -H ldaps://server.example.com -x -D "cn=admin,dc=example,dc=com" -W -b "dc=example,dc=com"
Secure OpenLDAP with TLS, MTLS, STARTTLS in Rocky Linux

The query is successful which would mean that we are successfully able to establish communication with LDAP server over MTLS.

 

Secure OpenLDAP with STARTTLS

Configure OpenLDAP server to enable TLS for all communication. Create a file named enable_starttls.ldif with the following content:

dn: cn=config
changetype: modify
replace: olcSecurity
olcSecurity: tls=1

Apply the changes using the ldapmodify command:

sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f enable_starttls.ldif
Secure OpenLDAP with TLS, MTLS, STARTTLS in Rocky Linux

Restart the OpenLDAP service to apply the changes:

sudo systemctl restart slapd

On OpenLDAP client, Add the following lines in /etc/openldap/ldap.conf:

TLS_CACERT /etc/openldap/certs/ca.crt
TLS_CERT /etc/openldap/certs/client.crt
TLS_KEY /etc/openldap/certs/client.key
TLS_REQCERT demand

The only difference here is that with STARTTLS we will perform the LDAP communication on a non-secure port i.e. port 389 unlike MTLS where we were using ldaps with port 636. For STARTLS you need not enable ldaps:/// in the server configuration because as explained earlier, It starts with a non-secure connection and upgrades to a secure connection using the STARTTLS command.

You can test STARTTLS using the ldapsearch command, which attempts to start TLS on an LDAP connection:

ldapsearch -H ldap://server.example.com -b "dc=example,dc=com" -D "cn=admin,dc=example,dc=com" -W -x 

Notice the error we get here:

ldap_bind: Confidentiality required (13)
additional info: TLS confidentiality required

This is because we have enforced TLS based communication. So we must add -ZZ to initiate STARTTLS.

ldapsearch -H ldap://server.example.com -b "dc=example,dc=com" -D "cn=admin,dc=example,dc=com" -W -x -ZZ

Here if you notice I am using default LDAP port number with additional argument -ZZ to enable STARTTLS.

Secure OpenLDAP with TLS, MTLS, STARTTLS in Rocky Linux

To verify if encryption is working, I have collected tcpdump using tcpdump -i any -w /home/deepak/ldap_starttls.pcap port 389. Here is the snippet from Wireshark:

Secure OpenLDAP with TLS, MTLS, STARTTLS in Rocky Linux
  • The extendedReq with LDAP_START_TLS_OID is the client requesting to start TLS on the existing LDAP connection.
  • Client Hello: The client initiates the TLS handshake.
  • Server Hello: The server responds to the client's handshake request.

This sequence shows that the STARTTLS operation is initiated, and the TLS handshake process is starting as expected

 

With ldap's native commands we don't have too many options to debug any TLS related failures. So we can rely on openssl command to debug any TLS related issues.

For MTLS communication, pass the client certificate and key and observe the output:

openssl s_client -connect server.example.com:636 -CAfile /etc/openldap/certs/ca.crt -cert /etc/openldap/certs/client.crt -key /etc/openldap/certs/client.key

Check if the TLS handshake is completed successfully. Look for the following in the debug output:

  • SSL handshake has read xxx bytes and written xxx bytes
  • Verification: OK

Ensure the server is requesting and correctly validating the client certificate. Look for the Acceptable client certificate CA names and Verify return code: 0 (ok).

The tls_write: want=24 error=Broken pipe error indicates the connection was terminated unexpectedly. This could be due to the server rejecting the client certificate or an issue with the client configuration.

With Optional MTLS or TLS you only need to pass CA certificate:

openssl s_client -connect server.example.com:636 -CAfile /etc/openldap/certs/ca.crt

You can also refer official OpenLDAP troubleshooting manual to cover more scenarios.

 

In this tutorial we learned to create our own Certificate Authority certificate, and then used this CA certificate to create ldap client certificate. This CA and client certificate will be used across all the ldap clients for encrypted and secure communication. I have created SAN certificate here but you can choose to create individual client certificates for all your ldap client nodes.

Refer official OpenLDAP Administration document and setting up OpenLDAP with TLS/SSL mutual authentication for more information.

Next you can read How to decrypt HTTPS & LDAPS Traffic using WireShark

 

Deepak Prasad

Deepak Prasad

Deepak Prasad is the founder of GoLinuxCloud, bringing over a decade of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, Networking, and Security. His extensive experience spans development, DevOps, networking, and security, ensuring robust and efficient solutions for diverse projects.

Certifications and Credentials:

  • Certified Kubernetes Application Developer (CKAD)
  • Go Developer Certification
  • Linux Foundation Certified System Administrator (LFCS)
  • Certified Ethical Hacker (CEH)
  • Python Institute PCAP (Certified Associate in Python Programming)
You can connect with him on his LinkedIn profile and join his Facebook and LinkedIn page.

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to admin@golinuxcloud.com

Thank You for your support!!

1 thought on “Secure OpenLDAP with TLS, MTLS, STARTTLS in Rocky Linux”

  1. Hi Experts,

    I want to change version from Version: 1 (0x0) to Version: 3 (0x2)
    I am working on the following topic “Configure OpenLDAP over TLS with RootCA Issued Certificate”.

    I have issued 3rd command on step 2.

    After that I am trying to print the certificate content using the following command “openssl req -text -noout -verify -in CSR.csr

    output :
    openssl req -text -noout -verify -in test.csr verify OK
    Certificate Request:
    Data:
    Version: 1 (0x0)
    Subject: CN = 10.0.101.239, O = AMI
    Subject Public Key Info:
    Public Key Algorithm: rsaEncryption
    RSA Public-Key: (3072 bit)

    Reply

Leave a Comment