#requires -version 2 Param( [Parameter(ParameterSetName='manual')] [string]$dc=$null, [Parameter(ParameterSetName='dns')] [switch]$useDns, [Parameter(ParameterSetName='auto')] [switch]$useADSite ) $ErrorActionPreference = 'Stop' # FROM https://www.myotherpcisacloud.com/post/2014/02/16/verifying-rpc-network-connectivity-like-a-boss.aspx Function Test-RPC { [CmdletBinding(SupportsShouldProcess=$True)] Param([Parameter(ValueFromPipeline=$True)][String[]]$ComputerName = 'localhost') BEGIN { $PInvokeCode = @' using System; using System.Collections.Generic; using System.Runtime.InteropServices; public class Rpc { // I found this crud in RpcDce.h [DllImport("Rpcrt4.dll", CharSet = CharSet.Auto)] public static extern int RpcBindingFromStringBinding(string StringBinding, out IntPtr Binding); [DllImport("Rpcrt4.dll")] public static extern int RpcBindingFree(ref IntPtr Binding); [DllImport("Rpcrt4.dll", CharSet = CharSet.Auto)] public static extern int RpcMgmtEpEltInqBegin(IntPtr EpBinding, int InquiryType, // 0x00000000 = RPC_C_EP_ALL_ELTS int IfId, int VersOption, string ObjectUuid, out IntPtr InquiryContext); [DllImport("Rpcrt4.dll", CharSet = CharSet.Auto)] public static extern int RpcMgmtEpEltInqNext(IntPtr InquiryContext, out RPC_IF_ID IfId, out IntPtr Binding, out Guid ObjectUuid, out IntPtr Annotation); [DllImport("Rpcrt4.dll", CharSet = CharSet.Auto)] public static extern int RpcBindingToStringBinding(IntPtr Binding, out IntPtr StringBinding); public struct RPC_IF_ID { public Guid Uuid; public ushort VersMajor; public ushort VersMinor; } public static List QueryEPM(string host) { List ports = new List(); int retCode = 0; // RPC_S_OK IntPtr bindingHandle = IntPtr.Zero; IntPtr inquiryContext = IntPtr.Zero; IntPtr elementBindingHandle = IntPtr.Zero; RPC_IF_ID elementIfId; Guid elementUuid; IntPtr elementAnnotation; try { retCode = RpcBindingFromStringBinding("ncacn_ip_tcp:" + host, out bindingHandle); if (retCode != 0) throw new Exception("RpcBindingFromStringBinding: " + retCode); retCode = RpcMgmtEpEltInqBegin(bindingHandle, 0, 0, 0, string.Empty, out inquiryContext); if (retCode != 0) throw new Exception("RpcMgmtEpEltInqBegin: " + retCode); do { IntPtr bindString = IntPtr.Zero; retCode = RpcMgmtEpEltInqNext (inquiryContext, out elementIfId, out elementBindingHandle, out elementUuid, out elementAnnotation); if (retCode != 0) if (retCode == 1772) break; retCode = RpcBindingToStringBinding(elementBindingHandle, out bindString); if (retCode != 0) throw new Exception("RpcBindingToStringBinding: " + retCode); string s = Marshal.PtrToStringAuto(bindString).Trim().ToLower(); if(s.StartsWith("ncacn_ip_tcp:")) ports.Add(int.Parse(s.Split('[')[1].Split(']')[0])); RpcBindingFree(ref elementBindingHandle); } while (retCode != 1772); // RPC_X_NO_MORE_ENTRIES } catch(Exception ex) { Console.WriteLine(ex); return ports; } finally { RpcBindingFree(ref bindingHandle); } return ports; } } '@ } PROCESS { ForEach($Computer In $ComputerName) { If($PSCmdlet.ShouldProcess($Computer)) { [Bool]$EPMOpen = $False $Socket = New-Object Net.Sockets.TcpClient $Socket.SendTimeout = 1000 $Socket.ReceiveTimeout = 1000 Write-Host " Connecting to endpoint mapper (TCP 135)..." -NoNewline -ForegroundColor White Try { $Socket.Connect($Computer, 135) If ($Socket.Connected) { $EPMOpen = $True Write-Host "PASS" -ForegroundColor Green } else { Write-Host "FAILED!" -ForegroundColor Red } $Socket.Close() } Catch { $Socket = $null Write-Host "FAILED!" -ForegroundColor Red } If ($EPMOpen) { Add-Type $PInvokeCode $RPCPorts = [Rpc]::QueryEPM($Computer) | Select-Object -Unique | Sort-Object [Bool]$AllPortsOpen = $True Foreach ($Port In $RPCPorts) { Write-Host " Port '$($Port)' open..." -NoNewline -ForegroundColor White $Socket = New-Object Net.Sockets.TcpClient $Socket.SendTimeout = 1000 $Socket.ReceiveTimeout = 1000 Try { $Socket.Connect($Computer, $Port) If (!$Socket.Connected) { $AllPortsOpen = $False Write-Host "FAILED!" -ForegroundColor Red } else { if (($Port -ge 6000) -and ($Port -le 6199)) { Write-Host "PASS" -ForegroundColor Green } else { Write-Host "WARNING" -ForegroundColor Yellow } } $Socket.Close() } Catch { $AllPortsOpen = $false Write-Host "FAILED!" -ForegroundColor Red $Socket = $null } } [PSObject]@{'ComputerName' = $Computer; 'EndPointMapperOpen' = $EPMOpen; 'RPCPortsInUse' = $RPCPorts; 'AllRPCPortsOpen' = $AllPortsOpen} } Else { [PSObject]@{'ComputerName' = $Computer; 'EndPointMapperOpen' = $EPMOpen} } } } } END { } } # Define common ports $tcpPorts = @{} $tcpPorts.Add('DNS',53) $tcpPorts.Add('Kerberos',88) $tcpPorts.Add('RPC Locator Service',135) $tcpPorts.Add('LDAP',389) $tcpPorts.Add('SMB',445) $tcpPorts.Add('KPASS',464) $tcpPorts.Add('LDAP-SSL',636) $tcpPorts.Add('gc',3268) $tcpPorts.Add('GC-SSL',3269) $domains = @() $ipPresentInDcList = $false $dcIpList = @() if ($useDns) { # Grab NICs $networkAdapterConfig = Get-WmiObject Win32_NetworkAdapterConfiguration -Namespace "root\CIMV2" $nic = $networkAdapterConfig | Where-Object {$_.IPEnabled -eq 'True'} if (($nic | Measure-Object).Count -gt 1) { # Multiple NICs found Start-Sleep 3 Write-Host "Multiple NICs found! Should not be used as a DC!" -ForegroundColor Red exit } $dcIpList = $null $dcIpList = $nic.DNSServerSearchOrder if ($dcIpList -ne $null) { Write-Host "Performing reverse DNS lookups on DNS resolvers:" -ForegroundColor White $dcList = $dcIpList | ForEach-Object { Write-Host " $($_) -> " -NoNewline -ForegroundColor White $thisDnsServer = $null try { $thisDnsServer = [System.Net.Dns]::GetHostEntry($_) try { [System.Net.IPAddress]$thisDnsServer.Hostname | Out-Null Write-Host "FAIL" -ForegroundColor Red } catch { $thisDnsServer.Hostname } } catch { Write-Host "FAIL" -ForegroundColor Red } } if ($dcList -eq $null) { exit } $domains = $dcList | ForEach-Object { ($_ -replace "$(($_ -split '\.')[0]).", "") } | Select-Object -Unique } else { Write-Host "Please ensure DNS resolvers specified and are working correctly!" -ForegroundColor Red exit } } elseif ($useADSite) { # Get Computer Site try { Write-Host "Getting local site..." -NoNewline -ForegroundColor White $adSite = [System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]::GetComputerSite() Write-Host "$($adSite.Name)" -ForegroundColor Green } catch { Write-Host "FAIL" -ForegroundColor Red } $servers = $adSite.Servers if ($servers -is [System.DirectoryServices.ActiveDirectory.DomainController]) { Write-Host "Unable to autodetect domains and domain controllers!" -ForegroundColor Red exit } else { $dcList = $adSite.Servers | ForEach-Object {$_.Name} } if ($adSite.Domains -eq $null) { $domains = ($servers | Select-Object Domain -unique) | ForEach-Object {$_.Domain.Name} } else { $domains = $adSite.Domains | ForEach-Object {$_.Name} } } elseif ($dc -ne $null) { if ($dc -is [string]) { $dcList = ((($dc -split ',') -split ';') -split ' ') | Where-Object {$_ -match '[A-Z0-9]'} } elseif ($dc -is [string[]]) { $dcList = $dc } else { Write-Host "Invalid paramater 'dc' parsed for domain controller(s)" -ForegroundColor Red exit } $dcList | ForEach-Object { $thisIp = $null try { $thisIp = [System.Net.IPAddress]$_ } catch { # Do Nothing } if ($thisIp -is [System.Net.IPAddress]) { $ipPresentInDcList = $true $dcIpList += $thisIp.IPAddressToString } elseif (!($_ -match '[A-Z0-9]+\.[A-Z0-9]+')) { # do a lookup??? Write-Host "Please specify all domain controller(s) using FQDN or IP Address" -ForegroundColor Red exit } else { $domains += ($_ -replace "$(($_ -split '\.')[0]).", "") } } $domains = $domains | Select-Object -Unique } # Sort DCs on per-domain basis $domainDcs = @{} Write-Host "Domain Name (Domain Controllers):" -ForegroundColor White if ($domains -ne $null) { $domains | ForEach-Object { $thisDomain = $null $thisDomain = $_ Write-Host " $($thisDomain) " -NoNewline -ForegroundColor Green $thisDcs = $null $thisDcs = $dcList | Where-Object {($_ -replace "$(($_ -split '\.')[0]).", "") -eq $thisDomain} Write-Host "($(($thisDcs | ForEach-Object {$_.ToLower()}) -join ';'))" $domainDcs.Add($_,$thisDcs) } } if ($ipPresentInDcList) { Write-Host " Domain Membership Unknown " -NoNewline -ForegroundColor Yellow Write-Host "($(($dcIpList | ForEach-Object {$_.ToLower()}) -join ';'))" $domainDcs.Add('unknown',$dcIpList) } ### TESTS ### $domainDcs.GetEnumerator() | ForEach-Object { $thisDomain = $null $thisDomain = $_.Name $thisDcs = $null $thisDcs = $_.Value # Test DNS if (!($thisDomain -eq 'unknown')) { Write-Host "Testing Domain '$($thisDomain)':" -ForegroundColor White Write-Host " Testing DNS lookup of '$($thisDomain)'..." -NoNewline -ForegroundColor White try { $lookup = [System.Net.Dns]::GetHostEntry($thisDomain) Write-Host "PASS" -ForegroundColor Green } catch { Write-Host "FAIL" -ForegroundColor Red } } else { Write-Host "Testing Domain Controllers with unknown parent domain:" -ForegroundColor White } # Per DC tests $thisDcs | ForEach-Object { $thisDc = $null $thisDc = $_ Write-Host " Testing Domain Controller '$($thisDc)':" -ForegroundColor White # Ping tests $pingable = $false Write-Host " Performing ping test..." -NoNewline -ForegroundColor White $pingable = Test-Connection -ComputerName $thisDc -Count 1 -ErrorAction SilentlyContinue -Quiet if ($pingable) { Write-Host "PASS" -ForegroundColor Green } else { Write-Host "FAIL" -ForegroundColor Red } # TCP Port Tests $tcpPorts.GetEnumerator() | Sort-Object -Property Value | ForEach-Object { Write-Host " Performing $($_.Name) test (TCP $($_.Value))..." -NoNewline -ForegroundColor White $tcpclient = New-Object system.net.sockets.TcpClient try { $connection = $null $connection = $tcpclient.Connect($thisDc,$_.Value) } catch {} if ($tcpclient.connected) { Write-Host "PASS" -ForegroundColor Green } else { Write-Host "FAIL" -ForegroundColor Red } $tcpclient.Close() $tcpclient = $null } # NTP Port Test Write-Host " Performing NTP test (UDP 123)..." -NoNewline -ForegroundColor White $udpClient = New-Object Net.Sockets.Socket([Net.Sockets.AddressFamily]::InterNetwork, [Net.Sockets.SocketType]::Dgram, [Net.Sockets.ProtocolType]::Udp) $udpClient.SendTimeOut = 2000 $udpClient.ReceiveTimeOut = 2000 # Construct a 48-byte client NTP time packet to send to the specified server # (Request Header: [00=No Leap Warning; 011=Version 3; 011=Client Mode]; 00011011 = 0x1B) [Byte[]]$NtpData = ,0 * 48 $NtpData[0] = 0x1B try { $udpClient.Connect($thisDc,123) try { $udpClient.Send($NtpData) | Out-Null $udpClient.Receive($NtpData) | Out-Null Write-Host "PASS" -ForegroundColor Green } catch { Write-Host "FAIL" -ForegroundColor Red } } catch { Write-Host "FAIL" -ForegroundColor Red } $udpClient.Shutdown("Both") $udpClient.Close() $udpClient = $null # LDAP tests (ADSI) if (!$useDns) { ## USED in pre DCPROMO scenarion when no DCs LDAP authentication is available ## so this will fail anyway @('389','636') | ForEach-Object { Write-Host " Performing LDAP connection test (port $($_))..." -NoNewline -ForegroundColor White $ldap = $null $ldap = [adsi]"LDAP://$($thisDc):$($_)" $Connection = [adsi]$ldap if ($Connection.Path) { Write-Host "PASS" -ForegroundColor Green } else { if ($_ -eq '636') { Write-Host "WARNING" -ForegroundColor Yellow } else { Write-Host "FAIL" -ForegroundColor Red } } } } # Test domain based shares @('NETLOGON','SYSVOL') | ForEach-Object { Write-Host " Connecting to '$($_)' share..." -NoNewline -ForegroundColor White try { $ls = Get-ChildItem "\\$($thisDc)\$($_)" Write-Host "PASS" -ForegroundColor Green } catch { Write-Host "FAIL" -ForegroundColor Red } } # RPC Endpoint Mapper Test $thisRpcTest = $null $thisRpcPortsInUse = $null $thisEndPointMapperOpen = $null $thisAllRPCPortsOpen = $null Write-Host " Performing RPC port tests (allowed: 135, 6000-6199):"-ForegroundColor White $thisRpcTest = Test-RPC -ComputerName $thisDc } }