rdp_login_success
This commit is contained in:
179
rdp_login_success_script.ps1
Normal file
179
rdp_login_success_script.ps1
Normal file
@@ -0,0 +1,179 @@
|
||||
# 服务器登录监控脚本 - 完整版(监控所有RDP相关登录类型)
|
||||
# 监控远程桌面登录并通过钉钉机器人推送通知(支持加签)
|
||||
|
||||
param (
|
||||
[string]$DingTalkWebhookUrl = "https://oapi.dingtalk.com/robot/send?access_token=d28bd09159097d9cc5793a183990927ce637bd8addafb5e4586e2687ca317039",
|
||||
[string]$DingTalkSecret = "SECd4bf3fb7703bd2826896deefa68d579e9945a67058ee9047ac5f8757ae800729"
|
||||
)
|
||||
|
||||
# 钉钉消息发送函数(支持加签)
|
||||
function Send-DingTalkMessage {
|
||||
param(
|
||||
[string]$消息内容
|
||||
)
|
||||
|
||||
try {
|
||||
# 计算签名
|
||||
$timestamp = [DateTimeOffset]::Now.ToUnixTimeMilliseconds()
|
||||
$stringToSign = "$timestamp`n$DingTalkSecret"
|
||||
|
||||
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
|
||||
$hmacsha.key = [Text.Encoding]::UTF8.GetBytes($DingTalkSecret)
|
||||
$signature = $hmacsha.ComputeHash([Text.Encoding]::UTF8.GetBytes($stringToSign))
|
||||
$signatureBase64 = [Convert]::ToBase64String($signature)
|
||||
$encodedSignature = [System.Web.HttpUtility]::UrlEncode($signatureBase64)
|
||||
|
||||
# 完整的请求URL
|
||||
$fullUrl = "$DingTalkWebhookUrl×tamp=$timestamp&sign=$encodedSignature"
|
||||
|
||||
$body = @{
|
||||
msgtype = "text"
|
||||
text = @{
|
||||
content = $消息内容
|
||||
}
|
||||
} | ConvertTo-Json -Depth 10
|
||||
|
||||
$response = Invoke-RestMethod -Uri $fullUrl -Method Post -Body $body -ContentType "application/json; charset=utf-8"
|
||||
Write-Host "✓ 钉钉消息发送成功: $($response.errmsg)" -ForegroundColor Green
|
||||
} catch {
|
||||
Write-Error "✗ 钉钉消息发送失败: $_"
|
||||
}
|
||||
}
|
||||
|
||||
# 登录类型说明
|
||||
$登录类型说明 = @{
|
||||
"2" = "交互式登录(本地控制台)"
|
||||
"3" = "网络登录(含NLA身份验证)"
|
||||
"4" = "批处理(计划任务)"
|
||||
"5" = "服务登录"
|
||||
"7" = "会话解锁"
|
||||
"8" = "网络明文(如IIS基本认证)"
|
||||
"9" = "新凭证(RunAs)"
|
||||
"10" = "远程交互(RDP无NLA)"
|
||||
"11" = "缓存交互(域凭据缓存)"
|
||||
}
|
||||
|
||||
# 程序启动信息
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
Write-Host " 服务器登录监控服务已启动" -ForegroundColor Cyan
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
Write-Host "服务器名称: $env:COMPUTERNAME" -ForegroundColor Yellow
|
||||
Write-Host "启动时间: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor Yellow
|
||||
Write-Host "监控类型: 所有远程桌面相关登录(类型3、7、10)" -ForegroundColor Yellow
|
||||
Write-Host "检查间隔: 5秒" -ForegroundColor Yellow
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
|
||||
# 记录上次检查的时间
|
||||
$上次检查时间 = (Get-Date).AddHours(-1)
|
||||
# 记录已发送过的登录事件,避免重复通知
|
||||
$已通知事件 = @{}
|
||||
|
||||
# 主循环
|
||||
while ($true) {
|
||||
try {
|
||||
# 获取新的登录事件(Event ID 4624)
|
||||
$事件列表 = Get-WinEvent -FilterHashtable @{
|
||||
LogName = 'Security'
|
||||
ID = 4624
|
||||
StartTime = $上次检查时间
|
||||
} -ErrorAction SilentlyContinue
|
||||
|
||||
foreach ($事件 in $事件列表) {
|
||||
# 解析事件XML
|
||||
$事件Xml = [xml]$事件.ToXml()
|
||||
|
||||
# 获取登录类型
|
||||
$登录类型 = ($事件Xml.Event.EventData.Data | Where-Object {$_.Name -eq "LogonType"}).'#text'
|
||||
|
||||
# 监控所有可能的远程桌面相关登录类型:3(NLA验证)、7(解锁)、10(传统RDP)
|
||||
if ($登录类型 -eq "3" -or $登录类型 -eq "7" -or $登录类型 -eq "10") {
|
||||
# 获取登录信息
|
||||
$用户名 = ($事件Xml.Event.EventData.Data | Where-Object {$_.Name -eq "TargetUserName"}).'#text'
|
||||
$域名 = ($事件Xml.Event.EventData.Data | Where-Object {$_.Name -eq "TargetDomainName"}).'#text'
|
||||
$来源IP = ($事件Xml.Event.EventData.Data | Where-Object {$_.Name -eq "IpAddress"}).'#text'
|
||||
$登录时间 = $事件.TimeCreated
|
||||
$记录ID = $事件.RecordId
|
||||
$登录GUID = ($事件Xml.Event.EventData.Data | Where-Object {$_.Name -eq "LogonGuid"}).'#text'
|
||||
|
||||
# 过滤本地IP和无效IP
|
||||
$有效IP = $来源IP -and $来源IP -ne "127.0.0.1" -and $来源IP -ne "::1" -and $来源IP -ne "-"
|
||||
|
||||
if ($有效IP) {
|
||||
# 生成唯一标识,避免重复通知
|
||||
$事件标识 = "$记录ID-$来源IP-$用户名"
|
||||
|
||||
if (-not $已通知事件.ContainsKey($事件标识)) {
|
||||
# 清理过旧的记录,避免内存溢出
|
||||
if ($已通知事件.Count -gt 1000) {
|
||||
$已通知事件.Clear()
|
||||
}
|
||||
|
||||
# 处理空域名
|
||||
if ([string]::IsNullOrEmpty($域名) -or $域名 -eq "-") {
|
||||
$域名 = $env:COMPUTERNAME
|
||||
}
|
||||
|
||||
# 获取登录类型说明
|
||||
$类型说明 = if ($登录类型说明.ContainsKey($登录类型)) {
|
||||
$登录类型说明[$登录类型]
|
||||
} else {
|
||||
"未知类型($登录类型)"
|
||||
}
|
||||
|
||||
# 添加额外说明
|
||||
$额外说明 = ""
|
||||
if ($登录类型 -eq "3") {
|
||||
$额外说明 = "(使用NLA验证的RDP连接)"
|
||||
} elseif ($登录类型 -eq "7") {
|
||||
$额外说明 = "(远程会话解锁)"
|
||||
} elseif ($登录类型 -eq "10") {
|
||||
$额外说明 = "(传统RDP连接)"
|
||||
}
|
||||
|
||||
# 构建钉钉消息
|
||||
$消息内容 = @"
|
||||
【服务器登录告警】
|
||||
━━━━━━━━━━━━━━━━━━━━━━
|
||||
🏢 服务器:$env:COMPUTERNAME
|
||||
📅 时间:$($登录时间.ToString('yyyy-MM-dd HH:mm:ss'))
|
||||
👤 用户:$域名\$用户名
|
||||
🔑 登录类型:$类型说明 $额外说明
|
||||
🌐 来源IP:$来源IP
|
||||
📝 记录ID:$记录ID
|
||||
━━━━━━━━━━━━━━━━━━━━━━
|
||||
"@
|
||||
|
||||
# 显示日志
|
||||
Write-Host "`n[$(Get-Date -Format 'HH:mm:ss')] 检测到新的远程登录" -ForegroundColor Yellow
|
||||
Write-Host " 用户: $域名\$用户名" -ForegroundColor White
|
||||
Write-Host " 类型: $类型说明 $额外说明" -ForegroundColor Cyan
|
||||
Write-Host " 来源IP: $来源IP" -ForegroundColor White
|
||||
Write-Host " 时间: $($登录时间.ToString('HH:mm:ss'))" -ForegroundColor White
|
||||
|
||||
# 发送钉钉通知
|
||||
Send-DingTalkMessage -消息内容 $消息内容
|
||||
|
||||
# 记录已通知
|
||||
$已通知事件[$事件标识] = $true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# 更新上次检查时间
|
||||
$上次检查时间 = Get-Date
|
||||
|
||||
# 显示运行状态(每5分钟显示一次)
|
||||
if (((Get-Date).Minute % 5) -eq 0 -and (Get-Date).Second -lt 5) {
|
||||
Write-Host "[$(Get-Date -Format 'HH:mm:ss')] 监控运行中,已监控到 $($已通知事件.Count) 次登录" -ForegroundColor Gray
|
||||
}
|
||||
|
||||
# 等待5秒后继续检查
|
||||
Start-Sleep -Seconds 5
|
||||
|
||||
} catch {
|
||||
Write-Error "监控过程发生错误: $_"
|
||||
Write-Host "等待10秒后重试..." -ForegroundColor Red
|
||||
Start-Sleep -Seconds 10
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user