Firewall Analyzer Tool

<#
.SYNOPSIS
Firewall Analyzer Tool

.DESCRIPTION
This script analyzes Windows Firewall configurations, rules, and potential issues across servers in your network.

.NOTES
File Name      : FirewallAnalyzer.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later, appropriate admin permissions
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\FirewallAnalyzer.ps1
#>

# Global variables
$global:reportPath = "$env:USERPROFILE\Desktop\Firewall_Analysis_Report_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"

<#
.SYNOPSIS
Displays the main menu of the tool.
#>
function Show-Menu {
    Clear-Host
    Write-Host "=== Firewall Analyzer Tool ===" -ForegroundColor Cyan
    Write-Host "1. Analyze Firewall Profiles"
    Write-Host "2. Check Firewall Rules"
    Write-Host "3. Analyze Inbound Rules"
    Write-Host "4. Analyze Outbound Rules"
    Write-Host "5. Check for Potentially Risky Rules"
    Write-Host "6. Analyze Firewall Logging Settings"
    Write-Host "7. Check Firewall Service Status"
    Write-Host "8. Generate Comprehensive HTML Report"
    Write-Host "9. Exit"
}

<#
.SYNOPSIS
Gets a list of servers to analyze.

.OUTPUTS
Array of server names.
#>
function Get-TargetServers {
    $option = Read-Host "Analyze (A)ll domain servers, (S)pecific servers, or (F)ile input? (A/S/F)"
    switch ($option.ToUpper()) {
        "A" {
            return (Get-ADComputer -Filter {OperatingSystem -like "*Server*"} | Select-Object -ExpandProperty Name)
        }
        "S" {
            $servers = @()
            do {
                $server = Read-Host "Enter server name (or press Enter to finish)"
                if ($server -ne "") { $servers += $server }
            } while ($server -ne "")
            return $servers
        }
        "F" {
            $filePath = Read-Host "Enter the path to the file containing server names"
            return (Get-Content $filePath)
        }
        default {
            Write-Host "Invalid option. Defaulting to all domain servers." -ForegroundColor Yellow
            return (Get-ADComputer -Filter {OperatingSystem -like "*Server*"} | Select-Object -ExpandProperty Name)
        }
    }
}

<#
.SYNOPSIS
Analyzes firewall profiles on target servers.

.PARAMETER Servers
Array of server names to analyze.

.OUTPUTS
Array of PSObjects containing firewall profile details.
#>
function Analyze-FirewallProfiles {
    param([string[]]$Servers)

    Write-Host "`nAnalyzing Firewall Profiles..." -ForegroundColor Yellow
    $profileResults = @()
    foreach ($server in $Servers) {
        try {
            $profiles = Get-NetFirewallProfile -CimSession $server -ErrorAction Stop
            foreach ($profile in $profiles) {
                $profileResults += [PSCustomObject]@{
                    Server = $server
                    ProfileName = $profile.Name
                    Enabled = $profile.Enabled
                    DefaultInboundAction = $profile.DefaultInboundAction
                    DefaultOutboundAction = $profile.DefaultOutboundAction
                    AllowInboundRules = $profile.AllowInboundRules
                    AllowLocalFirewallRules = $profile.AllowLocalFirewallRules
                }
            }
        }
        catch {
            Write-Host "Error analyzing firewall profiles on $server : $_" -ForegroundColor Red
        }
    }
    $profileResults | Format-Table -AutoSize
    return $profileResults
}

<#
.SYNOPSIS
Checks firewall rules on target servers.

.PARAMETER Servers
Array of server names to analyze.

.OUTPUTS
Array of PSObjects containing firewall rule details.
#>
function Check-FirewallRules {
    param([string[]]$Servers)

    Write-Host "`nChecking Firewall Rules..." -ForegroundColor Yellow
    $ruleResults = @()
    foreach ($server in $Servers) {
        try {
            $rules = Get-NetFirewallRule -CimSession $server -ErrorAction Stop
            $ruleResults += [PSCustomObject]@{
                Server = $server
                TotalRules = $rules.Count
                EnabledRules = ($rules | Where-Object { $_.Enabled -eq $true }).Count
                DisabledRules = ($rules | Where-Object { $_.Enabled -eq $false }).Count
                InboundRules = ($rules | Where-Object { $_.Direction -eq "Inbound" }).Count
                OutboundRules = ($rules | Where-Object { $_.Direction -eq "Outbound" }).Count
            }
        }
        catch {
            Write-Host "Error checking firewall rules on $server : $_" -ForegroundColor Red
        }
    }
    $ruleResults | Format-Table -AutoSize
    return $ruleResults
}

<#
.SYNOPSIS
Analyzes inbound firewall rules on target servers.

.PARAMETER Servers
Array of server names to analyze.

.OUTPUTS
Array of PSObjects containing inbound rule details.
#>
function Analyze-InboundRules {
    param([string[]]$Servers)

    Write-Host "`nAnalyzing Inbound Rules..." -ForegroundColor Yellow
    $inboundResults = @()
    foreach ($server in $Servers) {
        try {
            $inboundRules = Get-NetFirewallRule -CimSession $server -Direction Inbound -Enabled True -ErrorAction Stop
            foreach ($rule in $inboundRules) {
                $ports = (Get-NetFirewallPortFilter -AssociatedNetFirewallRule $rule).LocalPort -join ", "
                $inboundResults += [PSCustomObject]@{
                    Server = $server
                    RuleName = $rule.DisplayName
                    Action = $rule.Action
                    Protocol = (Get-NetFirewallPortFilter -AssociatedNetFirewallRule $rule).Protocol
                    LocalPort = if ($ports) { $ports } else { "Any" }
                    RemoteAddress = (Get-NetFirewallAddressFilter -AssociatedNetFirewallRule $rule).RemoteAddress -join ", "
                }
            }
        }
        catch {
            Write-Host "Error analyzing inbound rules on $server : $_" -ForegroundColor Red
        }
    }
    $inboundResults | Format-Table -AutoSize
    return $inboundResults
}

<#
.SYNOPSIS
Analyzes outbound firewall rules on target servers.

.PARAMETER Servers
Array of server names to analyze.

.OUTPUTS
Array of PSObjects containing outbound rule details.
#>
function Analyze-OutboundRules {
    param([string[]]$Servers)

    Write-Host "`nAnalyzing Outbound Rules..." -ForegroundColor Yellow
    $outboundResults = @()
    foreach ($server in $Servers) {
        try {
            $outboundRules = Get-NetFirewallRule -CimSession $server -Direction Outbound -Enabled True -ErrorAction Stop
            foreach ($rule in $outboundRules) {
                $ports = (Get-NetFirewallPortFilter -AssociatedNetFirewallRule $rule).RemotePort -join ", "
                $outboundResults += [PSCustomObject]@{
                    Server = $server
                    RuleName = $rule.DisplayName
                    Action = $rule.Action
                    Protocol = (Get-NetFirewallPortFilter -AssociatedNetFirewallRule $rule).Protocol
                    RemotePort = if ($ports) { $ports } else { "Any" }
                    RemoteAddress = (Get-NetFirewallAddressFilter -AssociatedNetFirewallRule $rule).RemoteAddress -join ", "
                }
            }
        }
        catch {
            Write-Host "Error analyzing outbound rules on $server : $_" -ForegroundColor Red
        }
    }
    $outboundResults | Format-Table -AutoSize
    return $outboundResults
}

<#
.SYNOPSIS
Checks for potentially risky firewall rules on target servers.

.PARAMETER Servers
Array of server names to analyze.

.OUTPUTS
Array of PSObjects containing potentially risky rule details.
#>
function Check-PotentiallyRiskyRules {
    param([string[]]$Servers)

    Write-Host "`nChecking for Potentially Risky Rules..." -ForegroundColor Yellow
    $riskyResults = @()
    foreach ($server in $Servers) {
        try {
            $rules = Get-NetFirewallRule -CimSession $server -Enabled True -ErrorAction Stop
            foreach ($rule in $rules) {
                $isRisky = $false
                $riskReason = @()

                if ($rule.Action -eq "Allow" -and $rule.Direction -eq "Inbound") {
                    $remoteAddress = (Get-NetFirewallAddressFilter -AssociatedNetFirewallRule $rule).RemoteAddress
                    if ($remoteAddress -contains "Any") {
                        $isRisky = $true
                        $riskReason += "Allows inbound from any address"
                    }

                    $localPort = (Get-NetFirewallPortFilter -AssociatedNetFirewallRule $rule).LocalPort
                    if ($localPort -contains "Any") {
                        $isRisky = $true
                        $riskReason += "Allows inbound on any port"
                    }
                }

                if ($isRisky) {
                    $riskyResults += [PSCustomObject]@{
                        Server = $server
                        RuleName = $rule.DisplayName
                        Direction = $rule.Direction
                        Action = $rule.Action
                        RiskReason = $riskReason -join ", "
                    }
                }
            }
        }
        catch {
            Write-Host "Error checking for risky rules on $server : $_" -ForegroundColor Red
        }
    }
    $riskyResults | Format-Table -AutoSize
    return $riskyResults
}

<#
.SYNOPSIS
Analyzes firewall logging settings on target servers.

.PARAMETER Servers
Array of server names to analyze.

.OUTPUTS
Array of PSObjects containing firewall logging setting details.
#>
function Analyze-FirewallLoggingSettings {
    param([string[]]$Servers)

    Write-Host "`nAnalyzing Firewall Logging Settings..." -ForegroundColor Yellow
    $loggingResults = @()
    foreach ($server in $Servers) {
        try {
            $profiles = Get-NetFirewallProfile -CimSession $server -ErrorAction Stop
            foreach ($profile in $profiles) {
                $loggingResults += [PSCustomObject]@{
                    Server = $server
                    ProfileName = $profile.Name
                    LogAllowed = $profile.LogAllowed
                    LogBlocked = $profile.LogBlocked
                    LogIgnored = $profile.LogIgnored
                    LogFileName = $profile.LogFileName
                    LogMaxSizeKilobytes = $profile.LogMaxSizeKilobytes
                }
            }
        }
        catch {
            Write-Host "Error analyzing firewall logging settings on $server : $_" -ForegroundColor Red
        }
    }
    $loggingResults | Format-Table -AutoSize
    return $loggingResults
}

<#
.SYNOPSIS
Checks firewall service status on target servers.

.PARAMETER Servers
Array of server names to analyze.

.OUTPUTS
Array of PSObjects containing firewall service status details.
#>
function Check-FirewallServiceStatus {
    param([string[]]$Servers)

    Write-Host "`nChecking Firewall Service Status..." -ForegroundColor Yellow
    $serviceResults = @()
    foreach ($server in $Servers) {
        try {
            $service = Get-Service -ComputerName $server -Name MpsSvc -ErrorAction Stop
            $serviceResults += [PSCustomObject]@{
                Server = $server
                Status = $service.Status
                StartType = $service.StartType
            }
        }
        catch {
            Write-Host "Error checking firewall service status on $server : $_" -ForegroundColor Red
        }
    }
    $serviceResults | Format-Table -AutoSize
    return $serviceResults
}

<#
.SYNOPSIS
Generates a comprehensive HTML report of all analyses.

.PARAMETER AllResults
Hashtable containing all analysis results.

.OUTPUTS
Saves an HTML report to the desktop.
#>
function Generate-HTMLReport {
    param([hashtable]$AllResults)

    Write-Host "`nGenerating Comprehensive HTML Report..." -ForegroundColor Yellow
    $reportContent = @"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Firewall Analysis Report</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 1200px; margin: 0 auto; padding: 20px; }
        h1, h2, h3 { color: #0078D4; }
        table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
    </style>
</head>
<body>
    <h1>Firewall Analysis Report</h1>
    <p>Generated on: $(Get-Date)</p>

    <h2>Firewall Profiles</h2>
    $($AllResults.FirewallProfiles | ConvertTo-Html -Fragment)

    <h2>Firewall Rules Summary</h2>
    $($AllResults.FirewallRules | ConvertTo-Html -Fragment)

    <h2>Inbound Rules</h2>
    $($AllResults.InboundRules | ConvertTo-Html -Fragment)

    <h2>Outbound Rules</h2>
    $($AllResults.OutboundRules | ConvertTo-Html -Fragment)

    <h2>Potentially Risky Rules</h2>
    $($AllResults.RiskyRules | ConvertTo-Html -Fragment)

    <h2>Firewall Logging Settings</h2>
    $($AllResults.LoggingSettings | ConvertTo-Html -Fragment)

    <h2>Firewall Service Status</h2>
    $($AllResults.ServiceStatus | ConvertTo-Html -Fragment)
</body>
</html>
"@

    $reportContent | Out-File -FilePath $global:reportPath
    Write-Host "Report generated and saved to: $global:reportPath" -ForegroundColor Green
}

# Main program loop
$targetServers = Get-TargetServers
$allResults = @{}

do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-9)"

    switch ($choice) {
        "1" { $allResults.FirewallProfiles = Analyze-FirewallProfiles -Servers $targetServers }
        "2" { $allResults.FirewallRules = Check-FirewallRules -Servers $targetServers }
        "3" { $allResults.InboundRules = Analyze-InboundRules -Servers $targetServers }
        "4" { $allResults.OutboundRules = Analyze-OutboundRules -Servers $targetServers }
        "5" { $allResults.RiskyRules = Check-PotentiallyRiskyRules -Servers $targetServers }
        "6" { $allResults.LoggingSettings = Analyze-FirewallLoggingSettings -Servers $targetServers }
        "7" { $allResults.ServiceStatus = Check-FirewallServiceStatus -Servers $targetServers }
        "8" { Generate-HTMLReport -AllResults $allResults }
        "9" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "9") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "9")

This Firewall Analyzer Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to analyze various aspects of Windows Firewall:
    • Firewall Profile analysis
    • Firewall Rules summary
    • Inbound Rules analysis
    • Outbound Rules analysis
    • Potentially Risky Rules check
    • Firewall Logging Settings analysis
    • Firewall Service Status check
  3. Flexible server selection (all domain servers, specific servers, or from a file).
  4. Comprehensive error handling for each analysis function.
  5. A function to generate an HTML report of all collected data.

Key features:

  • Detailed analysis of firewall profiles across multiple servers
  • Comprehensive overview of firewall rules, including inbound and outbound rules
  • Identification of potentially risky firewall rules
  • Analysis of firewall logging settings
  • Verification of firewall service status
  • HTML report generation for easy sharing and viewing of results

This tool is particularly useful for:

  • Network administrators managing Windows servers
  • Security professionals auditing firewall configurations
  • IT professionals performing security assessments
  • System administrators troubleshooting network connectivity issues

To use this script effectively:

  1. Run PowerShell as an administrator
  2. Ensure you have the necessary permissions to query the target servers
  3. Have the required PowerShell modules available (like ActiveDirectory if querying domain servers)

This script provides a comprehensive overview of Windows Firewall configurations and potential security issues across multiple servers in your network. It can significantly streamline the process of auditing and maintaining firewall configurations, enhancing the overall security posture of your Windows server environment.

0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *