Fix it now
LDAP 8 is a domain controller refusing a bind because the connection was not protected, not because the credential was wrong. A simple bind outside TLS and a SASL bind that never requested integrity are both rejected before the password is looked at. You change how the client connects, not what it sends.
reg add "HKLM\SYSTEM\CurrentControlSet\Services\NTDS\Diagnostics" /v "16 LDAP Interface Events" /t REG_DWORD /d 2 /f
certutil -DCInfo Verify
- Read the Directory Service log. Event 2886 says this controller is not configured to reject unprotected binds; Event 2887 is the 24-hour count of unprotected binds it accepted; Event 2888 is the same count once it is rejecting them.
- Collect Event 2889 for a full business cycle. That is the per-bind record, and it names the client IP address, the identity offered and whether it was an unsigned SASL bind or a simple bind. It only appears once you have raised the diagnostic value above.
- Move each named client to LDAPS on TCP 636 – or 3269 for a global catalog – or to a bind that negotiates signing. Both are acceptable to a hardened controller with no change to the account.
- If binds on 636 fail from everywhere including the controller itself, the certificate is the problem rather than the client.
certutil -DCInfo Verifychecks the domain controller certificates.
Set the diagnostic value back to 0 once you have your list, and do not raise enforcement across every controller before you have read 2889 for a full month, month end included. The clients you break will be the ones nobody documented.
If the application binds over TLS and stops appearing in Event 2889, you are done. If it cannot be moved, the next section covers the two settings involved and what each one actually does.
Why it happens
Microsoft publishes LDAP 8 as LDAP_STRONG_AUTH_REQUIRED, 0x08, “Strong authentication is required.” Its companion, LDAP 13, is LDAP_CONFIDENTIALITY_REQUIRED, 0x0d, “Confidentiality is required.” Neither says anything about your password or your account. They are the directory declining to have the conversation on the terms you offered.
Two separate controls produce them and they are constantly confused. LDAP server signing is the requirement that a SASL bind negotiate integrity; a simple bind cannot be signed at all, so the only way to keep one is to carry it inside TLS. Channel binding is a different thing: it ties an authenticated bind to the specific TLS channel it arrived on, so a session captured and relayed elsewhere cannot be reused. A client can satisfy one and fail the other.
Both are backed by registry values under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters. LDAPServerIntegrity is 1 for none and 2 for require signing. LdapEnforceChannelBinding is 0 for never, 1 for when supported, and 2 for always. The Group Policy settings that write them are Domain controller: LDAP server signing requirements and Domain controller: LDAP server channel binding token requirements.
The events are the trail leading up to enforcement, and reading them in order is the whole job. Event 2886 warns that this server is not yet rejecting unprotected binds. Event 2887 is the 24-hour summary while it still accepts them, carrying two counts: simple binds performed without SSL or TLS, and Negotiate, Kerberos, NTLM or Digest binds performed without signing. Event 2888 is that same summary once the server is configured to reject, so it tells you what you are currently breaking. Event 2889 is the only one that names anybody, and it is switched off by default.
The application does a simple bind on port 389
You have this one if Event 2889 names it with binding type 1, and its configuration shows port 389 with no TLS option enabled.
- Move the connection to port 636 with SSL, or to 389 with StartTLS where the application supports that instead.
- Confirm the client trusts the issuer of the domain controller certificate. An untrusted chain looks like a connection failure rather than a certificate one, and sends people back to the firewall.
- Test by hand from the same host on 636 before you change the application’s configuration.
- Where the application offers a signed or negotiated bind, that is equally acceptable and avoids the certificate question entirely.
The domain controllers have no usable certificate for LDAPS
You have this one if Binds on 636 fail from every client, including a test run on the domain controller itself.
- Run
certutil -DCInfo Verifyon each controller. You need Domain Admins or Enterprise Admins to run it. - Confirm each controller holds a certificate with server authentication usage, a private key, and a subject or alternative name matching how clients address it.
- Enrol from a suitable template through autoenrolment rather than issuing certificates by hand, so renewal is not a future outage.
- Retest on 636 from a client, not from the controller, because the client is where trust in the issuer has to exist.
Channel binding is enforced and the client cannot produce a token
You have this one if The client connects over TLS successfully and the bind is still refused, and the change followed a move of LdapEnforceChannelBinding to 2.
- Update the client, its LDAP library or its operating system to a build that supports channel binding tokens.
- In the meantime set LdapEnforceChannelBinding to 1, which requires binding only from clients able to provide it.
- Treat 1 as a staging post with a date on it rather than a destination, and retest each client as it is updated.
Windows clients are not requesting signing
You have this one if Windows-based applications fail while others succeed, and no LDAP client signing policy reaches those machines.
- Set Network security: LDAP client signing requirements to require signing in a policy covering the affected machines.
- Refresh policy on one machine and confirm the setting actually arrived by reading the resultant policy, rather than assuming the GPO applied.
- Test the applications on those machines afterwards, because the setting affects every outbound LDAP bind they make, not only the one you were chasing.
Full reference
The settings, and where each one lives
| Setting | Where | Values |
|---|---|---|
| Domain controller: LDAP server signing requirements | Group Policy on the domain controllers | Writes LDAPServerIntegrity |
LDAPServerIntegrity |
HKLM\SYSTEM\CurrentControlSet\Services\NTDS\Parameters |
1 none, 2 require signing |
| Domain controller: LDAP server channel binding token requirements | Group Policy on the domain controllers | Writes LdapEnforceChannelBinding |
LdapEnforceChannelBinding |
HKLM\SYSTEM\CurrentControlSet\Services\NTDS\Parameters |
0 never, 1 when supported, 2 always |
16 LDAP Interface Events |
HKLM\SYSTEM\CurrentControlSet\Services\NTDS\Diagnostics |
Raise to 2 or higher to log Event 2889 |
| Network security: LDAP client signing requirements | Group Policy on member machines | Whether Windows clients request signing when they bind |
Export the NTDS Parameters and Diagnostics keys before editing them, and prefer the Group Policy settings where they exist. Raising enforcement on every controller at once, before you know who is still binding unprotected, will take out applications nobody knew were using LDAP – and the list always includes something that matters.
Reading the four events in order
| Event | Logged when | What it gives you |
|---|---|---|
| 2886 | The server is not configured to reject unprotected binds | A warning, and the instruction to raise LDAP Interface Events to level 2 for detail |
| 2887 | Every 24 hours while it is still accepting them | Counts of simple binds without SSL or TLS, and of unsigned SASL binds |
| 2888 | Every 24 hours once it is rejecting them | The same two counts, but of binds rejected – what you are currently breaking |
| 2889 | Per bind, once the diagnostic is at level 2 | Client IP address and port, the identity offered, and binding type 0 for unsigned SASL or 1 for simple |
So the sequence is: turn on the diagnostic, collect 2889 until you are confident the list is complete, fix the clients, watch 2887 fall to zero, then enforce, then watch 2888 to confirm nothing was missed. Enforcing before 2887 reaches zero is guessing.
Ports, once the client is moving to TLS
| Port | Service |
|---|---|
| 389/TCP and UDP | LDAP |
| 636/TCP | LDAP over SSL |
| 3268/TCP | Global catalog LDAP |
| 3269/TCP | Global catalog LDAP over SSL |
An application reading across domains in a multi-domain forest needs the global catalog port, so moving it to TLS means 3269 rather than 636. Changing the port without changing the target is a common way to turn a signing problem into a “the account cannot be found” problem.
What appears on the list, and what you can actually do about it
- Line-of-business applications with a settings page: usually a five-minute change to the port and a checkbox, provided the client trusts your issuing CA.
- Appliances – copiers, door controllers, storage arrays, network kit: check for firmware that supports LDAPS. Where none exists, this belongs with that vendor, and no Windows licence changes it.
- Linux and Unix hosts: normally a configuration change in the LDAP client library plus the CA certificate in the trust store.
- Scripts and scheduled tasks written years ago against port 389: often the largest group by count and the easiest to fix.
- Servers on a Windows build that no longer receives updates: the one case where there is nothing to configure.
If you have to retreat
Setting the controllers back to accepting unprotected binds works immediately and puts you back where you started, which is exposed. If you do it, do it with a date attached and a list of the clients you are waiting on. An indefinite retreat is how the estate ends up in the same position two years later with more clients on the list, not fewer.
When a licence is the actual fix
Most of this list costs nothing: enrolling domain controller certificates and changing an application’s connection settings are free. There is one case where a licence really is the fix. A server on a Windows build that has left support will never receive the updates that let it negotiate signing or produce a channel binding token, and leaving signing unenforced for its benefit keeps every bind in the domain unprotected – which is the exact weakness these controls exist to close. Moving that workload onto a supported server is a licensing purchase, and Arco supplies Windows Server 2025 Standard; note that a Standard licence carries the right to run two virtual machines plus one Hyper-V host, so a virtual replacement may already be covered by capacity you hold. Read your Event 2889 list first, though: where the offender is an appliance, a copier or a Linux host, a Windows licence changes nothing and the fix belongs with that vendor.
Every code this article covers
| Code | What it points at | Source |
|---|---|---|
LDAP 8 |
LDAP_STRONG_AUTH_REQUIRED, 0x08: strong authentication is required | Microsoft Learn |
LDAP 13 |
LDAP_CONFIDENTIALITY_REQUIRED, 0x0d: confidentiality is required, meaning the connection must be inside TLS | Microsoft Learn |
Event ID 2886 |
Directory Service log warning that this server is not configured to reject unsigned SASL binds and clear-text simple binds | Microsoft Learn |
Event ID 2887 |
The 24-hour summary of unprotected binds accepted, with separate counts for unencrypted simple binds and unsigned SASL binds | Microsoft Learn |
Event ID 2889 |
The per-bind record naming client IP address, the identity offered and the binding type. Only logged once LDAP Interface Events is raised to level 2 or higher | Microsoft Learn |
Confirm the fix worked
- A test bind on port 636 with SSL succeeds against every domain controller, not just the first one you tried.
- Event 2889 no longer names the application you fixed, over a full day rather than a single test.
- The Event 2887 counts have fallen to zero and stayed there for a business cycle before you enforce anything.
- After enforcement, Event 2888 reports zero rejected binds.
certutil -DCInfo Verifyreports the domain controller certificates as valid on each controller.
Questions people ask about this
Can I just set the controllers back to accepting unsigned binds?
You can, and everything works again immediately, but you have reopened the exposure the setting exists to close. Use it as a short, dated retreat while you fix clients, not as a resting state.
Does LDAPS need a certificate from a public authority?
No. A certificate from your own internal CA is the normal choice, provided every client trusts that CA. Public certificates exist to validate names outside your organisation, which domain controller names generally are not.
What does this cost?
For most readers, nothing. Certificates from your own CA and application settings changes are free. A cost appears only where an application host is too old to comply and has to be replaced, and that is an end-of-support problem rather than an LDAP one.
How do I find every application binding unprotected before I enforce?
Raise the 16 LDAP Interface Events value under the NTDS Diagnostics key to 2 on the domain controllers and collect Event 2889 for a full business cycle. It names the client address and the identity for each bind, which is enough to build the work list.
Is signing the same thing as channel binding?
No, and treating them as one setting is the most common mistake here. Signing requires integrity on the bind. Channel binding ties the bind to the TLS channel it arrived on. They are separate registry values, separate policies, and a client can satisfy one while failing the other.
