Как мы с нуля реализовали двустороннее доверие «лес–лес» с Microsoft Active Directory

от автора

В проектах импортозамещения ИТ-продуктов почти всегда есть одна и та же проблема: нельзя просто взять и отключить уже существующее зарубежное решение. Особенно если речь идёт о службе каталогов и аутентификации.

Мы в МУЛЬТИФАКТОР разрабатываем собственную службу каталогов MULTIDIRECTORY (MD). Это полностью наша реализация: LDAP, ACL, RBAC, бизнес-логика и подсистема аудита написаны с нуля, модифицированный MIT Kerberos, DNS — PowerDNS, DHCP — Kea DHCP, групповые политики — Salt Stack. При этом служба изначально проектировалась с учётом обратной совместимости с экосистемой Microsoft: если сервис умел работать с Active Directory (AD), он, как правило, сможет работать и с MD.

MD поддерживает гибридную среду Linux+Windows. Но так как у заказчиков имеется полнофункциональная среда на базе Active Directory, то полная замена в один шаг невозможна как технически, так и организационно.

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

Почему без доверия не обойтись

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

Решение одно — настроить доверие между каталогами. В этом случае аутентификация и авторизация начинают работать сквозным образом: пользователь из одного домена может получить доступ к ресурсам другого, даже не замечая, где именно он находится.

Существует три основных вида доверительных отношений с внешними доменами:

1. Realm Trust — это по сути договорённость между двумя Kerberos-реалмами. Оно позволяет передавать тикеты и решает задачу аутентификации, но не выходит за пределы Kerberos. LDAP, группы, атрибуты и вся логика авторизации остаются вне этого механизма. В реальных инфраструктурах это быстро приводит к усложнению конфигурации и росту нагрузки на администраторов.

2. External Trust — используется для настройки доверия между отдельными доменами, которые не входят в один лес. Такой тип доверительных отношений подходит для точечной интеграции инфраструктур, предоставления временного доступа или взаимодействия с изолированными средами, где не требуется полноценное объединение каталогов. При этом External Trust имеет ряд ограничений. Доверие не распространяется автоматически на другие домены, поэтому каждую связь необходимо настраивать отдельно. Также по заявлению Microsoft External Trust не предназначен для работы с Kerberos, так как разрабатывался для поддержки NTLM.

3. Forest Trust. Доверие типа «лес–лес» устроено принципиально иначе. Оно изначально проектировалось в экосистеме Active Directory и охватывает не только Kerberos, но и все сопутствующие механизмы, касающиеся авторизации: пользователи, группы, SID, LDAP, системные протоколы Windows. В результате два каталога начинают восприниматься как связанная система, а доступ к ресурсам становится прозрачным для пользователя.

Почему мы начали с Realm Trust и почему этого оказалось недостаточно

Как и многие, мы начали с Realm Trust. Это быстрый способ закрыть базовые сценарии: пользователь может аутентифицироваться, тикеты Kerberos передаются, минимальная связность есть.

Однако мы понимали, что для сложных инфраструктур этого недостаточно. Основная проблема — авторизация. Kerberos подтверждает, кто пользователь, и даже передает состав групп через PAC, но это все равно не даёт полной картины его прав, и для настройки прав требуется ручная манипуляция администратора на конкретном сервере или ПК для настройки маппинга. Без этого многие системы либо не работают, либо требуют сложной дополнительной настройки.

Чтобы частично компенсировать это ограничение, мы реализовали механизм LDAP Forward — перенаправление LDAP-запросов в доверенный домен. Это позволило получать данные о пользователях и упростило часть сценариев, но по большей части это касается Linux-систем, которые базируются на авторизации через LDAP

Подробнее об этой реализации можно прочитать в одной из наших предыдущих статей.

Принципиально ситуацию это не изменило. Realm Trust по своей природе ограничен и не покрывает реальные требования enterprise-инфраструктур.

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

Если говорить о реализации доверия типа «лес–лес» вне Microsoft, практически вся экосистема так или иначе опирается на Samba. Это исторически объяснимо: именно Samba получила доступ к внутренним протоколам и исходному коду Microsoft и воспроизвела их в открытом виде.

FreeIPA, например, не реализует доверие самостоятельно — она использует компоненты Samba как RPC-прослойку.

На первый взгляд это удобно: можно взять готовую реализацию и встроить её в продукт. Но на практике у такого подхода есть серьёзные ограничения. Во-первых, это зависимость от стороннего кода на языке Си, который сложно контролировать и адаптировать. Во-вторых, чувствительность к изменениям в Windows, так как обновления в этой ОС могут влиять на поведение протоколов, и Trust начинает работать нестабильно.

Действительно, мы неоднократно сталкивались с кейсами, когда после обновления Windows доверие переставало работать, для восстановления работоспособности доверия требовалось откатить обновления, а исправление на стороне Samba занимало месяцы. Соответственно, все решения на базе Samba и FreeIPA в этом случае становятся заложниками команды Samba. Для инфраструктурного продукта это неприемлемо.

Поэтому мы решили пойти другим путём.

Решение: реализовать доверие с нуля

В начале 2025 года мы поставили амбициозную задачу реализовать двустороннее доверие типа «лес–лес» самостоятельно, не опираясь на код Samba. В качестве языка выбрали Python, причем осознанно, несмотря на сложность задачи.

Как оказалось, основная сложность это не Kerberos как таковой. В ходе изысканий стало понятно, что для реализации двустороннего доверия Microsoft использует не один протокол, а целый стек взаимосвязанных механизмов. В него входят:

  • Kerberos v5

  • NTLM v2

  • EPM (RPC Mapper)

  • Netlogon

  • DRSUAPI

  • SAMR

  • LSARPC (LSAD и LSAT)

  • SMB v2/v3

При этом один и тот же сценарий может использовать разные транспорты: через SMB  или напрямую через RPC.

Важно отметить, что NTLM v2 на сегодняшний день считается устаревшим и небезопасным. Microsoft рекомендует отказываться от его использования и указывает на возможное отключение поддержки в будущих версиях.

С учётом этого мы изначально строили реализацию доверия с опорой на Kerberos как основной и единственный механизм аутентификации.

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

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

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

Что пришлось разработать

Хотя в основе нашего решения используется MIT Kerberos, «из коробки» он не совместим с моделью Active Directory.

Ключевое отличие — отсутствие PAC (Privilege Attribute Certificate). В AD именно PAC несёт информацию, необходимую для авторизации: группы пользователя, SID и другие атрибуты. Без него корректная работа с Windows и AD Forest Trust невозможна. Поэтому поддержку PAC пришлось реализовать отдельно, благо MIT Kerberos позволяет расширять свой функционал.

Второй важный момент — способ идентификации. В AD один и тот же пользователь может быть идентифицирован по samAccountName (domain\user, domain.ru\user) и UPN (user@domain.ru). MIT Kerberos изначально работает только с принципалами формата username@REALM и чувствителен к регистру. Это потребовало доработки TGS-сервера, чтобы он мог корректно обрабатывать различные варианты.

Управление доверием и использование доверия

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

Под управлением доверием понимаются операции создания и обслуживания самого доверительного отношения между доменами. Это сценарии, которые обычно выполняются утилитами MS Windows, например netdom и nltest.

К таким операциям относятся:

  • создание доверия;

  • удаление доверия;

  • изменение направления доверия;

  • изменение атрибутов доверительных отношений;

  • проверка доверия;

  • обновление паролей доверительных отношений;

  • получение информации о доверенном лесе;

  • получение списка доверенных доменов.

Большая часть этих операций реализуется через протоколы LSARPC и Netlogon.

Netlogon оказался одним из ключевых протоколов при реализации Forest Trust. Именно через него строится Secure Channel между контроллерами доменов.

Проверить Secure Channel в Active Directory можно, например, командой:

nltest /SC_VERIFY:DOMAIN

С точки зрения протокола установка Secure Channel выглядит следующим образом:

Сначала вызывается ServerReqChallenge — сервер генерирует Server Challenge и передаёт его второй стороне.

Затем вызывается ServerAuthenticate3 — ключевой этап построения Secure Channel. На этом шаге стороны подтверждают корректность паролей доверительных отношений (TDO паролей) и вычисляют общий сессионный ключ.

Упрощённо схема выглядит так:

skey = AES(tdo_password, server_challenge, client_challenge)

Далее:

  • проверяется client_challenge;

  • вычисляется server_challenge;

  • согласуются поддерживаемые возможности сервера.

Например, на этом этапе можно объявить отсутствие поддержки устаревшего алгоритма RC4 или NetrServerPasswordSet.

После этого начинается обмен уже по зашифрованному Secure Channel.

Следующий вызов — LogonGetCapabilities. Он выполняется уже внутри защищённого канала и используется для согласования возможностей сервера.

Завершающим этапом обычно становится GetForestTrustInformation, в рамках которого передаётся ForestTrustInfo:

  • DNS-имя;

  • имя домена;

  • SID домена.

Отдельно стоит отметить механизм обновления паролей доверительных отношений. Active Directory раз в 30 дней инициирует смену пароля доверительных отношений как у себя, так и у доверенного домена. Для этого используется вызов NetrServerPasswordSet2 (или NetrServerPasswordSet при использовании RC4). После получения нового пароля доверительных отношений необходимо обновить:

  • TDO (Trusted Domain Object), используемый для secure channel;

  • принципал вида krbtgt/MD.LOC@AD.LOC, который используется KDC/TGS при выдаче междоменных билетов.

Без этого дальнейшая работа доверия Kerberos становится невозможной.

Протоколы LSAD и LSAT в сценариях использования доверия

LSAD используется для управления политиками безопасности и объектами доверия.

Во время работы доверия через LSAD выполняются:

  • открытие policy handle;

  • проверка существования доверенного домена;

  • получение информации о доверии;

  • закрытие policy handle.

Например, вызов LsarQueryTrustedDomainInfoByName используется для проверки существования доверенного домена.

Если домен отсутствует или информация о доверии некорректна, Active Directory завершает проверку с ошибкой.

LSAT, в свою очередь, используется для преобразования человекочитаемых идентификаторов в SID и обратно.

Основные методы:

  • LsarLookupNames4 — преобразование saMAccountName → SID;

  • LsarLookupSids3 — преобразование SID → saMAccountName.

Именно эти вызовы позволяют Active Directory корректно работать с пользователями и группами из другого леса.

Как в итоге работает доверие «лес–лес»

После создания доверительных отношений начинается второй этап — непосредственное использование доверия пользователями, группами и сервисами.

Типовые сценарии, позволяющие реализовать идентификацию, аутентификацию и авторизацию:

  • пользователь из одного леса обращается к ресурсам другого;

  • пользователь одного леса входит на рабочую станцию другого леса;

  • пользователь или группа одного леса добавляется в группу другого.

Один из самых показательных сценариев — добавление пользователя из MULTIDIRECTORY в группу Active Directory.

С точки зрения Active Directory пользователь хранится не как saMAccountName, а как SID. Поэтому перед добавлением необходимо выполнить преобразование идентификаторов.

В этом процессе участвуют два протокола:

  • LSAT — выполняет преобразование saMAccountName ↔ SID;

  • DRSUAPI — подтверждает существование объекта и его атрибутов.

Сначала AD через LSAT передаёт saMAccountName пользователя, например:

MD.LOC\user

В ответ MULTIDIRECTORY должен вернуть соответствующий SID:

S-1-5-21-2275084382-2134495226-2205412310-1001

Далее запускается цепочка вызовов DRSUAPI. Active Directory начинает последовательно проверять существование объекта:

  • отправляет CN/DN объекта;

  • запрашивает SID;

  • затем требует получить DisplayName по этому SID.

Только после успешного завершения этих проверок пользователь из MULTIDIRECTORY появляется в интерфейсах Active Directory как валидный объект.

С точки зрения сетевого взаимодействия процесс выглядит следующим образом:

  1. AD получает TGS у MD KDC.

  2. С этим TGS AD обращается к SMB-сервису MD.

  3. MD расшифровывает билет keytab-ключом и подтверждает подлинность TGS.

  4. После этого запускается Secure Channel на основе TDO пароля.

  5. Далее вызывается NetrLogonSamLogonEx.

Если взаимодействие шло через NTLM, в запросе передаются NTLM-хэши для проверки.

Если использовался Kerberos, парольные поля остаются пустыми, а через NetrLogonSamLogonEx передаётся PAC, ранее полученный вместе с TGS.

После этого Active Directory завершает вход пользователя из MULTIDIRECTORY в свою систему.

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

Что в итоге

К началу 2026 года нам удалось полностью реализовать двустороннее доверие типа «лес–лес» с Active Directory. Это включало поддержку необходимых протоколов, доработку Kerberos, реализацию PAC и Global Catalog, а также воспроизведение логики взаимодействия, используемой Microsoft.

Главный результат — не только сам механизм доверия, но и контроль над ним. Мы не зависим от сторонних реализаций, можем оперативно адаптироваться к изменениям в экосистеме и обеспечивать предсказуемое поведение в инфраструктуре заказчика.

И самое важное — это решает ключевую практическую задачу: позволяет строить гибридные инфраструктуры и мигрировать с Active Directory на Linux-каталог без остановки бизнеса.

В ближайших планах — использовать эти же протоколы для реализации полноценного Windows Domain Join. Следите за новостями!

ссылка на оригинал статьи https://habr.com/ru/articles/1037620/