# ====== 配置区 ====== $accessToken = "d28bd09159097d9cc5793a183990927ce637bd8addafb5e4586e2687ca317039" $secret = "SECd4bf3fb7703bd2826896deefa68d579e9945a67058ee9047ac5f8757ae800729" $threshold = 3 # 尝试失败次数阈值 $failCache = @{} # 失败计数缓存 # ====== 钉钉发送函数 ====== function Get-Signature { $timestamp = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds() $stringToSign = "$timestamp`n$secret" $hmac = New-Object System.Security.Cryptography.HMACSHA256 $hmac.Key = [Text.Encoding]::UTF8.GetBytes($secret) $hash = $hmac.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign)) $sign = [Convert]::ToBase64String($hash) $sign = [System.Net.WebUtility]::UrlEncode($sign) return @{ timestamp=$timestamp; sign=$sign } } function Send-DingTalk($msg) { $signData = Get-Signature $url = "https://oapi.dingtalk.com/robot/send?access_token=$accessToken×tamp=$($signData.timestamp)&sign=$($signData.sign)" $body = @{ msgtype="text"; text=@{ content=$msg } } | ConvertTo-Json -Depth 5 Invoke-RestMethod -Uri $url -Method Post -ContentType "application/json" -Body $body } # ====== 封禁函数(可选) ====== function Ban-IP($ip) { if (-not (Get-NetFirewallRule -DisplayName "RDP_Block_$ip" -ErrorAction SilentlyContinue)) { New-NetFirewallRule -DisplayName "RDP_Block_$ip" -Direction Inbound -RemoteAddress $ip -Action Block -Protocol TCP } } # ====== 查询日志 ====== $query = @" "@ $events = Get-WinEvent -FilterXml $query -MaxEvents 50 foreach ($event in $events) { # 处理 LogonType $logonTypeRaw = $event.Properties[8].Value $logonType = 0 if ($logonTypeRaw -match '%%(\d+)') { $logonType = [int]$matches[1] } else { $logonType = [int]$logonTypeRaw } # 只处理远程登录类型(10、134、2304,2313) if ($logonType -notin @(10, 134, 2304, 2313)) { continue } $user = $event.Properties[5].Value # 尝试多个索引获取 IP $ip = $event.Properties[18].Value if (-not $ip -or $ip -eq '-' -or $ip -match 'C:\\') { $ip = $event.Properties[19].Value } if (-not $ip -or $ip -eq '-' -or $ip -match 'C:\\') { $ip = $event.Properties[20].Value } if (-not $ip -or $ip -eq '-') { $ip = "UNKNOWN" } # 输出日志 Write-Host "RDP Failed login: $user from $ip at $($event.TimeCreated) LogonType=$logonType" # 累加失败次数 # 格式化时间 $time = $event.TimeCreated.ToString("yyyy-MM-dd HH:mm:ss") Write-Host "RDP Failed login: $user from $ip at $time LogonType=$logonType" # 累加失败次数 if ($ip -ne "UNKNOWN") { if (-not $failCache.ContainsKey($ip)) { $failCache[$ip] = 1 } else { $failCache[$ip]++ } $count = $failCache[$ip] if ($count -ge $threshold) { Ban-IP $ip # 推送钉钉(加入时间) $msg = @" !!!RDP Broke!!! IP: $ip username: $user failcounts: $count time: $time LogonType: $logonType "@ # Send-DingTalk $msg $failCache.Remove($ip) } } }