LDAPS работает, а Always отключит клиентов: как провести аудит CBT, которому можно верить
Успешное LDAPS-соединение и пустой журнал не доказывают, что клиенты переживут режим Always. Аудит channel binding надёжен, только когда на каждом контроллере включены оба условия записи событий, журнал не перетирается, а в отчёте есть заведомо известный клиент. Ниже проверка аудита, сбор событий и порядок включения.
Почему тишина в журнале Directory Service ничего не доказывает
Самая частая история, которую я разбираю в малых доменах: администратор включил LDAPS, подключил к нему принтеры, 1С и почтовый сервер, увидел, что всё работает, и записал в чек-лист «channel binding готов». Потом он открыл журнал Directory Service, не нашёл там ничего про токены привязки канала и успокоился окончательно. Проблема в том, что соединение по TLS и проверка токена привязки канала (CBT) — две разные вещи. Клиент может спокойно пройти рукопожатие TLS и вообще не передать токен, и при мягкой настройке контроллер это молча проглотит. Причём касается это не всех: по документации Microsoft привязка канала применяется только к SASL-привязкам (NTLM, Kerberos) поверх TLS, а простой bind логином и паролем и вход по клиентскому сертификату через LDAPS она не трогает. Поэтому первый вопрос к каждому устройству — не «ходит ли оно по LDAPS», а «каким типом bind». Если у вас домен и вы хотите понять, где у него такие места, начните с аудита Active Directory: аудит CBT — только одна из проверок, но самая коварная.
Почему молчит журнал, объясняет документация Microsoft, и эти условия стоит выучить наизусть. События 3039, 3074 и 3075 генерируются только тогда, когда политика канального связывания стоит в положении When Supported или Always. В положении Never контроллер вместо этого пишет только сводное событие 3040 (сколько незащищённых LDAPS-привязок было за сутки) и напоминание 3041, а картины по конкретным клиентам вы не получите вообще. Кроме того, подробное протоколирование LDAP включается отдельным параметром диагностики: значение «16 LDAP Interface Events» должно быть не ниже 2, а по умолчанию там 0. Итого пустой журнал означает одно из двух: либо клиентов, которые сломаются, нет, либо вы просто не включили запись. Угадайте, чего в малых офисах больше.
Здесь же развод с моей прошлой статьёй. В статье про события 3074 и 3075 я разбирал, что означает каждое событие и как выглядит сбор на практике. Сейчас вопрос другой: как убедиться, что сам аудит честный. Потому что хуже отсутствия аудита только аудит, который выдаёт зелёный цвет по неверным причинам. Пустой отчёт — самое опасное, что можно положить директору на стол: на него будут опираться и включат Always в пятницу вечером.
Что проверить до сбора: пять условий, без которых аудит слеп
Первое условие — обновления. Microsoft указывает, что политика и события канального связывания появились в обновлениях от 10 марта 2020 года, а события аудита 3074 и 3075 добавили позже: для Windows Server 2022 в августе 2023 года, для Windows Server 2019 в октябре 2023 года. Сначала они были выключены и требовали ручного включения. С 14 ноября 2023 года на Server 2022 и с 9 января 2024 года на Server 2019 дополнительный шаг не нужен. На практике это значит одно: если контроллер у вас не обновлялся с 2022 года, аудит на нём может просто не существовать. Сверьте уровень обновлений на каждом контроллере и не доверяйте памяти администратора.
Второе и третье условия — политика и диагностика, причём на каждом контроллере, а не на «основном». Политика называется «Domain controller: LDAP server channel binding token requirements» и пишет значение LdapEnforceChannelBinding в раздел параметров службы каталога: 0 — Never, 1 — When Supported, 2 — Always. Диагностика — это значение «16 LDAP Interface Events» в разделе Diagnostics той же службы, не ниже 2. Клиенты выбирают контроллер сами, поэтому принтер, который ходит на второй контроллер, останется невидимым, если вы смотрите только первый. Проверить оба условия на всех контроллерах сразу можно так:
$dcs = (Get-ADDomainController -Filter *).HostName
Invoke-Command -ComputerName $dcs -ScriptBlock {
$p = 'HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Parameters'
$d = 'HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Diagnostics'
[pscustomobject]@{
DC = $env:COMPUTERNAME
CBT = (Get-ItemProperty $p -Name LdapEnforceChannelBinding -ErrorAction SilentlyContinue).LdapEnforceChannelBinding
LdapLog = (Get-ItemProperty $d -Name '16 LDAP Interface Events').'16 LDAP Interface Events'
}
} | Format-Table DC, CBT, LdapLogЕсли в колонке CBT пусто, значение не задано явно: не гадайте, какой режим подразумевается, задайте политикой и проверьте ещё раз. Если в LdapLog стоит 0 — вы ничего не увидите, как бы ни вели себя клиенты. Включить диагностику можно командой Set-ItemProperty с типом DWord и значением 2 по тому же пути. Уровень 3 и выше Microsoft не рекомендует из-за нагрузки, а после расследования значение советуют возвращать в 0.
Четвёртое условие — размер и режим журнала, и о нём забывают чаще всего. Журнал Directory Service по умолчанию невелик и перезаписывает старые записи. На загруженном контроллере, где и без того пишутся события репликации, подробные события LDAP могут вытеснить недельную историю за пару суток, и вы увидите «чистый» отчёт за последние двое суток вместо тридцати дней. Посмотрите текущие параметры командой wevtutil gl 'Directory Service' и увеличьте лимит. Если место на системном диске не жалко, 256 МБ хватает малому офису с запасом:
wevtutil gl 'Directory Service'
wevtutil sl 'Directory Service' /ms:268435456Минимальный размер журнала по документации — 1048576 байт, размер всегда кратен 64 КБ. Про переполнение журналов на контроллере у меня есть отдельный разбор: там та же болезнь, только в журнале безопасности.
Пятое условие — контрольный клиент, и это единственный пункт, которого нет ни в одной инструкции вендора. До начала аудита найдите устройство, про которое точно знаете, что оно ходит в каталог по LDAPS именно SASL-привязкой (обычно в настройках LDAP это выбор NTLM или Kerberos вместо «простой» аутентификации) и старое: тот же МФУ, NAS, сканер. Устройство с простым bind на роль контрольного не годится: оно в событиях CBT не появится никогда, и это будет правильное поведение, а не слепота аудита. Через неделю сверьте: его адрес должен появиться в событиях. Если не появился, значит, либо аудит слеп, либо устройство ходит не так, как вы думали, и оба варианта стоят отдельного выяснения. Аудит без известной точки отсчёта — как термометр, который показывает 36,6 в любой среде. Да, на выяснение уйдёт лишний день. Зато вы не будете объяснять директору, почему у кассы в понедельник пропал вход.
Если разбираться со всем этим по каждому контроллеру руками некогда, мы это делаем в рамках аудита домена: проверяем обновления, политики, диагностику и журналы на всех контроллерах и отдаём короткий отчёт. Напишите, посмотрим ваш домен и скажем, насколько ему рано включать Always.
Как собрать события 3039, 3074 и 3075 со всех контроллеров
Собирать события вручную через Event Viewer на двух контроллерах можно ровно один раз. Дальше начинается рутина, а рутину я автоматизирую. Мне нужен список событий за период с полем «кто пришёл» и итог «сколько уникальных адресов и сколько событий каждого типа». Командлет Get-WinEvent принимает фильтр через хеш-таблицу с ключами LogName, Id и StartTime, а параметр ComputerName позволяет опрашивать другой компьютер без настройки удалённого PowerShell, но только по одному компьютеру за вызов, поэтому цикл по контроллерам обязателен. Ещё одна деталь: когда событий нет, Get-WinEvent возвращает ошибку, а когда нет доступа к журналу, тоже ошибку. Смешивать их нельзя, иначе недоступный контроллер превратится в «чистый».
Поэтому в скрипте ниже сначала проверяется, что журнал на контроллере вообще читается, и только потом идёт выборка. Клиентский адрес я вытаскиваю регулярным выражением из текста события: в примере из документации Microsoft в событии есть строка с адресом и портом клиента и идентификатор, под которым он пытался войти. Регулярка ищет первый IPv4-адрес, поэтому для IPv6-клиентов её придётся доработать, а формат сообщения проверьте на своей версии и в своей локализации.
$ids = 3039, 3074, 3075
$since = (Get-Date).AddDays(-14)
$rows = foreach ($dc in $dcs) {
try { $null = Get-WinEvent -ComputerName $dc -ListLog 'Directory Service' -ErrorAction Stop }
catch { Write-Warning "$dc : журнал недоступен: $($_.Exception.Message)"; continue }
Get-WinEvent -ComputerName $dc -ErrorAction SilentlyContinue -FilterHashtable @{
LogName = 'Directory Service'; Id = $ids; StartTime = $since
} | ForEach-Object {
[pscustomobject]@{
DC = $dc
Id = $_.Id
Time = $_.TimeCreated
ClientIP = [regex]::Match($_.Message, '\b\d{1,3}(\.\d{1,3}){3}\b').Value
}
}
}
$rows | Group-Object ClientIP, Id | Sort-Object Count -Descending | Select-Object Count, Name
$rows | Export-Csv C:\Temp\cbt-audit.csv -NoTypeInformation -Encoding UTF8Для обращения к удалённому журналу на контроллерах должно быть разрешено удалённое управление журналом событий в брандмауэре: документация прямо говорит, что для ComputerName нужно открыть правило службы журнала событий.
Сколько собирать? Я не ставлю фиксированных сроков, а привязываюсь к циклу работы организации. В музыкальной школе есть расписание четвертей, у бухгалтерии есть закрытие месяца, у склада есть сезонные отгрузки. Любое устройство, которое ходит в каталог раз в месяц или раз в квартал, не попадёт в двухнедельную выборку. Минимальный период для меня — полный месячный цикл, плюс отдельный контрольный проход по всему, что происходит редко: годовая инвентаризация, сертификат, который обновляется раз в год, отчёты по расписанию. Собранный CSV я кладу рядом с инвентаризационной таблицей и сверяю каждый адрес: свой, чужой или «непонятно чей». Последняя категория интереснее всего.
Как читать события и флаги: что делать с каждым клиентом
События читаются просто, пока не начнёшь их путать. Событие 3075 говорит, что клиент по SSL/TLS не передал сведений о привязке канала, а в режиме принуждения такой bind был бы отклонён; в самом событии есть поле, считает ли контроллер клиента способным к привязке, и по нему видно, «не умеет» он или «умеет, но не прислал». Событие 3074 говорит, что при принуждении bind не прошёл бы проверку токена; в описании Microsoft типовая причина — неправильно сформированный токен, а точную причину показывают флаги результата, о них ниже. Событие 3039 — другая история: это уже не прогноз, а отказ, bind не прошёл проверку токена. Если вы видите 3039 на этапе «аудита», значит, аудит давно закончился, а часть клиентов уже получает отказы. Для 2889 всё иначе: оно относится к подписи LDAP, а не к привязке канала, и смешивать эти два аудита в один отчёт не стоит.
Отдельно скажу про числа в самом событии. В примере из документации Microsoft в событии 3074 есть поле с флагами результата аудита, и в нём можно прочитать больше, чем в самом заголовке. Значение 0x01 — клиент должен поддерживать привязки, 0x02 — привязки отсутствуют, 0x04 — несовпадение хеша, 0x08 — отсутствующие привязки не разрешены, 0x10 — совпадение, 0x20 — требуется proxy-привязка, 0x40 — отсутствующие привязки разрешены. Значения складываются: 0x42 из примера Microsoft означает «привязок нет, но в текущем режиме это допустимо». Присутствие в сумме битов 0x0C указывает на отказ, битов 0x30 — на валидный токен. Я не заучиваю таблицу, а держу её в шпаргалке рядом со скриптом.
Что делать с найденным клиентом, зависит от его природы. Свожу в таблицу то, что у меня стало рабочей схемой: | Что видим | Вероятная причина | Что делаю | |---|---|---| | 3075 с одного адреса, устройство старое | клиент не умеет CBT | прошивка, иначе смена способа входа или замена | | 3075 с сервера приложений | своя LDAP-библиотека без токена | обновление библиотеки или конфигурации у разработчика | | 3074 из-за балансировщика или шлюза | токен не совпадает при посредническом TLS | убрать посредника из цепочки или не включать Always | | 3039 | bind уже отклонён | считать инцидентом, разбирать немедленно | Прошивка помогает не всегда, и здесь я не буду обещать, что обновление вылечит всё: «поддерживает ли устройство привязку канала» надо читать в документации производителя, а для не-Windows клиентов Microsoft прямо советует проверить, что и привязка канала, и подпись поддерживаются операционной системой и приложением.
Теперь про «почтовые и Linux-клиенты», потому что они составляют заметную часть теневого LDAP в малых офисах. Если у вас почтовый сервер, wiki или файловый сервер на Linux ходит в домен по LDAP, то его настройку надо смотреть так же внимательно, как принтеры. Я разбирал, как ведёт себя клиент SSSD при подключении к каталогу, и на практике поддержку привязки канала приходится проверять не по описанию, а по событиям на контроллере. А когда проблемы с каталогом проявляются на стороне почты, например когда ящики mailcow не создаются через LDAP, стоит заглянуть и в журнал контроллера, прежде чем винить почтовую систему.
Разбор: музыкальная школа «Соль-Диез», 19 рабочих мест и аудит, который чуть не засчитали
Условный клиент для этого разбора — музыкальная школа «Соль-Диез»: 19 рабочих мест, два контроллера домена (DC01 на Windows Server 2019, DC02 на Windows Server 2022), электронный журнал на отдельном сервере, пара МФУ и сетевое хранилище с архивом расписаний. Приходящий администратор прочитал бюллетень, включил на контроллерах When Supported и через неделю отчитался: событий нет, клиенты готовы, можно ставить Always. К счастью, перед включением директор попросил второе мнение, и это был тот редкий случай, когда осторожность дешевле энтузиазма.
Первое, что я сделал, — прошёл по пяти условиям из второго раздела. Политика When Supported оказалась только на DC01, а на DC02 в реестре вообще не было значения. Диагностика LDAP стояла на уровне 2 тоже только на DC01. И журнал Directory Service на нём был сжат до размера по умолчанию и перекручивался за двое суток. То есть «неделя тишины» была сутками тишины на одном из двух контроллеров, причём на том, куда клиенты заходили реже. Политику мы вынесли в GPO на подразделение Domain Controllers, диагностику включили на обоих узлах, журналы расширили до 256 МБ и поставили контрольный период в три недели, чтобы захватить конец четверти с отчётами и выгрузкой расписания.
Итог по цифрам: за 21 день собрали события с шести адресов. Из них два МФУ, сетевое хранилище, сервер электронного журнала, шлюз гостевой Wi-Fi-авторизации и один адрес, не числившийся в таблице учёта. Последний оказался забытым тестовым сервером прежнего подрядчика, и мы его просто выключили. Остальные пять закрывали по очереди: обновление прошивки там, где производитель подтвердил поддержку, перенастройка клиента на сервере журнала, а для шлюза Wi-Fi пришлось сменить способ проверки учётных данных. От старта аудита до переключения на Always прошло пять недель, а после включения событий 3039 в первую неделю не появилось и звонков в учительскую не было. Контрольным клиентом, кстати, было одно из МФУ, у которого адресная книга ходила в каталог NTLM-привязкой по LDAPS: его адрес появился в отчёте на третий день, и именно это доказало, что аудит не слепой.
Как переходить на Always и откатываться без простоя
К Always я перехожу, только когда выполнены три условия: журнал собирался не менее полного цикла работы организации, каждый найденный адрес закрыт или осознанно исключён, и есть понятный откат. Включаю режим тем же способом, каким включал аудит, то есть групповой политикой «Domain controller: LDAP server channel binding token requirements» на подразделение контроллеров, а не правкой реестра на каждом узле по отдельности. Разные значения на разных контроллерах дают плавающую ошибку: один и тот же клиент то работает, то нет, в зависимости от того, куда его отправил поиск контроллера. Применение политики на контроллерах проверяйте инструментами из статьи про диагностику групповых политик, а итоговое значение читайте из реестра командой reg query по тому же пути, что и раньше.
Откат — это возврат политики в When Supported, а не в Never. Так вы сразу останавливаете отказы, но сохраняете возможность видеть, кто именно упал. Заранее договоритесь, кто принимает решение откатывать и по какому признаку: по звонкам пользователей, по событиям 3039 или по тому и другому. Выбирайте окно, когда рядом есть человек, способный проверить принтеры, 1С и почту, а не пятничный вечер. И держите под рукой список «клиент → ответственный», собранный в ходе аудита: когда что-то отвалится, искать владельца устройства по памяти — худшее занятие на свете.
Что не надо путать и чего не стоит ждать от Always. Подпись LDAP и привязка канала — два разных механизма с разными политиками: «Domain controller: LDAP server signing requirements» со значениями None и Require signing (реестровый параметр LDAPServerIntegrity), а на Windows Server 2025 к ней добавилась «Domain controller: LDAP server signing requirements enforcement». Привязка канала защищает SASL-привязки внутри SSL/TLS, подпись — SASL-сессии без TLS на порту 389, и включение одного не отменяет другое. Про Windows Server 2025 Microsoft пишет так: в новых развёртываниях Active Directory подпись LDAP по умолчанию обязательна, политика CBT по умолчанию стоит в When supported, а аудит CBT включён. При обновлении с прежних версий существующие политики сохраняются. Отсюда практический вывод: новый контроллер на 2025 в старом домене может вести себя не так, как его соседи на 2019 и 2022. Поэтому не полагайтесь на умолчания ни на новом, ни на обновлённом контроллере: задавайте режим явно политикой и проверяйте реестр.
И последнее, о чём я предупреждаю всех. Аудит CBT — не разовая акция, а часть жизни домена. Новое МФУ, новая версия бизнес-приложения, переезд почты на другой сервер — каждое из этих событий может добавить клиента, который не умеет передавать токен. Поэтому после перехода на Always держите события на контроле в мониторинге, а при расширении домена возвращайтесь к проверке. Как подключить события Active Directory к наблюдению, я описывал в статье про мониторинг Active Directory в Zabbix. А вся цепочка, от проверки условий до переключения и контроля, у нас занимает от двух до пяти недель в зависимости от календаря организации; весь этот срок съедает не работа, а ожидание полного цикла событий.
Мы можем сделать это за вас. По шагам статьи: проверим обновления, политики, диагностику и размер журналов на каждом контроллере, соберём события и сведём клиентов в таблицу, закроем найденное и переключим домен на Always с планом отката. Срок — от двух до пяти недель, из них около недели наших трудозатрат, остальное — период наблюдения. На выходе вы получаете отчёт по клиентам, настроенную групповую политику и мониторинг событий. Стоимость аудита назовём после осмотра домена, а регулярное обслуживание серверов у нас от 7 000 ₽/мес.
Частые вопросы
Почему при When Supported я не вижу событий 3074 и 3075?
Чаще всего не включена диагностика: значение «16 LDAP Interface Events» должно быть не ниже 2 на каждом контроллере. Кроме того, на контроллере должны стоять обновления, добавившие аудит, а журнал Directory Service не должен перезаписываться за пару дней.
Достаточно ли того, что LDAPS у клиента работает?
Нет. TLS-соединение и токен привязки канала — разные вещи. Клиент может установить LDAPS и не передать токен, и в мягком режиме контроллер это допустит. При этом простой bind и вход по сертификату привязка канала не затрагивает — под удар попадают SASL-привязки (NTLM, Kerberos) поверх TLS. Судить о готовности нужно по событиям 3074, 3075 и 3039, а не по факту подключения.
Чем отличаются события 3074, 3075 и 3039?
3074 — при принуждении bind не прошёл бы проверку токена (например, токен сформирован неверно). 3075 — клиент не передал сведения о привязке канала, при принуждении bind был бы отклонён. 3039 — bind уже не прошёл проверку токена, то есть это отказ, а не прогноз.
Можно ли включать Always сразу на всех контроллерах?
Да, и это правильнее, чем по одному: политику задают GPO на подразделение контроллеров, чтобы режим везде был одинаковым. Откат делайте в When Supported, а не в Never, чтобы не терять видимость клиентов.
Влияет ли Always на подпись LDAP?
Нет, это две независимые политики. Привязка канала относится к соединениям по SSL/TLS, подпись задаётся отдельной политикой «Domain controller: LDAP server signing requirements». Проверяйте и настраивайте их раздельно.
Источники
- Microsoft Support: KB4520412 — требования к LDAP channel binding и LDAP signing — Проверено: имя политики и значения LdapEnforceChannelBinding (0, 1, 2), события 3039, 3074, 3075, флаги аудита, хронология обновлений 2020-2024. https://support.microsoft.com/en-us/topic/2020-2023-and-2024-ldap-channel-binding-and-ldap-signing-requirements-for-windows-kb4520412-ef185fb8-00f7-167d-744c-f299a66fc00a
- Microsoft Learn: как включить LDAP signing в Windows Server — Проверено: политика Domain controller: LDAP server signing requirements, события 2886-2889, включение «16 LDAP Interface Events» на уровень 2. https://learn.microsoft.com/en-us/troubleshoot/windows-server/active-directory/enable-ldap-signing-in-windows-server
- Microsoft Learn: диагностическое протоколирование AD DS и LDS — Проверено: путь раздела NTDS\Diagnostics, уровни 0-5, значение по умолчанию 0, рекомендация не использовать уровень 3 и выше. https://learn.microsoft.com/en-us/troubleshoot/windows-server/active-directory/configure-ad-and-lds-event-logging
- Microsoft Learn: Get-WinEvent — Проверено: ключи FilterHashtable (LogName, Id, StartTime), параметры ComputerName и ListLog, ограничение на один компьютер за вызов. https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.diagnostics/get-winevent
- Microsoft Learn: wevtutil — Проверено: синтаксис gl и sl, параметр /ms, минимальный размер журнала и кратность 64 КБ. https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/wevtutil
- Microsoft Learn: LDAP channel binding in Active Directory — Проверено: CBT применяется только к SASL-привязкам поверх TLS (не к simple bind и certificate bind), умолчание When supported и включённый аудит для новых развёртываний Windows Server 2025, события 3039-3041, 3074, 3075. https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/ldap-channel-binding



