Beyond configuration and connectivity, PowerShell can also inspect live network activity. This includes active TCP connections, adapter-level traffic counters, and protocol statistics. It offers object-based alternatives to tools such as netstat. Network telemetry and socket diagnostics in PowerShell are driven by the NetTCPIP and NetAdapter modules. Cmdlets such as Get-NetTCPConnection, Get-NetAdapterStatistics, and Get-NetIPStatistics replace legacy utilities like netstat.exe and interface hardware monitors, outputting structured objects that report active TCP sockets, hardware frame counters, packet drop rates, and IP-layer protocol errors.
Viewing Active Connections with Get-NetTCPConnection
The Get-NetTCPConnection cmdlet inspects the active TCP transport layer, acting as the structured object equivalent to netstat -ano. It catalogs local and remote IP addresses, ports, connection states, and the process identifier (PID) that owns each socket.
Get-NetTCPConnectionLocalAddress LocalPort RemoteAddress RemotePort State AppliedSetting
------------ --------- ------------- ---------- ----- --------------
0.0.0.0 135 0.0.0.0 0 Listen
192.168.1.42 51022 142.250.72.14 443 Established
127.0.0.1 5040 127.0.0.1 5041 Establishedwhere State is the connection status: Listen, Established, TimeWait, CloseWait, etc.
Filtering by Port or State
Get-NetTCPConnection -LocalPort 443
Get-NetTCPConnection -State Establishedwhere:
-LocalPortfilters connections bound to a specific local port.-Statefilters connections by their current TCP state.
Correlating Connections to Processes
Each connection includes an OwningProcess property (PID), which can be joined with Get-Process to identify which application owns the connection.
Get-NetTCPConnection -State Listen |
Select-Object -Property LocalAddress, LocalPort, OwningProcess,
@{Name="ProcessName"; Expression={(Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).ProcessName}} |
Sort-Object -Property LocalPortwhere:
Get-NetTCPConnectionretrieves the state of active TCP connections and listening sockets.-Statefilters connections by TCP lifecycle states (such asListen,Established,TimeWait,CloseWait, orSynSent).LocalAddressis the IP address assigned to the local interface hosting the socket.LocalPortis the TCP port number bound by the application.OwningProcessis the PID of the process managing the socket.(Get-Process -Id ...)is a calculated property expression dynamically looking up the process executable name corresponding to the PID.
./get-tcp-connections.ps1LocalAddress LocalPort OwningProcess ProcessName
------------ --------- ------------- -----------
0.0.0.0 80 4112 httpd
0.0.0.0 135 1024 svchost
0.0.0.0 445 4 System
0.0.0.0 3389 1288 TermService
0.0.0.0 5985 2340 wsmprovhostViewing Adapter Traffic with Get-NetAdapterStatistics
The Get-NetAdapterStatistics cmdlet queries Layer 2 packet counters, byte throughput, and hardware frame errors for physical and virtual network adapters.
Get-NetAdapterStatistics |
Select-Object -Property Name,
@{Name="Received(MB)"; Expression={[math]::Round($_.ReceivedBytes / 1MB, 2)}},
@{Name="Sent(MB)"; Expression={[math]::Round($_.SentBytes / 1MB, 2)}},
ReceivedDiscardedPackets,
OutboundDiscardedPacketswhere:
Get-NetAdapterStatisticsqueries low-level device counters from the network interface driver.ReceivedBytes/SentBytesare total cumulative data transferred through the adapter since system boot or driver re-initialization.ReceivedDiscardedPacketsare packets dropped by the adapter due to buffer starvation, hardware saturation, or driver exhaustion.OutboundDiscardedPacketsare packets dropped before transmission.
./get-adapter-stats.ps1Name : Ethernet0
Received(MB) : 0.61
Sent(MB) : 0.09
ReceivedDiscardedPackets : 0
OutboundDiscardedPackets : 0Measuring Throughput Over Time
$before = Get-NetAdapterStatistics -Name "Ethernet"
Start-Sleep -Seconds 5
$after = Get-NetAdapterStatistics -Name "Ethernet"
$receivedMBps = (($after.ReceivedBytes - $before.ReceivedBytes) / 5) / 1MB
$sentMBps = (($after.SentBytes - $before.SentBytes) / 5) / 1MB
Write-Output "Received: $([math]::Round($receivedMBps,2)) MB/s"
Write-Output "Sent: $([math]::Round($sentMBps,2)) MB/s"where:
$before / $after: snapshots of the counters taken 5 seconds apart.
- Dividing the byte delta by elapsed seconds and
1MBconverts the result into megabytes per second.
./measure-throughput.ps1Received: 1.24 MB/s
Sent: 0.31 MB/sViewing Protocol Statistics with Get-NetIPStatistics
The Get-NetIPStatistics cmdlet provides Layer 3 telemetry, querying the operational state of IPv4 and IPv6 stacks. It tracks packet forwarding, routing failures, fragmentation statistics, and header reassembly errors, much like the output of netstat -s.
Get-NetIPStatistics -AddressFamily IPv4 |
Select-Object -Property DatagramsReceived,
ForwardedDatagrams,
ReceivedAddressErrors,
ReceivedPacketsDiscarded,
ReassemblyFailureswhere:
Get-NetIPStatisticsqueries core network layer metrics across the host's IP implementation.-AddressFamily IPv4restricts statistics to IPv4 metrics (IPv6can also be targeted).ForwardedDatagramsis the number of packets routed by the host when acting as an IP router/gateway.ReceivedAddressErrorsare packets received where the target IP was invalid or not hosted locally.ReceivedPacketsDiscardedare packets discarded due to memory constraints or IP protocol-level invalidations.ReassemblyFailuresare fragmented packets that timed out before total reassembly.
./get-ip-statistics.ps1DatagramsReceived : 1245892
ForwardedDatagrams : 0
ReceivedAddressErrors : 4
ReceivedPacketsDiscarded : 0
ReassemblyFailures : 0Comparing IPv4 vs IPv6 Statistics
Get-NetIPStatistics -AddressFamily IPv6where -AddressFamily filters results to IPv4 or IPv6 statistics specifically.
Practical Usage
Connection and Traffic Health Check
A common diagnostic script combines connection counts, traffic volume, and discarded packet counters into a single health snapshot.
param([string]$AdapterName = "Ethernet")
$connections = Get-NetTCPConnection -State Established
$stats = Get-NetAdapterStatistics -Name $AdapterName
$ipStats = Get-NetIPStatistics -AddressFamily IPv4
[PSCustomObject]@{
ActiveConnections = $connections.Count
ReceivedMB = [math]::Round($stats.ReceivedBytes / 1MB, 2)
SentMB = [math]::Round($stats.SentBytes / 1MB, 2)
PacketsDiscarded = $ipStats.PacketsDiscarded
}where:
$connections.Countis the total number of currently established TCP connections.[math]::Round(... / 1MB, 2)converts cumulative byte counters into readable megabyte values.
./network-health-check.ps1 -AdapterName "Ethernet"ActiveConnections ReceivedMB SentMB PacketsDiscarded
----------------- ---------- ------ ----------------
42 1510.32 431.02 12Investigating Suspicious External Connections
Security auditing workflows frequently require scanning actively connected outbound sockets, flagging connections established to non-private IP addresses, and correlating them with the running binary on the local machine.
$connections = Get-NetTCPConnection -State Established |
Where-Object {
$_.RemoteAddress -notmatch "^127\." -and
$_.RemoteAddress -notmatch "^10\." -and
$_.RemoteAddress -notmatch "^172\.(1[6-9]|2[0-9]|3[0-1])\." -and
$_.RemoteAddress -notmatch "^192\.168\." -and
$_.RemoteAddress -notmatch "^::1$" -and
$_.RemoteAddress -notmatch "^fe80:"
}
$auditReport = foreach ($conn in $connections) {
$proc = Get-Process -Id $conn.OwningProcess -ErrorAction SilentlyContinue
[PSCustomObject]@{
LocalPort = $conn.LocalPort
RemoteAddress = $conn.RemoteAddress
RemotePort = $conn.RemotePort
PID = $conn.OwningProcess
ProcessName = if ($proc) { $proc.ProcessName } else { "Unknown / Terminated" }
Executable = if ($proc) { $proc.Path } else { "N/A" }
}
}
$auditReport | Format-Table -AutoSizewhere:
Get-NetTCPConnection -State Establishedrestricts the scope strictly to active, streaming data sessions.-notmatchuses regular expression patterns to exclude loopback, RFC1918 private IPv4 networks, and IPv6 link-local subnets.$proc.Pathidentifies the exact on-disk binary executing the network connection, allowing verification against security policies.
./audit-external-connections.ps1LocalPort RemoteAddress RemotePort PID ProcessName Executable
--------- ------------- ---------- --- ----------- ----------
51234 140.82.112.4 443 6212 git C:\Program Files\Git\cmd\git.exe
51388 52.178.17.2 443 9820 pwsh C:\Program Files\PowerShell\7\pwsh.exe
51402 20.189.173.12 443 1104 msedge C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe