Skip to content

Instantly share code, notes, and snippets.

@SweetAsNZ
Last active January 28, 2026 21:06
Show Gist options
  • Select an option

  • Save SweetAsNZ/df2332e5f10996b23defdeaf75043905 to your computer and use it in GitHub Desktop.

Select an option

Save SweetAsNZ/df2332e5f10996b23defdeaf75043905 to your computer and use it in GitHub Desktop.
Retrieves the Windows Firewall rules based on Local Port, Name, Remote IP from the local store and group policy.
function Get-WindowsFirewallRules {
<#
.SYNOPSIS
Retrieves the current Windows Firewall rules based on Local Port, Name, Remote IP.
.DESCRIPTION
This function fetches and displays the current firewall rules configured on the Windows system.
.PARAMETER LocalPort
The local port number to filter the firewall rules.
.PARAMETER Name
The name of the firewall rule to filter.
.PARAMETER RemoteIP
The remote IP address to filter the firewall rules.
.PARAMETER PolicyStore
The policy store to query. Default is 'ActiveStore' which shows all active rules from all sources.
Options: ActiveStore (default), PersistentStore, StaticServiceStore, ConfigurableServiceStore, RSOP
.EXAMPLE
Get-WindowsFirewallRules
This command retrieves and displays all the current Windows Firewall rules from ActiveStore.
.EXAMPLE
Get-WindowsFirewallRules -LocalPort 25
This command retrieves and displays the Windows Firewall rules for local port 25.
.EXAMPLE
Get-WindowsFirewallRules -LocalPort 25 | Format-Table Name, DisplayName, Direction, Action, Enabled, LocalPort , RemoteIP -Wrap
.NOTES
Author: Tim West
Created: 23/01/2026
Updated: 29/01/2026
Status: Production
Version: 2.1.2
.CHANGELOG
2026-01-23: Fixed parameter handling and implemented filters for LocalPort, Name, and RemoteIP.
2026-01-23: Fixed LocalPort filtering to properly handle rules with multiple ports and array comparisons.
2026-01-23: Added -Wrap to Format-Table to prevent RemoteIP truncation and display key properties only.
2026-01-23: Fixed LocalPort filtering to handle comma-separated port strings and string-to-int comparison.
2026-01-29: Fixed LocalPort filtering to properly detect arrays vs strings and handle type comparisons correctly.
2026-01-29: Simplified LocalPort comparison by normalizing all ports to strings before comparison.
2026-01-29: Complete rewrite - filter using native NetFirewall cmdlets BEFORE formatting to avoid comparison issues with calculated properties.
2026-01-29: Added PolicyStore parameter (defaults to ActiveStore) to query all active firewall rules from all sources. Added UDP protocol support for port filtering.
2026-01-29: Removed automatic Format-Table to return proper objects that can be piped and filtered by user.
.TODO
- Test other stuff not just name and local port
#>
[CmdletBinding()]
param (
[Parameter()]
[int[]]$LocalPort,
[Parameter()]
[string[]]$Name,
[Parameter()]
[string[]]$RemoteIP,
[Parameter()]
[ValidateSet('ActiveStore', 'PersistentStore', 'StaticServiceStore', 'ConfigurableServiceStore', 'RSOP')]
[string]$PolicyStore = 'ActiveStore'
)
$MeasureCommand = Measure-Command {
# Start with all firewall rules from specified policy store
$firewallRules = Get-NetFirewallRule -PolicyStore $PolicyStore -ErrorAction SilentlyContinue
# Filter by LocalPort if specified - do this BEFORE Select-Object
if ($LocalPort) {
$matchingRules = @()
foreach ($port in $LocalPort) {
# Check both TCP and UDP protocols
foreach ($protocol in @('TCP', 'UDP')) {
$portFilters = Get-NetFirewallPortFilter -PolicyStore $PolicyStore -Protocol $protocol -ErrorAction SilentlyContinue | Where-Object {
$_.LocalPort -eq $port -or $_.LocalPort -eq $port.ToString()
}
foreach ($filter in $portFilters) {
$rules = Get-NetFirewallRule -PolicyStore $PolicyStore -AssociatedNetFirewallPortFilter $filter -ErrorAction SilentlyContinue
$matchingRules += $rules
}
}
}
$firewallRules = $matchingRules | Select-Object -Unique
}
# Filter by Name if specified
if ($Name) {
$firewallRules = $firewallRules | Where-Object {
$_.Name -in $Name -or $_.DisplayName -in $Name
}
}
# Filter by RemoteIP if specified
if ($RemoteIP) {
$matchingRules = @()
foreach ($rule in $firewallRules) {
$addressFilter = Get-NetFirewallAddressFilter -AssociatedNetFirewallRule $rule -ErrorAction SilentlyContinue
foreach ($ip in $RemoteIP) {
if ($addressFilter.RemoteAddress -contains $ip) {
$matchingRules += $rule
break
}
}
}
$firewallRules = $matchingRules
}
# Now format the output with all properties
$firewallRules = $firewallRules | Select-Object -Property Name, DisplayName, Direction, Action, Enabled, Profile, PolicyStoreSourceType, EdgeTraversalPolicy,
@{Name = 'LocalPort'; Expression = { (Get-NetFirewallPortFilter -AssociatedNetFirewallRule $_).LocalPort } },
@{Name = 'RemoteIP'; Expression = { (Get-NetFirewallAddressFilter -AssociatedNetFirewallRule $_).RemoteAddress } },
@{Name = 'GUID'; Expression = { $_.Name } }
}
Write-Host -ForegroundColor Green "`nScript Took: $($MeasureCommand.TotalSeconds) secs"
Write-Host -ForegroundColor Green "Total Rules Found: $($firewallRules.Count)`n"
return $firewallRules
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment