X

Domain controllers required ports: Use PowerShell to check if they are listening

An Active Directory domain controller needs to listen on specific ports to service different client requests. For example, when a client computer needs to authenticate, it connects to a server which hosts KDC service and which is listening on the Port 88. Similarly, network ports TCP 139 and UDP 138 are required by the SYSVOL replication service that takes place between all domain controllers. At a minimum, they must listen on these required ports:

  • UDP Port 88 is required for authentication purposes. UDP Port 88 is used by clients and domain controllers to authenticate with each other.
  • Both UDP and TCP Port 135 are required for communication between domain controllers and clients to domain controllers.
  • TCP Port 139 and UDP 138 network ports are used by the SYSVOL replication service to replicate contents of SYSVOL folder.
  • UDP Port 389 for LDAP network port is used to handle normal authentication queries from client computers.
  • TCP and UDP Port 464 is used for Kerberos Password Change.
  • TCP Port 3268 and 3269 are required for Global Catalog communication from clients to domain controllers. Global catalog servers help in finding an object in the Active Directory quickly.
  • Both DNS TCP and UDP 53 network ports are used by clients and domain controllers for name resolution purposes.

Check the network port status on a domain controller

If you wish to check the network port status on a specific domain controller, you can run a simple NetStat command that will list all the network ports that a domain controller is listening on. To check the port status on a particular domain controller and to save the output to a text file, execute this command:

Netstat –an –b | find /I “’Listening” > C:\Temp\DCPorts.txt

When you execute the command, it checks all the ports that are listening on a domain controller and then saves the output to C:\Temp\DCPorts.TXT file. You can navigate through the file to ensure the domain controller is listening on the required network ports. However, it becomes difficult if you need to check network ports status on each domain controller. It might take a considerable amount of time if you use the above method to check the status of each port on each domain controller. This is where this article comes in handy. Here we provide a PowerShell script that connects to each domain controller and then collects the network port status.

Requirements for running the PowerShell script

Make sure you run the script from a Windows Server 2012 R2 member server or domain controller, and ensure to create a Temp folder on the C:\ drive as script generates a report by name “DCPortReport.CSV” under the C:\Temp folder. Apart from meeting the above requirements, there are a few other requirements that you need to meet:

  • First, download PortQry from Microsoft. The script uses the tool to collect the port status from the target domain controller.
  • Create a text file named “DCList.TXT” that contains the Active Directory domain controller names.

The script checks common domain controller ports such as UDP-389, TCP-389, UDP-135, TCP-135, UDP-88, TCP-88, UDP-445, and TCP-445. The status for each port is provided in the report generated by the script.


$TestCSVFile = “C:\Temp\DCPortReport.CSV”
Remove-Item $TestCSVFile -ErrorAction SilentlyContinue
$ThisString=”Domain Controller,Connection,Command Status, UDP-389, TCP-389, UDP-135, TCP-135, UDP-88, TCP-88, UDP-445, TCP-445,Final Status”
Add-Content “$TestCSVFile” $ThisString
$TestStatus=”Passed”
$TestText = “”
$sumVal=0
$ReachOrNot = “Yes”
$AnyGap = “No”
$TotNo = 0
$AnyOneOk=”No”
$IntDirNow = “C:\ReqPortTest”
mkdir $IntDirNow -Force
$PortQryExe = “C:\Temp\PortQry.exe”
Foreach ($ItemName in Get-Content “$GDCList”)
{
$IsDCGap = “No”
$ThisService=”NetLogon”
$Error.Clear()
Get-Service -Name “$ThisService” -ComputerName $ItemName
IF ($Error.Count -eq 0)
{
$AnyOneOk=”Yes”
$PortTCP389Status=”Listening”
$PortTCP135Status=”Listening”
$PortTCP88Status=”Listening”
$PortTCP445Status=”Listening”
$PortUDP389Status=”Listening”
$PortUDP135Status=”Listening”
$PortUDP88Status=”Listening”
$PortUDP445Status=”Listening”
$LookFor = “Filtered”
$ThisServer=$ItemName
$Port = “389”
$PortProtocol = “UDP”
$cmd = $PortQryExe + ” -n ” + $ThisServer + ” -p ” + $PortProtocol + ” -e ” + $port
$PortQryResultFile = “C:\Temp\ReqPortTest\”+$CurProfNowForAll+$ThisServer+”_”+$Port+”_”+$PortProtocol+”.TXT”
Remove-Item $PortQryResultFile -ErrorAction SilentlyContinue
$Output = Invoke-Expression $cmd
$Output | Out-file $PortQryResultFile
$ThisLookFor=$LookFor
$FoundOrNot=Select-String -Path $PortQryResultFile -Pattern $ThisLookFor
$TotFoundNow=$FoundOrNot.Count
$FinStatus=””
IF ($TotFoundNow -ne 0)
{
$PortUDP389Status = “Filtered”
$AnyGap = “Yes”
$IsDCGap = “Yes”
}
Remove-Item $PortQryResultFile -ErrorAction SilentlyContinue
$Port = “135”
$PortProtocol = “UDP”
$cmd = $PortQryExe + ” -n ” + $ThisServer + ” -p ” + $PortProtocol + ” -e ” + $port
$PortQryResultFile = “C:\Temp\ReqPortTest\”+$CurProfNowForAll+$ThisServer+”_”+$Port+”_”+$PortProtocol+”.TXT”
Remove-Item $PortQryResultFile -ErrorAction SilentlyContinue
$Output = Invoke-Expression $cmd
$Output | Out-file $PortQryResultFile
$ThisLookFor=$LookFor
$FoundOrNot=Select-String -Path $PortQryResultFile -Pattern $ThisLookFor
$TotFoundNow=$FoundOrNot.Count
$FinStatus=””
IF ($TotFoundNow -ne 0)
{
$PortUDP139Status = “Filtered”
$AnyGap = “Yes”
$IsDCGap = “Yes”
}
Remove-Item $PortQryResultFile -ErrorAction SilentlyContinue
$Port = “88”
$PortProtocol = “UDP”
$cmd = $PortQryExe + ” -n ” + $ThisServer + ” -p ” + $PortProtocol + ” -e ” + $port
$PortQryResultFile = “C:\Temp\ReqPortTest\”+$CurProfNowForAll+$ThisServer+”_”+$Port+”_”+$PortProtocol+”.TXT”
Remove-Item $PortQryResultFile -ErrorAction SilentlyContinue
$Output = Invoke-Expression $cmd
$Output | Out-file $PortQryResultFile
$ThisLookFor=$LookFor
$FoundOrNot=Select-String -Path $PortQryResultFile -Pattern $ThisLookFor
$TotFoundNow=$FoundOrNot.Count
$FinStatus=””
IF ($TotFoundNow -ne 0)
{
$PortUDP88Status = “Filtered”
$AnyGap = “Yes”
$IsDCGap = “Yes”
}
Remove-Item $PortQryResultFile -ErrorAction SilentlyContinue
$Port = “445”
$PortProtocol = “UDP”
$cmd = $PortQryExe + ” -n ” + $ThisServer + ” -p ” + $PortProtocol + ” -e ” + $port
$PortQryResultFile = “C:\Temp\ReqPortTest\”+$CurProfNowForAll+$ThisServer+”_”+$Port+”_”+$PortProtocol+”.TXT”
Remove-Item $PortQryResultFile -ErrorAction SilentlyContinue
$Output = Invoke-Expression $cmd
$Output | Out-file $PortQryResultFile
$ThisLookFor=$LookFor
$FoundOrNot=Select-String -Path $PortQryResultFile -Pattern $ThisLookFor
$TotFoundNow=$FoundOrNot.Count
$FinStatus=””
IF ($TotFoundNow -ne 0)
{
$PortUDP445Status = “Filtered”
$AnyGap = “Yes”
$IsDCGap = “Yes”
}
Remove-Item $PortQryResultFile -ErrorAction SilentlyContinue
$Port = “389”
$PortProtocol = “TCP”
$cmd = $PortQryExe + ” -n ” + $ThisServer + ” -p ” + $PortProtocol + ” -e ” + $port
$PortQryResultFile = “C:\Temp\ReqPortTest\”+$CurProfNowForAll+$ThisServer+”_”+$Port+”_”+$PortProtocol+”.TXT”
Remove-Item $PortQryResultFile -ErrorAction SilentlyContinue
$Output = Invoke-Expression $cmd
$Output | Out-file $PortQryResultFile
$ThisLookFor=$LookFor
$FoundOrNot=Select-String -Path $PortQryResultFile -Pattern $ThisLookFor
$TotFoundNow=$FoundOrNot.Count
$FinStatus=””
IF ($TotFoundNow -ne 0)
{
$PortTCP389Status = “Filtered”
$AnyGap = “Yes”
$IsDCGap = “Yes”
}
Remove-Item $PortQryResultFile -ErrorAction SilentlyContinue
$Port = “135”
$PortProtocol = “TCP”
$cmd = $PortQryExe + ” -n ” + $ThisServer + ” -p ” + $PortProtocol + ” -e ” + $port
$PortQryResultFile = “C:\Temp\ReqPortTest\”+$CurProfNowForAll+$ThisServer+”_”+$Port+”_”+$PortProtocol+”.TXT”
Remove-Item $PortQryResultFile -ErrorAction SilentlyContinue
$Output = Invoke-Expression $cmd
$Output | Out-file $PortQryResultFile
$ThisLookFor=$LookFor
$FoundOrNot=Select-String -Path $PortQryResultFile -Pattern $ThisLookFor
$TotFoundNow=$FoundOrNot.Count
$FinStatus=””
IF ($TotFoundNow -ne 0)
{
$PortTCP139Status = “Filtered”
$AnyGap = “Yes”
$IsDCGap = “Yes”
}
Remove-Item $PortQryResultFile -ErrorAction SilentlyContinue
$Port = “88”
$PortProtocol = “TCP”
$cmd = $PortQryExe + ” -n ” + $ThisServer + ” -p ” + $PortProtocol + ” -e ” + $port
$PortQryResultFile = “C:\Temp\ReqPortTest\”+$CurProfNowForAll+$ThisServer+”_”+$Port+”_”+$PortProtocol+”.TXT”
Remove-Item $PortQryResultFile -ErrorAction SilentlyContinue
$Output = Invoke-Expression $cmd
$Output | Out-file $PortQryResultFile
$ThisLookFor=$LookFor
$FoundOrNot=Select-String -Path $PortQryResultFile -Pattern $ThisLookFor
$TotFoundNow=$FoundOrNot.Count
$FinStatus=”Ok”
IF ($TotFoundNow -ne 0)
{
$PortTCP88Status = “Filtered”
$AnyGap = “Yes”
$IsDCGap = “Yes”
}
Remove-Item $PortQryResultFile -ErrorAction SilentlyContinue
$Port = “445”
$PortProtocol = “TCP”
$cmd = $PortQryExe + ” -n ” + $ThisServer + ” -p ” + $PortProtocol + ” -e ” + $port
$PortQryResultFile = “C:\Temp\ReqPortTest\”+$CurProfNowForAll+$ThisServer+”_”+$Port+”_”+$PortProtocol+”.TXT”
Remove-Item $PortQryResultFile -ErrorAction SilentlyContinue
$Output = Invoke-Expression $cmd
$Output | Out-file $PortQryResultFile
$ThisLookFor=$LookFor
$FoundOrNot=Select-String -Path $PortQryResultFile -Pattern $ThisLookFor
$TotFoundNow=$FoundOrNot.Count
$FinStatus=””
IF ($TotFoundNow -ne 0)
{
$PortTCP445Status = “Filtered”
$AnyGap = “Yes”
$IsDCGap = “Yes”
}
Remove-Item $PortQryResultFile -ErrorAction SilentlyContinue
IF ($PortTCP389Status -eq “Filtered” -or $PortTCP135Status -eq “Filtered” -or $PortTCP88Status -eq “Filtered” -or $PortTCP445Status -eq “Filtered” -or $PortUDP389Status -eq “Filtered” -or $PortUDP135Status -eq “Filtered” -or $PortUDP88Status -eq “Filtered” -or $PortUDP445Status -eq “Filtered”)
{
$FinStatus =”WARNING: This domain controller does not listen on required domain controller ports.”
}
$DCConError = “Ok”
$ComConError = “Ok”
$FinalStr = $ItemName+”,”+$DCConError+”,”+$ComConError+”,”+$PortUDP389Status+”,”+$PortTCP389Status+”,”+$PortUDP135Status+”,”+$PortTCP135Status+”,”+$PortUDP88Status+”,”+$PortTCP88Status+”,”+$PortUDP445Status+”,”+$PortTCP445Status+”,”+$FinStatus
Add-Content $TestCSVFile $FinalStr
IF ($IsDCGap -eq “Yes”)
{
$TotNo++
}
}
else
{
$ThisSTR = $ItemName+”,Error Connecting to Domain Controller”
Add-Content “$TestCSVFile” $ThisStr
}
}
IF ($AnyGap -eq “Yes”)
{
$TestStatus=”Critical”
$TestText = “Domain Controllers are not listening on the required ports. Please ensure all domain controllers are listening on the required ports and protocols.”
$SumVal = $TotNo
}
IF ($AnyGap -eq “No”)
{
$TestStatus=”Passed”
$TestText = “All domain controllers are listening on the required ports. Please ensure AD Health Profiler was able to execute Dynamic Pack against all domain controllers.”
$SumVal = “”
IF ($AnyOneOk -eq “No”)
{
$TestStatus=”Error”
$TestText = “Error Executing Dynamic Pack”
$SumVal = “”
}
}
$STR = $ADTestName +”,”+$TestStartTime+”,”+$TestStatus+”,”+$SumVal +”,”+$TestText


Once the script has been executed successfully, a report file named DCPortReport.CSV file will be created under “C:\Temp” folder. The report includes the port status for each domain controller as shown in the report below:

As you can see in the report, the script connected to each domain controller, ran thePortQry tool, and then collected the port status for each domain controller. As is indicated in the “Final Status” column of the report, DC3.TechGenix.com and DC4.TechGenix.com domain controllers are not listening on one or more ports. All you need to do is just check the output and make sure nothing on the operating system is preventing a domain controller from listening on the required network ports.

You may find this PowerShell script handy in case you wish to check the domain controllers port status in an Active Directory forest. While you can check the port status on a single domain controller by using the NetStat command as explained above, using the script will save you a lot of time. You can include the PowerShell script in your Active Directory Health Procedure and have the script run every month to ensure the domain controllers are listening on the required ports.