使用 PowerShellWindows Defender (以及 Windows 防火墙)结合来实现与 Fail2Ban 类似的功能是可行的,但需要更多的自定义配置和脚本编写。虽然 Fail2Ban 是专门为 Linux 系统设计的,它能通过日志文件分析和防火墙规则自动化来阻止恶意 IP 地址。Windows 系统中,您可以通过 PowerShell 脚本和 Windows Defender 防火墙来模拟类似的功能。

目标功能的实现

  1. 监控日志文件
    • PowerShell  可以用来监控事件日志文件和特定的日志文件,例如登录失败、SSH 失败、Windows 登录失败等。对于 Windows 系统,最常见的登录失败日志存储在 Windows 事件查看器中,路径一般为  Windows Logs > Security
  2. 触发规则
    • 可以设定规则,监控指定的事件,例如登录失败次数。如果检测到特定的事件(如多次登录失败),可以触发 PowerShell 脚本执行防火墙操作。
  3. 禁止恶意 IP
    • 通过 PowerShell 和 Windows 防火墙,可以将检测到的恶意 IP 地址添加到防火墙黑名单,类似于 Fail2Ban 的功能。
  4. 自动解封
    • 通过设置时间限制,可以创建一个定时任务,定期检查并删除黑名单中已过期的 IP 地址,从而实现自动解封。

详细步骤

1. 监控日志文件

Windows 系统中的登录失败事件通常可以通过事件 ID 4625 (代表登录失败)进行监控。PowerShell 可以定期检查这些事件。

# 获取登录失败的事件(4625为登录失败事件ID)
Get-WinEvent -LogName Security | Where-Object {$_.Id -eq 4625} | Select-Object TimeCreated, Message

您可以定期运行此脚本,或者设置一个 定时任务 来触发该脚本。

2. 触发规则

在 PowerShell 脚本中,您可以设定触发规则(例如,失败登录尝试超过一定次数)。假设我们设置一个阈值,超过 3 次失败尝试时,就认为是恶意行为。

$FailedLoginThreshold = 3
$TimeWindow = (Get-Date).AddMinutes(-5) # 设置 5 分钟内失败次数
$FailedLogins = Get-WinEvent -LogName Security | Where-Object {$_.Id -eq 4625 -and $_.TimeCreated -gt $TimeWindow}

if ($FailedLogins.Count -ge $FailedLoginThreshold) {
    # 如果失败次数超过阈值,则执行封禁动作
    $IPAddress = "攻击者的IP" # 从日志中提取攻击者IP地址
    # 添加到防火墙黑名单
    New-NetFirewallRule -DisplayName "Block $IPAddress" -Direction Inbound -Action Block -RemoteAddress $IPAddress
}

3. 禁止恶意 IP

通过 PowerShell 和 New-NetFirewallRule 命令,您可以将攻击者的 IP 地址添加到 Windows 防火墙的黑名单中。

New-NetFirewallRule -DisplayName "Block $IPAddress" -Direction Inbound -Action Block -RemoteAddress $IPAddress

4. 自动解封

为了自动解封,您可以通过定时任务来定期检查并删除超过特定时间限制的封禁规则。例如,假设我们封禁 10 分钟,并且想要定期检查并解封过期的 IP。

$blockList = Get-NetFirewallRule | Where-Object {$_.DisplayName -like "Block*"}
$now = Get-Date
foreach ($rule in $blockList) {
    $blockTime = $rule.CreationTime # 假设创建时间是规则添加时间
    if (($now - $blockTime).TotalMinutes -gt 10) {
        Remove-NetFirewallRule -Name $rule.Name
    }
}

5. 设置定时任务

为了让 PowerShell 脚本定期执行,您可以设置一个 Windows 任务计划,定时运行这些脚本:

$Action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "C:\Path\To\YourScript.ps1"
$Trigger = New-ScheduledTaskTrigger -Daily -At "12:00AM"
Register-ScheduledTask -Action $Action -Trigger $Trigger -TaskName "MonitorLoginFailures" -Description "Monitor login failures and block IPs"
  • 监控日志文件 :PowerShell 可以通过事件日志监控登录失败事件(如事件 ID 4625)并提取相关信息。
  • 触发规则 :可以设定阈值,例如 3 次失败登录,超过阈值就执行封禁操作。
  • 禁止恶意 IP :使用  New-NetFirewallRule 将恶意 IP 地址添加到 Windows 防火墙黑名单中。
  • 自动解封 :可以创建定时任务定期检查和删除封禁超过指定时间的 IP 地址。

虽然这个方案没有 Fail2Ban 那么简洁和自动化,但 PowerShell + Windows 防火墙确实可以实现类似的安全防护功能,尤其适用于需要在 Windows 环境下进行定制化控制的场景。


进一步改进和优化这个基于 PowerShell 和 Windows Defender 防火墙的解决方案,使其更高效、可靠,并具备更强的自动化功能,您可以考虑以下几点:

优化建议

1. 提高性能:减少事件日志查询频率

频繁地查询事件日志会消耗一定的系统资源,尤其是在高流量环境下。为了减少资源消耗,您可以优化查询频率,并且仅针对关键的登录失败事件进行分析。

  • 使用事件日志过滤器 :利用 Get-WinEvent 时,您可以指定时间范围和过滤条件,从而减少每次查询的数据量。
  • 缓存失败尝试记录 :记录 IP 地址和失败尝试次数,并在内存中进行跟踪,而不是每次都读取所有日志文件。

示例:使用 PowerShell 高效过滤事件

$FailedLoginThreshold = 3
$TimeWindow = (Get-Date).AddMinutes(-5) # 设置 5 分钟内失败次数
$FailedLogins = Get-WinEvent -LogName Security -FilterXPath "*[EventData[@Name='TargetUserName'] and (EventData='失败的用户名')]" | Where-Object {$_.Id -eq 4625 -and $_.TimeCreated -gt $TimeWindow}

2. 封禁规则的自动化管理

可以进一步增强防火墙规则的管理能力,使其能够灵活地添加、移除或临时禁用封禁的 IP 地址。

  • 封禁时间控制 :为每个封禁的 IP 设置具体的封禁时长,封禁超时后自动解除。通过 PowerShell 可以在封禁规则中嵌入有效期。
  • 封禁时长和策略 :增加封禁策略,例如首次封禁 5 分钟,第二次封禁 30 分钟,第三次封禁 1 小时,等等。

优化封禁规则管理:

$IPAddress = "攻击者的IP"
$ExistingRule = Get-NetFirewallRule | Where-Object {$_.DisplayName -eq "Block $IPAddress"}

if ($ExistingRule) {
    # 如果 IP 已经被封禁,则更新封禁时间
    Set-NetFirewallRule -Name $ExistingRule.Name -Enabled True
} else {
    # 新建封禁规则,并设置有效期为 30 分钟
    New-NetFirewallRule -DisplayName "Block $IPAddress" -Direction Inbound -Action Block -RemoteAddress $IPAddress
    Start-Sleep -Seconds 1800 # 30分钟后解封
    Remove-NetFirewallRule -DisplayName "Block $IPAddress"
}

3. 更智能的 IP 黑名单管理

为了防止误封,可以增加一些智能规则,避免同一个 IP 地址在短时间内反复封禁。

  • 白名单机制 :允许指定某些可信 IP 地址或网段(如公司内部网络)绕过封禁规则。
  • 自动解除封禁 :针对误封的 IP,可以增加用户反馈机制,定期检查封禁列表,并允许手动或自动解除封禁。

示例:白名单机制

$WhiteList = @("192.168.1.1", "10.0.0.1")
$IPAddress = "攻击者的IP"

if ($WhiteList -contains $IPAddress) {
    Write-Host "$IPAddress 是白名单IP,不封禁"
} else {
    # 进行封禁操作
    New-NetFirewallRule -DisplayName "Block $IPAddress" -Direction Inbound -Action Block -RemoteAddress $IPAddress
}

4. 增加邮件或通知功能

为了方便管理员实时了解封禁信息,可以添加邮件或其他通知功能,告警某个 IP 被封禁。您可以使用 PowerShell 配置邮件通知,当某个 IP 被封禁时,自动发送一封警报邮件。

$smtpServer = "smtp.yourdomain.com"
$smtpFrom = "admin@yourdomain.com"
$smtpTo = "you@yourdomain.com"
$messageSubject = "IP Blocked"
$messageBody = "The IP address $IPAddress has been blocked due to repeated login failures."
$mailmessage = New-Object system.net.mail.mailmessage
$mailmessage.from = ($smtpFrom)
$mailmessage.To.add($smtpTo)
$mailmessage.Subject = $messageSubject
$mailmessage.Body = $messageBody

$smtp = New-Object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($mailmessage)

5. 日志文件优化与分析

  • 日志存储与分析 :为避免日志文件变得庞大且难以管理,可以将日志文件保存到指定目录,并定期进行分析。可以创建一个独立的日志文件,用于记录被封禁的 IP 地址、封禁时间、解封时间等信息。
  • 日志清理 :定期清理过期的封禁日志,并对日志文件大小进行管理。
# 将封禁日志写入文件
$logFilePath = "C:\Logs\blocked_ips.log"
$logEntry = "$IPAddress was blocked at $($Get-Date)"
Add-Content -Path $logFilePath -Value $logEntry

# 清理超过 30 天的封禁日志
$logFiles = Get-ChildItem -Path "C:\Logs" -Filter "*.log"
foreach ($log in $logFiles) {
    if (($Get-Date) - $log.CreationTime).Days -gt 30) {
        Remove-Item $log.FullName
    }
}

6. 提高代码的健壮性与错误处理

为了避免因为单个脚本错误导致整个封禁机制崩溃,可以加强 PowerShell 脚本的错误处理和异常捕获。

try {
    # 封禁 IP
    New-NetFirewallRule -DisplayName "Block $IPAddress" -Direction Inbound -Action Block -RemoteAddress $IPAddress
} catch {
    Write-Error "封禁 IP 地址 $IPAddress 失败: $_"
    # 发送邮件或其他通知
}

综合优化示例

结合上述优化建议,下面是一个集成优化的完整 PowerShell 脚本示例:

$FailedLoginThreshold = 3
$TimeWindow = (Get-Date).AddMinutes(-5)
$WhiteList = @("192.168.1.1", "10.0.0.1")
$logFilePath = "C:\Logs\blocked_ips.log"

# 获取登录失败事件
$FailedLogins = Get-WinEvent -LogName Security -FilterXPath "*[EventData[@Name='TargetUserName'] and (EventData='失败的用户名')]" | Where-Object {$_.Id -eq 4625 -and $_.TimeCreated -gt $TimeWindow}

foreach ($event in $FailedLogins) {
    $IPAddress = "攻击者的IP"  # 从事件中提取 IP 地址
    
    if ($WhiteList -contains $IPAddress) {
        Write-Host "$IPAddress 是白名单IP,不封禁"
    } else {
        $ExistingRule = Get-NetFirewallRule | Where-Object {$_.DisplayName -eq "Block $IPAddress"}

        if ($ExistingRule) {
            Write-Host "$IPAddress 已经被封禁,更新封禁时间"
            Set-NetFirewallRule -Name $ExistingRule.Name -Enabled True
        } else {
            Write-Host "封禁 IP 地址:$IPAddress"
            New-NetFirewallRule -DisplayName "Block $IPAddress" -Direction Inbound -Action Block -RemoteAddress $IPAddress
            # 记录封禁日志
            $logEntry = "$IPAddress was blocked at $($Get-Date)"
            Add-Content -Path $logFilePath -Value $logEntry
            Start-Sleep -Seconds 1800 # 30分钟后解封
            Remove-NetFirewallRule -DisplayName "Block $IPAddress"
        }
    }
}

# 清理过期日志
$logFiles = Get-ChildItem -Path "C:\Logs" -Filter "*.log"
foreach ($log in $logFiles) {
    if (($Get-Date) - $log.CreationTime).Days -gt 30) {
        Remove-Item $log.FullName
    }
}

通过以上优化,您可以实现:

  1. 提高性能 :减少对事件日志的查询频率,避免不必要的资源消耗。
  2. 智能封禁管理 :自动更新封禁时间,避免误封,添加白名单。
  3. 邮件和通知功能 :实时通知管理员封禁事件。
  4. 日志管理和清理 :定期清理过期的封禁日志文件。
  5. 错误处理 :增加异常处理和日志记录,增强脚本的鲁棒性。

通过这些改进,您的防护系统将变得更加智能、高效且易于维护,类似于 Linux 中的 Fail2Ban,但适用于 Windows 环境。


进一步优化和改进您的 Windows Defender 防火墙管理脚本,我们可以从以下几个方面入手:增强脚本的灵活性、提高性能、增加更多的自定义功能、以及确保安全性和可维护性。以下是进一步优化的具体建议:

1. 增强日志管理与分析

优化日志存储和分析功能,确保日志系统在高负载时能够稳定工作,并且对重要事件进行详细记录。

(1) 异步日志记录

避免日志记录阻塞主线程,可以考虑将日志记录操作异步化。使用后台任务将日志写入文件,而主线程继续处理事件分析。

示例代码:

# 异步日志写入函数
function Write-LogAsync {
    param (
        [string]$message
    )

    Start-Job -ScriptBlock {
        param($msg)
        $logFilePath = "C:\Logs\blocked_ips.log"
        Add-Content -Path $logFilePath -Value "$msg \`t $(Get-Date)"
    } -ArgumentList $message
}

# 使用异步写入日志
Write-LogAsync "IP $IPAddress was blocked due to multiple failed logins."

(2) 日志结构化与可搜索性

使用结构化日志格式(如 JSON 或 CSV)而不是纯文本日志,可以方便后期的自动化分析和查询。

示例代码:

# 结构化日志写入(JSON 格式)
$logEntry = @{
    Timestamp = (Get-Date)
    IPAddress = $IPAddress
    Action = "Blocked"
    Reason = "Multiple failed login attempts"
}
$logFilePath = "C:\Logs\blocked_ips.json"
$logEntry | ConvertTo-Json | Out-File -Append -FilePath $logFilePath

(3) 日志轮换与归档

为了避免日志文件过大,您可以实现日志轮换功能。可以按日期创建新的日志文件,且定期归档旧日志文件。

$logFilePath = "C:\Logs\blocked_ips.log"
$logFileName = "blocked_ips_$(Get-Date -Format 'yyyy-MM-dd').log"

# 将日志文件移至归档目录
if (Test-Path $logFilePath) {
    Move-Item -Path $logFilePath -Destination "C:\Logs\Archive\$logFileName"
}

# 创建新日志文件
New-Item -Path $logFilePath -ItemType File

2. 动态封禁策略:基于尝试次数和时间窗口

根据用户的失败尝试次数、时间窗口和封禁持续时间灵活调整封禁策略,避免对相同 IP 地址的反复封禁,同时提高防护能力。

(1) 封禁时间动态调整

根据攻击者的行为模式,调整封禁时间。例如,首次封禁 10 分钟,第二次封禁 30 分钟,第三次封禁 1 小时,依此类推。

$failedAttempts = 5  # 用户失败的尝试次数
$banTime = 10 # 初始封禁时间(分钟)

if ($failedAttempts -gt 3) {
    $banTime = 30
} elseif ($failedAttempts -gt 5) {
    $banTime = 60
}

# 封禁 IP 地址
New-NetFirewallRule -DisplayName "Block $IPAddress" -Direction Inbound -Action Block -RemoteAddress $IPAddress
Start-Sleep -Seconds ($banTime * 60)
Remove-NetFirewallRule -DisplayName "Block $IPAddress"

(2) 防止封禁“死锁”问题

如果封禁的 IP 地址在封禁时间内重复登录失败,避免对同一 IP 地址的不断封禁。

$maxRetryLimit = 5
$blockedIps = @{}  # 存储封禁的 IP 地址和封禁时间

# 检查是否已封禁该 IP 地址
if ($blockedIps.ContainsKey($IPAddress)) {
    $lastBanTime = $blockedIps[$IPAddress]
    if ((Get-Date) - $lastBanTime).TotalMinutes -lt 30) {
        Write-Host "IP $IPAddress is still within the ban period."
    } else {
        Write-Host "Removing ban on IP $IPAddress."
        Remove-NetFirewallRule -DisplayName "Block $IPAddress"
        $blockedIps.Remove($IPAddress)
    }
} else {
    # 新封禁
    Write-Host "Blocking IP address: $IPAddress"
    New-NetFirewallRule -DisplayName "Block $IPAddress" -Direction Inbound -Action Block -RemoteAddress $IPAddress
    $blockedIps[$IPAddress] = Get-Date
}

3. 提升性能和效率

减少重复的操作,避免每次都进行不必要的网络查询和日志写入。

(1) 使用批量处理封禁操作

如果有多个 IP 地址需要封禁,尽量批量处理,而不是一一处理。批量操作可以显著提高性能,尤其是在高并发情况下。

$blockedIpsBatch = @("192.168.1.100", "192.168.1.101", "192.168.1.102")

foreach ($IPAddress in $blockedIpsBatch) {
    New-NetFirewallRule -DisplayName "Block $IPAddress" -Direction Inbound -Action Block -RemoteAddress $IPAddress
}

# 过一段时间后解封
Start-Sleep -Seconds 3600 # 等待1小时
foreach ($IPAddress in $blockedIpsBatch) {
    Remove-NetFirewallRule -DisplayName "Block $IPAddress"
}

(2) 使用缓存来减少重复查询

避免每次都查询日志文件或重新计算封禁次数。可以将尝试失败的 IP 地址存储在内存中,通过缓存机制减少不必要的计算。

$loginFailures = @{}  # 存储 IP 地址和其失败的次数

# 获取失败登录事件
$FailedLogins = Get-WinEvent -LogName Security -FilterXPath "*[EventData[@Name='TargetUserName'] and (EventData='失败的用户名')]" | Where-Object {$_.Id -eq 4625}

foreach ($event in $FailedLogins) {
    $IPAddress = "攻击者的IP"
    
    # 如果该 IP 已经在缓存中,增加失败次数
    if ($loginFailures.ContainsKey($IPAddress)) {
        $loginFailures[$IPAddress]++
    } else {
        $loginFailures[$IPAddress] = 1
    }
    
    # 如果失败次数达到阈值,封禁该 IP 地址
    if ($loginFailures[$IPAddress] -ge $FailedLoginThreshold) {
        New-NetFirewallRule -DisplayName "Block $IPAddress" -Direction Inbound -Action Block -RemoteAddress $IPAddress
    }
}

4. 增强灵活性和扩展性

(1) 支持多种封禁类型

除了封禁 IP 地址外,还可以支持封禁特定的端口、协议,或者封禁指定的用户名和主机名。

$BlockedUser = "attackeruser"
$BlockedPort = 3389  # 例如 RDP 端口

New-NetFirewallRule -DisplayName "Block $BlockedUser" -Direction Inbound -Action Block -RemoteUserName $BlockedUser
New-NetFirewallRule -DisplayName "Block Port $BlockedPort" -Direction Inbound -Action Block -LocalPort $BlockedPort

(2) 自动化通知

当某个 IP 地址被封禁时,除了写入日志,还可以通过 API 或者 Webhook 通知系统管理员。

# 发送 Webhook 通知
function Send-WebhookNotification {
    param (
        [string]$webhookUrl,
        [string]$message
    )

    $body = @{ message = $message } | ConvertTo-Json
    Invoke-RestMethod -Uri $webhookUrl -Method Post -Body $body -ContentType "application/json"
}

# 发送通知
Send-WebhookNotification -webhookUrl "https://your-webhook-url.com" -message "IP $IPAddress has been blocked due to multiple failed login attempts."

5. 自动更新与自我修复功能

为了确保脚本在运行过程中不会因某些外部因素(如防火墙规则被误删或配置被修改)而停止工作,可以添加自我修复功能。例如,检查和恢复被删除的防火墙规则。

# 检查防火墙规则是否存在
$ruleName = "Block $IPAddress"
$existingRule = Get-NetFirewallRule | Where-Object {$_.DisplayName -eq $ruleName}

if (-not $existingRule) {
    Write-Host "防火墙规则 $ruleName 不存在,正在恢复..."
    New-NetFirewallRule -DisplayName $ruleName -Direction Inbound -Action Block -RemoteAddress $IPAddress
}

总结

通过上述进一步优化,可以使您的 Windows Defender 防火墙管理脚本更加高效、灵活、可维护,并且具备更强的扩展性。

进一步优化和改进Windows Defender防火墙管理脚本,我们可以从以下几个方面进行加强:提高性能、增强灵活性和可维护性、增加高级功能、增强安全性以及提升监控能力。以下是具体的建议和代码实现:

1. 高效的日志管理

日志记录是防火墙管理的重要组成部分,它帮助系统管理员追踪防火墙规则、封禁历史以及安全事件。为了进一步提升性能和可维护性,可以对日志管理进行优化。

(1) 使用异步和批量日志记录

日志的写入操作应该尽量避免阻塞主逻辑,因此建议使用异步写入和批量处理的方式,尤其是当日志量非常大的时候。

# 异步日志记录函数
function Write-LogAsync {
    param (
        [string]$message
    )
    
    Start-Job -ScriptBlock {
        param($msg)
        $logFilePath = "C:\Logs\firewall_activity.log"
        $logEntry = @{
            Timestamp = (Get-Date)
            Message   = $msg
        }
        $logEntry | ConvertTo-Json | Out-File -Append -FilePath $logFilePath
    } -ArgumentList $message
}

# 使用异步记录日志
Write-LogAsync "IP $IPAddress was blocked due to multiple failed login attempts."

(2) 日志轮换和归档

日志文件过大会影响性能,也可能导致数据丢失,因此建议添加日志轮换和归档机制,按日期或文件大小创建新日志,并自动归档旧日志。

# 检查并归档日志
$logFilePath = "C:\Logs\firewall_activity.log"
$logFileName = "firewall_activity_$(Get-Date -Format 'yyyy-MM-dd').log"
$archivePath = "C:\Logs\Archive"

# 若日志文件存在,则进行归档
if (Test-Path $logFilePath) {
    Move-Item -Path $logFilePath -Destination "$archivePath\$logFileName"
}

# 创建新的日志文件
New-Item -Path $logFilePath -ItemType File -Force

2. 动态调整封禁策略

封禁策略的灵活性对防御攻击至关重要。在面对频繁的攻击时,封禁策略需要能够根据攻击者行为自动调整封禁时长、封禁范围等。

(1) 自适应封禁时长

根据攻击频率动态调整封禁时长。比如,如果一个 IP 连续多次失败登录,可以增加封禁的时长。

$failedAttempts = 5  # 假设失败尝试次数
$banTime = 10        # 初始封禁时间(分钟)

# 根据失败次数动态调整封禁时长
if ($failedAttempts -ge 5) {
    $banTime = 30    # 封禁30分钟
} elseif ($failedAttempts -ge 10) {
    $banTime = 60    # 封禁1小时
}

# 执行封禁
New-NetFirewallRule -DisplayName "Block $IPAddress" -Direction Inbound -Action Block -RemoteAddress $IPAddress
Start-Sleep -Seconds ($banTime * 60)
Remove-NetFirewallRule -DisplayName "Block $IPAddress"

(2) 限制同一IP的封禁频率

避免过度封禁同一IP,可以限制对同一IP的封禁次数。比如,超过一定次数后,自动解除封禁。

$maxBanCount = 3   # 最大封禁次数
$blockedIps = @{}   # 存储IP和封禁次数

if ($blockedIps.ContainsKey($IPAddress)) {
    $blockedIps[$IPAddress]++
    if ($blockedIps[$IPAddress] -ge $maxBanCount) {
        Write-Host "IP $IPAddress exceeded max ban count. Removing from block list."
        Remove-NetFirewallRule -DisplayName "Block $IPAddress"
        $blockedIps.Remove($IPAddress)
    }
} else {
    $blockedIps[$IPAddress] = 1
    New-NetFirewallRule -DisplayName "Block $IPAddress" -Direction Inbound -Action Block -RemoteAddress $IPAddress
}

3. 优化性能:减少不必要的重复操作

(1) 减少重复计算与查询

如果IP已经封禁且在封禁时间内,避免重复计算和不必要的封禁操作。通过内存缓存来存储封禁的状态信息,减少多次查询。

$blockedIpsCache = @{}

# 检查缓存中的封禁状态
if ($blockedIpsCache.ContainsKey($IPAddress)) {
    $banInfo = $blockedIpsCache[$IPAddress]
    if ((Get-Date) - $banInfo.LastBlocked).TotalMinutes -lt $banInfo.BanDuration) {
        Write-Host "IP $IPAddress is still within the ban period. No action needed."
    } else {
        Write-Host "Ban period expired for IP $IPAddress. Unblocking..."
        Remove-NetFirewallRule -DisplayName "Block $IPAddress"
        $blockedIpsCache.Remove($IPAddress)
    }
} else {
    # 执行封禁
    Write-Host "Blocking IP $IPAddress"
    New-NetFirewallRule -DisplayName "Block $IPAddress" -Direction Inbound -Action Block -RemoteAddress $IPAddress
    $blockedIpsCache[$IPAddress] = @{ LastBlocked = Get-Date; BanDuration = 60 }
}

(2) 批量操作与优化

对于多个IP封禁,尽量通过批量操作来提高效率。例如,使用 New-NetFirewallRule 封禁多个IP时,尽量将所有封禁操作组合在一起,避免逐个执行。

$blockedIpsBatch = @("192.168.1.100", "192.168.1.101", "192.168.1.102")

# 批量封禁多个IP
foreach ($IPAddress in $blockedIpsBatch) {
    New-NetFirewallRule -DisplayName "Block $IPAddress" -Direction Inbound -Action Block -RemoteAddress $IPAddress
}

# 批量解除封禁
Start-Sleep -Seconds 3600  # 假设封禁一小时
foreach ($IPAddress in $blockedIpsBatch) {
    Remove-NetFirewallRule -DisplayName "Block $IPAddress"
}

4. 提升灵活性和可扩展性

(1) 动态配置与外部数据源集成

为脚本提供更多自定义选项,可以将封禁的规则、时长等参数从外部配置文件或数据库中读取,提升灵活性和可扩展性。

# 从配置文件中读取封禁时长
$config = Get-Content "C:\Config\firewall_config.json" | ConvertFrom-Json
$banTime = $config.BanTime

# 动态封禁
New-NetFirewallRule -DisplayName "Block $IPAddress" -Direction Inbound -Action Block -RemoteAddress $IPAddress
Start-Sleep -Seconds ($banTime * 60)
Remove-NetFirewallRule -DisplayName "Block $IPAddress"

(2) 增加多种封禁类型

可以支持不仅仅是IP封禁,还可以根据用户名、端口等条件进行封禁。这使得防火墙策略更为灵活和细粒度。

$BlockedUser = "attackeruser"
$BlockedPort = 3389  # 例如 RDP 端口

# 封禁特定用户
New-NetFirewallRule -DisplayName "Block $BlockedUser" -Direction Inbound -Action Block -RemoteUserName $BlockedUser

# 封禁特定端口
New-NetFirewallRule -DisplayName "Block Port $BlockedPort" -Direction Inbound -Action Block -LocalPort $BlockedPort

5. 自动化监控和告警

(1) 使用Webhook推送报警

通过集成第三方通知服务(如Slack、Teams、邮件、Webhook等),当封禁规则生效时可以即时向系统管理员发出告警通知。

# 发送Webhook通知
function Send-WebhookNotification {
    param (
        [string]$webhookUrl,
        [string]$message
    )
    
    $body = @{ message = $message } | ConvertTo-Json
    Invoke-RestMethod -Uri $webhookUrl -Method Post -Body $body -ContentType "application/json"
}

# 发送封禁IP通知
Send-WebhookNotification -webhookUrl "https://your-webhook-url.com" -message "IP $IPAddress has been blocked due to multiple failed login attempts."

(2) 定期自检与恢复

为了防止系统出现配置异常,可以定期检查并恢复防火墙规则,确保系统的持续性和安全性。

# 定期检查和恢复防火墙规则
$expectedRules = @("Block $IPAddress")
$currentRules = Get-NetFirewallRule | Select-Object -ExpandProperty DisplayName

foreach ($rule in $expectedRules) {
    if (-not ($currentRules -contains $rule)) {
        Write-Host "Rule $rule is missing. Re-adding..."
        New-NetFirewallRule -DisplayName $rule -Direction Inbound -Action Block -
New-NetFirewallRule -DisplayName $rule -Direction Inbound -Action Block -RemoteAddress $IPAddress
    }
}

通过定期检查当前的防火墙规则,我们可以确保系统始终保持预期的安全策略。如果有任何规则丢失或被修改,脚本会自动恢复缺失的规则。这种方法可以减少人为错误导致的安全漏洞。

6. 强化安全性和防止滥用

(1) 增加对脚本操作的审计和监控

为了确保脚本本身的安全性,可以引入额外的审计和监控机制,确保脚本操作不会被滥用,避免恶意用户绕过防火墙。

# 审计脚本执行日志
$scriptAuditFile = "C:\Logs\firewall_script_audit.log"

function Write-AuditLog {
    param (
        [string]$action,
        [string]$username
    )

    $logEntry = @{
        Timestamp = (Get-Date)
        Username  = $username
        Action    = $action
    }

    $logEntry | ConvertTo-Json | Out-File -Append -FilePath $scriptAuditFile
}

# 写入执行日志
Write-AuditLog -action "Blocked IP $IPAddress" -username $env:USERNAME

此功能会记录每次操作的用户名、操作时间以及操作内容。这对于追踪和审计防火墙规则的修改非常有用。

(2) 防止脚本被篡改

为了防止脚本被恶意修改,可以通过代码签名、哈希验证等方式确保脚本的完整性。可以在脚本开始时进行哈希验证,确保它没有被篡改。

# 计算脚本的哈希值并与预期哈希值比较
$expectedHash = "abc123..."  # 预期哈希值
$currentHash = Get-FileHash -Path $MyInvocation.MyCommand.Path -Algorithm SHA256

if ($currentHash.Hash -ne $expectedHash) {
    Write-Host "Warning: Script has been modified! Exiting..."
    exit
}

通过这种方式,脚本可以在每次执行时验证自身的完整性,确保脚本没有被篡改,从而防止恶意修改和攻击。

(3) 限制脚本执行权限

可以通过组策略或权限管理确保只有特定的管理员才能运行该防火墙管理脚本,避免普通用户执行可能带来安全隐患的操作。

# 检查当前用户是否有管理员权限
if (-not (Test-UserIsAdministrator)) {
    Write-Host "You do not have sufficient permissions to run this script. Exiting..."
    exit
}

function Test-UserIsAdministrator {
    $groups = [System.Security.Principal.WindowsIdentity]::GetCurrent().Groups
    $adminGroup = [System.Security.Principal.SecurityIdentifier] "S-1-5-32-544"  # Administrators group SID
    return $groups -contains $adminGroup
}

通过此功能,只有具有管理员权限的用户才能执行脚本,从而减少脚本被未经授权的用户滥用的风险。

7. 脚本的自动化与调度

为了提升脚本的自动化程度,可以利用Windows任务调度器将防火墙管理脚本定时运行。例如,可以设置定期扫描封禁记录、恢复丢失的防火墙规则、清理过期的封禁记录等任务。

# 创建一个新的任务,定期执行脚本
$taskAction = New-ScheduledTaskAction -Execute "Powershell.exe" -Argument "C:\Scripts\firewall_manager.ps1"
$taskTrigger = New-ScheduledTaskTrigger -Daily -At "2:00AM"
$taskSettings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries

Register-ScheduledTask -TaskName "Firewall Manager Task" -Action $taskAction -Trigger $taskTrigger -Settings $taskSettings

通过自动化任务调度,防火墙规则可以按照预设的时间间隔自动执行,不需要人工干预。

8. 异常处理与容错机制

在执行脚本时,可能会遇到一些异常情况,比如网络连接问题、规则添加失败等。为确保脚本能够可靠运行,建议加入异常处理机制。

try {
    # 执行封禁操作
    New-NetFirewallRule -DisplayName "Block $IPAddress" -Direction Inbound -Action Block -RemoteAddress $IPAddress
} catch {
    Write-Host "Error occurred while blocking IP $IPAddress: $_"
    # 记录错误日志
    Write-LogAsync "Failed to block IP $IPAddress: $_"
}

通过加入 try...catch 语句块,可以捕获运行中的异常并处理,防止脚本崩溃,确保系统能够稳定运行。

优化后的 Windows Defender 防火墙管理脚本,涵盖了以下方面的增强:

  1. 日志管理: 采用异步和批量日志记录,支持日志轮换与归档。
  2. 封禁策略: 动态调整封禁时长、限制同一 IP 封禁次数、支持多种封禁类型(IP、端口、用户名等)。
  3. 性能优化: 减少重复计算,支持批量操作。
  4. 灵活性和可扩展性: 通过外部配置文件或数据库实现动态配置,支持多种封禁条件。
  5. 自动化与监控: 集成通知服务(Webhook),定期自检恢复防火墙规则。
  6. 安全性: 加强对脚本的审计、哈希验证,限制脚本执行权限,增加异常处理与容错机制。

这些改进可以显著提高防火墙管理脚本的可维护性、灵活性、性能和安全性,为系统管理员提供更强大的防护能力。


进一步优化和改进 Windows Defender 防火墙管理脚本,可以从以下几个方面进行加强,以提高其性能、可靠性、安全性和可维护性:

1. 高效的防火墙规则管理

(1) 批量管理和批量操作

当需要处理大量的 IP 地址时,单次添加或删除规则可能会影响性能。为了提高效率,可以采用批量操作方式,避免每个操作都进行一次防火墙更新。可以将多个 IP 地址或规则一次性提交到防火墙。

# 批量封禁IP
function Block-IPAddresses {
    param (
        [string[]]$IPAddresses
    )
    $rules = @()
    foreach ($IPAddress in $IPAddresses) {
        $rules += New-NetFirewallRule -DisplayName "Block $IPAddress" -Direction Inbound -Action Block -RemoteAddress $IPAddress
    }
    return $rules
}

# 批量解封IP
function Unblock-IPAddresses {
    param (
        [string[]]$IPAddresses
    )
    foreach ($IPAddress in $IPAddresses) {
        Remove-NetFirewallRule -DisplayName "Block $IPAddress"
    }
}

# 示例: 批量封禁
$blockedIPs = @("192.168.1.1", "192.168.1.2", "192.168.1.3")
Block-IPAddresses -IPAddresses $blockedIPs

这种方式不仅提升了操作的效率,而且减少了防火墙中规则更新的次数,从而提高了系统的响应速度。

(2) 使用自定义标签分类管理

为了便于管理和维护防火墙规则,可以为每个规则添加自定义标签,区分不同类型的规则(例如,黑名单、白名单、临时封禁等)。

# 添加标签字段
function Add-FirewallRuleWithTag {
    param (
        [string]$IPAddress,
        [string]$tag
    )

    New-NetFirewallRule -DisplayName "Block $IPAddress - $tag" -Direction Inbound -Action Block -RemoteAddress $IPAddress -Description "Block IP for $tag"
}

# 示例: 添加带标签的封禁规则
Add-FirewallRuleWithTag -IPAddress "192.168.1.10" -tag "BruteForce"

这种分类管理方法便于后续根据规则标签查找和管理防火墙规则。

2. 自动化日志清理与维护

随着时间的推移,防火墙规则日志会增多,可能会占用大量存储空间。因此,需要定期清理过期的封禁记录或日志文件。

(1) 定期清理过期日志

# 删除超过30天的日志文件
$logDirectory = "C:\Logs"
$logFiles = Get-ChildItem -Path $logDirectory | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) }

foreach ($file in $logFiles) {
    Remove-Item $file.FullName -Force
    Write-Host "Deleted old log file: $($file.Name)"
}

通过定期清理过期日志,避免存储空间被过多的日志文件占用。

(2) 日志归档和压缩

为了保留日志历史记录,同时减少存储空间占用,可以对过期日志进行归档和压缩。

# 将日志文件压缩并归档
$logFile = "C:\Logs\firewall_log.txt"
$archiveDir = "C:\Logs\Archive"
$archiveFile = "$archiveDir\firewall_log_$(Get-Date -Format yyyyMMdd).zip"

# 压缩日志
Compress-Archive -Path $logFile -DestinationPath $archiveFile
Remove-Item $logFile -Force

Write-Host "Archived log file: $archiveFile"

3. 强化安全性与权限控制

(1) 强化脚本权限验证与日志记录

增加对管理员权限的严格验证,并对不具备权限的操作进行记录和报警。

# 检查用户是否具有管理员权限
function Is-AdminUser {
    $groups = [System.Security.Principal.WindowsIdentity]::GetCurrent().Groups
    $adminSID = [System.Security.Principal.SecurityIdentifier]"S-1-5-32-544"
    return $groups -contains $adminSID
}

if (-not (Is-AdminUser)) {
    Write-Host "Error: You must run this script with administrator privileges."
    # 记录未授权访问
    Write-AuditLog -action "Unauthorized access attempt" -username $env:USERNAME
    exit
}

此外,如果脚本在执行过程中发生未授权访问或错误操作,可以立即记录并警告管理员。

(2) 防止脚本滥用的时间限制

对于脚本的执行进行时间限制,防止恶意用户在非授权时间修改防火墙规则。

# 限制脚本执行时间为每天的特定时段
$startTime = (Get-Date).Date.AddHours(8)  # 上午8点
$endTime = (Get-Date).Date.AddHours(18)   # 下午6点

if ((Get-Date) -lt $startTime -or (Get-Date) -gt $endTime) {
    Write-Host "Error: This script can only be run between 8 AM and 6 PM."
    exit
}

这样,即便脚本被滥用,也能在非授权时间内自动退出,增加脚本的安全性。

4. 异常处理与监控

(1) 增加详细的错误处理

对防火墙规则的添加、删除操作增加详细的错误处理机制。如果脚本在执行过程中出现错误,应记录详细的错误信息,并根据不同类型的错误采取不同的恢复措施。

try {
    # 尝试添加防火墙规则
    New-NetFirewallRule -DisplayName "Block $IPAddress" -Direction Inbound -Action Block -RemoteAddress $IPAddress
} catch {
    $errorMessage = "Error blocking IP $IPAddress: $_"
    Write-Host $errorMessage
    Write-LogAsync $errorMessage
    # 可以发送邮件通知管理员
    Send-ErrorEmailNotification -ErrorMessage $errorMessage
}

# 发送邮件通知
function Send-ErrorEmailNotification {
    param (
        [string]$ErrorMessage
    )

    $mailParams = @{
        To       = "admin@domain.com"
        From     = "firewall-script@domain.com"
        Subject  = "Firewall Script Error Notification"
        Body     = $ErrorMessage
        SmtpServer = "smtp.domain.com"
    }
    Send-MailMessage @mailParams
}

通过发送邮件或其他通知方式,确保管理员能够及时了解脚本执行中的问题,及时修复。

(2) 记录更详细的执行状态和性能

定期记录脚本的执行时间、执行结果、和性能指标等信息,以便进行优化和调优。

# 记录脚本执行时间
$startTime = Get-Date
# 执行脚本的操作
$endTime = Get-Date
$executionDuration = $endTime - $startTime
Write-Host "Script executed in $($executionDuration.TotalSeconds) seconds"
Write-LogAsync "Script executed in $($executionDuration.TotalSeconds) seconds"

5. 配置管理与版本控制

(1) 支持配置文件管理

可以将防火墙规则配置存储在外部文件中(如 JSON 或 XML),允许动态加载和修改规则,而无需直接修改脚本内容。

# 从配置文件加载规则
$configFile = "C:\Config\firewall_rules.json"
$config = Get-Content -Path $configFile | ConvertFrom-Json

foreach ($rule in $config.rules) {
    New-NetFirewallRule -DisplayName $rule.name -Direction Inbound -Action Block -RemoteAddress $rule.ipAddress
}

(2) 版本控制

通过 Git 或其他版本控制系统管理脚本的版本,确保每次修改都可以追溯,避免错误操作。

进一步优化方向

  1. 批量操作与批量封禁 :提升处理多个规则的效率。
  2. 日志清理与归档 :减少存储空间占用,保留历史记录。
  3. 加强安全性 :限制脚本的执行权限和时段,增强审计。
  4. 自动化与容错 :增强脚本的容错性,支持定期自检与恢复。
  5. 配置管理 :支持通过配置文件动态加载防火墙规则,便于管理和扩展。

这些改进将进一步提升脚本的可维护性、性能和安全性,帮助管理员更高效地管理防火墙规则并应对各种挑战。


Comments

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

登录

注册

重设密码

请输入您的用户名或电子邮箱地址。您会收到一封包含创建新密码链接的电子邮件。