Как работает аутентификация через LDAP: схема запроса, bind и проверка учетных данных | AdminWiki

Как работает аутентификация через LDAP: схема запроса, bind и проверка учетных данных

06 сентября 2026 16 мин. чтения
Содержание статьи

Короткий ответ: как работает LDAP-аутентификация

LDAP-аутентификация подтверждает учетную запись через операцию bind. Приложение получает логин и пароль, подключается к LDAP-серверу, при необходимости находит полный DN пользователя через SearchRequest, затем отправляет BindRequest с этим DN и паролем. Сервер проверяет данные и возвращает BindResponse с кодом результата, например success или invalidCredentials.

Когда пользователь вводит короткий логин, например ivan, приложение обычно не может сразу выполнить bind. Сначала оно подключается сервисной учетной записью, ищет запись по фильтру вроде (uid=ivan), получает DN uid=ivan,ou=people,dc=example,dc=org и повторяет bind уже от имени пользователя. Если DN заранее известен по шаблону, поиск можно пропустить.

Simple bind передает имя учетной записи и пароль внутри LDAP-запроса. Сам механизм simple bind не шифрует пароль, поэтому TLS нужно установить до пользовательского bind. Успешная проверка пароля подтверждает личность, но не выдает права на SSH, sudo, приложение или отдельный ресурс.

Участники запроса: клиент, каталог и приложение

В типовой схеме участвуют три логических компонента:

  • LDAP-клиент формирует протокольные операции и принимает ответы сервера. Им может быть веб-приложение, VPN-шлюз, Linux-клиент через SSSD, NAS или утилита ldapsearch.
  • LDAP-сервер принимает соединение, выполняет bind, обрабатывает поиск и проверяет учетные данные по данным каталога.
  • Приложение принимает решение о входе и доступе. Оно может делегировать проверку SSSD, PAM или встроенному LDAP-модулю.

LDAP-сервер не обязан знать, что запрос пришел от SSH или веб-приложения. Для него это набор операций протокола: подключение, TLS, bind, поиск записей, чтение атрибутов и завершение сеанса.

Полный путь от логина до успешного входа

  1. Пользователь вводит логин и пароль в приложении или передает их SSH-клиенту.
  2. Клиент разрешает имя LDAP-сервера через DNS и устанавливает TCP-соединение с портом 389 или 636.
  3. При LDAPS TLS запускается сразу после TCP-подключения. При StartTLS клиент сначала подключается к LDAP на порту 389, затем выполняет расширенную операцию StartTLS.
  4. Клиент выполняет bind сервисной учетной записи, если ему нужно искать пользователя по короткому логину.
  5. LDAP-клиент отправляет SearchRequest с Base DN, областью поиска и фильтром, например (uid=ivan).
  6. Клиент получает DN найденной записи и проверяет, что результат единственный.
  7. Клиент отправляет пользовательский BindRequest с найденным DN и введенным паролем.
  8. После успешного bind приложение запрашивает группы, идентификаторы и дополнительные атрибуты.
  9. Локальная или прикладная политика проверяет, разрешен ли вход этому пользователю.
  10. После завершения работы клиент отправляет UnbindRequest или закрывает соединение.

При прямом bind этапы с сервисной учетной записью и поиском отсутствуют. Клиент сразу использует известный DN, например uid=ivan,ou=people,dc=example,dc=org.

Что означает успешный bind

Ответ BindResponse с кодом success означает, что LDAP-сервер принял переданное имя и пароль и установил соответствующий аутентифицированный контекст соединения. Пароль сервер не возвращает.

Успешный bind не означает автоматический доступ к ресурсам. Приложение может отклонить вход из-за отсутствия пользователя в разрешенной группе. SSH может применить AllowGroups, PAM может запретить вход по локальному правилу, а sudo проверит отдельную политику. Подробная схема групп и ролей приведена в статье о настройке LDAP-групп и ролей.

LDAP-каталог, DN и запись пользователя

LDAP хранит информацию в виде иерархии записей, или entry. Каждая запись имеет уникальное полное имя DN, набор атрибутов и один или несколько классов объектов. Клиент использует эти данные, чтобы найти пользователя, проверить его пароль и получить признаки, необходимые для последующего контроля доступа.

Как устроена запись пользователя в LDAP

Запись пользователя может выглядеть так:

dn: uid=ivan,ou=people,dc=example,dc=org
objectClass: inetOrgPerson
objectClass: posixAccount
uid: ivan
cn: Ivan Petrov
mail: ivan@example.org
uidNumber: 10001
gidNumber: 10000
homeDirectory: /home/ivan
loginShell: /bin/bash

В этой записи:

  • dn содержит полный идентификатор записи в дереве LDAP.
  • objectClass определяет допустимые и обязательные атрибуты.
  • uid часто используется как короткий логин в OpenLDAP.
  • cn содержит отображаемое имя или полное имя пользователя.
  • mail хранит адрес электронной почты, если он предусмотрен схемой.
  • uidNumber и gidNumber нужны Linux-системам, которые используют каталог как источник POSIX-идентификаторов.
  • homeDirectory и loginShell помогают создать Linux-сеанс.

Пароль может храниться в атрибуте userPassword, но формат и права чтения зависят от схемы и настроек сервера. Клиенту обычно запрещают читать этот атрибут. При пользовательском bind сервер сам сравнивает переданный пароль с сохраненным представлением.

Группы могут описываться атрибутами member и memberOf. Поддержка вложенных групп, автоматического memberOf и схемы групп зависит от LDAP-сервера.

DN, RDN и Base DN на практическом примере

В DN uid=ivan,ou=people,dc=example,dc=org отдельные части имеют разные роли:

  • RDN, относительное имя записи, это первая часть uid=ivan. Она отличает запись от соседних объектов внутри родительского контейнера.
  • OU ou=people обозначает подраздел или контейнер пользователей.
  • Base DN dc=example,dc=org задает корень области поиска.
  • DN объединяет все компоненты и однозначно адресует запись в дереве.

Поиск может выполняться с разной областью:

  • base проверяет только сам объект, указанный в Base DN;
  • one проверяет непосредственные дочерние записи;
  • sub обходит Base DN и вложенные ветки.

Если клиент ищет пользователя с Base DN ou=groups,dc=example,dc=org, запись из ou=people не попадет в результат. Ошибка Base DN может дать noSuchObject, а неподходящий фильтр часто возвращает пустой результат при доступном сервере и рабочем bind.

LDAP-фильтр проверяет атрибуты записи. Фильтр (uid=ivan) ищет точное значение атрибута uid. Условия можно комбинировать, например (&(objectClass=person)(uid=ivan)). В реальной команде символ амперсанда может потребовать экранирования как HTML-сущность.

OpenLDAP и Active Directory: что меняется в записи пользователя

Общая последовательность LDAP-операций сохраняется, но схема каталога и имена атрибутов различаются.

ЗадачаOpenLDAP, частый вариантActive Directory, частый вариант
ЛогинuidsAMAccountName или userPrincipalName
Контейнер пользователяou=peopleOU=Users или другая OU
ГруппыgroupOfNames, membergroup, member, вычисляемые связи
POSIX-атрибутыuidNumber, gidNumber, loginShellМогут отсутствовать или задаваться расширением схемы

Нельзя переносить фильтр (uid=login) в Active Directory без проверки схемы. Там может использоваться (sAMAccountName=login) или фильтр по userPrincipalName. Сначала получите тестовую запись через поиск и проверьте реальные имена атрибутов.

Как LDAP находит пользователя: прямой bind и search-then-bind

Логин, который вводит человек, часто не совпадает с полным DN. LDAP-сервер проверяет пароль для конкретного имени записи, поэтому клиенту нужно либо знать DN заранее, либо сначала найти его поиском.

Прямой bind по известному DN

При прямом bind клиент формирует запрос, где поле name уже содержит DN пользователя:

BindRequest
version: 3
name: uid=ivan,ou=people,dc=example,dc=org
authentication: simple
password: пароль пользователя

Этот вариант подходит, когда структура DN стабильна и приложение может безопасно построить имя из логина. Пример шаблона: uid={login},ou=people,dc=example,dc=org.

Шаблон нельзя применять без экранирования специальных символов DN. Запятая, знак плюса, обратный слеш, кавычки и некоторые другие символы могут изменить смысл имени. Если логин может содержать такие символы, используйте библиотечную функцию экранирования DN.

Преимущество прямого bind, один LDAP-запрос вместо поиска и пользовательского bind. Ограничение, приложение должно точно знать структуру каталога и не сможет работать с разными OU без дополнительной логики.

Поиск DN через сервисную учетную запись

Сценарий search-then-bind подходит, когда пользователь вводит короткий логин:

  1. Клиент устанавливает TLS-сеанс.
  2. Клиент выполняет bind сервисной учетной записи, например uid=svc-reader,ou=people,dc=example,dc=org.
  3. Клиент отправляет поиск по Base DN ou=people,dc=example,dc=org и фильтру (uid=ivan).
  4. Сервер возвращает запись и ее DN.
  5. Клиент проверяет, что найден ровно один пользователь.
  6. Клиент закрывает или переиспользует сервисный контекст и выполняет bind найденного DN с паролем пользователя.

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

Тестовый поиск можно выполнить так:

ldapsearch -H ldaps://ldap.example.org -x -D 'uid=svc-reader,ou=people,dc=example,dc=org' -W -b 'ou=people,dc=example,dc=org' '(uid=ivan)' dn

Ключ -W запрашивает пароль интерактивно. Секрет не попадает в командную строку, историю shell и список процессов.

Почему поиск пользователя не заменяет проверку пароля

SearchRequest только находит доступную запись и возвращает разрешенные атрибуты. Успешный поиск говорит, что сервисная учетная запись может читать объект по заданному фильтру. Пароль пользователя на этом этапе не проверяется.

Подтверждение личности происходит во втором bind. Если приложение принимает найденную запись без пользовательского bind, любой человек, знающий логин, может пройти проверку без знания пароля. Сервисный bind подтверждает права самого сервиса и не подтверждает личность конечного пользователя.

Simple bind LDAP: состав запроса и ответ сервера

Операция bind устанавливает аутентификационный контекст LDAP-сеанса. В протоколе LDAP версии 3 запрос содержит версию протокола, имя учетной записи и способ аутентификации.

Что содержит BindRequest

Логическая структура BindRequest выглядит так:

  • version, обычно значение 3;
  • name, DN пользователя, DN сервисной учетной записи или пустое имя для anonymous bind;
  • authentication, например simple authentication с паролем.

При simple bind пароль передается серверу внутри протокольного поля аутентификации. LDAP-кодировка BER и транспорт TCP не защищают секрет от перехвата. Защита появляется только после успешного TLS-сеанса, если клиент проверяет сертификат и не допускает откат к незашифрованному соединению.

Возможны три распространенных варианта:

  • Пользовательский bind: в name указан DN пользователя, а в authentication передан введенный пароль.
  • Сервисный bind: в name указан технический DN с правами поиска.
  • Anonymous bind: имя и пароль пустые. Сервер может запретить такой режим или дать ему ограниченный доступ.

Anonymous bind не подтверждает личность клиента. Его использование допустимо только при осознанно открытом чтении публичных данных и с учетом политики конкретного сервера.

Что содержит BindResponse

Сервер возвращает код результата и, при наличии, диагностическое сообщение. Частые значения:

КодСмыслЧто проверить
successBind выполненПереходить к группам и политике доступа
invalidCredentialsНеверное имя, пароль или недопустимый способ входаDN, пароль, блокировку учетной записи и формат логина
unwillingToPerformСервер отказался выполнять операцию по политике или из-за состояния каталогаПолитику bind, требования к шифрованию и серверные журналы
confidentialityRequiredСервер требует защищенный каналLDAPS или StartTLS и проверку сертификата
unavailableСервис временно недоступенСостояние сервера, сеть, DNS и балансировщик

Диагностическое сообщение LDAP помогает администратору, но его не следует без фильтра показывать пользователю. В тексте ошибки могут оказаться DN, имена внутренних узлов или сведения о политике каталога.

Пример последовательности LDAP-операций

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

TCP connect to ldap.example.org:636
TLS handshake and certificate validation
BindRequest: service account
BindResponse: success
SearchRequest: base=ou=people,dc=example,dc=org, filter=(uid=ivan)
SearchResultEntry: dn=uid=ivan,ou=people,dc=example,dc=org
SearchResultDone: success
BindRequest: user DN, simple authentication
BindResponse: success
SearchRequest: groups and account attributes
UnbindRequest

При прямом bind последовательность короче:

TCP connect
TLS handshake
BindRequest: user DN and password
BindResponse: success
SearchRequest: groups or attributes
UnbindRequest

После завершения bind клиент может выполнять разрешенные операции в контексте этой учетной записи. Объем доступа определяется ACL каталога, а не самим фактом успешной аутентификации.

LDAP авторизация и аутентификация: что происходит после проверки пароля

Аутентификация отвечает на вопрос, кто передал учетные данные. Авторизация решает, что этому пользователю разрешено делать. Эти проверки могут проходить в LDAP, в приложении, в PAM, в SSH или сразу в нескольких компонентах.

Аутентификация подтверждает личность, авторизация определяет доступ

Успешный пользовательский bind подтверждает соответствие пароля конкретному DN. После него приложение должно определить, разрешен ли вход и какие действия доступны пользователю.

Примеры авторизационных правил:

  • SSH принимает только членов группы ssh-users.
  • Веб-приложение разрешает административную панель группе app-admins.
  • Linux проверяет группы через NSS и разрешает sudo только пользователям, перечисленным в отдельной политике.
  • LDAP ACL запрещает сервисной учетной записи читать часть атрибутов.

Пользователь может успешно пройти bind и получить отказ на любом из этих этапов. При диагностике нужно разделять ошибку пароля, ошибку поиска групп и отказ прикладной политики.

Какие данные запрашиваются после bind

После проверки пароля клиент может получить:

  • uid, cn, mail и другие атрибуты профиля;
  • uidNumber и gidNumber для POSIX-идентификации;
  • homeDirectory и loginShell для Linux-сеанса;
  • членство в группах через member, memberOf или отдельный поиск групп;
  • атрибуты, которые приложение использует для ролей и ограничений.

Приложение может выполнять дополнительные LDAP-поиски с DN пользователя в качестве базы. В другой схеме оно ищет группы по фильтру, который содержит DN пользователя. Конкретный способ зависит от каталога и модели групп.

Группы LDAP и доступ к ресурсам

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

dn: cn=ssh-users,ou=groups,dc=example,dc=org
objectClass: groupOfNames
cn: ssh-users
member: uid=ivan,ou=people,dc=example,dc=org

Обратная связь через memberOf может формироваться сервером автоматически или отсутствовать. Вложенные группы требуют отдельной поддержки и дополнительных запросов. Нельзя считать пользователя членом группы только потому, что похожее имя найдено в каталоге.

Практичная политика начинается с принципа запрета по умолчанию. LDAP-пользователь получает доступ к SSH, sudo или приложению только после прохождения отдельного правила группы, роли или ACL. Проверку нужно тестировать учетной записью без нужной группы, чтобы убедиться в отказе.

Безопасность simple bind: LDAPS или StartTLS

Simple bind без TLS раскрывает пароль на транспортном уровне. Любой компонент, который может наблюдать незашифрованный трафик между клиентом и LDAP-сервером, получает возможность перехватить учетные данные. Для пользовательского bind TLS должен завершиться до отправки пароля.

LDAPS через порт 636

При LDAPS клиент открывает TLS-соединение сразу:

  1. Клиент подключается к имени сервера на порту 636.
  2. Сервер отправляет сертификат.
  3. Клиент проверяет цепочку доверия, имя в SAN, срок действия и параметры TLS.
  4. После успешной проверки клиент отправляет LDAP bind.

В URI клиента используется схема ldaps://. Имя в URI должно совпадать с DNS-именем, указанным в SAN сертификата. Подключение к IP-адресу при сертификате только на DNS-имя вызовет ошибку проверки имени.

StartTLS на порту 389

StartTLS начинается с обычного LDAP-соединения, которое затем переводится в защищенный режим:

  1. Клиент подключается к порту 389.
  2. Клиент отправляет расширенную операцию StartTLS.
  3. Сервер отвечает готовностью к TLS.
  4. Клиент выполняет TLS-рукопожатие и проверяет сертификат.
  5. Только после успешного TLS клиент отправляет сервисный или пользовательский bind.

Пароль нельзя отправлять между TCP-подключением и завершением StartTLS. Установка TLS после bind не защищает уже переданный секрет.

Что проверить в TLS-сеансе

  • Корневой и промежуточные сертификаты доверенного CA установлены на клиенте.
  • Имя LDAP endpoint совпадает с SAN сертификата.
  • Системные часы клиента и сервера синхронизированы.
  • Сертификат не просрочен и не отозван по правилам вашей инфраструктуры.
  • Клиент и сервер согласуют разрешенную версию TLS и набор шифров.
  • Проверка сертификата включена, а режим доверия к любому сертификату не используется в production.

Отключение проверки сертификата часто создает иллюзию рабочего LDAPS. Трафик может шифроваться, но клиент не подтверждает, с каким сервером установил соединение. Подробная проверка сертификатов, прав bind-аккаунта и TLS-диагностика описаны в материале о безопасности LDAP-аутентификации.

Как LDAP-аутентификация работает в Linux: SSSD, PAM и NSS

В Linux протокол LDAP обычно скрыт за системными компонентами. Приложение SSH передает учетные данные PAM, SSSD выполняет LDAP-запросы и может хранить кэш, а NSS возвращает сведения о пользователях и группах системным утилитам.

Роли SSSD, PAM и NSS в одной схеме

  • SSSD подключается к LDAP или Active Directory, выполняет поиск, bind, получение групп и кэширование. Его параметры задаются для конкретного домена в конфигурации SSSD.
  • PAM участвует в проверке пароля и правилах входа. Модули PAM передают запрос в SSSD и могут дополнительно применять ограничения.
  • NSS отвечает за поиск учетных записей и групп через системные вызовы. Команды getent и id показывают, видит ли система каталог как источник идентификационной информации.

NSS не заменяет проверку пароля. Команда getent passwd ivan может вернуть запись пользователя, но это не доказывает, что пароль верный. За проверку учетных данных отвечает PAM через настроенный провайдер.

Как проходит вход пользователя по SSH

  1. sshd получает логин и пароль от SSH-клиента.
  2. SSH передает запрос в PAM.
  3. PAM обращается к SSSD или другому настроенному модулю.
  4. SSSD устанавливает защищенное LDAP-соединение, при необходимости выполняет поиск DN и проверяет пользовательский пароль bind-операцией.
  5. SSSD получает группы и идентификаторы пользователя.
  6. PAM и SSH проверяют локальные ограничения, включая разрешенные группы и запреты.
  7. Система определяет домашний каталог, shell и окружение, после чего запускает сеанс.

Успешный LDAP bind может завершиться отказом SSH. Причина часто находится в AllowUsers, AllowGroups, PAM-правилах, отсутствии домашнего каталога или запрещенном shell.

Кэш SSSD и локальные учетные записи

SSSD может кэшировать идентификационные данные, группы и результаты аутентификации. Поэтому getent passwd ivan иногда возвращает пользователя при недоступном LDAP-сервере. Это не означает, что каталог отвечает сейчас.

Нужно разделять:

  • Кэш идентификации позволяет получить имя, UID, GID и другие сведения.
  • Офлайн-аутентификация позволяет войти без связи с каталогом, если политика SSSD разрешает такой режим и в кэше есть подходящие данные.
  • Локальная учетная запись хранится в системных файлах и может работать независимо от LDAP.

Сравнивайте результат getent, логи SSSD и доступность LDAP в момент проверки. Для подключения Linux к каталогу через SSSD, PAM и NSS используйте отдельное руководство по настройке LDAP-клиента.

Для лабораторного стенда с Linux-клиентом, LDAP-сервером и отдельной сетью можно использовать виртуальную инфраструктуру, например Timeweb Cloud. Тестовые узлы лучше изолировать, ограничить доступ к LDAP-портам и не применять реальные учетные данные.

Проверка LDAP bind и типовые ошибки

Диагностику выполняйте снизу вверх: сначала сеть и TLS, затем сервисный bind, поиск DN, пользовательский bind, группы и локальная политика. Такой порядок отделяет ошибку подключения от неверного пароля и отказа авторизации.

Проверка соединения, TLS и сервисного bind

  1. Проверьте разрешение имени LDAP-сервера через DNS.
  2. Проверьте доступность порта 389 или 636 с узла приложения.
  3. Убедитесь, что клиент доверяет CA и проверяет имя сертификата.
  4. Выполните ldapwhoami с тем же URI и режимом TLS, который использует целевое приложение.
  5. Проверьте сервисный bind отдельно от поиска пользователя.

Пример проверки LDAPS:

ldapwhoami -H ldaps://ldap.example.org -x -D 'uid=svc-reader,ou=people,dc=example,dc=org' -W

Для StartTLS используется порт 389 и ключ -ZZ, который требует успешного TLS:

ldapwhoami -H ldap://ldap.example.org:389 -ZZ -x -D 'uid=svc-reader,ou=people,dc=example,dc=org' -W

Не заменяйте -ZZ на режим, который позволяет продолжить соединение после ошибки TLS. Иначе клиент может перейти к незашифрованному bind.

Проверка поиска пользователя и его DN

Проверьте Base DN, область поиска, атрибут логина и количество результатов. Для OpenLDAP фильтр может выглядеть как (uid=ivan), для Active Directory часто используется (sAMAccountName=ivan).

ldapsearch -H ldaps://ldap.example.org -x -D 'uid=svc-reader,ou=people,dc=example,dc=org' -W -b 'ou=people,dc=example,dc=org' -s sub '(uid=ivan)' dn

Ожидаемый результат содержит один DN. Пустой результат обычно указывает на неверный фильтр, Base DN, область поиска, регистр или отсутствие прав чтения. Несколько записей означают неоднозначный логин. Код noSuchObject чаще связан с отсутствующей веткой Base DN, а insufficientAccessRights указывает на ACL сервера.

Проверка пользовательского bind

После получения DN проверьте bind тестовой учетной записи отдельной командой:

ldapwhoami -H ldaps://ldap.example.org -x -D 'uid=ivan,ou=people,dc=example,dc=org' -W

Если команда возвращает invalidCredentials, проверьте точный DN, пароль, срок действия учетной записи, блокировку и правила смены пароля. Убедитесь, что приложение не отправляет короткий логин вместо DN, если сервер ожидает полное имя записи.

Не включайте пароль в команду, переменные окружения с широким доступом, историю shell, журналы CI и диагностические отчеты. Для проверки используйте интерактивный ввод или механизм секретов, предусмотренный вашим клиентом.

Почему вход не работает после успешного bind

Когда пользовательский bind успешен, проверьте следующие уровни:

  • Группы: видит ли клиент нужную группу и совпадает ли DN пользователя с атрибутом member.
  • NSS: возвращают ли getent passwd ivan и id ivan правильные UID, GID и группы.
  • PAM: разрешает ли стек вход по SSH и не срабатывает ли отдельное ограничение.
  • SSH: корректны ли AllowUsers, AllowGroups, shell и настройки доступа.
  • Домашний каталог: существует ли путь из homeDirectory и может ли система его создать.
  • Sudo: есть ли пользователь или его группа в разрешенной политике sudo.
  • Кэш SSSD: не показывает ли клиент устаревшие группы или старую запись.

Сопоставляйте логи клиента и сервера по времени запроса. Полезно сначала повторить проверку через ldapwhoami и ldapsearch, затем проверить SSSD и PAM, и только после этого менять конфигурацию SSH или приложения.

Пошаговый чек-лист для ошибок LDAP и Active Directory с проверкой DNS, порта, TLS, bind, Base DN, фильтров и групп собран в статье о диагностике ошибок аутентификации.

Рабочая проверка LDAP-аутентификации должна повторять параметры production-клиента: тот же endpoint, имя сервера, режим TLS, Base DN, фильтр и учетную запись. Тест с другим URI или отключенной проверкой сертификата не подтверждает исправность реальной схемы.
Поделиться:
Сохранить гайд? В закладки браузера