#requires -version 2.0 # ============================================================================================== # # Microsoft PowerShell Source File -- Created with SAPIEN Technologies PrimalScript 2009 # # NAME: Get-TCP # # AUTHOR: Jeffery Hicks , JDH Information Technology Solutions # DATE : 7/29/2010 # # # Jeffery Hicks # http://jdhitsolutions.com/blog # follow on Twitter: http://twitter.com/JeffHicks # # # "Those who forget to script are doomed to repeat their work." # **************************************************************** # * DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED * # * THOROUGHLY IN A LAB ENVIRONMENT. USE AT YOUR OWN RISK. IF * # * YOU DO NOT UNDERSTAND WHAT THIS SCRIPT DOES OR HOW IT WORKS, * # * DO NOT USE IT OUTSIDE OF A SECURE, TEST SETTING. * # **************************************************************** # # ============================================================================================== Function Get-TCP { <# .Synopsis Get TCP Netstat information .Description This function calls the command line NETSTAT.EXE tool and returns an object representation of the TCP data. Protocol : TCP Localhost : 172.16.10.127 LocalPort : 49259 RemoteHost : 74.201.86.29 RemotePort : https Status : ESTABLISHED The default is the local computer without name resolution. However you can specify a remote computername, assuming the remote computer is running PowerShell 2.0 and has remoting enabled. Use -ResolveHost to resolve IP addresses to host names. This is a little slower. This function will only return IPv4 hosts and addresses .Parameter Computername The name of the computer to query. The default is the localhost. .Parameter ResolveHost Resolve IP addresses to host names. This is a little slower. The is the equivalent of running Netstat.exe without any parameters. .Parameter ResolvePort Resolve the service name associated with the port. This requires access to the legacy Services file found at $env:windir\system32\drivers\etc\services. .Parameter IncludeRaw Include the raw netstat data. .Example PS C:\> get-tcp Return TCP Netstat information for the local computer. .Example PS C:\> get-tcp "Server1","Server2" -resolve Return TCP Netstat information for computers Server1 and Server2 with resolved IP addresses. .Example PS C:\> get-content computers.txt } get-tcp -resolveHost | where {$_.RemotePort -eq 80} | format-table -autosize Get HTTP connections for every computer in computers.txt and present as a formatted table. .Example PS C:\> get-tcp | sort RemotePort | Select RemotePort -unique Get a sorted list of all remote connections by port. .Inputs Strings .Outputs Custom object .Link http://jdhitsolutions.com/blog .Link Invoke-Command .Notes NAME: Get-TCP VERSION: 1.5 AUTHOR: Jeffery Hicks LASTEDIT: July 29, 2010 Learn more with a copy of Windows PowerShell 2.0: TFM (SAPIEN Press 2010) #> [cmdletbinding()] Param( [Parameter(Position=0,ValueFromPipeline=$True)] [string[]]$Computername=$env:computername, [switch]$ResolveHost, [switch]$ResolvePort, [switch]$IncludeRaw ) Begin { Write-Verbose "Starting $($myinvocation.mycommand)" if ($ResolveHost) { Write-Verbose "Resolving host names"} if ($ResolvePort) {Write-Verbose "Resolving port names"} #put everything into a script block so that if the computer #is remote it can be executed using Invoke-Command $scriptblock={netstat.exe -n | where {$_.Contains("TCP") -AND $_ -notmatch "\["}} Write-Verbose "Caching Services information" $file="$env:windir\system32\drivers\etc\services" #get just tcp services $services=Get-Content -Path $file | Select-String -Pattern "/tcp" Write-Verbose $($scriptblock.ToString()) #define the name resolution function Function Resolve-DNS { [cmdletbinding()] Param( [Parameter(Position=0,Mandatory=$True,ValueFromPipeline=$True, HelpMessage="Enter an IP Address to resolve")] [string[]]$Address ) Begin { Write-Verbose "Starting Resolve-DNS" #turn off error pipeline $errorActionPreference="SilentlyContinue" } Process { foreach ($IP in $Address) { Write-Verbose "Resolving $IP" $dns=[System.net.DNS]::GetHostByAddress("$IP") if (-not $dns) { Write-Verbose "no record found for $IP" $h=$IP $a=$null } else { $h=$dns.hostname $a=$dns.AddressList } New-Object -TypeName PSobject -Property @{ Hostname=$h Addresses=$a } } #foreach } #process End { #turn On error pipeline $errorActionPreference="Continue" } } #end function } #begin Process { foreach ($computer in $computername) { Write-Verbose "Getting raw NETSTAT data from $($computer.toUpper())" if ($computer -eq $env:computername) { #just run the script block if local computer $data=&$scriptblock } else { Try { $data=Invoke-Command -ScriptBlock $scriptblock -computername $computer -errorAction "Stop" } Catch { Write-Warning "Failed to run command on $computer" Write-Warning $error[0].exception.message } } #else #process data Write-Verbose "Returned $($data.count) items" Write-Verbose "Parsing data" #initialize a hash table for IP names $hash=@{} foreach ($tcp in $data) { Write-Verbose $tcp.trim() #split the line removing empty spaces $arr=$tcp.trim().split() | where {$_} $localData=$arr[1].Split(":") $remoteData=$arr[2].Split(":") $protocol=$arr[0] $raw=$tcp.trim() $local=$localData[0] [int]$localPort=$localData[1] $remote=$remoteData[0] [int]$remotePort=$remoteData[1] $status=$arr[3] #if resolve host requested build a dictionary or #ip addresses so we don't need to resolve one already resolved #and change the property value accordingly if ($resolveHost) { if ($hash.contains("$local")) { $local=$hash.Item("$local") } else { #look up name Write-Verbose "Resolving $local" $localLookup=Resolve-DNS "$local" #add to hash $hash.Add("$local",$localLookup.Hostname) #update property $local=$localLookup.Hostname } #do the same for remote if ($hash.contains("$remote")) { $remote=$hash.Item("$remote") } else { #look up name Write-Verbose "Resolving $remote" $remoteLookup=Resolve-DNS "$remote" #add to hash $hash.Add("$remote",$localLookup.Hostname) #update property $remote=$RemoteLookup.Hostname } } #if $resolveHost #resolve ports if specified if ($resolvePort) { #this is a mini scriptblock to return the service name #in lieu of a full-blown function $getsvc={Param ([string]$port) Write-Verbose "searching for $port" $service=$services | Select-String -pattern "\s$port/tcp" if ($service) { $data=$service.ToString().Trim().split() | where {$_} Write-Output $data[0] } else { Write-Output $port } } #end $getSvc [string]$localPort=&$getsvc $localPort [string]$remotePort=&$getsvc $remotePort } #end resolveport #create a new object and pipe it to Select-Object so that #the properties are in a nice order $obj=New-Object -TypeName "PSObject" -Property @{ Protocol=$protocol Localhost=$local LocalPort=$localPort RemoteHost=$remote RemotePort=$remotePort Status=$status } if ($IncludeRaw) { $obj | Add-Member -MemberType "Noteproperty" -Name "Raw" -Value $raw -PassThru | Select-Object -Property Protocol,LocalHost,LocalPort,RemoteHost,RemotePort,Status,Raw } else { $obj | Select-Object -Property Protocol,LocalHost,LocalPort,RemoteHost,RemotePort,Status } } #foreach $tcp } #foreach computer } #Process End { Write-Verbose "Ending $($myinvocation.mycommand)" } } #end function