Skip to content

Instantly share code, notes, and snippets.

@nzbart
Last active May 12, 2020 15:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nzbart/7a1cb07c9554c212a8d7 to your computer and use it in GitHub Desktop.
Save nzbart/7a1cb07c9554c212a8d7 to your computer and use it in GitHub Desktop.
Run a network capture on Windows without installing Wireshark or any other tools on your servers.

Load the module and use Start-NetworkCapture, followed by Stop-NetworkCapture. Note that this would typically be run from a remote management machine, not by logging into the server that the trace will be run on.

# the capture files for each machine will be saved in a directory under the current directory
ipmo .\NetworkCapture.psm1

# using Windows auth - for computers on the same domain that you have admin privileges over
Start-NetworkCapture -ComputerNames <remoteserver1, remoteserver2>
Stop-NetworkCapture -ComputerNames <remoteserver1, remoteserver2>

# filter by IP address
Start-NetworkCapture -ComputerNames <remoteserver1, remoteserver2> -Ipv4AddressFilter a.b.c.d
Stop-NetworkCapture -ComputerNames <remoteserver1, remoteserver2>

# pass credentials
$c = Get-Credential
Start-NetworkCapture -ComputerNames <remoteserver1, remoteserver2> -Credential $c -Authentication Credssp -Ipv4AddressFilter a.b.c.d
Stop-NetworkCapture -ComputerNames <remoteserver1, remoteserver2> -Credential $c -Authentication Credssp

# if you prefer Wireshark over Microsoft Message Analyser, run this:
Convert-CaptureFilesToWiresharkFormat
#requires -version 3
$ErrorActionPreference = 'Stop'
$networkTraceFileName = 'NetworkTrace'
function LaunchSingleRemoteCommand([string][parameter(mandatory)]$ComputerName, [pscredential]$Credential, [System.Management.Automation.Runspaces.AuthenticationMechanism]$Authentication, [scriptblock][parameter(mandatory)]$ScriptBlock)
{
$args = @{
ComputerName = $ComputerName
ScriptBlock = $ScriptBlock
}
if($Credential) {
$args.Credential = $Credential
}
if($Authentication) {
$args.Authentication = $Authentication
}
Invoke-Command @args
}
function LaunchRemoteCommand([string[]][parameter(mandatory)]$ComputerNames, [pscredential]$Credential, [System.Management.Automation.Runspaces.AuthenticationMechanism]$Authentication, [scriptblock][parameter(mandatory)]$ScriptBlock)
{
$ComputerNames | % {
LaunchSingleRemoteCommand $_ $Credential $Authentication $ScriptBlock
}
}
function Start-NetworkCapture([string[]][parameter(mandatory)]$ComputerNames, [pscredential]$Credential, [System.Management.Automation.Runspaces.AuthenticationMechanism]$Authentication = [System.Management.Automation.Runspaces.AuthenticationMechanism]::Default, [ipaddress]$Ipv4AddressFilter)
{
LaunchRemoteCommand $ComputerNames $Credential $Authentication {
$tempLocation = Join-Path $env:TEMP $using:networkTraceFileName
if(Test-Path "$tempLocation.*") {
Write-Host "Removing previous capture file..."
rm "$tempLocation.*"
}
$args = 'trace', 'start', 'capture=yes', "traceFile=$tempLocation.etl"
if($using:Ipv4AddressFilter) {
$args += "ipv4.address=$using:Ipv4AddressFilter"
$args += "ethernet.type=ipv4"
}
netsh.exe $args
if(!$?) {
throw "Failed to start capture."
}
}
}
function Stop-NetworkCapture([string[]][parameter(mandatory)]$ComputerNames, [pscredential]$Credential, [System.Management.Automation.Runspaces.AuthenticationMechanism]$Authentication = [System.Management.Automation.Runspaces.AuthenticationMechanism]::Default)
{
LaunchRemoteCommand $ComputerNames $Credential $Authentication {
netsh.exe trace stop
if(!$?) {
throw "Failed to stop capture."
}
}
Write-Host "Copying trace files to the local machine..."
$ComputerNames | % {
$networkTraceFileBase = LaunchSingleRemoteCommand -ComputerName $_ -Credential $Credential -Authentication $Authentication -ScriptBlock { Join-Path $env:TEMP $using:networkTraceFileName}
$remotePathBase = $networkTraceFileBase -replace '^(?<drive>[a-zA-Z]):', "\\$_\`${drive}$"
if($remotePathBase -eq $networkTraceFileBase) {
throw "Failed to translate local path into remote UNC path: $networkTraceFileBase."
}
$remoteFolder = Split-Path $remotePathBase
$remoteFile = (Split-Path -Leaf $remotePathBase) + '.*'
$drive = New-PSDrive -Name NetworkCaptureDrive -PSProvider FileSystem -Root $remoteFolder -Credential $Credential
try {
$tempDirectory = "Working $([guid]::NewGuid())"
md $tempDirectory | Out-Null
cp "NetworkCaptureDrive:\$remoteFile" $tempDirectory
# Work around file locking bug in Get-WinEvent:
# https://github.com/PowerShell/PowerShell/issues/3979
$traceFilePath = Resolve-Path "$tempDirectory\NetworkTrace.etl" | select -expand Path
$job = Start-Job -command { $logs = Get-WinEvent -Oldest -Path $using:traceFilePath | select -first 1 -last 1; function FormatEventTime($Event) { ($Event | select -Expand TimeCreated).ToString('o') -replace ':', '-' }; "$(FormatEventTime ($logs | select -First 1)) - $(FormatEventTime ($logs | select -Last 1))" }
$dateRange = $job | Wait-Job | Receive-Job
$job | Remove-Job
$directoryName = "$dateRange on $_"
# Work around file locking bug in Get-WinEvent:
# https://github.com/PowerShell/PowerShell/issues/3979
$timer = [System.Diagnostics.Stopwatch]::StartNew()
$success = $false;
while($timer.ElapsedMilliseconds -lt 20000) {
try {
mv $tempDirectory $directoryName
$success = $true
}
catch {
# we'll try again
}
}
if(!$success) {
throw "Failed to rename directory $tempDirectory to $directoryName."
}
} finally {
Remove-PSDrive $drive
}
}
}
function Convert-CaptureFilesToWiresharkFormat
{
ls -r *.etl | % {
$sourceFile = $_.FullName
$destinationFile = [io.path]::ChangeExtension($sourceFile, 'cap')
if(!(Test-Path $destinationFile)) {
$session = New-PefTraceSession -Path $destinationFile -SaveOnStop
$session | Add-PefMessageProvider -Provider $sourceFile
$session | Start-PefTraceSession
}
}
}
Export-ModuleMember Start-NetworkCapture
Export-ModuleMember Stop-NetworkCapture
Export-ModuleMember Convert-CaptureFilesToWiresharkFormat
@diltonE
Copy link

diltonE commented May 2, 2019

To override the default file size append $args with

'maxSize=0', 'fileMode=single'

Reference: How to run a NETSH Trace

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment