marli-EndpointInUse.ps1
function marli-EndpointInUse{ function New_Entry ([int]$xposi,[int]$yposi,[string]$Text,[System.ConsoleColor]$Color){ $position=$Host.ui.RawUI.CursorPosition $position.x = $xposi $position.y = $yposi $Host.ui.RawUI.CursorPosition=$position Write-Host $Text -ForegroundColor $Color } function Mainmenu { Clear-Host Write-Host '[' -NoNewline Write-Host ' ]>------ Downloading Endpoints' Write-Host '[' -NoNewline Write-Host ' ]>------ Checking Connections' Write-Host '[' -NoNewline Write-Host ' ]>------ Compare results' } function Download-MicrosoftEndpoints { [CmdletBinding(DefaultParameterSetName = 'Default')] #Hide download progress, get current JSON url, retrieve all Endpoints and Convert it from JSON format $ProgressPreference = "SilentlyContinue" try { $site = Invoke-WebRequest -Uri 'https://learn.microsoft.com/en-us/microsoft-365/enterprise/urls-and-ip-address-ranges?view=o365-worldwide' -UseBasicParsing $jsonlink = ($site.Links | where-Object OuterHTML -match 'JSON formatted').href } catch { Write-Warning ("Error downloading JSON file, please check if https://learn.microsoft.com/en-us/microsoft-365/enterprise/urls-and-ip-address-ranges?view=o365-worldwide is accessible") return } try { $Endpoints = Invoke-WebRequest -Uri $jsonlink -ErrorAction Stop -UseBasicParsing | ConvertFrom-Json } catch { Write-Warning ("Error downloading worldwide Microsoft Endpoints, please check if {0} is accessible" -f $jsonlink) return } $TestEndpoints = $Endpoints | Where-Object urls -ne $null | Select-Object urls, tcpports, udpports, ips, notes, serviceAreaDisplayName #Test Microsoft Endpoint Adresses and report if failed or succeeded $total = foreach ($TestEndpoint in $TestEndpoints) { if ($TestEndpoint.tcpPorts) { foreach ($tcpport in $TestEndpoint.tcpPorts.split(',')) { foreach ($testurl in $TestEndpoint.urls) { #Test connection and retrieve all information $results = $null If ($testurl -match "\*"){$testurl = $testurl.Replace("*.","")} $results = (Resolve-DnsName -Name $testurl -DnsOnly -ErrorAction SilentlyContinue).IP4Address If ($results) { $Status = 'Succeeded' $ipaddress = $results } else { $Status = "Failed or couldn't resolve DNS name" $ipaddress = "Not applicable" } [PSCustomObject]@{ Status = $Status URL = $testurl TCPport = $tcpport IPAddressUsed = $ipaddress } } } } } return $total } function Get-NetAllConnections { # unfortunately netstat takes a lot of time to run $cmdOutput = netstat -a $connections = $cmdOutput[4..$cmdOutput.count] | ConvertFrom-String -PropertyNames Empty, Protocol, LocalAddress, RemoteAddress, State | Select Protocol, LocalAddress, RemoteAddress, State $getNetAllConnections = @() foreach ($connection in $connections) { $getNetTCPConnetion_FakeObject = New-Object -TypeName psobject $getNetTCPConnetion_FakeObject | Add-Member -MemberType NoteProperty -Name Protocol -Value $connection.Protocol # split netstat LocalAddress value by ':' because it contains both address and port $tempCon = $connection.LocalAddress -split "(:)" $lastIndexOfFirstPart = $tempCon.count - 3 $tempConPart1Buffer = "" foreach ($row in $tempCon[0..$lastIndexOfFirstPart]) { $tempConPart1Buffer += $row } $tempConPart1 = $tempConPart1Buffer $indexOfSecondPart = $tempCon.count - 1 $tempConPart2 = $tempCon[$indexOfSecondPart] # with PS version 7 this could be simplyfied, because -split supports negative values: #$tempCon = ($connection.LocalAddress -split "(:)", -1) #$tempConPart1 = $tempCon[0] #$tempConPart2 = $tempCon[1] $getNetTCPConnetion_FakeObject | Add-Member -MemberType NoteProperty -Name LocalAddress -Value $tempConPart1 $getNetTCPConnetion_FakeObject | Add-Member -MemberType NoteProperty -Name LocalPort -Value $tempConPart2 # split netstat RemoteAddress value by ':' because it contains both address and port $tempCon = $connection.RemoteAddress -split "(:)" $lastIndexOfFirstPart = $tempCon.count - 3 $tempConPart1Buffer = "" foreach ($row in $tempCon[0..$lastIndexOfFirstPart]) { $tempConPart1Buffer += $row } $tempConPart1 = $tempConPart1Buffer $indexOfSecondPart = $tempCon.count - 1 $tempConPart2 = $tempCon[$indexOfSecondPart] # with PS version 7 this could be simplyfied, because -split supports negative values: #$tempCon = ($connection.LocalAddress -split "(:)", -1) #$tempConPart1 = $tempCon[0] #$tempConPart2 = $tempCon[1] $getNetTCPConnetion_FakeObject | Add-Member -MemberType NoteProperty -Name RemoteAddress -Value $tempConPart1 $getNetTCPConnetion_FakeObject | Add-Member -MemberType NoteProperty -Name RemotePort -Value $tempConPart2 $getNetTCPConnetion_FakeObject | Add-Member -MemberType NoteProperty -Name State -Value connection.State $getNetAllConnections += $getNetTCPConnetion_FakeObject } # if you want to display output and format it the same as 'Get-NetTCPConnection' does: #$getNetAllConnections | Format-Table return $getNetAllConnections } function Filter-Results($Connections, $Endpoints){ $List = @() If ($endpoints -and $Connections) { Foreach ($endpoint in $endpoints) { $ips = $endpoint.IPAddressUsed If ($ips.Count -ge 2) { Foreach ($ip in $ips) { Foreach ($conn in $Connections) { If ($conn -eq $ip) { $line = '' | Select URL, EndpointIP $line.URL = $endpoint.URL $line.EndpointIP = $ip $List += $line } } } } else{ Foreach ($conn in $Connections) { If ($conn -eq $ips) { $line = '' | Select URL, EndpointIP $line.URL = $endpoint.URL $line.EndpointIP = $ips $List += $line } } } } } If (!$List) { $line = '' | Select URL, EndpointIP $line.URL = '' $line.EndpointIP = '' $List += $line } return $List | Sort-Object -Unique URL, EndpointIP } [System.Console]::CursorVisible = $false Mainmenu #Download Endpoints If (!$endpoints){ New_Entry -xposi 1 -yposi 0 -Text '<' -Color Yellow $endpoints = Download-MicrosoftEndpoints | Where-Object {$_.Status -eq 'Succeeded'} } If ($endpoints){ New_Entry -xposi 1 -yposi 0 -Text '+' -Color Green } else{ New_Entry -xposi 1 -yposi 0 -Text 'x' -Color Red #break } #Check own Connections New_Entry -xposi 1 -yposi 1 -Text '<' -Color Yellow $Connections = $null $Connections = (Get-NetAllConnections).RemoteAddress | Where-Object {$_ -notmatch ':' -and $_ -like '*.*'} | Sort-Object -Unique If ($Connections){ New_Entry -xposi 1 -yposi 1 -Text '+' -Color Green } else{ New_Entry -xposi 1 -yposi 1 -Text 'x' -Color Red break } #Filtering results New_Entry -xposi 1 -yposi 2 -Text '<' -Color Yellow $results = Filter-Results -Connections $Connections -Endpoints $endpoints If ($results){ New_Entry -xposi 1 -yposi 2 -Text '+' -Color Green } else{ New_Entry -xposi 1 -yposi 2 -Text 'x' -Color Red break } Clear-Host return $results [System.Console]::CursorVisible = $True } |