Skip to content

Commit 296c88a

Browse files
committed
Network health script.
1 parent 7045e21 commit 296c88a

2 files changed

Lines changed: 586 additions & 0 deletions

File tree

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
function CountAvailableEphemeralPorts([string]$protocol = "TCP") {
2+
3+
[uint32]$portRangeSize = 64
4+
# First, remove all the text bells and whistle (plain text, table headers, dashes, empty lines, ...) from netsh output
5+
$tcpRanges = (netsh int ipv4 sh excludedportrange $protocol) -replace "[^0-9,\ ]", '' | ? { $_.trim() -ne "" }
6+
7+
# Then, remove any extra space characters. Only capture the numbers representing the beginning and end of range
8+
$tcpRangesArray = $tcpRanges -replace "\s+(\d+)\s+(\d+)\s+", '$1,$2' | ConvertFrom-String -Delimiter ","
9+
#Convert from PSCustomObject to Object[] type
10+
$tcpRangesArray = @($tcpRangesArray)
11+
12+
# Extract the ephemeral ports ranges
13+
$EphemeralPortRange = (netsh int ipv4 sh dynamicportrange $protocol) -replace "[^0-9]", '' | ? { $_.trim() -ne "" }
14+
$EphemeralPortStart = [Convert]::ToUInt32($EphemeralPortRange[0])
15+
$EphemeralPortEnd = $EphemeralPortStart + [Convert]::ToUInt32($EphemeralPortRange[1]) - 1
16+
17+
# Find the external interface
18+
$externalInterfaceIdx = (Get-NetRoute -DestinationPrefix "0.0.0.0/0")[0].InterfaceIndex
19+
$hostIP = (Get-NetIPConfiguration -ifIndex $externalInterfaceIdx).IPv4Address.IPAddress
20+
21+
# Extract the used TCP ports from the external interface
22+
$usedTcpPorts = (Get-NetTCPConnection -LocalAddress $hostIP -ErrorAction Ignore).LocalPort
23+
$usedTcpPorts | % { $tcpRangesArray += [pscustomobject]@{P1 = $_; P2 = $_ } }
24+
25+
# Extract the used TCP ports from the 0.0.0.0 interface
26+
$usedTcpGlobalPorts = (Get-NetTCPConnection -LocalAddress "0.0.0.0" -ErrorAction Ignore).LocalPort
27+
$usedTcpGlobalPorts | % { $tcpRangesArray += [pscustomobject]@{P1 = $_; P2 = $_ } }
28+
# Sort the list and remove duplicates
29+
$tcpRangesArray = ($tcpRangesArray | Sort-Object { $_.P1 } -Unique)
30+
31+
$tcpRangesList = New-Object System.Collections.ArrayList($null)
32+
$tcpRangesList.AddRange($tcpRangesArray)
33+
34+
# Remove overlapping ranges
35+
for ($i = $tcpRangesList.P1.Length - 2; $i -gt 0 ; $i--) {
36+
if ($tcpRangesList[$i].P2 -gt $tcpRangesList[$i + 1].P1 ) {
37+
$tcpRangesList.Remove($tcpRangesList[$i + 1])
38+
$i++
39+
}
40+
}
41+
42+
# Remove the non-ephemeral port reservations from the list
43+
$filteredTcpRangeArray = $tcpRangesList | ? { $_.P1 -ge $EphemeralPortStart }
44+
$filteredTcpRangeArray = $filteredTcpRangeArray | ? { $_.P2 -le $EphemeralPortEnd }
45+
46+
if ($null -eq $filteredTcpRangeArray) {
47+
$freeRanges = @($EphemeralPortRange[1])
48+
}
49+
else {
50+
$freeRanges = @()
51+
# The first free range goes from $EphemeralPortStart to the beginning of the first reserved range
52+
$freeRanges += ([Convert]::ToUInt32($filteredTcpRangeArray[0].P1) - $EphemeralPortStart)
53+
54+
for ($i = 1; $i -lt $filteredTcpRangeArray.length; $i++) {
55+
# Subsequent free ranges go from the end of the previous reserved range to the beginning of the current reserved range
56+
$freeRanges += ([Convert]::ToUInt32($filteredTcpRangeArray[$i].P1) - [Convert]::ToUInt32($filteredTcpRangeArray[$i - 1].P2) - 1)
57+
}
58+
59+
# The last free range goes from the end of the last reserved range to $EphemeralPortEnd
60+
$freeRanges += ($EphemeralPortEnd - [Convert]::ToUInt32($filteredTcpRangeArray[$filteredTcpRangeArray.length - 1].P2))
61+
}
62+
63+
# Count the number of available free ranges
64+
[uint32]$freeRangesCount = 0
65+
($freeRanges | % { $freeRangesCount += [Math]::Floor($_ / $portRangeSize) } )
66+
67+
return $freeRangesCount
68+
}
69+
70+
function CheckPortExhaustion {
71+
Write-Host "Checking Port Exhaustion"
72+
$avTcpPorts = CountAvailableEphemeralPorts -protocol TCP
73+
if($avTcpPorts -lt 10) {
74+
Write-Host "Available TCP ports are $avTcpPorts. Port exhaustion suspected." -ForegroundColor Red
75+
return $true
76+
}
77+
$avUdpPorts = CountAvailableEphemeralPorts -protocol UDP
78+
if($avTcpPorts -lt 10) {
79+
Write-Host "Available UDP ports are $avUdpPorts. Port exhaustion suspected." -ForegroundColor Red
80+
return $true
81+
}
82+
Write-Host "Available TCP Ports : $avTcpPorts , UDP Ports : $avUdpPorts . No port exhaustion suspected." -ForegroundColor Green
83+
return $false
84+
}
85+
86+
Write-Host "Total wait time : 100 seconds..."
87+
88+
for($i = 1; $i -le 10; $i++) {
89+
Write-Host "Iteration : $i"
90+
if(CheckPortExhaustion) {
91+
Write-Host "DNS Issue Found." -ForegroundColor Red
92+
return
93+
}
94+
Start-Sleep -Seconds 10
95+
}

0 commit comments

Comments
 (0)