= "IPAddress"
Expression = { $.IPAddress }
}, @{
Name = "PrefixLength"
Expression = { $.PrefixLength }
}, @{
Name = "AddressFamily"
Expression = { $_.AddressFamily }
}
}
Usage
Get-NetworkInterfaceState -InterfaceAlias "Ethernet*"
**Rationale:** This function wraps `Get-NetIPAddress` to return a clean, predictable object structure. It filters for IPv4 by default to avoid dual-stack noise and selects only relevant properties. This pattern ensures downstream scripts receive consistent data shapes.
#### 2. TCP Handshake Validation
ICMP ping tests host reachability but does not verify service availability. A host may respond to ping while the target port is closed or blocked. TCP handshake validation is required to confirm that a service is listening and accepting connections.
**Implementation:**
```powershell
function Invoke-TcpHandshakeTest {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string[]]$TargetHost,
[Parameter(Mandatory = $true)]
[int]$TargetPort,
[int]$TimeoutMs = 3000
)
$results = foreach ($hostName in $TargetHost) {
try {
$connection = Test-NetConnection -ComputerName $hostName -Port $TargetPort -WarningAction SilentlyContinue
[PSCustomObject]@{
TargetHost = $hostName
TargetPort = $TargetPort
TcpTestSucceeded = $connection.TcpTestSucceeded
RemoteAddress = $connection.RemoteAddress
LatencyMs = $connection.Latency
Status = if ($connection.TcpTestSucceeded) { "Open" } else { "Closed/Filtered" }
}
}
catch {
[PSCustomObject]@{
TargetHost = $hostName
TargetPort = $TargetPort
TcpTestSucceeded = $false
RemoteAddress = $null
LatencyMs = $null
Status = "Error: $($_.Exception.Message)"
}
}
}
return $results
}
# Usage
Invoke-TcpHandshakeTest -TargetHost @("db-server-01", "api-gateway") -TargetPort 5432
Rationale: This function accepts multiple targets and a specific port, returning a uniform result set. It captures latency and remote address resolution, which are critical for diagnosing DNS issues or routing anomalies. Error handling ensures the script continues even if a host is unreachable, preventing pipeline breaks.
3. Subnet Enumeration and Device Discovery
Identifying active devices on a subnet is essential for inventory management and troubleshooting missing endpoints. Naive loops can be slow; PowerShell 7+ supports parallel execution for faster scans.
Implementation:
function Invoke-SubnetDiscovery {
[CmdletBinding()]
param(
[string]$SubnetBase = "192.168.1",
[int]$StartHost = 1,
[int]$EndHost = 254
)
$hosts = $StartHost..$EndHost | ForEach-Object { "$SubnetBase.$_" }
$hosts | ForEach-Object -Parallel {
$ip = $_
$result = Test-Connection -ComputerName $ip -Count 1 -Quiet -ErrorAction SilentlyContinue
[PSCustomObject]@{
IPAddress = $ip
IsAlive = $result
}
} -ThrottleLimit 50 | Where-Object { $_.IsAlive -eq $true }
}
# Usage
Invoke-SubnetDiscovery -SubnetBase "10.0.0" -StartHost 10 -EndHost 50
Rationale: Using ForEach-Object -Parallel significantly reduces scan time for large subnets. The ThrottleLimit parameter prevents resource exhaustion. The function filters results to return only alive hosts, reducing noise. This approach is ideal for automated inventory scripts or detecting rogue devices.
4. Socket State Forensics
Analyzing active TCP connections reveals application behavior, connection leaks, and port conflicts. Get-NetTCPConnection provides real-time kernel data on socket states.
Implementation:
function Analyze-TcpSocketState {
[CmdletBinding()]
param(
[string]$LocalPortFilter = $null,
[string]$StateFilter = $null
)
$query = Get-NetTCPConnection
if ($LocalPortFilter) {
$query = $query | Where-Object { $_.LocalPort -eq $LocalPortFilter }
}
if ($StateFilter) {
$query = $query | Where-Object { $_.State -eq $StateFilter }
}
$query | Group-Object -Property State |
Select-Object -Property @{
Name = "ConnectionState"
Exp = { $_.Name }
}, @{
Name = "Count"
Exp = { $_.Count }
}, @{
Name = "SampleConnections"
Exp = { $_.Group | Select-Object -First 3 | Format-Table -AutoSize | Out-String }
}
}
# Usage
Analyze-TcpSocketState -LocalPortFilter 8080 -StateFilter "Established"
Rationale: This function aggregates connections by state, providing a summary view. It allows filtering by port and state, which is useful for debugging services stuck in TimeWait or detecting connection leaks. The output includes sample connections for quick inspection.
5. Container Runtime Verification
Docker and container runtimes rely on virtual networking and TCP bridges. Failures often stem from daemon crashes, named pipe issues, or context misconfigurations.
Implementation:
function Validate-ContainerEndpoint {
[CmdletBinding()]
param(
[string]$Endpoint = "localhost",
[int]$TcpPort = 2375
)
$serviceStatus = Get-Service -Name "*docker*" -ErrorAction SilentlyContinue
$tcpCheck = Invoke-TcpHandshakeTest -TargetHost $Endpoint -TargetPort $TcpPort
[PSCustomObject]@{
DockerServiceRunning = [bool]$serviceStatus
TcpEndpointReachable = $tcpCheck.TcpTestSucceeded
ContextInfo = docker context ls 2>&1 | Out-String
Diagnostics = if (-not $serviceStatus) { "Docker service not running" }
elseif (-not $tcpCheck.TcpTestSucceeded) { "TCP endpoint unreachable; check daemon config or firewall" }
else { "Endpoint healthy" }
}
}
# Usage
Validate-ContainerEndpoint -Endpoint "localhost" -TcpPort 2375
Rationale: This function combines service status, TCP validation, and Docker context inspection into a single diagnostic report. It helps distinguish between service failures, network issues, and configuration errors. Note that Docker Desktop on Windows may use named pipes by default; adjust the port check based on your environment.
Pitfall Guide
| Pitfall Name | Explanation | Fix |
|---|
| ICMP vs. TCP Assumption | Assuming a host is reachable because ping succeeds. Firewalls often allow ICMP but block TCP ports. | Always validate specific TCP ports using Test-NetConnection or Invoke-TcpHandshakeTest. |
| IPv6 Masking | Test-Connection may resolve to IPv6, masking IPv4 connectivity issues. | Force address family using -AddressFamily IPv4 in diagnostic cmdlets. |
| DNS Resolution Latency | Test-NetConnection hangs if DNS is slow or failing, causing false timeouts. | Use IP addresses directly or implement timeout handling. Check DNS with Resolve-DnsName. |
| Firewall False Negatives | Local firewall rules may block outbound diagnostic traffic, leading to incorrect conclusions. | Verify outbound rules with Get-NetFirewallRule. Test from a known-good host. |
| Docker Named Pipe vs. TCP | Docker on Windows often uses named pipes, not TCP. Checking port 2375 may fail even if Docker is healthy. | Check DOCKER_HOST environment variable or Docker context. Use named pipe paths if applicable. |
| Stale ARP Cache | arp -a may show devices that are no longer on the network, causing confusion. | Clear ARP cache with Clear-DnsCache or Remove-NetNeighbor. Use active discovery instead. |
| Resource Exhaustion in Scans | Scanning large subnets without throttling can overwhelm CPU or trigger IDS alerts. | Use ForEach-Object -Parallel with ThrottleLimit. Implement rate limiting in scripts. |
Production Bundle
Action Checklist
Decision Matrix
| Scenario | Recommended Approach | Why | Cost Impact |
|---|
| Quick Host Check | Test-Connection with -Count 1 | Fast, low overhead, sufficient for basic reachability. | Minimal CPU/Network. |
| Service Availability | Invoke-TcpHandshakeTest | Validates TCP handshake; confirms service is listening. | Low overhead; accurate. |
| Subnet Inventory | Invoke-SubnetDiscovery with Parallel | Efficient scanning; returns structured data. | Moderate CPU; scalable. |
| Connection Leak Debug | Analyze-TcpSocketState | Aggregates socket states; identifies stuck connections. | Low overhead; high insight. |
| CI/CD Network Gate | Custom PowerShell function with assertions | Automated, repeatable, integrates with pipelines. | Development time; long-term savings. |
Configuration Template
# NetworkDiagnostics.psm1
# Reusable module for network diagnostics
function Initialize-NetworkDiagnostics {
[CmdletBinding()]
param()
# Import required modules
Import-Module NetTCPIP -ErrorAction Stop
# Define common ports for validation
$script:CommonPorts = @{
SSH = 22
HTTP = 80
HTTPS = 443
MySQL = 3306
Postgres = 5432
Docker = 2375
}
Write-Verbose "Network diagnostics initialized."
}
function Test-NetworkHealth {
[CmdletBinding()]
param(
[string[]]$Targets,
[string]$PortName = "HTTPS"
)
Initialize-NetworkDiagnostics
$port = $script:CommonPorts[$PortName]
if (-not $port) {
throw "Unknown port name: $PortName"
}
$results = Invoke-TcpHandshakeTest -TargetHost $Targets -TargetPort $port
return $results
}
Export-ModuleMember -Function Test-NetworkHealth
Quick Start Guide
- Open PowerShell: Launch PowerShell 7+ for parallel execution support.
- Check Interface: Run
Get-NetworkInterfaceState to verify local IP configuration.
- Test Connectivity: Use
Invoke-TcpHandshakeTest -TargetHost "example.com" -TargetPort 443 to validate TCP access.
- Analyze Sockets: Run
Analyze-TcpSocketState -StateFilter "Established" to inspect active connections.
- Automate: Save functions to a module and integrate into your deployment or monitoring scripts.