Monday, February 20, 2012

Securing OpenLDAP Communications (LDAPS)

Securing OpenLDAP Communications (LDAPS)[part 2 of 4]

Introduction

Having setup a directory server and unix server clients it is now possible to authenticate OS users against the directory as a shared user repository for multiple nix based servers. However, we are not yet in a state that is ready for production, one issue to address is security. There are many aspects to security, this posting is only covering off one aspect, namely the transport level security where we change the configuration to make use of TLS to encrypt all data flowing in or out of the directory server so that it becomes impossible (well very hard) for someone to snoop the traffic on the network and discover a users' password.
In this example we make use of a self signed certificate to perform the encryption. This is fine for an internal directory server where we have control over all the clients and can set them up to trust the self-signed certificate. For production servers you should use a certificate from one of the trusted certificate authorities. The process for configuring openLDAP will be similar for self-signed or a certificate gained via a certificate authority. For details about self-signing or requesting from an authority see the openssl website and various blogs on the internet.

Creating a self signed certificate

We are using a self-signed certificate to perform the encryption. This can be done using the openssl tool, this is installed as part of the openssl package. In the distributions I have been using this has already been installed but if it is not present then use yum to install the package or download and add the rpm

# cd /etc/openldap/cacerts
# openssl req -newkey rsa:1024 -x509 -nodes -out server.pem -keyout server-key.pem -days 3650

answer the questions asked. An example shown below.

[root@c1718-10-100 cacerts]# openssl req -newkey rsa:1024 -x509 -nodes -out server.pem -keyout server-key.pem -days 3650
Generating a 1024 bit RSA private key
............................++++++
.................++++++
writing new private key to 'server.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [GB]:
State or Province Name (full name) [Berkshire]:
Locality Name (eg, city) [Newbury]:
Organization Name (eg, company) [My Company Ltd]:Your Company
Organizational Unit Name (eg, section) []:Your organisation
Common Name (eg, your name or your server's hostname) []:ldap-host
Email Address []:your.name@yourorg.com

This creates a self-signed certificate and key.

Configure OpenLDAP to use certificate for LDAPS communications.

Now we link this to OpenLDAP so that it uses the certificate to perform the encryption, enabling LDAPS. Simply add the following four lines to the slapd.conf file:-

...
TLSCACertificateFile /etc/openldap/cacerts/server.pem
TLSCertificateFile /etc/openldap/cacerts/server.pem
TLSCertificateKeyFile /etc/openldap/cacerts/server-key.pem
TLSCipherSuite HIGH:MEDIUM:+SSLv2
...

Now edit the file /etc/sysconfig/ldap and set up the machine so that it will start listening for LDAPS and stop listening for the plain text clients.
Contents of ldap file:-

# Parameters to ulimit called right before starting slapd
# - use this to change system limits for slapd
ULIMIT_SETTINGS=

# How long to wait between sending slapd TERM and KILL
# signals when stopping slapd by init script
# - format is the same as used when calling sleep
STOP_DELAY=3s

# By default only listening on ldap:/// is turned on.
# If you want to change listening options for slapd,
# set following three variables to yes or no
SLAPD_LDAP=no
SLAPD_LDAPS=yes
SLAPD_LDAPI=no

At this point is should now be possible to use any of the LDAP client browsers. (Apache Directory Studio, LDAP Browser, JXplorer etc.) to bind to the directory and query it's content via LDAPS. (The default port for LDAPS is 636, so the URL will be LDAPS://<your LDAP Host>:636.)

Client configuration to authenticate users via LDAP.

Now we need to configure the client side machines to authenticate via LDAP, using the secure LDAPS protocol. This is done via configuration in the files /etc/nsswitch.conf and /etc/ldap.conf. The former instructing the OS to use ldap to authenticate users and the latter providing the detail on how the server is to connect to LDAP.
For the nsswitch.conf file we simply include the check against ldap in the list of sources for passwd, group and shadow. Thus the file will look like:-

...
passwd: files ldap
shadow: files ldap
group: files ldap
...

Note - this file instructs the OS on the order of authentication methods, in this case the first attempt is to use the local file system (/etc/passwd etc.) and if the user is not registered there then lookup the user in LDAP. It is important to ensure that the order is - files then ldap. This ensures that should the directory be inaccessible it is still possible to authenticate and log onto the OS for management.
Now we need to make the necessary adjustments to the ldap.conf configuration file. The changes we do instruct the machine on where the directory is, what the base DN is, any authentication credentials required and the certificate trust store. The first step is to copy the server.pem file we created on the LDAP server over to this server. Then edit the pem file to remove the private key from the list of certificates. Copy the file into the directory /etc/openldap/cacerts
So the original file will look similar to :-

-----BEGIN RSA PRIVATE KEY-----
MIICXwIBAAKBgQDub+8oTFoVg+SBeqPCDN4EyspH+01ZFqCqyFlFORwi7LppNuXM
RlHuLYpBJpk0aJccm9Eqkxv2pc47ceNRkqWPjFVi1wOU+sfNBWAKZYOo7qgzrvMO
HY3Ge006stM0uYRSsd5RnwaKY+6vRmn0IOLyZXWq9XTNKyXlKfpJ4r8xhwIDAQAB
AoGBANk0ZKPMMgAJfz6oLsdWG2Y4Kd86wTJX15LcId5acRQrnIC+PsZAhOA44goJ
lGTWplmsY/Wpvz6HuoASdmbX9TI2BbH3Jr6xInqSGZN1jd4Fz10od/fyDKt+PueI
RoQWnPk9g7A93qAPtimbJUu3GCOvPPXvBCU8TSk2nZbdNrmZAkEA/DKpk1dywwS9
nRg9RqmIodSnhuslWeXUPSTA+RxGeQwKlYSNJNg4dspubVAUmnk4SBn4e6ICkbkB
2NBjhwsaEwJBAPIIKeUAnOhYyFFcPFJTAN/doA+wRKcjArNdlXFKGUk3mOh5bD1u
00K3i8RssV8Kdwfx/N+WM0xhaTUmmav9eT0CQQCIy4InpZteJMgk2e0C0xqFjS9n
bxq5nsxMjg8OEEQ5jEqBZ3CXt6CI7qyPJozGbVIV6eBaTzpNiKhzzjTuHxt5AkEA
pZXqO69IqjmbivZEmroI3h/9Ut5wibyNK3O6O1DLrejopxvzbrA0vu9eIxuN2g0J
1Ji9PabAH+CBHwjyl9WJrQJBAOFnotghVVR4dMToavKautfYkxQ5qVGlWyZKMRNw
n0klBjWxyI5n9B3Wyj7FgjAQbEVfnWhu4NVQiDWwoa1jXR4=
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIDmTCCAwKgAwIBAgIJAM7175vFl2JXMA0GCSqGSIb3DQEBBQUAMIGQMQswCQYD
VQQGEwJHQjESMBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MQ8w
DQYDVQQKEwZPcmFjbGUxDDAKBgNVBAsTA09TQzEWMBQGA1UEAxMNMTAuMTI4LjEw
LjEwMDEkMCIGCSqGSIb3DQEJARYVZG9uLmZvcmJlc0BvcmFjbGUuY29tMB4XDTEy
MDIyMDEwNTI1OVoXhsIDKDIxNzEwNTI1OVowgZAxCzAJBgNVBAYTAkdCMRIwEAYD
VQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxDzANBgNVBAoTBk9yYWNs
ZTEMMAoGA1UECxMDT1NDMRYwFAYDVQQDEw0xMC4xMjguMTAuMTAwMSQwIgYJKoZI
hvcNAQkBFhVkb24uZm9yYmVzQG9yYWNsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD
gY0AMIGJAoGBAO5v7yhMWhWD5IF6o8IM3gTKykf7TVkWoKrIWUU5HCLsumk25cxG
Ue4tikEmmTRolxyb0SqTG/alzjtx41GSpY+MVWLXA5T6x80FYAplg6juqDOu8w4d
jcZ7TTqy0zS5hFKx3lGfBopj7q9GafQg4vJldar1dM0rJeUp+knivzGHAgMBAAGj
gfgwgfUwHQYDVR0OBBYEFBquWl1CHXjqZYvxldfyyZ8mHnTKMIHFBgNVHSMEgb0w
gbqAFBquWl1CHXjqZYvxldfyyZ8mHnTKoYGWpIGTMIGQMQswCQYDVQQGEwJHQjES
MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MQ8wDQYDVQQKEwZP
cmFjbGUxDDAKBgNVBAsTA09TQzEWMBQGA1UEAxMNMTAuMTI4LjEwLjEwMDEkMCIG
CSqGSIb3DQEJARYVZG9uLmZvcmJlc0BvcmFjbGUuY29tggkAzvXvm8WXYlcwDAYD
VR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQDIywo7nKBux3SvNN6nBOkqNjNR
wBLzcZBFZipQlJ3Uj/ukKU7U8l9PzTTUW2m+M2vsGy7L5CNV/knW/mXUmeLC2255
2E3xHI3Rl5QnY6XVXy27ZrLF5xhWFPMR+8uSfFT+48mOlVk2uRrmyhwpZriDhpYT
hKScnYV/PpvIdsB7YA==
-----END CERTIFICATE-----

Remove the first "private key" entry to leave just the certificate:-

-----BEGIN CERTIFICATE-----
MIIDmTCCAwKgAwIBAgIJAM7175vFl2JXMA0GCSqGSIb3DQEBBQUAMIGQMQswCQYD
VQQGEwJHQjESMBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MQ8w
DQYDVQQKEwZPcmFjbGUxDDAKBgNVBAsTA09TQzEWMBQGA1UEAxMNMTAuMTI4LjEw
LjEwMDEkMCIGCSqGSIb3DQEJARYVZG9uLmZvcmJlc0BvcmFjbGUuY29tMB4XDTEy
MDIyMDEwNTI1OVoXDTIyMDIxNzEwNTI1OVowgZAxCzAJBgNVBAYTAkdCMRIwEAYD
VQQIEwlCZXJrc2hpcmUxEDAOBasdfjkTB05ld2J1cnkxDzANBgNVBAoTBk9yYWNs
ZTEMMAoGA1UECxMDT1NDMRYwFAYDVQQDEw0xMC4xMjguMTAuMTAwMSQwIgYJKoZI
hvcNAQkBFhVkb24uZm9yYmVzQG9yYWNsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD
gY0AMIGJAoGBAO5v7yhMWhWD5IF6o8IM3gTKykf7TVkWoKrIWUU5HCLsumk25cxG
Ue4tikEmmTRolxyb0SqTG/alzjtx41GSpY+MVWLXA5T6x80FYAplg6juqDOu8w4d
jcZ7TTqy0zS5hFKx3lGfBopjjs8kasdg4vJldar1dM0rJeUp+knivzGHAgMBAAGj
gfgwgfUwHQYDVR0OBBYEFBquWl1CHXjqZYvxldfyyZ8mHnTKMIHFBgNVHSMEgb0w
gbqAFBquWl1CHXjqZYvxldfyyZ8mHnTKoYGWpIGTMIGQMQswCQYDVQQGEwJHQjES
MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MQ8wDQYDVQQKEwZP
cmFjbGUxDDAKBgNVBAsTA09TQzEWMBQGA1UEAxMNMTAuMTI4LjEwLjEwMDEkMCIG
CSqGSIb3DQEJARYVZG9uLmZvcmJlc0BvcmFjbGUuY29tggkAzvXvm8WXYlcwDAYD
VR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQDIywo7nKBux3SvNN6nBOkqNjNR
wBLzcZBFZipQlJ3Uj/ukKU7U8l9PzTTUW2m+M2vsGy7L5CNV/knW/mXUmeLC2255
2E3xHI3Rl5QnY6XVXy27ZrLF5xhWFPMR+8uSfFT+48mOlVk2uRrmyhwpZriDhpYT
hKScnYV/PpvIdsB7YA==
-----END CERTIFICATE-----

now edit the ldap.conf file to comment out the entries for the host:port and replace them with the entry for the uri, pointing at your directory server instance. We also have to specify that ssl is on and the location of the cacert file. Thus we end up with:-

#host 10.128.10.100

# The distinguished name of the search base.
base dc=oscexa,dc=com

# Another way to specify your LDAP server is to provide an
# uri with the server name. This allows to use
# Unix Domain Sockets to connect to a local LDAP Server.
#uri ldap://127.0.0.1/
uri ldaps://192.168.10.100:636
#uri ldapi://%2fvar%2frun%2fldapi_sock/
# Note: %2f encodes the '/' used as directory separator
...
# OpenLDAP SSL mechanism
# start_tls mechanism uses the normal LDAP port, LDAPS typically 636
#ssl start_tls
ssl on

# OpenLDAP SSL options
# Require and verify server certificate (yes/no)
# Default is to use libldap's default behavior, which can be configured in
# /etc/openldap/ldap.conf using the TLS_REQCERT setting. The default for
# OpenLDAP 2.0 and earlier is "no", for 2.1 and later is "yes".
#tls_checkpeer yes

# CA certificates for server certificate verification
# At least one of these are required if tls_checkpeer is "yes"
#tls_cacertfile /etc/ssl/ca.cert
#tls_cacertdir /etc/ssl/certs
tls_cacertfile /etc/openldap/cacerts/server.pem
...

Now check that the authentication is working as you would expect. i.e. You use a test user in the directory that is not on the local filesystem and authenticate to the OS as that user.

Time Synchronisation

When using SSL to secure communications it becomes important to ensure that your servers are all sync'd to the same time source.  NTP is the simplest mechanism to use to perform this sync.  To setup ntp simply edit the file /etc/ntp.conf and ensure that you put in the line to identify your NTP server.  eg.

...
server <IP address of NTP server>
...

then restart your NTP daemon.



# service ntpd restart

You can check that things are working via the ntpq command line option.

# ntpq -n -c peers
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
 127.127.1.0     .LOCL.          10 l   53   64    1    0.000    0.000   0.001
 192.168.2.2      192.168.196.118  3 u   52   64    1    0.749  834.723   0.001

The numbers for the delay, offset and jitter should be non-zero.  If they are showing up as 0 then the chances are that you are not able to access the NTP server correctly.  If this is the case check the network access to the NTP server and that the server is responding to NTP requests.  Secondly, check the current time on your server and compare it to the time on the NTP server.  If the two are out by more than about 10 minutes then NTP assumes that things are very wrong and will not sync the time on the two machines.