Although there are optimized applications to perform this task such as Angry Port Scanner, NMAP, Advanced Port Scanner, etc, I believe that PowerShell is convenient and this implementation is adequate for practical use. This bypasses the need to install additional applications on the host machine.
# checkPorts.ps1
# Version 0.0.3
# This function uses portqry to test connections toward a list of remote servers.
$remoteComputers=@(
'server1',
'server2'
)
$ports=@(
# RPC client-server communication
[PSCustomObject] @{protocol='tcp';port=135},
# SMB 2.0 & CIFS
# [PSCustomObject] @{protocol='udp';port=137}, # Netapps SMB1/CIFS Legacy NetBios/Name resolution
# [PSCustomObject] @{protocol='udp';port=138}, # Netapps SMB1/CIFS Legacy NetBios/Name resolution
[PSCustomObject] @{protocol='tcp';port=139}, # Netapps CIFS NetBios/Name resolution
[PSCustomObject] @{protocol='tcp';port=445},
# WinRM
[PSCustomObject] @{protocol='tcp';port=5985}
#[PSCustomObject] @{protocol='tcp';port=5986},
# MS SQL Default
#[PSCustomObject] @{protocol='tcp';port=1433},
# Dynamic port range
#[PSCustomObject] @{protocol='tcp';port=49152},
#[PSCustomObject] @{protocol='tcp';port=65535}
)
function checkPorts($servers,$ports){
function includePortQry{
if (!(Get-Command portqry.exe -ErrorAction SilentlyContinue)){
if (!(Get-Command choco.exe -ErrorAction SilentlyContinue)) {
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))}
choco install portqry -y
if (Get-Command portqry.exe -ErrorAction SilentlyContinue){return $true}else{return $false}
}else{
return $true
}
}
$portQryExists=includePortQry
if(!$portQryExists){
write-warning "Unable to proceed without portqry"
return $false
}
$results=@()
foreach ($remoteComputer in $servers){
#$ip=[System.Net.Dns]::GetHostAddresses($remoteComputer).IPAddressToString|select -first 1
write-host "Now scanning $remoteComputer"
$result=@()
foreach ($item in $ports){
$port=$item.port
$protocol=$item.protocol
$reachable=if($port -ne 135){
$command={
param($remoteComputer,$protocol,$port)
$command="portqry -n $remoteComputer -p $protocol -e $port|find ': LISTENING'"
invoke-expression $command
}
$jobId=(Start-Job $command -Args $remoteComputer,$protocol,$port).Id
$startCount=0;$waitSeconds=5
do{
$jobStatus=(get-job -id $jobId).State
if($jobStatus -eq 'Completed'){
$jobResult=receive-job $jobId
}else{
if($startCount++ -eq $waitSeconds){
$jobStatus='Completed'
$null=remove-job -id $jobId -force
$jobResult=$false
}else{
sleep 1
}
}
}until($jobStatus -eq 'Completed')
[bool]($jobResult)
}else{
[bool](portqry -n $remoteComputer -p $protocol -e $port|find 'Total endpoints found: ')
}
write-host "$port/$protocol : $reachable"
$result+=[PSCustomObject]@{
computername=$remoteComputer
port=$port
protocol=$protocol
reachable=$reachable
}
}
#$resultString=$results.GetEnumerator()|sort-object {[int]$_.Name}|out-string
$results+=$result
$resultString=$result|sort-object -property port|out-string
write-host $resultString
}
return $results
}
$scanResults=checkPorts $remoteComputers $ports
write-output $scanResults
# checkAllPorts.ps1
# Version 0.02
# This function scans all ports at the target and return an Array of sorted dictionary entries
# Multi-threading has been included in this iteration
function checkAllPorts($target='portquiz.net',[int16[]]$ports,$maxThreads=8){
function connectionTest($computerName='portquiz.net',$port,$timeout,$verbose){
$result=@{}
function Check-NetConnection($computername,$port,$timeout=1000,$verbose=$false) {
$tcp = New-Object System.Net.Sockets.TcpClient;
try {
$connect=$tcp.BeginConnect($computername,$port,$null,$null)
$wait = $connect.AsyncWaitHandle.WaitOne($timeout,$false)
if(!$wait){
$null=$tcp.EndConnect($connect)
$tcp.Close()
if($verbose){
Write-Host "Connection Timeout" -ForegroundColor Red
}
Return $false
}else{
$error.Clear()
$null=$tcp.EndConnect($connect) # Dispose of the connection to release memory
if(!$?){
if($verbose){
write-host $error[0].Exception.Message -ForegroundColor Red
}
$tcp.Close()
return $false
}
$tcp.Close()
Return $true
}
} catch {
return $false
}
}
$success=Check-NetConnection $computerName $port
$result."$port"=$success
return $result
}
function getResults($wait=$false){
if($results){Clear-Variable results}
while(!$results){
$results=if($wait){Get-Job|Receive-Job -wait}else{Get-Job|Receive-Job}
}
remove-job -State Completed
if($results){
$results|%{
IF ($_.Values -eq $true){
Write-Host "$($_.Keys)`t: open" -ForegroundColor Green
}else{
Write-Host "$($_.Keys)`t: closed" -ForegroundColor Red
}
}
return $results
}else{
return $false
}
}
$allResults=@{}
if($ports){
$allPorts=$ports
}else{
$allPorts = 1..65535
}
$i=0
foreach ($port in $allPorts){
if($i++ -lt $maxThreads){
$null=start-job -ScriptBlock{
param($connectionTest,$target,$port)
return [ScriptBlock]::Create($connectionTest).invoke($target,$port)
} -Args ${function:connectionTest},$target,$port
}else{
do{
$xHashes=getResults
$xHashes|%{$allResults+=$_}
$i=(get-job -state Running).count
}until($i -lt $maxThreads)
$null=start-job -ScriptBlock{
param($connectionTest,$target,$port)
return [ScriptBlock]::Create($connectionTest).invoke($target,$port)
} -Args ${function:connectionTest},$target,$port
}
}
if((get-job -state Running).count){
$xHashes=getResults -wait $true
$xHashes|%{$allResults+=$_}
get-job|remove-job
}
return $allResults.getenumerator()|Sort-Object {[int]$_.Name}
}
$portScanResult=checkAllPorts -port $(1..20)
# checkAllPorts.ps1
# This function scans all ports at the target and return a hash table with the results
function checkAllPorts($target='portquiz.net',$ports){
function Check-NetConnection($computername,$port,$timeout=200,$verbose=$false) {
$tcp = New-Object System.Net.Sockets.TcpClient;
try {
$connect=$tcp.BeginConnect($computername,$port,$null,$null)
$wait = $connect.AsyncWaitHandle.WaitOne($timeout,$false)
if(!$wait){
$null=$tcp.EndConnect($connect)
$tcp.Close()
if($verbose){
Write-Host "Connection Timeout" -ForegroundColor Red
}
Return $false
}else{
$error.Clear()
$null=$tcp.EndConnect($connect) # Dispose of the connection to release memory
if(!$?){
if($verbose){
write-host $error[0].Exception.Message -ForegroundColor Red
}
$tcp.Close()
return $false
}
$tcp.Close()
Return $true
}
} catch {
return $false
}
}
$results=@{}
if($ports){
$allPorts=$ports
}else{
$allPorts = 1..65535
}
foreach ($port in $allPorts) {
$isPortOpen=Check-NetConnection -computername $target -Port $port
$results."$port"=$isPortOpen
IF ($isPortOpen){
Write-Host "$port`t: open" -ForegroundColor Green
}else{
Write-Host "$port`t: closed" -ForegroundColor Red
}
}
return $results
}
Categories: