first commit
This commit is contained in:
106
rdp_login_script.ps1
Normal file
106
rdp_login_script.ps1
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
# ====== 配置区 ======
|
||||||
|
$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 = @"
|
||||||
|
<QueryList>
|
||||||
|
<Query Id="0" Path="Security">
|
||||||
|
<Select Path="Security">*[System[(EventID=4625)]]</Select>
|
||||||
|
</Query>
|
||||||
|
</QueryList>
|
||||||
|
"@
|
||||||
|
|
||||||
|
$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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user