Created
February 15, 2026 02:04
-
-
Save ahhh/fbc20c56620288134ceba9086ce20257 to your computer and use it in GitHub Desktop.
quick and dirty powershell script to loop over netstat connections and tie them to a process w/ a little supporting info. Added a good bit of caching and state comparison to get htop-like display
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| $seen = @{} | |
| $dnsCache = @{} | |
| $geoCache = @{} | |
| function Resolve-Name($ip) { | |
| if ($dnsCache.ContainsKey($ip)) { | |
| return $dnsCache[$ip] | |
| } | |
| try { | |
| $name = (Resolve-DnsName $ip -ErrorAction Stop).NameHost | |
| } catch { | |
| $name = $ip | |
| } | |
| $dnsCache[$ip] = $name | |
| return $name | |
| } | |
| function Get-Geo($ip) { | |
| if ($geoCache.ContainsKey($ip)) { return $geoCache[$ip] } | |
| try { | |
| $r = Invoke-RestMethod "http://ip-api.com/json/$ip" -TimeoutSec 3 | |
| $info = [PSCustomObject]@{ | |
| country = $r.countryCode | |
| region = $r.regionName | |
| city = $r.city | |
| isp = $r.isp | |
| } | |
| } catch { | |
| $info = [PSCustomObject]@{ | |
| country = "?" | |
| region = "?" | |
| city = "?" | |
| isp = "?" | |
| } | |
| } | |
| $geoCache[$ip] = $info | |
| return $info | |
| } | |
| while ($true) { | |
| # Get connections | |
| $connections = netstat -ano | Select-String ESTABLISHED | |
| # Build fingerprint snapshot for display refresh | |
| $currentKeys = @() | |
| foreach ($line in $connections) { | |
| $parts = ($line -replace "\s+", " ").Trim().Split(" ") | |
| $remote = $parts[2] | |
| $procId = $parts[-1] | |
| if ($remote -match "127\.0\.0\.1|::1") { continue } | |
| $ip = $remote.Split(":")[0] | |
| $currentKeys += "$ip-$procId" | |
| } | |
| $currentSnapshot = ($currentKeys | Sort-Object) -join "`n" | |
| if ($currentSnapshot -eq $lastSnapshot) { | |
| Start-Sleep 0.3 | |
| continue | |
| } | |
| $lastSnapshot = $currentSnapshot | |
| Clear-Host | |
| Write-Host "External connections" | |
| Write-Host "===================================" | |
| # Loop and display connections | |
| foreach ($line in $connections) { | |
| $parts = ($line -replace "\s+", " ").Trim().Split(" ") | |
| $remote = $parts[2] | |
| $procId = $parts[-1] | |
| if ($remote -match "127\.0\.0\.1|::1") { continue } | |
| $ip = $remote.Split(":")[0] | |
| $proc = (Get-Process -Id $procId -ErrorAction SilentlyContinue).ProcessName | |
| if ($procId -eq $PID) { continue } | |
| if (!$proc) { $proc = "?" } | |
| $name = Resolve-Name $ip | |
| $geo = Get-Geo $ip | |
| $key = "$ip-$procId" | |
| if (-not $seen.ContainsKey($key)) { | |
| Write-Host "NEW: $proc -> $name [$ip] $($geo.country) $($geo.region) $($geo.city) $($geo.isp)" -ForegroundColor Yellow | |
| $seen[$key] = $true | |
| } | |
| else { | |
| Write-Host "$proc -> $name [$ip] $($geo.country) $($geo.region) $($geo.city) $($geo.isp)" | |
| } | |
| } | |
| Start-Sleep 0.3 | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| REM inspiration behind watcher script | |
| @echo off | |
| :loop | |
| cls | |
| echo Established connections (refresh every 2 seconds) | |
| echo ================================================= | |
| netstat -ano | findstr /v "127.0.0.1 ::1" | find "ESTABLISHED" | |
| timeout /t 2 /nobreak >nul | |
| goto loop |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment