UMGUM.COM 

Перевод 389-AS/DS на SSL ( Защищаем сетевые соединения LDAP-инстанса "389-DS" и сервера администрирования "389-AS" SSL/TLS-шифрованием с последующим отключением небезопасного протокола доступа. )

11 декабря 2019  (обновлено 14 марта 2020)

OS: "Linux Ubuntu 18 (Bionic) LTS".
Application: "389 Administration & Directory Server v.1.3.7", "OpenSSL".

Задача: защитить клиент-серверные соединения LDAP-инстанса "389-DS" и сервера администрирования "389-AS" SSL/TLS-шифрованием с последующим отключением небезопасного протокола доступа.

Сервисы "389-DS" могут обслуживать клиентов как в открытом виде, так и в защищённом SSL/TLS-шифрованием соединении, при этом поддерживается три режима работы:

1. Open LDAP, TCP:389 - передача данных в открытом виде.
2. LDAP with StartTLS, TCP:389 - включение шифрования данных по требованию клиента.
3. LDAPS with SSL/TLS, TCP:636 - обязательное шифрование передаваемых данных.

Таким образом, при подключении к LDAP-сервису клиент может выбрать, насколько защищённое соединение ему устанавливать, в зависимости от секретности задачи.

Зачем применять шифрование клиентских соединения при работе с LDAP, внутри которого пользовательские пароли хранятся в виде "хешей"? На удивление многие считают, что если пароль на стороне сервера "хеширован", то и на этапе аутентификации при подключении он не будет раскрыт. Налицо отсутствие причинно-следственной связи, но не всем это понятно без демонстрации доказательств.

Посмотрим, что можно выловить из сетевых пакетов простейшего запроса выборки атрибутов одной записи, с предварительной аутентификацией, разумеется:


$ ldapsearch -x -v -H ldap://ldap0.example.net -D "uid=userOne,ou=People,dc=example,dc=net" -w password -b uid=userOne,ou=People,dc=example,dc=net

На компьютере, откуда исходят запросы (это непринципиально - трафик можно прослушивать и на транзитных узлах), запускаем "tcpdump":

# tcpdump -nn -A -q -l -i eth0 dst ldap0.example.net && port 389

....
...&uid=userOne,ou=People,dc=example,dc=net..password
....

В аналогичных условиях запускаем "tshark" (более умелая утилита - "terminal-based Wireshark" - способная структурировать трафик по патернам, в нашем случае LDAP):

# tshark -i vnet0 -f "dst ldap0.example.net && port 389" -n -O ldap -Y "ldap.protocolOp == 0"

....
Transmission Control Protocol, Src Port: 57418, Dst Port: 389, Seq: 1, Ack: 1, Len: 56
Lightweight Directory Access Protocol
  LDAPMessage bindRequest(1) "uid=userOne,ou=People,dc=example,dc=net" simple
    messageID: 1
    protocolOp: bindRequest (0)
      bindRequest
        version: 3
        name: uid=userOne,ou=People,dc=example,dc=net
        authentication: simple (0)
          simple: password

Очевидно, что "простой (simple)" метод аутентификации LDAP без инкапсуляции в SSL/TLS должен стать запретным для всех областей применения, кроме демонстрации возможностей на тестовом стенде.

Считаю разумным вообще запретить подключения к LDAP-сервису извне по незащищённому протоколу LDAP, что мы и сделаем в дальнейшем, после настройки SSL/TLS для серверов "389-AS/DS".

Последовательность дальнейших действий такова:

1. Генерируем сертификаты.
2. Настраиваем LDAPS для "389-DS".
3. Методика возврата к предыдущим настройкам "389-DS".
4. Проверка работы клиента с "389-DS" через SSL/TLS.
5. Настраиваем SSL/TLS для "389-AS".
6. Методика возврата к предыдущим настройкам "389-AS".
7. Деактивируем поддержку устаревшего SSLv3.
8. Опционально переводим "389-AS/DS" на IPv4.
9. Закрываем доступ извне к незащищённому LDAP.

Генерируем сертификаты.

В качестве SSL-сертификата в "389-AS/DS" применяется классический "x509". Можно попробовать использовать обычный SSL-сертификат, вроде тех, которыми обеспечивают HTTPS для web-сайтов. Можно воспользоваться инфраструктурой локального удостоверяющего (сертификационного) центра, если таковой на предприятии уже функционирует, и создать для LDAP-сервиса сертификат, подписанный всей цепочкой доверенных узлов. А можно создать и применить "самоподписанный" сертификат, особенно если сервис не публичный, предприятие небольшое и блюсти красоту нет необходимости или возможности.

Воспользуемся документацией от разработчиков: для "RHDS" и для "FDS" (немного старого).

Следуя правильным путём, мы бы средствами "389-DS" сформировали запрос на выпуск сертификата для целевого LDAP-инстанса, отправили его в центр сертификации предприятия, получили в ответ готовый сертификат и уже его импортировали в "NSS-базу сертификатов" LDAP-инстанса.

Но мы здесь разбираем вариант с применением "самоподписанного" корневого сертификата, так что просто создаём его, потом создаём подписанные им сертификаты компонентов и размещаем их NSS-хранилищах.

Заготовим место в файловой системе условно основного LDAP-сервера, где будем создавать и хранить сертификаты всех участников схемы:

# mkdir -p /etc/ssl/dirsrv
# cd /etc/ssl/dirsrv

Заготовим файл с "цифровым шумом", который потребуется в полуавтоматизированных процедурах создания сертификатов:

# openssl rand -out /root/.rnd -hex 256

Создаём закрытую и открытую часть корневого сертификата ("самоподписанного"):

# openssl req \
  -subj "/C=RU/ST=State/L=City/O=Example, Inc./OU=IT/CN=Self-Signed Root CA certificat" \
  -newkey rsa:4096 -nodes -keyout ./ss-rootCA.key \
  -x509 -days 3650 -out ./ss-rootCA.crt

Теперь мы располагаем двумя частями "самоподписанного" корневого сертификата: публичной "ss-rootCA.crt" и секретной "ss-rootCA.key", используемой только для подписания других сертификатов.

Далее создаём простейший сертификат для LDAP-инстанса, заверяя его "самоподписанным" корневым сертификатом (в три этапа, с "закрытым" ключём, CSR-запросом, и затем подписанным сертификатом):

# openssl genrsa -out ./ldap0.example.net.key 4096
# openssl req -new \
  -subj "/OU=389 Administration\/Directory Server/CN=ldap0.example.net" \
  -key ./ldap0.example.net.key \
  -out ./ldap0.example.net.csr
# openssl x509 -req \
  -in ./ldap0.example.net.csr \
  -CA ./ss-rootCA.crt -CAkey ./ss-rootCA.key -CAcreateserial \
  -days 3650 -out ./ldap0.example.net.crt

Просмотр содержимого сертификата - всех трёх его компонентов:

# openssl rsa -noout -text -in ./ldap0.example,net.key | less
# openssl req -noout -text -in ./ldap0.example.net.csr | less
# openssl x509 -noout -text -in ./ldap0.example.net.crt | less

Компонуем приватную и публичную части сертификата в PFX-контейнер - в таком виде они удобнее импортируются впоследствии в NSS-хранилище LDAP-инстанса (конечно же, не забываем пароль, которым будет защищён контейнер с сертифкатом):

# openssl pkcs12 -export -name "(AS/DS) ldap0.example,net" -out ./ldap0.example.net.p12 -inkey ./ldap0.example.net.key -in ./ldap0.example.net.crt

Очевидно, что такие наборы из "приватного" ключа, CSR-запроса, итогового сертификата и PXF-контейнера нужно создать для всех LDAP-инстансов и серверов администрирования настраиваемой схемы, запускаемых на отдельных сетевых узлах.

Обращаю внимание на то, что все наборы сертификатов, подписываемых одним корневым сертификатом, очень желательно генерировать в одном месте, например выделенном для хранения "приватного" ключа корневого сертификата. Дело в том, что при каждом создании и подписании нового сертификата в рабочей директории создаётся и обновляется файл "ss-rootCA.srl", содержащий случайный набор символов с присоединённым в конце шестнадцатеричным порядковым номером очередного сертификата (простая последовательность: 01,02,03,...). Так вот, если генерировать и подписывать сертификаты в разных местах, то у них могут оказаться одинаковые номера, что впоследствии будет замечено чутким клиентским приложением, которое откажется принимать такие сертификаты.

# chown -R root:root /etc/ssl/dirsrv
# chmod -R go-rwx /etc/ssl/dirsrv

Настраиваем LDAPS для "389-DS".

Теперь настроим поддержку SSL/TLS LDAP-инстанса. Его "база сертификатов" располагается в файловой директории с настройками "/etc/dirsrv/slapd-ldap0-example-net".

Для простоты и краткости дальнейших команд переходим в директорию конфигурации LDAP-инстанса и будем работать уже там:

# cd /etc/dirsrv/slapd-ldap0-example-net

Первым делом есть смысл запросить посредством утилиты "certutil" из набора "libnss3" перечень возможно уже имеющихся сертификатов:

# certutil -d . -L

Если LDAP-сервис свежеустановленный, то "NSS-база сертификатов" для него отсутствует или неактивированна. Создадим зашифрованное и защищённое отдельным паролем (не забываем его) хранилище SSL-сертификатов (файлы "key3.db", "cert8.db" & "secmod.db"):

# certutil -d . -N

В процессе создания "NSS-базы сертификатов" задаётся пароль доступа к таковой. В дальнейшем потребуется вводить этот пароль для доступа к хранилищу сертификатов и это доставит некоторые неудобства - дело в том, что даже сам сервер "389-DS" не сможет запуститься без процедуры ввода пароля для доступа к SSL/TLS-сертификатам, которыми он должен шифровать соединения клиентов - в дальнейшем ещё придётся обходить это ограничение, а пока будим вводить пароль вручную.

Сразу импортируем публичную часть корневого сертификата (он у нас "самоподписанный") в NSS-хранилище, объявив его доверенным узлом - удостоверяющим центром (это важная для сетевой связности участников схемы репликации процедура, хотя SSL-сервис запустится и без неё):

# certutil -A -d . -n "Self-Signed Root CA certificat" -t "CT,," -a -i /etc/ssl/dirsrv/ss-rootCA.crt

Импортируем заготовленный ранее контейнер с "приватной" и публичной частями сертификата LDAP-инстанса:

# pk12util -d . -n "(AS/DS) ldap0.example,net" -i /etc/ssl/dirsrv/ldap0.example.net.p12

Ненужные сертификаты легко удалить, указав в качестве идентификатора их наименование:

# certutil -D -d . -n "Instance certificate"

После создания сертификатов включаем функционал поддержки шифрования клиентских соединений:

В GUI "389 Console" это выглядит так:

DS Console -> Configuration -> "ldap0.example.net" -> Encryption:
  Enable SSL for this server: on
  Use this cipher family RSA
    Security Device: internal
    Certificate: (AS/DS) ldap0.example.net
  Client Authentication:
    # Перед нами не стоит задача аутентификации клиентов посредством сертификатов (мы только защищаем трафик шифрованием), потому явно отключаем это функционал.
    Do not allow client authentication
    # (до перевода на SSL сервера "389-AS" нет смысла переключать на SSL GUI-утилиту "389-console")
    Use SSL in Console: off
Save.

На этом настройка поддержки SSL/TLS-шифрования для "389-DS" завершена и нужно будет перезагрузить LDAP-инстанс. Вот здесь в полной мере проявится неудобство от обязательной защиты "NSS-базы сертификатов" паролем, который вводится только интерактивно - при запуске сервер "389-DS" обратится к сервису хранилища сертификатов, который запросит посредством метода "tty-ask-password" ввести пароль:

....
Please enter password with the systemd-tty-ask-password-agent tool!
Enter PIN for Internal (Software) Token: ***

Не вдаваясь в детали реализации, сразу приведу решение автоматизации. Используемый для запроса пароля сервис "systemd-tty-ask-password-agent" принимает таковой их простого текстового файла с зарезервированным именем "pin.txt", размещаемого в одной директории с целевой "NSS-базой":

# vi /etc/dirsrv/slapd-ldap0-example-net/pin.txt

Internal (Software) Token:<passoword>

Обращаю внимание - текстовая конструкция в примере выше должна быть такой с точностью до символа, а между двоеточием и паролем пробелы недопустимы.

Разумеется, файл с паролем закрываем от посторонних:

# chown dirsrv:dirsrv /etc/dirsrv/slapd-ldap0-example-net/pin.txt
# chmod go-rwx /etc/dirsrv/slapd-ldap0-example-net/pin.txt

Теперь можно перезапускать LDAP-инстанс:

# stop-dirsrv ldap0-example-net && start-dirsrv ldap0-example-net

Проверяем, прослушивает ли сервис теперь и TCP:636 - порт для SSL/TLS-соединений:

# netstat -apn | grep -i "^tcp" | grep -i listen | grep -i "ns-slapd"

tcp ... 0.0.0.0:636  0.0.0.0:*  LISTEN .../ns-slapd
tcp ... 0.0.0.0:389  0.0.0.0:*  LISTEN .../ns-slapd

После настройки функционала поддержки SSL/TLS-шифрования также станет возможна аутентификация пользователей посредством выдаваемых им индивидуальных SSL-сертификатов, но это необязательный функционал - главное, чего мы сейчас добиваемся, так это защита клиент-серверного трафика от прослушивания посторонними.

Методика возврата к предыдущим настройкам "389-DS".

Если что-то пошло не так, и потребуется быстро отключить поддержку SSL/TLS в "389-DS":

$ ldapmodify -h 127.0.0.1 -p 389 -D "cn=Directory Manager" -W

dn: cn=config
changetype: modify
replace: nsslapd-security
nsslapd-security: off

dn: cn=RSA,cn=encryption,cn=config
changetype: modify
replace: nsSSLActivation
nsSSLActivation: off

^d

# stop-dirsrv ldap0-example-net && start-dirsrv ldap0-example-net

Проверка работы клиента с "389-DS" через SSL/TLS.

Легко проверить, готов ли LDAP-сервер принимать SSL/TLS-соединения.

Пробуем соединиться через порт для LDAP, поддерживающий "StartTLS":

$ echo QUIT | openssl s_client -starttls ldap -connect ldap0.example.net:389 | less

Пробуем соединиться и запросить сертификат через выделенный только для SSL-порт:

$ echo QUIT | openssl s_client -connect ldap0.example.net:636 | openssl x509 -noout -text | less
$ echo QUIT | openssl s_client -connect ldap0.example.net:636 | less

CONNECTED(00000005)
depth=1 CN = Self-Signed Root CA cert
verify error:num=19:self signed certificate in certificate chain
....

В журнале событий LDAP-сервера будут фиксироваться эти попытки, с указанием протокола шифрования.

В сообщениях утилиты "openssl" выше было видно, что проверить действительность сертификата невозможно, так как он "самоподписанный". Из-за этого большинство приложений не будут подключаться к LDAP-серверу без явного указания игнорировать результаты проверки подлинности сертификата:

$ ldapsearch -x -v -H ldaps://ldap0.example.net -D "uid=app0,ou=Services,dc=example,dc=net" -W -b uid=userOne,ou=People,dc=example,dc=net

ldap_initialize( ldaps://ldap0.example.net:636/??base )
Enter LDAP Password:
ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1)

Тот же принцип и для соединения через порт TCP:389, предназначенный для открытой передачи данных, с запросом шифрования посредством "StartTLS" - использование "самоподписанного" сертификата по умолчанию недопустимо:

$ ldapsearch -x -v -ZZ -H ldap://ldap0.example.net -D "uid=app0,ou=Services,dc=example,dc=net" -W -b uid=userOne,ou=People,dc=example,dc=net

ldap_initialize( ldap://ldap0.example.net:389/??base )
ldap_start_tls: Connect error (-11)
  additional info: (unknown error code)

Выяснить, что конкретно не срабатывает при подключении к LDAP-серверу, помогает включение режима отладки (ключ "-d") - в данном случае видно, что клиентское приложение не может проверить валидность цепи доверия сертификатов:

$ ldapsearch -d 1 -x -v -H ldaps://ldap0.example.net -D "uid=app0,ou=Services,dc=example,dc=net" -W -b uid=userOne,ou=People,dc=example,dc=net

....
ldap_initialize( ldaps://ldap0.example.net:636/??base )
....
connect success
....
TLS: peer cert untrusted or revoked (0x42)
TLS: can't connect: (unknown error code).
....

Специальным параметром, передаваемым здесь в переменной окружения, укажем утилите "ldapsearch" не запрашивать проверку валидности SSL/TLS-сертификата сервера:

$ LDAPTLS_REQCERT=allow ldapsearch -x -v -H ldaps://ldap0.example.net -D "uid=app0,ou=Services,dc=example,dc=net" -W -b uid=userOne,ou=People,dc=example,dc=net

Теперь соединение должно пройти успешно.

Настраиваем LDAPS для "389-AS".

Настройка поддержки SSL для сервера администрирования "389-AS" во многом аналогична тому, как это делается для LDAP-инстанса, с той только разницей, что в итоге "389-AS" полностью переключается на SSL/TLS.

Переходим в директорию с конфигурацией сервера администрирования, проверяем наличие возможно имеющихся сертификатов и опционально создаём хранилище сертификатов (если оно не инициализировано ранее):

# cd /etc/dirsrv/admin-serv
# certutil -d . -L
# certutil -d . -N

Сразу импортируем публичную часть корневого сертификата (он у нас "самоподписанный") в NSS-хранилище, объявив его доверенным узлом - удостоверяющим центром (это очень важная для сетевой связности участников схемы администрирования процедура):

# certutil -A -d . -n "Self-Signed Root CA certificat" -t "CT,," -a -i /etc/ssl/dirsrv/ss-rootCA.crt

Импортируем заготовленный ранее контейнер с "приватной" и публичной частями сертификата LDAP-инстанса (если FQDN сервисов "389-DS" и "389-AS" одинаковый, то и сертификат можно использовать один и тот же):

# pk12util -d . -n "(AS/DS) ldap0.example.net" -i /etc/ssl/dirsrv/ldap0.example.net.p12

В GUI "389 Console" в обязательном порядке сразу указываем, что к хранилищу конфигурации сервера администрирования теперь нужно подключаться с использованием SSL (важно понимать, что сервер администрирования "389-AS" хранит свою конфигурацию в одном из инстансов "389-DS" - а ранее мы его уже перевели на SSL):

DS Console -> Configuration -> Administration Server -> Configuration DS:
  LDAP Host: ldap0.example.net
  LDAP Port: 636
  Secure Connection: on
Save.

В GUI "389 Console" указываем, что к основному управляемому LDAP-инстансу "389-DS" теперь нужно подключаться с использованием SSL (ранее мы его перевели на SSL):

DS Console -> Configuration -> Administration Server -> User DS:
  Set User Directory:
    LDAP Host and Port: ldap0.example.net:636
    Secure Connection: on
    User Directory Subtree: dc=example,dc=net
    Bind DN: cn=Directory Manager
    Bind Password: ***
Save.

В GUI "389 Console" включаем шифрование соединений к самому серверу администрирования:

DS Console -> Configuration -> Administration Server -> Encryption:
  Enable SSL for this server: on
  Use this cipher family RSA
    Security Device: internal
    Certificate: (AS/DS) ldap0.example.net
  Disable Client Authentication
Save.

В GUI "389 Console" переключаем соединения от этой самой консоли на SSL:

DS Console -> Configuration -> "ldap0.example.net" -> Encryption:
  Enable SSL for this server: on
    ....
    Use SSL in Console: on
Save.

В процессе включения LDAPS для "389-DS" я уже упоминал о "хитром скоке", которым мы сообщаем сервису пароль для доступа к его же NSS-базе сертификатов. Так вот у сервиса "389-AS" подход примерно такой же.

В конфигурационном файле NSS-подсистемы указываем не запрашивать пароль интерактивно, а считывать его из текстового файла:

# vi /etc/dirsrv/admin-serv/nss.conf

....
#Pass Phrase Dialog:
NSSPassPhraseDialog file://etc/dirsrv/admin-serv/pin.txt
....

Пароль к NSS-базе сертификатов указываем в текстовом файле (посимвольно следуем примеру, без кавычек, не допуская между двоеточием и паролем пробелов):

# vi /etc/dirsrv/admin-serv/pin.txt

internal (software):<password>

Файл с паролем закрываем от доступа посторонних:

# chown dirsrv:dirsrv /etc/dirsrv/admin-serv/pin.txt
# chmod go-rwx /etc/dirsrv/admin-serv/pin.txt

Несмотря на то, что в GUI "389 Console" мы включили режим шифрования соединений сервера администрирования, в ряде случаев в конфигурационном файле сервиса, принимающего запросы, оказывается не указан перечень допустимых SSL-протоколов, без которого сервис не стартует - исправляем это:

# vi /etc/dirsrv/admin-serv/console.conf

....
NSSProtocol TLSv1.0,TLSv1.1,TLSv1.2
....

Так же будет полезно помочь web-серверу определиться, на каком FQDN ему принимать запросы:

# vi /etc/dirsrv/admin-serv/httpd.conf

....
ServerName ldap0.example.net:9830
....

Теперь последовательно перезапускаем "389-DS" и "389-AS":

# stop-ds-admin
# stop-dirsrv ldap0-example-net && start-dirsrv ldap0-example-net
# start-ds-admin

Как минимум, для начала, сервис должен прослушивать один TCP-порт - всё тот же, что раньше без шифрования - теперь он принимает только SSL/TLS-запросы:

# netstat -apn | grep -i "^tcp" | grep -i listen | grep -i "apache"

Проверка должна показать, что "389-AS" принимает соединения с новым сертификатом:

$ echo QUIT | openssl s_client -connect ldap0.example.net:9830 | openssl x509 -noout -text | less

Теперь подключение к серверу администрирования возможны только через HTTPS (например с URL "https://ldap0.example.net:9830") - как в очень скромном web-интерфейсе "389 Administration Express", так и через "389 Console".

Методика возврата к предыдущим настройкам "389-AS".

При анализе проблем подключения к серверу администрирования "389-AS" прежде всего стоит обратить внимание на поведение используемой для этого GUI-утилиты "389 Console".

Включите прослушивание трафика между клиентом и сервером, на порту TCP:8930 - иногда, в то время, как утилита "389-console" заявляет о невозможности подключения к серверу, сведений о посылаемых пакетах нет - то есть это java-приложение сбоит само себе внутри и сервер тут не при чём.

Стоит помнить о возможности запустить "389-console" в режиме отладки с ключём "-D 9", что даст возможность изучить её внутренний мир и понять, в какую сторону копать дальше. На практике утилита удивляет капризами и тому будет посвящена отдельная публикация.

Если что-то пошло совсем не так, то следующими шагами возвращаем "389-AS" к работе на незащищённом HTTP.

Обязательно останавливаем сервер администрирования:

# stop-ds-admin

Параметрами с говорящими именами отключаем поддержку SSL/TLS в конфигурационном файле сервиса:

# vi /etc/dirsrv/admin-serv/local.conf

....
configuration.nsAdminAccessHosts: *
....
configuration.nsServerSecurity: off
....
configuration.encryption.RSA.nsSSLActivation: off
....

Указываем "389-AS" не обращаться к NSS-базе сертификатов:

# vi /etc/dirsrv/admin-serv/console.conf

....
NSSEngine off
....

Ищем, где точно располагаются опции конфигурирования сервера администрирования в иерархии LDAP-сервиса:

$ ldapsearch -x -LLL -h 127.0.0.1 -D "cn=Directory Manager" -W  -b "o=NetscapeRoot" "(objectclass=nsAdminConfig)" dn

dn: cn=configuration,cn=admin-serv-ldap0,cn=389 Administration Server,cn=Server Group,cn=ldap0.example.net,ou=local,o=NetscapeRoot

Деактивируем ограничения по доступу и поддержку SSL/TLS для "389-AS":

$ ldapmodify -h 127.0.0.1 -D "cn=Directory Manager" -W

dn: cn=configuration,cn=admin-serv-ldap0,cn=389 Administration Server,cn=Server Group,cn=ldap0.example.net,ou=local,o=NetscapeRoot
changetype: modify
replace: nsAdminAccessHosts
nsAdminAccessHosts: *

dn: cn=configuration,cn=admin-serv-ldap0,cn=389 Administration Server,cn=Server Group,cn=ldap0.example.net,ou=local,o=NetscapeRoot
changetype: modify
replace: nsServerSecurity
nsServerSecurity: off

^d

Запускаем сервер администрирования:

# start-ds-admin

Деактивируем поддержку устаревшего SSLv3.

В "Linux Ubuntu 18 LTS" случилось так, что из применяемого в ней современного "OpenSSL" уже вырезана поддержка "SSLv3", а компоненты "389-AS/DS" ещё пытаются этот метод шифрования использовать, засыпая журнал событий предупреждениями о невозможности активировать часть функционала.

Есть смысл явно отключить во всех компонентах "389-AS/DS" устаревший протокол "SSLv3" и указать, какие впредь следует использовать:

# vi /etc/dirsrv/admin-serv/local.conf

....
configuration.encryption.nsSSL3: off
....

# vi /etc/dirsrv/admin-serv/adm.conf

....
sslVersionMin: TLS1.0
sslVersionMax: TLS1.1

$ ldapmodify -h 127.0.0.1 -D "cn=Directory Manager" -W

dn: cn=encryption,cn=config
changetype: modify
replace: nsSSL3
nsSSL3: off

dn: cn=encryption,cn=config
changetype: modify
replace: nsTLS1
nsTLS1: on

dn: cn=encryption,cn=config
changetype: modify
replace: sslVersionMin
sslVersionMin: TLS1.0

dn: cn=encryption,cn=config
changetype: modify
replace: sslVersionMax
sslVersionMax: TLS1.2

^d

$ ldapmodify -h 127.0.0.1 -D "cn=Directory Manager" -W

dn: cn=encryption,cn=configuration,cn=admin-serv-ldap0,cn=389 Administration Server,cn=Server Group,cn=ldap0.example.net,ou=local,o=NetscapeRoot
changetype: modify
replace: nsSSL3
nsSSL3: off

dn: cn=encryption,cn=configuration,cn=admin-serv-ldap0,cn=389 Administration Server,cn=Server Group,cn=ldap0.example.net,ou=local,o=NetscapeRoot
changetype: modify
replace: nsTLS1
nsTLS1: on

dn: cn=encryption,cn=configuration,cn=admin-serv-ldap0,cn=389 Administration Server,cn=Server Group,cn=ldap0.example.net,ou=local,o=NetscapeRoot
changetype: modify
replace: sslVersionMin
sslVersionMin: TLS1.0

dn: cn=encryption,cn=configuration,cn=admin-serv-ldap0,cn=389 Administration Server,cn=Server Group,cn=ldap0.example.net,ou=local,o=NetscapeRoot
changetype: modify
replace: sslVersionMax
sslVersionMax: TLS1.2

^d

# stop-ds-admin
# stop-dirsrv ldap0-example-net && start-dirsrv ldap0-example-net
# start-ds-admin

Опрос сетевым сканером покажет, что сервер отвечает только современным методам шифрования:

$ nmap --script ssl-enum-ciphers -p 9830 ldap0.example.net

....
| ssl-enum-ciphers:
|   TLSv1.0:
....
|   TLSv1.1:
....
|   TLSv1.2:
....

Опционально переводим "389-AS/DS" на IPv4.

По умолчанию "389-DS" запускается в режиме прослушивания IPv4 и IPv6, а "389-AS" - только IPv4. Возможны неполадки связи (например из-за отсутствия разрешения имён в DNS для IPv6), потому можно явно перевести оба сервиса на IPv4:

$ ldapmodify -h 127.0.0.1 -D "cn=Directory Manager" -W

dn: cn=config
changetype: modify
replace: nsslapd-listenhost
nsslapd-listenhost: 0.0.0.0

dn: cn=config
changetype: modify
replace: nsslapd-securelistenhost
nsslapd-securelistenhost: 0.0.0.0

^d

# stop-ds-admin
# stop-dirsrv ldap0-example-net && start-dirsrv ldap0-example-net
# start-ds-admin

# netstat -apn | grep -i "^tcp" | grep -i listen | grep -iE "(ns-slap|apache)"

tcp ... 0.0.0.0:636   0.0.0.0:* LISTEN .../ns-slapd
tcp ... 0.0.0.0:389   0.0.0.0:* LISTEN .../ns-slapd
tcp ... 0.0.0.0:9830  0.0.0.0:* LISTEN .../apache2

Закрываем доступ извне к незащищённому LDAP.

В отличии от "OpenLDAP" в конфигурации "389-AS/DS" нет возможности указать комбинации вариантов, откуда и кому разрешены подключения к тому или иному порту. Можно лишь включить или полностью выключить обслуживание запросов клиентов на сетевом порту.

Следуя жёсткому курсу недопущения утечки конфиденциальных данных надо бы вообще выключить незащищённый LDAP-сервис, оставив только LDAPS - но с "самоподписанными" сертификатами это может вызвать проблемы связности компонентов, а потому лучше оставить себе возможность оперативно разрешить соединения без шифрования хотя бы на локальной сетевой петле.

В итоге, проще всего запретить не-SSL доступ снаружи средствами сетевого защитного экрана несущей операционной системы:

# iptables -t filter -L INPUT -n -v --line-numbers
# iptables -A INPUT -p TCP --dport 389 -j REJECT -m comment --comment "Forbidden connect to insecure LDAP"

Опционально можно организовать подключение к закрытому небезопасному порту для внутренних сервисов (только через локальную сетевую петлю, например), добавлением разрешительного правила непосредственно перед запретительным:

# iptables -I INPUT 1 -i lo -p TCP --dport 389 -j ACCEPT -m comment --comment "Allow use insecure LDAP only from localhost"

При необходимости правила легко избирательно удалить:

# iptables -t filter -L INPUT -n -v --line-numbers
# iptables -D INPUT 1

Устанавливаем сервис для автоматического сохранения правил "iptables" и применения таковых при запуске операционной системы:

# aptitude install iptables-persistent

Сохраняем текущее состояние конфигурации "сетевого фильтра":

# netfilter-persistent save

Как вариант, правила можно сохранить утилитой из дистрибутивного набора "iptables" (подобным образом можно наладить их активацию при запуске системы, но это уже ручная работа):

# iptables-save > /etc/iptables/rules.v4


Заметки и комментарии к публикации:


Оставьте свой комментарий ( выразите мнение относительно публикации, поделитесь дополнительными сведениями или укажите на ошибку )