Active Directory LDAP/LDAPS Security Monitor
A PowerShell script for auditing and monitoring LDAP/LDAPS security across Active Directory environments. Produces interactive HTML reports and CSV exports covering Domain Controllers and member/application servers.
LDAP signing and channel binding are critical security controls that prevent man-in-the-middle attacks against Active Directory. This script gives you a complete picture of your environment's LDAP security posture in a single HTML report — covering every Domain Controller and every member/application server (including Exchange).
- LDAP signing — server-side enforcement on DCs, client-side configuration on app servers
- Channel binding — whether DCs are enforcing channel binding tokens over LDAPS
- LDAPS certificates — installed, expiry date, issuer, days remaining
- TLS protocol status — TLS 1.2/1.3 enabled, SSL 3.0/TLS 1.0/TLS 1.1 disabled
- Security events — 2886, 2887, 2888, 2889 (unsigned bind events), 3039, 3040, 3041 (channel binding events)
- Active connections — live LDAP/LDAPS connections per server with direction (Inbound/Outbound/Listening), remote IP, process name
- Risk scoring — per-server composite risk score with colour-coded severity
- Unreachable servers — servers that could not be queried, listed explicitly
(Add screenshots of your HTML report here after your first run)
| Requirement | Details |
|---|---|
| PowerShell | 5.1 or later (built into Windows Server 2012 R2+) |
| AD Module | RSAT-AD-PowerShell feature installed on the machine running the script |
| WinRM | Enabled on all target servers (ports 5985/5986) |
| Permissions | Domain Admin or equivalent — script queries registry and event logs remotely |
| Network | Access to all DCs and member servers via WinRM |
# On Windows Server
Install-WindowsFeature RSAT-AD-PowerShell
# On Windows 10/11
Add-WindowsCapability -Online -Name Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0# Run on each remote server (or via GPO)
winrm quickconfig -quiet- Download
AD-LDAPAudit.ps1from this repository - Place it in a folder on your Domain Controller or admin workstation (e.g.
C:\Scripts\) - Run from an elevated PowerShell prompt
.\AD-LDAPAudit.ps1Reports are saved to .\Reports\ by default.
.\AD-LDAPAudit.ps1 -ReportsFolder "C:\AuditReports".\AD-LDAPAudit.ps1 -EventLogHours 48.\AD-LDAPAudit.ps1 -ReportsFolder "D:\Reports" -EventLogHours 72| File | Contents |
|---|---|
LDAP_Connections_YYYYMMDD_HHMMSS.html |
Full interactive HTML report |
LDAP_Connections_YYYYMMDD_HHMMSS.csv |
All connections in CSV format |
LDAP_SecurityEvents_YYYYMMDD_HHMMSS.csv |
Security events in CSV format |
LDAP_SecurityConfig_YYYYMMDD_HHMMSS.csv |
Security configuration in CSV format |
| Section | Description |
|---|---|
| Summary | Total connections, active LDAP/LDAPS counts, event count, unreachable servers |
| Unreachable Servers | Servers that could not be queried — listed with reason |
| Risk Scoring | Composite risk gauge and per-server risk bars |
| Top Offending Servers | Ranked table of servers with highest risk scores |
| LDAPS Readiness Dashboard | Progress bars for each security requirement across the fleet |
| Security Configuration | Per-server signing, channel binding, cert, TLS settings |
| Connection Details | Live connections with direction, remote IP, process name |
| Security Events | LDAP signing and channel binding events from the last N hours |
| Reference | Event ID descriptions, registry paths, remediation guidance |
All tables have a filter box and Export CSV button.
For member/application servers (Exchange, IIS, middleware), the script reads LDAPClientIntegrity — the client-side signing setting:
| Value | Meaning | Report shows |
|---|---|---|
| 0 | None — unsigned binds | Red ✗ |
| 1 | Negotiate signing — signs when DC requires it | Green ✓ (recommended rollout starting point) |
| 2 | Require signing — always signed | Green ✓ (fully enforced) |
| Not Set | Registry key absent — GPO may not have refreshed | Amber ⚠ |
For Domain Controllers, the script reads LDAPServerIntegrity (server-side) — values 1 and 2 both mean signing is enforced.
By default, Windows does not log Event 2889 (individual unsigned bind events with client IP). To enable it, set the following on each Domain Controller:
Registry: HKLM\SYSTEM\CurrentControlSet\Services\NTDS\Diagnostics
Value: 16 LDAP Interface Events
Type: REG_DWORD
Data: 2
PowerShell — single DC:
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Diagnostics" `
-Name "16 LDAP Interface Events" -Value 2 -Type DWordPowerShell — all DCs at once:
$DCs = (Get-ADDomainController -Filter *).HostName
foreach ($dc in $DCs) {
Invoke-Command -ComputerName $dc -ScriptBlock {
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\NTDS\Diagnostics" `
-Name "16 LDAP Interface Events" -Value 2 -Type DWord
}
Write-Host "Set on $dc" -ForegroundColor Green
}To revert: Set the value back to 0.
This key is DC-only. Do not set it on Exchange or application servers.
This script is designed to support a phased LDAP signing rollout:
Run the script as-is. Identify which servers have signing configured and which have unsigned bind events.
Apply GPO setting Network security: LDAP client signing requirements = Negotiate signing to application server OUs. Re-run the script — servers with the GPO applied show 1 ✓ Negotiate (Client).
Once confident all app servers are negotiating correctly and no legitimate unsigned binds remain, change selected servers from Negotiate to Require. The script clearly distinguishes between the two states so you can track progress.
- Verify WinRM is running:
Test-WSMan -ComputerName <servername> - Check firewall allows ports 5985/5986
- Confirm the account running the script has remote management rights
- The script checks both
HKLM:\SYSTEM\CurrentControlSet\Services\LDAP\LDAPClientIntegrityand the GPO policy pathHKLM:\SOFTWARE\Policies\Microsoft\Windows\LDAP\LDAPClientIntegrity - Run
gpupdate /forceon the server and re-run the script - Check WinRM connectivity — if the script cannot connect it cannot read the registry
- Windows Server 2012 R2 and later have TLS 1.2 enabled by default without registry keys
- The script detects TLS 1.2 by checking for an explicit registry enable key — if absent it reports Not Set
- This is typically a reporting gap rather than a real security gap
- Ensure you are running PowerShell 5.1 or later
- This error was present in early versions and is fixed in v1.0.0
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-improvement) - Commit your changes (
git commit -m "Add my improvement") - Push to the branch (
git push origin feature/my-improvement) - Open a Pull Request
MIT License — see LICENSE for full text.
Rob van Blerk
If this tool is useful to you, feel free to star the repository and share it with your network.