How to Generate a Firewall Rules Report in Batch Script
The Windows Firewall is the first line of defense against network-based attacks. However, it can also be the source of mysterious connectivity issues if a rule is blocking a specific port or application. Manually scrolling through the "Windows Defender Firewall with Advanced Security" GUI is difficult and makes it easy to miss conflicting rules. A Batch script can export every active firewall rule into a single, searchable report for security auditing and troubleshooting.
This guide will explain how to audit firewall rules using netsh and PowerShell.
Method 1: Complete Firewall Audit Report
This method generates a comprehensive text report of all firewall rules with a header, profile status summary, and the full rule listing.
Implementation
@echo off
setlocal
:: Generate timestamp for filename
for /f "delims=" %%t in (
'powershell -NoProfile -Command "Get-Date -Format yyyyMMdd_HHmmss"'
) do set "Stamp=%%t"
set "ReportFile=%~dp0FirewallAudit_%COMPUTERNAME%_%Stamp%.txt"
:: Verify admin privileges
net session >nul 2>&1
if errorlevel 1 (
echo [ERROR] Firewall auditing requires administrator privileges. >&2
echo Right-click and select "Run as administrator." >&2
endlocal
exit /b 1
)
echo [INFO] Generating firewall audit report...
:: =============================================
:: Report Header
:: =============================================
(
echo ==================================================
echo WINDOWS FIREWALL AUDIT REPORT
echo ==================================================
) > "%ReportFile%"
for /f "delims=" %%d in ('powershell -NoProfile -Command "Get-Date -Format yyyy-MM-dd"') do set "_date=%%d"
for /f "delims=" %%t in ('powershell -NoProfile -Command "Get-Date -Format HH:mm:ss"') do set "_time=%%t"
echo Generated: %_date% %_time% >> "%ReportFile%"
echo Computer: %COMPUTERNAME% >> "%ReportFile%"
echo. >> "%ReportFile%"
:: =============================================
:: Firewall Profile Status
:: =============================================
echo --- Firewall Profile Status --- >> "%ReportFile%"
echo. >> "%ReportFile%"
netsh advfirewall show allprofiles state >> "%ReportFile%"
echo. >> "%ReportFile%"
:: =============================================
:: Inbound Rules
:: =============================================
echo [1/2] Collecting inbound rules...
echo --- INBOUND RULES --- >> "%ReportFile%"
echo. >> "%ReportFile%"
netsh advfirewall firewall show rule name=all dir=in >> "%ReportFile%"
echo. >> "%ReportFile%"
:: =============================================
:: Outbound Rules
:: =============================================
echo [2/2] Collecting outbound rules...
echo --- OUTBOUND RULES --- >> "%ReportFile%"
echo. >> "%ReportFile%"
netsh advfirewall firewall show rule name=all dir=out >> "%ReportFile%"
echo. >> "%ReportFile%"
echo ================================================== >> "%ReportFile%"
echo [OK] Firewall report saved to: %ReportFile%
endlocal
exit /b 0
What the profile status reveals:
The firewall has three profiles that activate based on the network connection type:
| Profile | When Active | Typical Setting |
|---|---|---|
| Domain | Connected to a domain network | Most permissive (managed by Group Policy) |
| Private | Home or trusted network | Moderate |
| Public | Coffee shop, airport, hotel | Most restrictive |
If any profile shows State: OFF, the firewall is completely disabled for that network type, a significant security concern that the report immediately surfaces.
Method 2: Port-Specific Rule Search
When troubleshooting why a specific application (web server, database, RDP) cannot accept connections, you need to find rules affecting a particular port.
@echo off
setlocal
set "Port=%~1"
if "%Port%"=="" (
echo Usage: %~nx0 ^<port_number^>
echo.
echo Examples:
echo %~nx0 80 Search for rules affecting port 80
echo %~nx0 3389 Search for RDP rules
echo %~nx0 1433 Search for SQL Server rules
endlocal
exit /b 1
)
net session >nul 2>&1
if errorlevel 1 (
echo [ERROR] Administrator privileges required. >&2
endlocal
exit /b 1
)
echo [INFO] Searching for firewall rules affecting port %Port%...
echo --------------------------------------------------
powershell -NoProfile -Command ^
"$portRules = Get-NetFirewallRule -Enabled True -ErrorAction SilentlyContinue |" ^
" Where-Object {" ^
" $portFilter = $_ | Get-NetFirewallPortFilter -ErrorAction SilentlyContinue;" ^
" $portFilter.LocalPort -contains '%Port%' -or $portFilter.RemotePort -contains '%Port%'" ^
" };" ^
"if (-not $portRules) {" ^
" Write-Host \"No enabled rules found specifically for port %Port%.\";" ^
" Write-Host '';" ^
" Write-Host 'If the port is blocked, it may be due to the default profile policy:';" ^
" Get-NetFirewallProfile | ForEach-Object {" ^
" Write-Host \" $($_.Name) profile: Default inbound action = $($_.DefaultInboundAction)\"" ^
" };" ^
" exit 0" ^
"};" ^
"Write-Host \"Found $($portRules.Count) rule(s) affecting port %Port%:`n\";" ^
"$portRules | ForEach-Object {" ^
" $pf = $_ | Get-NetFirewallPortFilter -ErrorAction SilentlyContinue;" ^
" [PSCustomObject]@{" ^
" Name = $_.DisplayName;" ^
" Direction = $_.Direction;" ^
" Action = $_.Action;" ^
" Protocol = $pf.Protocol;" ^
" LocalPort = $pf.LocalPort -join ',';" ^
" Profile = ($_.Profile -join ',');" ^
" Enabled = $_.Enabled" ^
" }" ^
"} | Format-Table -AutoSize -Wrap"
echo --------------------------------------------------
endlocal
exit /b 0
Sample output:
Found 2 rule(s) affecting port 3389:
Name Direction Action Protocol LocalPort Profile Enabled
---- --------- ------ -------- --------- ------- -------
Remote Desktop - User Mode (TCP) Inbound Allow TCP 3389 Domain True
Remote Desktop - User Mode (TCP) Inbound Allow TCP 3389 Private True
When no rules match:
If no rules specifically mention the port, traffic is governed by the profile's default action. The script displays the default inbound action for each profile, typically "Block" for Public and "Block" or "Allow" for Domain. This tells you whether the port is blocked by default policy rather than by a specific rule.
Method 3: Structured CSV Export for Security Audit
For compliance auditing, fleet-wide review, or importing into a security tool, export all firewall rules to a structured CSV with all relevant fields.
@echo off
setlocal
set "OutFile=%~dp0firewall_rules_%COMPUTERNAME%.csv"
net session >nul 2>&1
if errorlevel 1 (
echo [ERROR] Administrator privileges required. >&2
endlocal
exit /b 1
)
echo [INFO] Exporting firewall rules to CSV...
powershell -NoProfile -Command ^
"$rules = Get-NetFirewallRule -ErrorAction Stop;" ^
"$results = $rules | ForEach-Object {" ^
" $pf = $_ | Get-NetFirewallPortFilter -ErrorAction SilentlyContinue;" ^
" $af = $_ | Get-NetFirewallAddressFilter -ErrorAction SilentlyContinue;" ^
" $appf = $_ | Get-NetFirewallApplicationFilter -ErrorAction SilentlyContinue;" ^
" [PSCustomObject]@{" ^
" Name = $_.DisplayName;" ^
" Direction = [string]$_.Direction;" ^
" Action = [string]$_.Action;" ^
" Enabled = [string]$_.Enabled;" ^
" Profile = $_.Profile -join ',';" ^
" Protocol = $pf.Protocol;" ^
" LocalPort = ($pf.LocalPort -join ',');" ^
" RemotePort = ($pf.RemotePort -join ',');" ^
" LocalAddress = ($af.LocalAddress -join ',');" ^
" RemoteAddress = ($af.RemoteAddress -join ',');" ^
" Program = $appf.Program;" ^
" Description = $_.Description" ^
" }" ^
"};" ^
"$results | Export-Csv -Path '%OutFile%' -NoTypeInformation;" ^
"$enabled = ($results | Where-Object Enabled -eq 'True').Count;" ^
"$disabled = ($results | Where-Object Enabled -eq 'False').Count;" ^
"$allow = ($results | Where-Object { $_.Action -eq 'Allow' -and $_.Enabled -eq 'True' }).Count;" ^
"$block = ($results | Where-Object { $_.Action -eq 'Block' -and $_.Enabled -eq 'True' }).Count;" ^
"Write-Host ('Exported ' + $results.Count + ' rules to: %OutFile%');" ^
"Write-Host (' Enabled: ' + $enabled + ' Disabled: ' + $disabled);" ^
"Write-Host (' Active Allow: ' + $allow + ' Active Block: ' + $block)"
if errorlevel 1 (
echo [ERROR] Export failed. >&2
endlocal
exit /b 1
)
endlocal
exit /b 0
Sample summary output:
Exported 342 rules to: C:\Scripts\firewall_rules_WORKSTATION-07.csv
Enabled: 198 Disabled: 144
Active Allow: 172 Active Block: 26
What to look for in a security audit:
- Inbound Allow rules: Every inbound Allow rule is a potential entry point. Review each one to confirm it is intentional and necessary.
- Rules with
RemoteAddress = Any: These allow connections from any IP address. Consider restricting to specific subnets for sensitive services. - Rules with
Program = Any: These allow any application to use the port. Prefer application-specific rules. - Disabled rules: Not currently active, but could be re-enabled. Review for rules that were disabled as a temporary workaround and forgotten.
- Duplicate rules: Multiple rules with the same DisplayName may have been created by repeated software installations. Sort the CSV by Name to identify duplicates.
Method 4: Firewall Configuration Backup
Before making changes based on your audit, always back up the current firewall configuration. This allows you to restore the exact rule set if a change causes problems.
@echo off
setlocal
for /f "delims=" %%t in (
'powershell -NoProfile -Command "Get-Date -Format yyyyMMdd_HHmmss"'
) do set "Stamp=%%t"
set "BackupFile=%~dp0firewall_backup_%COMPUTERNAME%_%Stamp%.wfw"
net session >nul 2>&1
if errorlevel 1 (
echo [ERROR] Administrator privileges required. >&2
endlocal
exit /b 1
)
echo [INFO] Backing up firewall configuration...
netsh advfirewall export "%BackupFile%"
if errorlevel 1 (
echo [ERROR] Backup failed. >&2
endlocal
exit /b 1
)
echo [OK] Firewall backup saved to: %BackupFile%
echo.
echo To restore this configuration:
echo netsh advfirewall import "%BackupFile%"
endlocal
exit /b 0
Why backup before changes:
Firewall rules are complex and interdependent. Deleting a rule that appears unnecessary might break an application that relies on it. The .wfw file captures the complete firewall state (all profiles, all rules, all settings) and can be restored with a single command.
How to Avoid Common Errors
Wrong Way: Using netsh firewall (Without advfirewall)
:: DEPRECATED:does not show modern per-app and per-port rules
netsh firewall show config
The netsh firewall (without advfirewall) command is deprecated since Windows Vista. It does not display the advanced rule types used by modern Windows and returns incomplete information.
Correct Way: Always use netsh advfirewall firewall or PowerShell's Get-NetFirewallRule.
Wrong Way: Using findstr to Search for Ports
:: UNRELIABLE: "80" matches 80, 8080, 8081, 180, etc.
netsh advfirewall firewall show rule name=all | findstr /i "80"
Substring matching produces false positives. Searching for port 80 also matches 8080, 8081, 180, and the number 80 appearing in rule descriptions.
Correct Way: Use PowerShell's Get-NetFirewallPortFilter (Method 2), which matches exact port values.
Problem: Rules May Be Profile-Specific
A rule that allows RDP on the Domain profile but not on the Public profile will work at the office but fail at a coffee shop. If you only check whether the rule exists without checking its profile, you'll miss this distinction.
Solution: Always include the Profile column in your reports. Method 2 and Method 3 include profile information for every rule.
Problem: Default Policy vs. Explicit Rules
If no explicit rule matches a port, the default profile action applies. On most systems, the default inbound action is "Block." A port can be blocked without any explicit "Block" rule, simply by the absence of an "Allow" rule.
Solution: Method 2 shows the default inbound action for each profile when no matching rules are found, helping diagnose "missing rule" situations.
Best Practices and Rules
1. Audit Inbound Allow Rules First
In a security audit, every inbound Allow rule is a potential entry point for attackers. Review each one to confirm it is intentional, necessary, and scoped as narrowly as possible (specific port, specific program, specific remote address).
2. Check All Three Profiles
A rule may be enabled for Domain but not Public, or vice versa. A laptop that works at the office but fails at home often has a rule that only applies to the Domain profile.
3. Always Back Up Before Making Changes
Use Method 4 to create a .wfw backup before deleting or modifying rules. A single netsh advfirewall import command restores the complete configuration.
4. Look for Duplicate Rules
Software installers frequently add a new firewall rule on every installation or update, creating dozens of identical entries. Use Method 3's CSV export, sort by Name, and remove duplicates.
5. Export Regularly for Compliance
For environments subject to security compliance (PCI-DSS, HIPAA, SOX), export the firewall rules monthly and archive the CSV files. This provides evidence that the firewall configuration was reviewed and maintained.
Conclusions
Generating a firewall rules report provides the clarity needed to identify security gaps and resolve connectivity issues. By using netsh advfirewall for comprehensive text reports, PowerShell for structured querying and CSV export, and configuration backups for safety, you ensure that your firewall is doing exactly what it should, protecting your system while allowing legitimate traffic to flow. This professional, data-driven approach to firewall management is essential for security compliance and network troubleshooting.