Networking/Test-PortConnectivity.ps1
|
<#
.SYNOPSIS Tests TCP port connectivity to one or more hosts. .DESCRIPTION Attempts TCP connections to specified ports on target hosts and reports whether each port is open or closed. Useful for firewall validation, migration readiness checks, and network troubleshooting. Uses System.Net.Sockets.TcpClient for fast, lightweight connection tests. No external modules required. .PARAMETER ComputerName One or more hostnames or IP addresses to test. Accepts pipeline input. .PARAMETER Port One or more TCP ports to test on each host. .PARAMETER Timeout Connection timeout in milliseconds. Defaults to 1000 (1 second). .PARAMETER OutputPath Optional path to export results as CSV. .EXAMPLE PS> .\Networking\Test-PortConnectivity.ps1 -ComputerName 'server01' -Port 443,80,3389 Tests ports 443, 80, and 3389 on server01. .EXAMPLE PS> .\Networking\Test-PortConnectivity.ps1 -ComputerName 'dc01','dc02' -Port 389,636,53 -Timeout 2000 Tests LDAP, LDAPS, and DNS ports on two domain controllers with a 2-second timeout. .EXAMPLE PS> Get-Content .\servers.txt | .\Networking\Test-PortConnectivity.ps1 -Port 443 -OutputPath '.\port-scan.csv' Reads server names from a file and exports port 443 connectivity results to CSV. .EXAMPLE PS> .\Networking\Test-PortConnectivity.ps1 -ComputerName '10.0.0.1' -Port 22,3389,5985 Tests SSH, RDP, and WinRM ports on a specific IP address. #> [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [Alias('CN', 'HostName', 'IPAddress')] [string[]]$ComputerName, [Parameter(Mandatory)] [ValidateRange(1, 65535)] [int[]]$Port, [Parameter()] [ValidateRange(100, 30000)] [int]$Timeout = 1000, [Parameter()] [string]$OutputPath ) begin { $allResults = [System.Collections.Generic.List[PSCustomObject]]::new() } process { foreach ($computer in $ComputerName) { foreach ($p in $Port) { Write-Verbose "Testing $computer`:$p (timeout: ${Timeout}ms)" $tcpClient = New-Object -TypeName System.Net.Sockets.TcpClient $portOpen = $false try { $connectTask = $tcpClient.ConnectAsync($computer, $p) $waitResult = $connectTask.Wait($Timeout) if ($waitResult -and $tcpClient.Connected) { $portOpen = $true } } catch { # Connection failed — port is closed or host unreachable $portOpen = $false } finally { $tcpClient.Dispose() } $allResults.Add([PSCustomObject]@{ ComputerName = $computer Port = $p Status = if ($portOpen) { 'Open' } else { 'Closed' } Timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss' }) $statusLabel = if ($portOpen) { 'Open' } else { 'Closed' } Write-Verbose " $computer`:$p — $statusLabel" } } } end { if ($OutputPath) { $allResults | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8 Write-Output "Exported $($allResults.Count) port test results to $OutputPath" } else { Write-Output $allResults } } |