How To Encrypt OpenLDAP Connections Using STARTTLS
Table of Contents
Introduction #
OpenLDAP provides an LDAP directory service that is flexible and well-supported. However, out-of-the-box, the server itself communicates over an unencrypted web connection. In this guide, we will demonstrate how to encrypt connections to OpenLDAP using STARTTLS to upgrade conventional connections to TLS. We will be using an Ubuntu 14.04 as our LDAP server.
Prerequisites #
Before you get started with this guide, you should have a non-root user with sudo
set up on your server. To set up a user of this type, follow our Ubuntu 14.04 initial setup guide.
We will cover how to install OpenLDAP on an Ubuntu 14.04 server in this guide. If you already have OpenLDAP installed on your server, you can skip the relevant installation and configuration steps.
LDAP Over SSL vs LDAP with STARTTLS #
There are two ways to encrypt LDAP connections with SSL/TLS.
Traditionally, LDAP connections that needed to be encrypted were handled on a separate port, typically 636
. The entire connection would be wrapped with SSL/TLS. This process, called LDAP over SSL, uses the ldaps://
protocol. This method of encryption is now deprecated.
STARTTLS is an alternative approach that is now the preferred method of encrypting an LDAP connection. STARTTLS “upgrades” a non-encrypted connection by wrapping it with SSL/TLS after/during the connection process. This allows unencrypted and encrypted connections to be handled by the same port. This guide will utilize STARTTLS to encrypt connections.
Setting the Hostname and FQDN #
Before you get started, we should set up our server so that it correctly resolves its hostname and fully qualified domain name (FQDN). This will be necessary in order for our certificates to be validated by clients. We will assume that our LDAP server will be hosted on a machine with the FQDN of ldap.example.com
.
To set the hostname in all of the relevant places on your server, use the hostnamectl
command with the set-hostname
option. Set the hostname to the short hostname (do not include the domain name component):
sudo hostnamectl set-hostname ldap
Next, we need to set the FQDN of our server by making sure that our /etc/hosts
file has the correct information:
sudo nano /etc/hosts
Find the line that maps the 127.0.1.1
IP address. Change the first field after the IP address to the FQDN of the server, and the second field to the short hostname. For our example, it would look something like this:
/etc/hosts
. . .
127.0.1.1 ldap.example.com ldap
127.0.0.1 localhost
. . .
Save and close the file when you are finished.
You can check that you’ve configured these values correctly by typing:
hostname
This should return your short hostname:
short hostname
ldap
Check the FQDN by typing:
hostname -f
This should return the FQDN:
FQDN setting
ldap.example.com
Installing the LDAP Server and GnuTLS Software #
After ensuring that your hostname is set properly, we can install the software we need. If you already have OpenLDAP installed and configured, you can skip the first sub-section.
Install the OpenLDAP Server #
If you do not already have OpenLDAP installed, now is the time to fix that. Update your server’s local package index and install the software by typing:
sudo apt-get update
sudo apt-get install slapd ldap-utils
You will be asked to provide an LDAP administrative password. Feel free to skip the prompt, as we will be reconfiguring immediately after.
In order to access some additional prompts that we need, we’ll reconfigure the package after installation. To do so, type:
sudo dpkg-reconfigure slapd
Answer the prompts appropriately, using the information below as a starting point:
Omit OpenLDAP server configuration? No (we want an initial database and configuration)
DNS domain name: example.com
(use the server’s domain name, minus the hostname. This will be used to create the base entry for the information tree)
Organization name: Example Inc (This will simply be added to the base entry as the name of your organization)
Administrator password: [whatever you’d like]
Confirm password: [must match the above]
Database backend to use: HDB (out of the two choices, this has the most functionality)
Do you want the database to be removed when slapd is purged? (your choice. Choose “Yes” to allow a completely clean removal, choose “No” to save your data even when the software is removed)
Move old database? Yes
Allow LDAPv2 protocol? No
Install the SSL Components #
Once your OpenLDAP server is configured, we can go ahead and install the packages we’ll use to encrypt our connection. The Ubuntu OpenLDAP package is compiled against the GnuTLS SSL libraries, so we will use GnuTLS to generate our SSL credentials:
sudo apt-get install gnutls-bin ssl-cert
With all of our tools installed, we can begin creating the certificates and keys needed to encrypt our connections.
Create the Certificate Templates #
To encrypt our connections, we’ll need to configure a certificate authority and use it to sign the keys for the LDAP server(s) in our infrastructure. So for our single server setup, we will need two sets of key/certificate pairs: one for the certificate authority itself and one that is associated with the LDAP service.
To create the certificates needed to represent these entities, we’ll create some template files. These will contain the information that the certtool
utility needs in order to create certificates with the appropriate properties.
Start by making a directory to store the template files:
sudo mkdir /etc/ssl/templates
Create the CA Template #
Create the template for the certificate authority first. We’ll call the file ca_server.conf
. Create and open the file in your text editor:
sudo nano /etc/ssl/templates/ca_server.conf
We only need to provide a few pieces of information in order to successfully create a certificate authority. We need to specify that the certificate will be for a CA (certificate authority) by adding the ca
option. We also need the cert_signing_key
option to give the generated certificate the ability to sign additional certificates. We can set the cn
to whatever descriptive name we’d like for our certificate authority:
caserver.conf
cn = LDAP Server CA
ca
cert_signing_key
Save and close the file.
Create the LDAP Service Template #
Next, we can create a template for our LDAP server certificate called ldap_server.conf
. Create and open the file in your text editor with sudo
privileges:
sudo nano /etc/ssl/templates/ldap_server.conf
Here, we’ll provide a few different pieces of information. We’ll provide the name of our organization and set the tls_www_server
, encryption_key
, and signing_key
options so that our cert has the basic functionality it needs.
The cn
in this template must match the FQDN of the LDAP server. If this value does not match, the client will reject the server’s certificate. We will also set the expiration date for the certificate. We’ll create a 10 year certificate to avoid having to manage frequent renewals:
ldapserver.conf
organization = "Example Inc"
cn = ldap.example.com
tls_www_server
encryption_key
signing_key
expiration_days = 3652
Save and close the file when you’re finished.
Create CA Key and Certificate #
Now that we have our templates, we can create our two key/certificate pairs. We need to create the certificate authority’s set first.
Use the certtool
utility to generate a private key. The /etc/ssl/private
directory is protected from non-root users and is the appropriate location to place the private keys we will be generating. We can generate a private key and write it to a file called ca_server.key
within this directory by typing:
sudo certtool -p --outfile /etc/ssl/private/ca_server.key
Now, we can use the private key that we just generated and the template file we created in the last section to create the certificate authority certificate. We will write this to a file in the /etc/ssl/certs
directory called ca_server.pem
:
sudo certtool -s --load-privkey /etc/ssl/private/ca_server.key --template /etc/ssl/templates/ca_server.conf --outfile /etc/ssl/certs/ca_server.pem
We now have the private key and certificate pair for our certificate authority. We can use this to sign the key that will be used to actually encrypt the LDAP session.
Create LDAP Service Key and Certificate #
Next, we need to generate a private key for our LDAP server. We will again put the generated key in the /etc/ssl/private
directory for security purposes and will call the file ldap_server.key
for clarity.
We can generate the appropriate key by typing:
sudo certtool -p --sec-param high --outfile /etc/ssl/private/ldap_server.key
Once we have the private key for the LDAP server, we have everything we need to generate a certificate for the server. We will need to pull in almost all of the components we’ve created thus far (the CA certificate and key, the LDAP server key, and the LDAP server template).
We will put the certificate in the /etc/ssl/certs
directory and name it ldap_server.pem
. The command we need is:
sudo certtool -c --load-privkey /etc/ssl/private/ldap_server.key --load-ca-certificate /etc/ssl/certs/ca_server.pem --load-ca-privkey /etc/ssl/private/ca_server.key --template /etc/ssl/templates/ldap_server.conf --outfile /etc/ssl/certs/ldap_server.pem
Give OpenLDAP Access to the LDAP Server Key #
We now have all of the certificates and keys we need. However, currently, our OpenLDAP process will be unable to access its own key.
A group called ssl-cert
already exists as the group-owner of the /etc/ssl/private
directory. We can add the user our OpenLDAP process runs under (openldap
) to this group:
sudo usermod -aG ssl-cert openldap
Now, our OpenLDAP user has access to the directory. We still need to give that group ownership of the ldap_server.key
file though so that we can allow read access. Give the ssl-cert
group ownership over that file by typing:
sudo chown :ssl-cert /etc/ssl/private/ldap_server.key
Now, give the ssl-cert
group read access to the file:
sudo chmod 640 /etc/ssl/private/ldap_server.key
Our OpenSSL process can now access the key file properly.
Configure OpenLDAP to Use the Certificate and Keys #
We have our files and have configured access to the components correctly. Now, we need to modify our OpenLDAP configuration to use the files we’ve made. We will do this by creating an LDIF file with our configuration changes and loading it into our LDAP instance.
Move to your home directory and open a file called addcerts.ldif
. We will put our configuration changes in this file:
cd ~
nano addcerts.ldif
To make configuration changes, we need to target the cn=config
entry of the configuration DIT. We need to specify that we are wanting to modify the attributes of the entry. Afterwards we need to add the olcTLSCACertificateFile
, olcCertificateFile
, and olcCertificateKeyFile
attributes and set them to the correct file locations.
The end result will look like this:
addcerts.ldif
dn: cn=config
changetype: modify
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/ssl/certs/ca_server.pem
-
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ssl/certs/ldap_server.pem
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ssl/private/ldap_server.key
Save and close the file when you are finished. Apply the changes to your OpenLDAP system using the ldapmodify
command:
sudo ldapmodify -H ldapi:// -Y EXTERNAL -f addcerts.ldif
We can reload OpenLDAP to apply the changes:
sudo service slapd force-reload
Our clients can now encrypt their connections to the server over the conventional ldap://
port by using STARTTLS.
Setting up the Client Machines #
In order to connect to the LDAP server and initiate a STARTTLS upgrade, the clients must have access to the certificate authority certificate and must request the upgrade.
On the OpenLDAP Server #
If you are interacting with the OpenLDAP server from the server itself, you can set up the client utilities by copying the CA certificate and adjusting the client configuration file.
First, copy the CA certificate from the /etc/ssl/certs
directory to a file within the /etc/ldap
directory. We will call this file ca_certs.pem
. This file can be used to store all of the CA certificates that clients on this machine may wish to access. For our purposes, this will only contain a single certificate:
sudo cp /etc/ssl/certs/ca_server.pem /etc/ldap/ca_certs.pem
Now, we can adjust the system-wide configuration file for the OpenLDAP utilities. Open up the configuration file in your text editor with sudo
privileges:
sudo nano /etc/ldap/ldap.conf
Adjust the value of the TLS_CACERT
option to point to the file we just created:
/etc/ldap/ldap.conf
. . .
TLS_CACERT /etc/ldap/ca_certs.pem
. . .
Save and close the file.
You should now be able to upgrade your connections to use STARTTLS by passing the -Z
option when using the OpenLDAP utilities. You can force STARTTLS upgrade by passing it twice. Test this by typing:
ldapwhoami -H ldap:// -x -ZZ
This forces a STARTTLS upgrade. If this is successful, you should see:
STARTTLS success
anonymous
If you mis-configured something, you will likely see an error like this:
STARTTLS failure
ldap_start_tls: Connect error (-11)
additional info: (unknown error code)
Configuring Remote Clients #
If you are connecting to your OpenLDAP server from remote servers, you will need to complete a similar process. First, you must copy the CA certificate to the client machine. You can do this easily with the scp
utility.
Forwarding SSH Keys to the Client
If you connect to your OpenLDAP server using SSH keys and your client machine is also remote, you will need to add them to an agent and forward them when connecting to your client machine.
To do this, on your local machine, start the SSH agent by typing:
eval $(ssh-agent)
Add your SSH key to the agent by typing:
ssh-add
Now, you can forward your SSH keys when you connect to your LDAP client machine by adding the -A
flag:
ssh -A user@ldap_client
Copying the CA Certificate
Once you are connected to the OpenLDAP client, you can copy the CA certificate by typing:
scp user@ldap.example.com:/etc/ssl/certs/ca_server.pem ~/
Now, append the copied certificate to the list of CA certificates that the client knows about. This will append the certificate to the file if it already exists and will create the file if it doesn’t:
cat ~/ca_server.pem | sudo tee -a /etc/ldap/ca_certs.pem
Adjust the Client Configuration
Next, we can adjust the global configuration file for the LDAP utilities to point to our ca_certs.pem
file. Open the file with sudo
privileges:
sudo nano /etc/ldap/ldap.conf
Find the TLS_CACERT
option and set it to the ca_certs.pem
file:
/etc/ldap/ldap.conf
. . .
TLS_CACERT /etc/ldap/ca_certs.pem
. . .
Save and close the file when you are finished.
Test the STARTTLS upgrade by typing this:
ldapwhoami -H ldap://ldap.example.com -x -ZZ
If the STARTTLS upgrade is successful, you should see:
STARTTLS success
anonymous
Force Connections to Use TLS (Optional) #
We’ve successfully configured our OpenLDAP server so that it can seamlessly upgrade normal LDAP connections to TLS through the STARTTLS process. However, this still allows unencrypted sessions, which may not be what you want.
If you wish to force STARTTLS upgrades for every connection, you can adjust your server’s settings. We will only be applying this requirement to the regular DIT, not the configuration DIT accessible beneath the cn=config
entry.
First, you need to find the appropriate entry to modify. We will print a list of all of the DITs (directory information trees: the hierarchies of entries that an LDAP server handles) that the OpenLDAP server has information about as well as the entry that configures each DIT.
On your OpenLDAP server, type:
sudo ldapsearch -H ldapi:// -Y EXTERNAL -b "cn=config" -LLL -Q "(olcSuffix=*)" dn olcSuffix
The response should look something like this:
DITs Served by OpenLDAP
dn: olcDatabase={1}hdb,cn=config
olcSuffix: dc=example,dc=com
You may have more DIT and database pairs if your server is configured to handle more than one DIT. Here, we have a single DIT with the base entry of dc=example,dc=com
, which would be the entry created for a domain of example.com
. This DIT’s configuration is handled by the olcDatabase={1}hdb,cn=config
entry. Make note of the DNs of the DITs you want to force encryption on.
We will use an LDIF file to make the changes. Create the LDIF file in your home directory. We will call it forcetls.ldif
:
nano ~/forcetls.ldif
Inside, target the DN you want to force TLS on. In our case, this will be dn: olcDatabase={1}hdb,cn=config
. We will set the changetype
to “modify” and add the olcSecurity
attribute. Set the value of the attribute to “tls=1” to force TLS for this DIT:
forcetls.ldif
dn: olcDatabase={1}hdb,cn=config
changetype: modify
add: olcSecurity
olcSecurity: tls=1
Save and close the file when you are finished.
To apply the change, type:
sudo ldapmodify -H ldapi:// -Y EXTERNAL -f forcetls.ldif
Reload the OpenLDAP service by typing:
sudo service slapd force-reload
Now, if you search the dc=example,dc=com
DIT, you will be refused if you do not use the -Z
option to initiate a STARTTLS upgrade:
ldapsearch -H ldap:// -x -b "dc=example,dc=com" -LLL dn
TLS required failure
Confidentiality required (13)
Additional information: TLS confidentiality required
We can demonstrate that STARTTLS connections still function correctly:
ldapsearch -H ldap:// -x -b "dc=example,dc=com" -LLL -Z dn
TLS required success
dn: dc=example,dc=com
dn: cn=admin,dc=example,dc=com
Conclusion #
You should now have an OpenLDAP server configured with STARTTLS encryption. Encrypting your connection to the OpenLDAP server with TLS allows you to verify the identity of the server you are connecting with. It also shields your traffic from intermediate parties. When connecting over an open network, encrypting your traffic is essential.