Last active
January 28, 2026 21:06
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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