Skip to content

Instantly share code, notes, and snippets.

@SweetAsNZ
Last active May 23, 2025 02:42
Show Gist options
  • Save SweetAsNZ/edea6aeac79e194a95b94f94d67bf90b to your computer and use it in GitHub Desktop.
Save SweetAsNZ/edea6aeac79e194a95b94f94d67bf90b to your computer and use it in GitHub Desktop.
Parse Search Get Windows Firewall Logs for Drops or Allows by IP Within X Hours Before Now
<#
.Synopsis
Get Local Windows Firewall Drops or Allows
.DESCRIPTION
Long description
.EXAMPLE
Get-FirewallDropOrAllows -IP 1.1.1.1 -DropOrAllow Drop -MinsAgo 1
.EXAMPLE
#WIP
Get-FirewallDropOrAllows -IP 10.1.1.1 -DropOrAllow Drop -Protocol 'TCP' -HoursAgo 1 -ExportToCSV:$true
#>
Function Get-FirewallDropOrAllows {
[cmdletbinding()]
Param(
[string]$IP = '127.0.0.1'
,
[Parameter(Mandatory=$true)]
[ValidateSet("Drop", "Allow")]
[string]$DropOrAllow = 'Drop' # or 'Allow'
,
$Protocol = 'TCP' #WIP
,
# Change this to your desired lookback window. Zero is do not use, use mins
[int]$HoursAgo = 0
,
[int]$MinsAgo = 5
,
# How many of the last (latest) log lines to show
[int]$Last = 20
,
# Exclude Port or IP or Whatever
[string]$Exclude = '224.0.0.252'
,
$LogPath = 'C:\Windows\System32\LogFiles\Firewall\pfirewall.log'
,
[bool]$ExportToCSV = $false
)
# Load log
$GCFWLog = Get-Content $LogPath
# Extract field names from the header
$FieldLine = $GCFWLog | Where-Object { $_ -like '#Fields:*' } | Select-Object -Last 1
$Fields = $FieldLine -replace '^#Fields:\s+', '' -split '\s+'
# Filter out comments and blank lines
$DataLines = $GCFWLog | Where-Object { $_ -notmatch '^#' -and $_.Trim() -ne '' }
if($IP -eq '' -or $null -eq $IP){
$IPs = Get-NetIPAddress -AddressFamily IPv4 | Where-Object {
$_.IPAddress -notlike '169.254.*' -and $_.IPAddress -ne '127.0.0.1'
} | Select-Object -ExpandProperty IPAddress
If($Ips.count -eq 1){
$IP = $Ips
}
Else{
Write-Warning "No IP Specified and there are more than one locally, specify `$IP"
}
}
# Filter by VBR and Drop/Allow
if($Exclude -ne '' -and $null -ne $Exclude -and $Broadcast -ne "" -and $null -ne $Broadcast){
$FilteredLines = $DataLines | Where-Object { $_ -match $IP -and $_ -match $DropOrAllow -and $_ -notmatch $Exclude -and $_ -notmatch $Broadcast}
}
elseif($Exclude -eq '' -or $null -eq $Exclude -and $Broadcast -ne "" -or $null -ne $Broadcast){
$FilteredLines = $DataLines | Where-Object { $_ -match $IP -and $_ -match $DropOrAllow -and $_ -notmatch $Broadcast}
}
elseif($Exclude -ne '' -and $null -ne $Exclude -and $Broadcast -eq "" -or $null -eq $Broadcast){
$FilteredLines = $DataLines | Where-Object { $_ -match $IP -and $_ -match $DropOrAllow -and $_ -notmatch $Exclude}
}
elseif($Exclude -eq '' -or $null -eq $Exclude -and $Broadcast -eq "" -or $null -eq $Broadcast){
$FilteredLines = $DataLines | Where-Object { $_ -match $IP -and $_ -match $DropOrAllow}
}
# Parse and filter by time
if($HoursAgo -gt 0){
$CutoffTime = (Get-Date).AddHours(-$HoursAgo)
}
if($MinsAgo -gt 0){
$CutoffTime = (Get-Date).AddHours(-($MinsAgo/60))
}
$ParsedObjects = foreach ($line in $FilteredLines) {
$values = $line -split '\s+'
if ($values.Count -eq $Fields.Count) {
$tempObj = @{}
for ($i = 0; $i -lt $Fields.Count; $i++) {
$tempObj[$Fields[$i]] = $values[$i]
}
# Attempt to parse datetime
if ($tempObj.ContainsKey('date') -and $tempObj.ContainsKey('time')) {
$entryDateTime = [datetime]::ParseExact("$($tempObj.date) $($tempObj.time)", 'yyyy-MM-dd HH:mm:ss', $null)
if ($entryDateTime -ge $CutoffTime) {
[PSCustomObject]$tempObj
}
}
}
}
if($ExportToCSV){
$OutFile = "$($env:USERPROFILE)\firewall-log-$DropOrAllow-$($HoursAgo)-hours.csv"
$ParsedObjects | Export-Csv -Path $OutFile -NoTypeInformation
Write-Host "Exported to $OutFile"
if($Protocol -ne $null -and $Protocol -ne ""){
# Export to CSV
$ProtocolOnly| Export-Csv -NoTypeInformation "$($env:USERPROFILE)\Firewall-Log-$($Protocol).csv"
}
}
else{
$ProtocolOnly = $ParsedObjects | Where-Object { $_.protocol -eq $Protocol }
}
If($Testing){
#WIP
$ProtocolOnly = $ParsedObjects | Where-Object { $_.protocol -eq 'TCP' }
$ParsedObjects | Get-Member
$ParsedObjects | Select-Object -ExpandProperty protocol | Sort-Object | Get-Unique
}
if($Last -ne "" -and $null -ne $Last -and $Last -gt 0){
$ParsedObjects | ConvertTo-Csv -NoTypeInformation | Select -Last $Last
}
else{
$ParsedObjects | ConvertTo-Csv -NoTypeInformation
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment