Advertisement
gangstanthony

Get-PortStats.ps1

Apr 13th, 2016
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # https://www.reddit.com/r/PowerShell/comments/4emc45/changing_output_of_script_to_csv/
  2.  
  3. function Get-PortStats {
  4.     param (
  5.         [string[]]$Computers = $env:computername,
  6.         [string]$User,
  7.         [string]$Password,
  8.         [int]$CollectionInterval,
  9.         [string]$OutputFilePath,
  10.         [string]$PsExecLocation
  11.     )
  12.  
  13.     begin {
  14.         function ProcessArguments ($paComputers, $paUser, $paPassword) {
  15.             #// Processes the arguments passed into the script such as getting the appropriate credentials if specified.
  16.             $paComputers = $paComputers.Split(';')
  17.             if ($paComputers -isnot [System.String[]]) {
  18.                 $paComputers = @($paComputers)
  19.             }
  20.    
  21.             #// If credentials are passed into this script, then make them secure.
  22.             if ($paUser -ne '') {        
  23.                 if ($paPassword -ne '') {
  24.                     $paPassword = ConvertTo-SecureString -AsPlainText -Force -String $paPassword
  25.                     $paCredential = New-Object System.Management.Automation.PsCredential -ArgumentList $paUser, $paPassword
  26.                 } else {
  27.                     $paCredential = Get-Credential -Credential $paUser
  28.                 }  
  29.             }
  30.  
  31.             [pscustomobject]@{
  32.                 Computers = $paComputers
  33.                 Credential = $paCredential
  34.             }
  35.         }
  36.  
  37.         function Invoke-PsExec ($peComputer, $peCommand, $peUser, $pePassword, $peCredential) {
  38.             #// Executes PsExec to get data from remote computers.
  39.             if ($PsExecLocation) {
  40.                 $PsExec = $PsExecLocation
  41.             } else {
  42.                 $PsExec = '.\psexec.exe'
  43.             }
  44.  
  45.             if ($peUser -ne '') {
  46.                 if ($pePassword -eq '') {
  47.                     $pePassword = $peCredential.GetNetworkCredential().Password
  48.                 }
  49.                 $sPsCmd = "$PsExec \\$peComputer /AcceptEula -u $peUser -p `"$pePassword`" -s $peCommand 2> `$null"
  50.                 Write-Warning 'Credentials sent in clear text to the remote computer using PsExec! Prevent this by not providing credentials to this script and logging in with a domain account with admin privileges to the remote computer or by using network encryption such as IPSec.'
  51.             } else {
  52.                 $sPsCmd = "$PsExec \\$peComputer /AcceptEula $peCommand"
  53.             }
  54.            
  55.             Invoke-Expression -Command $sPsCmd
  56.         }
  57.  
  58.         function Get-TcpDynamicPortRange ($tdprComputer, $tdprUser, $tdprPassword, $tdprCredential) {
  59.             $sCmd = 'netsh int ipv4 show dynamicportrange tcp'
  60.  
  61.             if ($tdprComputer -eq $env:COMPUTERNAME) { # local
  62.                 $oOutput = Invoke-Expression -Command $sCmd
  63.             } else { # not local
  64.                 #// Use PsExec
  65.                 $oOutput = Invoke-PsExec -peComputer $tdprComputer -peCommand $sCmd -peUser $tdprUser -pePassword $tdprPassword -peCredential $tdprCredential
  66.             }
  67.    
  68.             $oDynamicPortRange = [pscustomobject]@{
  69.                 StartPort = 0
  70.                 EndPort = 0
  71.                 NumberOfPorts = 0
  72.             }
  73.  
  74.             foreach ($sLine in $oOutput) {
  75.                 if ($sLine.IndexOf('Start Port') -ge 0) {
  76.                     $aLine = $sLine.Split(':')
  77.                     [int]$oDynamicPortRange.StartPort = $aLine[1]
  78.                 }
  79.        
  80.                 if ($sLine.IndexOf('Number of Ports') -ge 0) {
  81.                     $aLine = $sLine.Split(':')
  82.                     [int]$oDynamicPortRange.NumberOfPorts = $aLine[1]
  83.                 }
  84.             }
  85.            
  86.             $oDynamicPortRange.EndPort = $oDynamicPortRange.StartPort + $oDynamicPortRange.NumberOfPorts - 1
  87.            
  88.             $oDynamicPortRange
  89.         }
  90.  
  91.         function Get-ActiveTcpConnections ($atcComputer, $atcUser, $atcPassword, $atcCredential) {
  92.             $sCmd = 'netstat -ano -p tcp'
  93.  
  94.             if ($Computer -eq $env:COMPUTERNAME) { # local
  95.                 $oOutput = Invoke-Expression -Command $sCmd
  96.             } else { # not local
  97.                 #// Use PsExec
  98.                 $oOutput = Invoke-PsExec -peComputer $atcComputer -peCommand $sCmd -peUser $atcUser -pePassword $atcPassword -peCredential $atcCredential
  99.             }
  100.    
  101.             if ($oOutput -ne $null) {
  102.                 $u = $oOutput.GetUpperBound(0)
  103.                 $oOutput = $oOutput[4..$u]
  104.                 foreach ($sLine in $oOutput) {
  105.                     $iPropertyIndex = 0
  106.                     $aLine = @($sLine.Split(' ')).where{$_ -notmatch '^\s*$'}
  107.                     $oActiveConnection = @{}
  108.                     for ($c = 0; $c -lt $aLine.Count;$c++) {
  109.                         if ($aLine[$c] -ne '') {
  110.                             switch ($iPropertyIndex) {
  111.                                 0 {
  112.                                     $oActiveConnection.Add('Proto', $aLine[$c])
  113.                                 }
  114.                                 1 {
  115.                                     $aIpPort = $aLine[$c].Split(':')
  116.                                     $oActiveConnection.Add('LocalAddress', $aIpPort[0])
  117.                                     $oActiveConnection.Add('LocalPort', [int]$aIpPort[1])
  118.                                 }
  119.                                 2 {
  120.                                     $aIpPort = $aLine[$c].Split(':')
  121.                                     $oActiveConnection.Add('ForeignAddress', $aIpPort[0])
  122.                                     $oActiveConnection.Add('ForeignPort', [int]$aIpPort[1])
  123.                                 }
  124.                                 3 {
  125.                                     $oActiveConnection.Add('State', $aLine[$c])
  126.                                 }
  127.                                 4 {
  128.                                     $oActiveConnection.Add('PID', [int]$aLine[$c])
  129.                                 }
  130.                             }
  131.                             $iPropertyIndex++
  132.                         }
  133.                     }
  134.                     [pscustomobject]$oActiveConnection
  135.                 }
  136.             }
  137.         }
  138.        
  139.         function Get-EphemeralPortStats ($ArrayOfComputerNames, $epsUser, $epsPassword, $epsCredential) {
  140.             $epsHtDynamicPortRange = @{}
  141.    
  142.             foreach ($Computer in $ArrayOfComputerNames) {    
  143.                 if ($epsHtDynamicPortRange.ContainsKey($Computer) -eq $false) {
  144.                     $oDynamicPortRange = Get-TcpDynamicPortRange -tdprComputer $Computer -tdprUser $epsUser -tdprPassword $epsPassword -tdprCredential $epsCredential
  145.                     [Void]$epsHtDynamicPortRange.Add($Computer, $oDynamicPortRange)
  146.                 } else {
  147.                     $oDynamicPortRange = $epsHtDynamicPortRange[$Computer]
  148.                 }
  149.  
  150.                 [int]$iDynamicStartPort = $oDynamicPortRange.StartPort
  151.                 [int]$iDynamicEndPort = $oDynamicPortRange.EndPort
  152.                 [int]$iDynamicNumberOfPorts = $oDynamicPortRange.NumberOfPorts
  153.  
  154.                 $oActiveConnections = Get-ActiveTcpConnections -atcComputer $Computer -atcUser $epsUser -atcPassword $epsPassword -atcCredential $epsCredential | Sort LocalPort -Descending
  155.                 $aUniqueLocalAddresses = @($oActiveConnections | Sort {[version]$_.LocalAddress} | Select LocalAddress -Unique).where{$_.localaddress -ne '0.0.0.0'}
  156.                 $aDynamicPortRangeConnections = @($oActiveConnections).Where{($_.LocalPort -gt $iDynamicStartPort) -and ($_.LocalPort -lt $iDynamicEndPort)}
  157.  
  158.                 foreach ($oUniqueLocalAddress in $aUniqueLocalAddresses) {
  159.                     if ($oUniqueLocalAddress.LocalAddress -ne '0.0.0.0') {
  160.                         #// Ephemeral ports of each LocalAddress
  161.                         [string]$sUniqueLocalAddress = $oUniqueLocalAddress.LocalAddress
  162.                         [array]$aIpEphemeralPortConnections = @($aDynamicPortRangeConnections).Where{($_.LocalAddress -eq $sUniqueLocalAddress)} | Select LocalPort -Unique | Sort
  163.                        
  164.                         $oStats = @{}
  165.                         $oStats.Add('Computer', $Computer)
  166.                         $oStats.Add('DateTime', $(Get-Date))
  167.                         $oStats.Add('LocalAddress', $sUniqueLocalAddress)
  168.                         $oStats.Add('Max#OfEPorts', [int]$oDynamicPortRange.NumberOfPorts)
  169.  
  170.                         if ($aIpEphemeralPortConnections -ne $null) {
  171.                             $oStats.Add('#OfEPortsInUse', [int]$aIpEphemeralPortConnections.Count)
  172.                             $iPercentage = [int]$aIpEphemeralPortConnections.Count / [int]$oDynamicPortRange.NumberOfPorts * 100
  173.                             $iPercentage = [Math]::Round($iPercentage, 1)
  174.                         } else {
  175.                             $oStats.Add('#OfEPortsInUse', 0)
  176.                             $iPercentage = 0        
  177.                         }
  178.                        
  179.                         $oStats.Add('%EPortUsage', $iPercentage)
  180.  
  181.                         #// Listening ports of each LocalAddress
  182.                         [array]$aIpListeningPorts = @($oActiveConnections).Where{($_.State -eq 'LISTENING') -and (($_.LocalAddress -eq $sUniqueLocalAddress) -or ($_.LocalAddress -eq '0.0.0.0'))} | Select LocalPort | Sort LocalPort | Get-Unique -AsString
  183.  
  184.                         if ($aIpListeningPorts -ne $null) {
  185.                             $oStats.Add('#OfTcpListeningPorts', [int]$aIpListeningPorts.Count)
  186.                         } else {
  187.                             $oStats.Add('#OfTcpListeningPorts', 0)
  188.                         }
  189.  
  190.                         #// Number of PIDs
  191.                         [array]$aIpPids = @($oActiveConnections).Where{($_.LocalAddress -eq $sUniqueLocalAddress) -or ($_.LocalAddress -eq '0.0.0.0')} | Select PID -Unique | Sort PID
  192.  
  193.                         if ($aIpPids -ne $null) {
  194.                             $oStats.Add('#OfPids', [int]$aIpPids.Count)
  195.                         } else {
  196.                             $oStats.Add('#OfPids', 0)
  197.                         }
  198.  
  199.                         [pscustomobject]$oStats
  200.                     }
  201.                 }
  202.             }
  203.         }
  204.     }
  205.  
  206.     process {        
  207.         $pa = ProcessArguments -paComputers $Computers -paUser $User -paPassword $Password
  208.         $Computers = $pa.computers
  209.         $Credential = $pa.credential
  210.  
  211.         if ($CollectionInterval) {
  212.             $stop = $false
  213.         } else {
  214.             $stop = $true
  215.         }
  216.        
  217.         do {
  218.             $oPortStats = Get-EphemeralPortStats -ArrayOfComputerNames $Computers -epsUser $User -epsPassword $Password -epsCredential $Credential
  219.            
  220.             $oPortStats | Format-Table -AutoSize
  221.  
  222.             if ($OutputFilePath) {
  223.                 $oPortStats | Export-Csv $OutputFilePath -NoTypeInformation
  224.             }
  225.  
  226.             if ($CollectionInterval) {
  227.                 Write-Host "Sleeping for $CollectionInterval seconds..." -NoNewline
  228.                 Start-Sleep -Seconds $CollectionInterval
  229.             }
  230.  
  231.             Write-Host 'Done!'
  232.         } until ($stop)
  233.     }
  234. }
  235.  
  236. Get-PortStats -Computers $env:computername -OutputFilePath c:\temp\portstats.csv -PsExecLocation C:\PSTools\PsExec.exe
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement