fix: RCM 1149 silent drop on RDS servers (2.1.5-SAC)
Should-IgnoreEvent rejected every 1149 because ComputerName is always '-'; add persistent poll cursor, skip logging, and Diagnose on NETLOGON publish list. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+75
-8
@@ -90,7 +90,7 @@ $script:SkipLogDetailLimit = 15
|
||||
# строки ниже, если правки «мелкие» и вы не хотите менять отображаемую версию в логах).
|
||||
# Рекомендация: при значимых релизах меняйте и $ScriptVersion, и version.txt одинаково; при только
|
||||
# исправлениях на шаре — достаточно поднять patch в version.txt (например 1.3.0.1).
|
||||
$ScriptVersion = "2.1.4-SAC"
|
||||
$ScriptVersion = "2.1.5-SAC"
|
||||
|
||||
# Логи (все под InstallRoot)
|
||||
$LogFile = Join-Path $script:InstallRoot "Logs\login_monitor.log"
|
||||
@@ -115,6 +115,7 @@ $LoginSuccessNotifyDedupSeconds = 90
|
||||
$HeartbeatFile = Join-Path $script:InstallRoot "Logs\last_heartbeat.txt"
|
||||
$GatewayPollCursorFile = Join-Path $script:InstallRoot "Logs\last_rdgateway_poll.txt"
|
||||
$SecurityPollCursorFile = Join-Path $script:InstallRoot "Logs\last_security_poll.txt"
|
||||
$Rcm1149PollCursorFile = Join-Path $script:InstallRoot "Logs\last_rcm1149_poll.txt"
|
||||
$DeployUpdateMarkerFile = Join-Path $script:InstallRoot "deploy_last_update.txt"
|
||||
# Построчные правила подавления уведомлений Security 4624/4625 (см. ignore.lst.example в репозитории).
|
||||
$script:IgnoreListPath = Join-Path $script:InstallRoot "ignore.lst"
|
||||
@@ -138,6 +139,8 @@ $RDGatewayEvents = @(302, 303)
|
||||
$GatewayEventsLookbackMinutes = 60
|
||||
# Security 4624/4625/4648: персистентный cursor + replay не старше N мин (медленный boot / поздний старт агента).
|
||||
$SecurityEventsLookbackMinutes = 60
|
||||
# RCM 1149: персистентный cursor + replay (как Security).
|
||||
$Rcm1149EventsLookbackMinutes = 60
|
||||
|
||||
# RDP Remote Connection Manager: User authentication succeeded — событие 1149 (workstation + RDS server)
|
||||
$EnableRcm1149Monitoring = 1
|
||||
@@ -3228,8 +3231,10 @@ function Should-IgnoreEvent {
|
||||
if ($Username -like $p) { return $true }
|
||||
}
|
||||
|
||||
if ($ComputerName -eq "Authz" -or $ComputerName -like "Authz*") { return $true }
|
||||
if ($ComputerName -eq "NtLmSsp" -or $ComputerName -like "NtLmSsp*" -or $ComputerName -like "*NtLmSsp*") { return $true }
|
||||
if ($EventID -ne 1149) {
|
||||
if ($ComputerName -eq "Authz" -or $ComputerName -like "Authz*") { return $true }
|
||||
if ($ComputerName -eq "NtLmSsp" -or $ComputerName -like "NtLmSsp*" -or $ComputerName -like "*NtLmSsp*") { return $true }
|
||||
}
|
||||
|
||||
foreach ($lp in $ExcludedLogonProcesses) {
|
||||
if ($ProcessName -like "*$lp*") { return $true }
|
||||
@@ -3239,13 +3244,14 @@ function Should-IgnoreEvent {
|
||||
}
|
||||
|
||||
if ($SourceIP -eq "127.0.0.1" -or $SourceIP -like "fe80:*") { return $true }
|
||||
if ($ComputerName -eq "-" -or $ComputerName -eq "N/A") { return $true }
|
||||
# RCM 1149 не содержит WorkstationName; caller передаёт ComputerName='-'.
|
||||
if ($EventID -ne 1149 -and ($ComputerName -eq "-" -or $ComputerName -eq "N/A")) { return $true }
|
||||
|
||||
foreach ($pattern in $ExcludedComputerPatterns) {
|
||||
if ($ComputerName -like $pattern) { return $true }
|
||||
}
|
||||
|
||||
if ($EventID -in 4624, 4625) {
|
||||
if ($EventID -in 4624, 4625, 1149) {
|
||||
if (Test-RdpMonitorIgnoreListMatch -EventId ([string]$EventID) -Username $Username `
|
||||
-ComputerName $ComputerName -SourceIP $SourceIP) {
|
||||
return $true
|
||||
@@ -3757,6 +3763,51 @@ function Set-RdpSecurityPollCursor {
|
||||
}
|
||||
}
|
||||
|
||||
function Get-RdpRcm1149PollCursor {
|
||||
$now = Get-Date
|
||||
$fresh = $now.AddSeconds(-10)
|
||||
$maxAgeMin = [math]::Max(1, [int]$Rcm1149EventsLookbackMinutes)
|
||||
$lookbackFloor = $now.AddMinutes(-1 * $maxAgeMin)
|
||||
|
||||
if (-not (Test-Path -LiteralPath $Rcm1149PollCursorFile)) {
|
||||
Write-Log "RCM 1149: cursor отсутствует — replay с $($lookbackFloor.ToString('dd.MM.yyyy HH:mm:ss')) (lookback ${maxAgeMin} мин)."
|
||||
return $lookbackFloor
|
||||
}
|
||||
try {
|
||||
$raw = (Get-Content -LiteralPath $Rcm1149PollCursorFile -TotalCount 1 -ErrorAction Stop).Trim()
|
||||
if ([string]::IsNullOrWhiteSpace($raw)) {
|
||||
Write-Log "RCM 1149: cursor пуст — replay с $($lookbackFloor.ToString('dd.MM.yyyy HH:mm:ss')) (lookback ${maxAgeMin} мин)."
|
||||
return $lookbackFloor
|
||||
}
|
||||
$parsed = [datetime]::Parse($raw, [Globalization.CultureInfo]::InvariantCulture, [Globalization.DateTimeStyles]::RoundtripKind)
|
||||
if ($parsed.Kind -eq [DateTimeKind]::Utc) {
|
||||
$parsed = $parsed.ToLocalTime()
|
||||
}
|
||||
if ($parsed -lt $lookbackFloor) {
|
||||
Write-Log "RCM 1149: cursor старше $maxAgeMin мин — replay с $($lookbackFloor.ToString('dd.MM.yyyy HH:mm:ss'))."
|
||||
return $lookbackFloor
|
||||
}
|
||||
Write-Log "RCM 1149: cursor=$($parsed.ToString('dd.MM.yyyy HH:mm:ss')) (lookback cap ${maxAgeMin} мин)."
|
||||
return $parsed
|
||||
} catch {
|
||||
Write-Log "RCM 1149: не удалось прочитать cursor ($Rcm1149PollCursorFile) — replay с $($lookbackFloor.ToString('dd.MM.yyyy HH:mm:ss'))."
|
||||
return $lookbackFloor
|
||||
}
|
||||
}
|
||||
|
||||
function Set-RdpRcm1149PollCursor {
|
||||
param([Parameter(Mandatory = $true)][datetime]$Cursor)
|
||||
try {
|
||||
$dir = Split-Path -Parent $Rcm1149PollCursorFile
|
||||
if (-not (Test-Path -LiteralPath $dir)) {
|
||||
New-Item -ItemType Directory -Path $dir -Force | Out-Null
|
||||
}
|
||||
Write-TextFileUtf8Bom -Path $Rcm1149PollCursorFile -Text ($Cursor.ToString('o'))
|
||||
} catch {
|
||||
Write-Log "WARN: RCM 1149 cursor save failed: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
function Test-RdgGatewayBenignErrorCode {
|
||||
param([string]$ErrorCode)
|
||||
if ([string]::IsNullOrWhiteSpace($ErrorCode)) { return $true }
|
||||
@@ -4426,7 +4477,7 @@ function Start-LoginMonitor {
|
||||
Write-Log "RD Gateway: журнал недоступен — опрос 302/303 отключён ($RDGatewayLogName)"
|
||||
}
|
||||
}
|
||||
$lastRcmCheckTime = (Get-Date).AddSeconds(-10)
|
||||
$lastRcmCheckTime = Get-RdpRcm1149PollCursor
|
||||
$lastRcmShadowCheckTime = (Get-Date).AddSeconds(-10)
|
||||
$lastWinRmCheckTime = (Get-Date).AddSeconds(-10)
|
||||
$lastAdminShare5140CheckTime = (Get-Date).AddSeconds(-10)
|
||||
@@ -4697,16 +4748,27 @@ function Start-LoginMonitor {
|
||||
} -ErrorAction SilentlyContinue
|
||||
|
||||
if ($rcmEvents) {
|
||||
$rcmNotified = 0
|
||||
$rcmSkipped = 0
|
||||
foreach ($event in $rcmEvents) {
|
||||
if ($event.TimeCreated -le $lastRcmCheckTime) { continue }
|
||||
$rcmInfo = Get-Rcm1149EventInfo -Event $event
|
||||
if ($rcmInfo.Username -like "*$") { continue }
|
||||
if ($rcmInfo.Username -like "*$") {
|
||||
$rcmSkipped++
|
||||
Write-Log "Skip 1149: User=$($rcmInfo.Username) IP=$($rcmInfo.ClientIP) — machine account"
|
||||
continue
|
||||
}
|
||||
if (Should-IgnoreEvent -Username $rcmInfo.Username -ProcessName "-" `
|
||||
-ComputerName "-" -EventID 1149 -LogonType 10 -SourceIP $rcmInfo.ClientIP) { continue }
|
||||
-ComputerName "-" -EventID 1149 -LogonType 10 -SourceIP $rcmInfo.ClientIP) {
|
||||
$rcmSkipped++
|
||||
Write-Log "Skip 1149: User=$($rcmInfo.Username) IP=$($rcmInfo.ClientIP) — built-in exclusion or ignore.lst"
|
||||
continue
|
||||
}
|
||||
|
||||
$dedupKey1149 = Get-RdpLoginSuccessNotifyDedupKey -SecurityLogComputerName $event.MachineName `
|
||||
-Username $rcmInfo.Username -SourceIP $rcmInfo.ClientIP -LogonType 10
|
||||
if (-not (Test-RdpLoginSuccessNotifyDedupAllow -DedupKey $dedupKey1149)) {
|
||||
$rcmSkipped++
|
||||
Write-Log "Notify dedup 1149: User=$($rcmInfo.Username) IP=$($rcmInfo.ClientIP) (window ${LoginSuccessNotifyDedupSeconds}s)"
|
||||
continue
|
||||
}
|
||||
@@ -4725,8 +4787,13 @@ function Start-LoginMonitor {
|
||||
ip_address = $rcmInfo.ClientIP
|
||||
event_id_windows = 1149
|
||||
} | Out-Null
|
||||
$rcmNotified++
|
||||
}
|
||||
$lastRcmCheckTime = Update-MonitorPollCursor -CurrentCursor $lastRcmCheckTime -Events @($rcmEvents)
|
||||
Set-RdpRcm1149PollCursor -Cursor $lastRcmCheckTime
|
||||
if ($rcmNotified -gt 0 -or $rcmSkipped -gt 0) {
|
||||
Write-Log "RCM 1149 poll: fetched=$(@($rcmEvents).Count) notified=$rcmNotified skipped=$rcmSkipped cursor=$($lastRcmCheckTime.ToString('dd.MM.yyyy HH:mm:ss'))"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user