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