Domain controller hardening: the DC baseline
A practical checklist for hardening domain controllers: security baselines, Print Spooler, logon rights, RDP, egress, and patch priorities.
Domain controllers are the single highest-value target in most Windows environments: compromise one and an attacker effectively owns the domain. Yet DCs are frequently treated like ordinary member servers — left with default roles enabled, reachable over RDP by half the helpdesk, and allowed to browse the internet for "convenience." This guide walks through the concrete configuration steps that shrink a DC's attack surface to what it actually needs: authentication, replication, and DNS.
Everything below is additive to your existing patching cadence, not a replacement for it. Treat this as the minimum bar for any DC, whether you run two or two hundred.
Apply the Microsoft security baseline
Start from Microsoft's published Security Compliance Toolkit baseline for the Domain Controller role rather than inventing your own policy from scratch. The baseline GPOs encode Microsoft's current guidance for audit policy, User Rights Assignment, and security options, and they are versioned per Windows Server release.
- Download the current Security Compliance Toolkit (SCT) and the matching Windows Server security baseline for your DC OS version from Microsoft.
- Import the baseline GPOs into your domain (linked to a test OU first) using the package's
Baseline-ADImport.ps1script or the Group Policy Management Console (GPMC) Import Settings wizard.LGPO.exeonly applies settings to the local policy of a single test machine. - Diff the baseline against your current DC GPOs using
Get-GPOReport -ReportType Htmlbefore rollout, so you know exactly what will change. - Link the baseline GPO to an OU containing only domain controllers (normally the built-in Domain Controllers OU), never to the domain root.
# Export current DC-linked GPOs for comparison before importing the baseline
Get-GPO -All | Where-Object { (Get-GPInheritance -Target "OU=Domain Controllers,DC=corp,DC=example,DC=com").GpoLinks.DisplayName -contains $_.DisplayName } |
ForEach-Object { Get-GPOReport -Guid $_.Id -ReportType Html -Path "C:\GPOBackup\$($_.DisplayName).html" }Re-run the baseline import each time Microsoft ships an update; treat it like patch management, not a one-time project.
Disable the Print Spooler service on DCs
The Print Spooler service has been the entry point for multiple critical vulnerabilities, most notably PrintNightmare (CVE-2021-34527), plus a long tail of point-and-print driver-installation issues and coercion abuse (spooler-based RPC coercion feeding into NTLM relay). None of this functionality is needed on a domain controller.
# Disable and stop the Print Spooler on all DCs
Get-ADDomainController -Filter * | ForEach-Object {
Invoke-Command -ComputerName $_.HostName -ScriptBlock {
Stop-Service -Name Spooler -Force
Set-Service -Name Spooler -StartupType Disabled
}
}Enforce this centrally via GPO so it survives reboots and re-provisioning:
- Computer Configuration → Policies → Windows Settings → Security Settings → System Services → Print Spooler → set to Disabled.
Verify:
Get-ADDomainController -Filter * | ForEach-Object {
Get-Service -ComputerName $_.HostName -Name Spooler | Select-Object MachineName, Status, StartType
}If a legacy application genuinely requires print services on a server, that is a job for a dedicated, non-DC print server — never a domain controller.
Restrict local and RDP logon to Tier 0 only
Every account that can log on interactively or over RDP to a DC is, functionally, a Domain Admin. Apply the User Rights Assignment settings below through a GPO linked to the Domain Controllers OU, and populate them with a dedicated Tier 0 admin group rather than broad groups like Domain Admins or Server Admins.
| Right | GPO path | Recommended membership |
|---|---|---|
| Allow log on locally | Computer Configuration → Windows Settings → Security Settings → Local Policies → User Rights Assignment | Tier 0 Admins only |
| Allow log on through Remote Desktop Services | (same path) | Tier 0 Admins only (small, named group) |
| Deny log on through Remote Desktop Services | (same path) | All non-Tier-0 admin groups (not Domain Users: Tier 0 admins are members too, and deny overrides allow) |
| Deny access to this computer from the network | (same path) | Local accounts and Tier 1/Tier 2 admin groups (never Domain Users: every user and computer needs network logon to DCs for SYSVOL and Group Policy) |
# Verify current Allow log on through RDS membership on a DC
$dc = "DC01"
secedit /export /cfg C:\Temp\dc01-secpol.cfg /areas USER_RIGHTS
Select-String -Path C:\Temp\dc01-secpol.cfg -Pattern "SeRemoteInteractiveLogonRight"Pair this with the Tier 0 & privileged access model: Tier 0 admins should connect from Privileged Access Workstations, not from their day-to-day laptops, and standing RDP access should be replaced with just-in-time elevation where possible.
Block outbound internet access from domain controllers
A DC has no legitimate reason to browse arbitrary internet hosts. Outbound access is a common post-compromise channel for command-and-control callbacks and data staging. Restrict DC egress at the network firewall to only what is operationally required:
- Windows Update / WSUS or a patch management endpoint
- NTP/time sync sources (if not using an internal time hierarchy)
- Certificate revocation/OCSP endpoints if publicly hosted
- Any required directory-sync endpoints (e.g., Entra Connect, if not co-located)
# Example firewall intent (implement in your perimeter/NGFW, not just Windows Firewall)
DENY DC-subnet -> ANY (0.0.0.0/0) port 80,443 [default deny]
ALLOW DC-subnet -> WSUS-server port 8530,8531
ALLOW DC-subnet -> approved-NTP port 123Do not rely solely on Windows Defender Firewall for this — enforce it at the network layer so a local policy change on the DC cannot silently reopen egress.
Patch priorities: ZeroLogon, PetitPotam/coercion, PrintNightmare
Three vulnerability classes deserve standing priority in your patch cycle because each one can lead directly to domain compromise:
ZeroLogon (CVE-2020-1472) — exploits a flaw in the Netlogon secure channel to reset a DC's machine account password. Patch fully (the initial 2020 patch plus the enforcement phase that requires all Netlogon clients to use secure RPC) and confirm enforcement mode:
Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters" -Name "FullSecureChannelProtection" -ErrorAction SilentlyContinueSee ZeroLogon for background on the vulnerability itself.
PetitPotam and other coercion techniques — abuse RPC/DCOM interfaces to coerce a DC into authenticating to an attacker-controlled endpoint, typically feeding an NTLM relay attack against AD CS or LDAP. Mitigations:
- Enable Extended Protection for Authentication (EPA) on AD CS web enrollment endpoints and LDAP.
- Disable NTLM where feasible, or at minimum enforce LDAP/LDAPS signing and channel binding.
- Deploy RPC filters to block unauthenticated calls to
EFSRPC/MS-RPRN-style interfaces from non-DC hosts where not required.
PrintNightmare — covered above via Spooler disablement; patch regardless, since some subsidiary print-driver CVEs affect non-spooler code paths too.
Track these three CVE families as "patch within 72 hours of release" items in your vulnerability management SLA, separate from routine Patch Tuesday cadence.
Secure time synchronization (w32time)
Kerberos depends on time synchronization within a 5-minute skew by default; an attacker who can manipulate a DC's clock can disrupt authentication or create conditions for ticket replay. Ensure your PDC Emulator syncs to a trusted external time source and all other DCs sync to the domain hierarchy — never let DCs sync independently to arbitrary internet NTP servers.
# On the PDC Emulator
w32tm /config /manualpeerlist:"time.windows.com,0x8 pool.ntp.org,0x8" /syncfromflags:manual /reliable:yes /update
Restart-Service w32time
# Verify
w32tm /query /status
w32tm /query /sourceDisable unnecessary roles and features
Audit each DC with Get-WindowsFeature and remove anything beyond AD DS, DNS, and required management tools. Common offenders: IIS left installed from an old CA install, Telnet Client, SMB1, and unused file-sharing roles.
Get-WindowsFeature | Where-Object Installed -eq $true | Select-Object Name, InstallState
Disable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol -NoRestartVerification summary
# Quick DC hardening health check
Get-ADDomainController -Filter * | ForEach-Object {
$dc = $_.HostName
[PSCustomObject]@{
DC = $dc
SpoolerRunning = (Get-Service -ComputerName $dc -Name Spooler).Status
SMB1Enabled = (Get-SmbServerConfiguration -CimSession $dc).EnableSMB1Protocol
TimeSource = (w32tm /query /source /computer:$dc)
}
}What it breaks
- Management tooling that RDPs directly to DCs. Some backup, monitoring, or patching agents assume interactive RDP or unrestricted local logon. Re-point these to service accounts with explicitly delegated rights, or move to agent-based management that doesn't require interactive logon rights.
- Legacy print-dependent tooling that (incorrectly) used a DC as a fallback print server.
- Third-party monitoring agents that phone home over the internet directly from the DC; these need to be routed through an approved proxy or moved off-box.
- NTLM-relay-adjacent integrations that relied on unsigned LDAP or non-EPA-aware AD CS enrollment; these need to be updated to support signing/channel binding before you enforce it domain-wide.
Combine this hardening with the practices in Kerberos hardening and Object & ACL security — a hardened DC OS is only half the picture if the directory's ACLs and Kerberos configuration are still permissive.
Frequently asked questions
Should the Print Spooler service be disabled on all domain controllers?
Yes, unless a DC genuinely acts as a print server, which it should not. Disabling the Spooler service removes the PrintNightmare (CVE-2021-34527) and point-and-print driver-installation attack surface entirely, and is a standard Microsoft and CIS recommendation for DCs.
Can administrators still RDP to domain controllers after this hardening?
Only accounts explicitly granted the Allow log on through Remote Desktop Services right, which should be limited to a small Tier 0 admin group. Everyone else should manage DCs through Windows Admin Center, PowerShell remoting from a Privileged Access Workstation, or Just Enough Administration endpoints instead of interactive RDP.
Why do domain controllers need to be blocked from outbound internet access?
DCs hold the domain's credential material and have no legitimate need to browse the web or reach arbitrary internet hosts. Blocking outbound access (except to required Microsoft update or time endpoints) closes a common command-and-control and data-exfiltration path used once a DC is compromised.
Domain controller hardening: the DC baseline