OpenLDAP: включить поддержку шифрования TLS для сервера и phpLdapAdmin клиента

Автор: | 01/04/2014
 

openldap_logoЧто такое TLS можно почитать тут>>>.

Наша задача – обеспечить шифрование между LDAP-сервером и его клиентом – phpLdapAdmin. Хотя они и работают  в данном случае на одном хосте – но даже в таком случае это имеет смысл, особенно – если на сервере имеются учётные записи для других пользователей с доступом к консоли. Почему – будет показано в конце.

Настройка выполняется на:

# uname -ro
FreeBSD 9.1-RELEASE-p5

В роли LDAP-сервера установлен:

# pkg_info | grep openldap
openldap-client-2.4.38 Open source LDAP client implementation
openldap-server-2.4.38_1 Open source LDAP server implementation

И:

# pkg_info | grep ldapadmin
phpldapadmin-1.2.3_2,1 PHP application to administer LDAP over the web

Про установку OpenLDAP на FreeBSD можно почитать тут>>>.

Первым делом – генерируем необходимые ключи.

Кратко:

key – приватный ключ сервера;
csrcertificate signing request, файл запроса для получения подписанного сертификата;
crt – собственно, сам сертификат сервера, он же – публичная часть ключа key.

Создаём ключ:

# openssl genrsa -out slapd.key
Generating RSA private key, 512 bit long modulus
...........++++++++++++
..........++++++++++++
e is 65537 (0x10001)

Создаём файл csr, который сами же потом подпишем.

Важно: в Common Name крайне рекомендуется указывать полное имя домена сервера:

# openssl req -new -key slapd.key -out slapd.csr
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) [AU]:UA
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:Kiev
Organization Name (eg, company) [Internet Widgits Pty Ltd]:ServerName
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:domain.in.ua
Email Address []:root@domain.in.ua

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Создаём и подписываем сертификат:

# openssl x509 -req -in slapd.csr -days 365 -signkey slapd.key -out slapd.crt
Signature ok
subject=/C=UA/ST=Some-State/L=Kiev/O=Domain/CN=domain.in.ua/emailAddress=root@domain.in.ua
Getting Private key

Создаём каталог, в котором будут храниться файлы:

# mkdir /home/domain/.ssh
# mv slapd.* /home/domain/.ssh
# chown -R ldap:ldap /home/domain/.ssh/
# chmod -R 500 /home/domain/.ssh/

Будьте внимательны с правами доступа к директории – не забывайте, что для доступа в неё требуется бит выполнения.

Например – если директория .ssh открыта всем:

 # ls -la ../ | grep ssh
drwxr-xr-x   5 setevoy  setevoy        512 Feb 16 18:33 .ssh

А ключи будут храниться во вложенной директории, и на неё у пользователя не будет права на выполнение:

# ls -l | grep slapd
dr--------  2 ldap     ldap        512 Feb 16 18:31 slapd

То LDAP не запустится:

 # service slapd restart
Stopping slapd.
Waiting for PIDS: 41615.
Starting slapd.
/usr/local/etc/rc.d/slapd: WARNING: failed to start slapd

Переходим к настройке самого сервера OpenLDAP:

# vim /usr/local/etc/openldap/slapd.conf

Раскомментируем строку:

security ssf=1 update_ssf=112 simple_bind=64

Тут:

ssf=1 – требовать шифрование;
update_ssf=112 – использовать 112-bit шифрование для операций с обновлениями записей;
simple_bind=64 – использовать 64-bit шифрвание при простой аутентификации.

Далее добавляем указание пути к используемым файлам:

TLSCertificateFile /home/domain/.ssh/slapd.crt
TLSCertificateKeyFile /home/domain/.ssh/slapd.key
TLSCACertificateFile /home/domain/.ssh/slapd.crt

Сохраняем, выходим и проверяем корректность файла конфигурации:

# slaptest -u
config file testing succeeded

Перезапускаем сервер:

# service slapd restart
Stopping slapd.
Waiting for PIDS: 61268.
Starting slapd.
# service slapd status
slapd is running as pid 61294.

Можно уже проверить – работает ли наш TLS на стороне сервера. Для этого – попробуем добавить ldif-файл с помощью ldapadd и ключём -Z, который явно указывает использовать TLS:

# ldapadd -Z -x -D "cn=root,dc=domain" -W -f base.ldif
ldap_start_tls: Connect error (-11)
additional info: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (self signed certificate)
Enter LDAP Password:
ldap_result: Can't contact LDAP server (-1)

Редактируем настройки ldap-клиента openldap-client-2.4.38, который устанавливается вместе с самим сервером и который используется phpLdapAdmin для подключения к серверу:

# vim /usr/local/etc/openldap/ldap.conf

Указываем корневую запись каталога (suffix в конфигурации LDAP-демона – /usr/local/etc/openldap/slapd.conf):

BASE    dc=domain
URI     ldap://localhost

Указываем о необходимости использования TLS:

ssl start_tls

И путь к публичной части ключа сервера:

tls_cacert /home/domain/.ssh/slapd.crt

И снова проверяем:

# ldapadd -Z -x -D "cn=root,dc=domain" -W -f base.ldif

Если получаем ошибку такого плана:

# ldapadd -Z -x -D "cn=root,dc=domain" -W -f base.ldif
ldap_start_tls: Connect error (-11)
Enter LDAP Password:
ldap_result: Can't contact LDAP server (-1)

Добавьте ключи -d -1 что бы запустить ldapadd в debug-режиме и увидеть точное описание ошибки:

# ldapadd -Z -d -1 -x -D "cn=root,dc=domain" -W -f base.ldif
...
ldap_msgfree
TLS: could not load verify locations (file:`/home/domain/.ssh/slapd.csr',dir:`').

Сначала – проверьте права на доступ к каталогу/файлу публичного сертификата. Если всё в порядке – замените tls_cacert на tls_cacertdir, и укажите не путь к самому файлу – а путь к директории:

tls_cacertdir /home/domain/.ssh/

Ещё одна возможная ошибка выглядит так:

# ldapadd -Z -x -D "cn=root,dc=domain" -W -f base.ldif
ldap_start_tls: Connect error (-11)
        additional info: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (self signed certificate)

Так как в данному случае используется самоподписанный сертификат – добавте опцию tls_reqcert и отключите вообще запрос на проверку валидности сертификата (never), либо установите в try опцию tls_reqcert:

tls_reqcert never

В итоге – файл /usr/local/etc/openldap/ldap.conf будет иметь примерно такой вид:

BASE    dc=domain
URI     ldap://localhost

ssl start_tls
tls_cacertdir /home/domain/.ssh/
tls_reqcert never

Сохраняем, переходим к настройке phpLdapAdmin:

# cd /usr/local/www/phpldapadmin/config/
# vim config.php

Раскомментируем и редактируем строки:

$servers->setValue('server','host','127.0.0.1');
$servers->setValue('server','port',389);

Чуть ниже находим строку:

// $servers->setValue('server','tls',false);

И меняем false (отключено) на true:

$servers->setValue('server','tls',true);

Сохраняем.

Теперь – немного о том, зачем включать шифрование.

Первый пример – без использования TLS.

Запускаем tcpdump с ключём -X (выводить содержимое перехваченных пакетов), и подключаемся к серверу с аутентификацией, например:

# ldapsearch -D "cn=root,dc=domain" -w PASSWORD

Или – просто заходим через phpLdapAdmin.

В результатах tcpdump видим:

# tcpdump -i lo0 -X -s 1024 port 389
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo0, link-type NULL (BSD loopback), capture size 1024 bytes
...                  ..1.
13:24:56.434552 IP localhost.36413 > localhost.ldap: Flags [P.], seq 1:45, ack 1, win 1120, options [nop,nop,TS val 296891025 ecr 2568106421], length 44
0x0000:  4500 0060 ddab 4000 4006 0000 7f00 0001  E..`..@.@.......
0x0010:  7f00 0001 8e3d 0185 c8ee eea7 6886 d0f3  .....=......h...
0x0020:  8018 0460 fe54 0000 0101 080a 11b2 3291  ...`.T........2.
0x0030:  9912 31b5 302a 0201 0160 2502 0103 0414  ..1.0*...`%.....
0x0040:  636e 3d72 6f6f 742c 6463 3d66 7265 6570  cn=root,dc=doma
0x0050:  726f 7879 800a 4e30 7761 7272 616e 7479  in..PASSWORD

В последних двух строках видно, что во время аутентификации логин/пароль передаются в открытом виде.

Теперь – повторяем ту же операцию, но уже с активным TLS:

13:26:22.928932 IP localhost.63566 > localhost.ldap: Flags [P.], seq 32:171, ack 15, win 1120, options [nop,nop,TS val 296977517 ecr 3091728088], length 139
0x0000:  4500 00bf de6b 4000 4006 0000 7f00 0001  E....k@.@.......
0x0010:  7f00 0001 f84e 0185 4c26 bbcc 8a1e 9387  .....N..L&......
0x0020:  8018 0460 feb3 0000 0101 080a 11b3 846d  ...`...........m
0x0030:  b848 06d8 8089 0103 0100 6000 0000 2000  .H........`.....
0x0040:  0039 0000 3800 0035 0000 8800 0087 0000  .9..8..5........
0x0050:  8400 0016 0000 1300 000a 0700 c000 0033  ...............3
0x0060:  0000 3200 002f 0000 4500 0044 0000 4103  ..2../..E..D..A.
0x0070:  0080 0000 0500 0004 0100 8000 0015 0000  ................
0x0080:  1200 0009 0600 4000 0014 0000 1100 0008  ......@.........
0x0090:  0000 0604 0080 0000 0302 0080 0000 ff3f  ...............?
0x00a0:  12e4 7ae2 0157 103b 9f51 f49a 5eb5 80ad  ..z..W.;.Q..^...
0x00b0:  ac52 b8e0 ccce f91e 02ed a903 97af d2    .R.............

Логина/пароля уже не видно, что и требовалось.

При включенном TLS-шифровании – для консольных утилит необходимо использовать ключ -Z:

# ldapsearch -Z -b 'dc=domain' 'uid=sysuser' | tail -n 1
# numResponses: 1