Get-NetFirewallRule: Audit Windows Firewall Rules

Windows Firewall usually gets switched on and forgotten. Every installer that "asks permission" creates a rule, and years later the machine has hundreds of exceptions nobody has reviewed. Reading that in the graphical console is painful. In PowerShell, Get-NetFirewallRule turns the whole list into objects you can filter and export in seconds.
What Get-NetFirewallRule is
Get-NetFirewallRule is part of the NetSecurity module, already included in Windows 10, Windows 11 and Windows Server. It reads the rules of Windows Defender Firewall with Advanced Security and returns each one with properties such as DisplayName, Enabled, Direction, Action and Profile. The official documentation is on Microsoft Learn.
One detail that trips up many people: the rule itself does not show the port or the program. That data lives in separate "filters", queried with their own cmdlets. We'll use both.
Listing enabled inbound rules
Open PowerShell as administrator:
Get-NetFirewallRule -Direction Inbound -Enabled True -Action Allow |
Select-Object DisplayName, Profile |
Sort-Object DisplayNameThis lists only what matters for attack surface: rules that allow inbound connections and are active. Outbound and block rules can wait.
How do you see the port and program for each rule?
Combine the rule with its filters: Get-NetFirewallPortFilter shows protocol and port, and Get-NetFirewallApplicationFilter shows the executable. The filters accept the rule through the pipeline.
Get-NetFirewallRule -Direction Inbound -Enabled True -Action Allow | ForEach-Object {
$porta = $_ | Get-NetFirewallPortFilter
$app = $_ | Get-NetFirewallApplicationFilter
[pscustomobject]@{
Regra = $_.DisplayName
Protocolo = $porta.Protocol
PortaLocal = $porta.LocalPort
Programa = $app.Program
}
} | Format-Table -AutoSizeOn a home machine, the result usually includes File Sharing, Network Discovery and Remote Desktop rules, plus programs like browsers and games. Each line is a port that someone on the same network can try to reach.
Signs of a suspicious rule
Without guessing malware from names, these patterns deserve a closer look:
- Program in a user folder — an inbound rule pointing to
AppData,TemporDownloads - High port with no known owner — any local port you can't tie to installed software
- "Any" or "Public" profile — an inbound rule open on public networks (cafés, airports)
- Generic or empty name — rules called "Allow", "Rule1" and the like
To filter the first case:
Get-NetFirewallRule -Direction Inbound -Enabled True -Action Allow |
Where-Object { ($_ | Get-NetFirewallApplicationFilter).Program -like "*\Users\*" } |
Select-Object DisplayName, ProfileFound something odd? Before deleting, disable it and see if anything breaks. It's one command to undo:
Disable-NetFirewallRule -DisplayName "Rule name"Only use Remove-NetFirewallRule once you're sure. And in a corporate environment, check whether the rule came from a Group Policy (GPO), because it may come back on its own.
Checking profiles and the firewall log
The firewall has three profiles: Domain, Private and Public. Check that all are on and what the default inbound action is:
Get-NetFirewallProfile |
Select-Object Name, Enabled, DefaultInboundAction, DefaultOutboundActionOn a workstation you expect Enabled: True and DefaultInboundAction: Block on all three. If a profile shows as off, someone (or something) touched it — and it's worth cross-checking with what PowerShell log auditing recorded.
The blocked-connections log is off by default. To enable it:
Set-NetFirewallProfile -Profile Domain,Private,Public -LogBlocked True -LogMaxSizeKilobytes 16384The file lives by default at %systemroot%\system32\LogFiles\Firewall\pfirewall.log. With it, you can see who is knocking on closed ports — useful after you protect RDP against brute force.
Exporting a report to compare later
An audit with no record is useless the second time. Save a CSV today and compare next month:
$hoje = Get-Date -Format "yyyy-MM-dd"
Get-NetFirewallRule -Direction Inbound -Enabled True -Action Allow |
Select-Object DisplayName, Profile, Direction, Action |
Export-Csv "$env:USERPROFILE\Desktop\firewall-$hoje.csv" -NoTypeInformation -Encoding UTF8Next round, Compare-Object between the two CSVs shows exactly which rules appeared or disappeared.
A rule with no open port is worth nothing on its own
An inbound rule only matters if a program is listening on that port. So cross-check the firewall list against what is actually open, using Get-NetTCPConnection, and against the executables of Windows services. On Linux the same reasoning applies to UFW on Ubuntu.
The bigger lesson: a firewall is a policy, not a product. The most dangerous rule is the one you created "just to test" and never removed. Set aside ten minutes a month to run this report. To go deeper on ports, start with the post on open ports on Windows.




Comments