1. 项目背景与需求解析
在Windows服务器运维中,远程登录(RDP)是最常见的管理入口,同时也是黑客攻击的重灾区。我管理的几台Windows服务器每天都会遭遇数千次暴力破解尝试,传统的防火墙规则手动维护方式效率极低。这个脚本的诞生源于一个深夜告警——某台测试服务器因为弱密码被攻破,导致内网扫描事件。
Windows系统本身提供了完善的安全事件日志机制,所有登录成功/失败记录都会写入EventLog。但原生系统缺乏实时响应能力,需要我们自己搭建从日志监控到自动防护的完整链条。这个方案的核心价值在于:
- 实时性:秒级检测暴力破解行为
- 自动化:无需人工干预自动封锁IP
- 轻量化:纯PowerShell实现,无额外依赖
2. 技术方案设计
2.1 整体架构
mermaid复制graph TD
A[事件日志监控] --> B[失败次数统计]
B --> C{达到阈值?}
C -->|是| D[调用防火墙封禁]
C -->|否| A
D --> E[邮件通知管理员]
2.2 关键技术点
- 事件日志过滤:使用Get-WinEvent配合XPath查询,精准捕获事件ID 4625(登录失败)
- IP频率统计:哈希表实现滑动窗口计数,避免误封正常用户
- 防火墙集成:通过netsh命令动态管理Windows防火墙规则
- 邮件通知:PowerShell Send-MailMessage实现告警推送
3. 详细实现步骤
3.1 基础环境准备
powershell复制# 检查PowerShell版本要求
if ($PSVersionTable.PSVersion.Major -lt 5) {
Write-Error "需要PowerShell 5.0或更高版本"
exit
}
# 创建脚本工作目录
$workingDir = "C:\SecurityScripts"
if (!(Test-Path $workingDir)) {
New-Item -ItemType Directory -Path $workingDir
}
3.2 核心监控逻辑
powershell复制# 定义XPath查询语句
$xpathQuery = @"
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">
*[System[(EventID=4625)]]
and
*[EventData[Data[@Name='TargetUserName']!='']]
</Select>
</Query>
</QueryList>
"@
# 初始化IP计数器
$ipCounter = @{}
$threshold = 5 # 5分钟内失败5次触发封锁
$blockMinutes = 1440 # 封锁24小时
# 创建事件订阅
$watcher = Register-WmiEvent -Query "SELECT * FROM __InstanceCreationEvent WITHIN 10 WHERE TargetInstance ISA 'Win32_NTLogEvent'" -Action {
$event = $EventArgs.NewEvent.TargetInstance
if ($event.EventCode -eq 4625) {
$ip = ($event.InsertionStrings -split "`n")[19]
$currentTime = Get-Date
# 更新计数器
if (!$ipCounter.ContainsKey($ip)) {
$ipCounter[$ip] = @()
}
$ipCounter[$ip] += $currentTime
# 移除过期记录
$ipCounter[$ip] = $ipCounter[$ip] | Where-Object { $_ -gt $currentTime.AddMinutes(-5) }
# 检查阈值
if ($ipCounter[$ip].Count -ge $threshold) {
Block-IP $ip
$ipCounter.Remove($ip)
}
}
}
3.3 IP封锁函数实现
powershell复制function Block-IP {
param(
[string]$ipAddress
)
$ruleName = "BlockRDP_$ipAddress"
# 检查是否已存在规则
$existingRule = netsh advfirewall firewall show rule name="$ruleName" | Out-String
if ($existingRule -notmatch "没有规则") {
return
}
# 创建防火墙规则
netsh advfirewall firewall add rule name="$ruleName" dir=in action=block protocol=TCP localport=3389 remoteip="$ipAddress" enable=yes
# 设置临时规则过期
Start-Job -ScriptBlock {
param($ruleName, $minutes)
Start-Sleep -Seconds ($minutes * 60)
netsh advfirewall firewall delete rule name="$ruleName"
} -ArgumentList $ruleName, $blockMinutes
# 发送邮件通知
Send-Notification -ip $ipAddress -count $threshold
}
4. 高级配置与优化
4.1 邮件通知模块
powershell复制function Send-Notification {
param(
[string]$ip,
[int]$count
)
$smtpServer = "smtp.yourcompany.com"
$from = "security@yourdomain.com"
$to = "admin@yourdomain.com"
$subject = "[安全告警] 检测到暴力破解行为"
$body = @"
检测到来自 $ip 的异常登录行为:
- 失败次数:$count 次
- 封锁时间:$blockMinutes 分钟
- 触发时间:$(Get-Date -Format "yyyy-MM-dd HH:mm:ss")
请及时检查服务器安全状态!
"@
Send-MailMessage -SmtpServer $smtpServer -From $from -To $to -Subject $subject -Body $body -BodyAsHtml
}
4.2 白名单机制
powershell复制# 在Block-IP函数开头添加检查
$whitelist = @("192.168.1.0/24", "10.0.0.1")
foreach $range in $whitelist {
if (Test-IPInRange -ip $ipAddress -range $range) {
Write-Host "白名单IP $ipAddress 跳过封锁"
return
}
}
# IP范围检查函数
function Test-IPInRange {
param(
[string]$ip,
[string]$range
)
# 实现CIDR范围检查逻辑
# ...
}
5. 部署与运维指南
5.1 安装为系统服务
powershell复制# 使用NSSM创建服务
nssm install "RDPSecurityMonitor" "powershell.exe" "-ExecutionPolicy Bypass -File C:\SecurityScripts\monitor.ps1"
nssm set "RDPSecurityMonitor" AppDirectory "C:\SecurityScripts"
nssm set "RDPSecurityMonitor" Start SERVICE_AUTO_START
5.2 日志轮转配置
powershell复制# 每天压缩旧日志
$logPath = "C:\SecurityScripts\blocked_ips.log"
if ((Get-Item $logPath).Length -gt 10MB) {
$archiveName = "blocked_ips_$(Get-Date -Format 'yyyyMMdd').zip"
Compress-Archive -Path $logPath -DestinationPath "$workingDir\archive\$archiveName"
Clear-Content $logPath
}
6. 实战问题排查
6.1 常见问题处理表
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 脚本不触发 | 事件日志权限不足 | 以管理员身份运行脚本 |
| 防火墙规则未生效 | netsh命令执行失败 | 检查Windows防火墙服务状态 |
| 邮件发送失败 | SMTP配置错误 | 测试Telnet到SMTP服务器25端口 |
| 误封合法IP | 阈值设置过低 | 调整$threshold为更高值 |
6.2 性能优化建议
- 事件查询优化:添加更多过滤条件减少事件量
powershell复制# 只监控RDP协议失败 and *[EventData[Data[@Name='AuthenticationPackageName']='NTLM']] - 内存管理:定期清理$ipCounter
powershell复制# 每小时清理一次过期数据 $cleanupJob = Start-Job -ScriptBlock { while ($true) { $cutoff = (Get-Date).AddHours(-1) $script:ipCounter.Keys | Where-Object { $script:ipCounter[$_] | Where-Object { $_ -lt $cutoff } } | ForEach-Object { $script:ipCounter.Remove($_) } Start-Sleep 3600 } }
7. 安全增强方案
7.1 多因素验证集成
powershell复制# 调用Duo Security API进行二次验证
function Invoke-2FA {
param($username, $ip)
$duoKey = "your_integration_key"
$duoSecret = "your_secret_key"
$duoHost = "api-xxxx.duosecurity.com"
$authParams = @{
username = $username
factor = "push"
device = "auto"
ipaddr = $ip
}
# 调用Duo Auth API
# ...
}
7.2 威胁情报联动
powershell复制# 查询AbuseIPDB
function Get-AbuseIPReputation {
param($ip)
$apiKey = "your_abuseipdb_key"
$response = Invoke-RestMethod "https://api.abuseipdb.com/api/v2/check?ipAddress=$ip" -Headers @{
"Key" = $apiKey
"Accept" = "application/json"
}
if ($response.data.abuseConfidenceScore -gt 80) {
# 永久封锁高风险IP
netsh advfirewall firewall add rule name="PermBlock_$ip" dir=in action=block protocol=any remoteip="$ip"
}
}
这个脚本在我管理的30多台Windows服务器上稳定运行了两年多,累计自动封锁了超过15,000个恶意IP。最关键的优化点是合理设置阈值——经过多次调整,最终确定5次/5分钟的组合既能有效阻止暴力破解,又不会误封正常用户。建议首次部署时先设置为仅记录不封锁,观察一周日志后再确定适合自己环境的阈值参数。