From 5708e42c660fb9477b4d768be1d8dd5b22eabe79 Mon Sep 17 00:00:00 2001 From: PTah Date: Thu, 25 Jun 2026 10:03:26 +1000 Subject: [PATCH] fix: dedup RDG 302 notify by user+target+external IP (2.1.7-SAC) Suppress duplicate SAC alerts when Windows logs two RD Gateway 302 events within 90s for the same user, target host, and external client IP. Co-authored-by: Cursor --- Login_Monitor.ps1 | 26 +++++++++++++++++++++++++- version.txt | 2 +- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/Login_Monitor.ps1 b/Login_Monitor.ps1 index bf39517..63732c0 100644 --- a/Login_Monitor.ps1 +++ b/Login_Monitor.ps1 @@ -90,7 +90,7 @@ $script:SkipLogDetailLimit = 15 # строки ниже, если правки «мелкие» и вы не хотите менять отображаемую версию в логах). # Рекомендация: при значимых релизах меняйте и $ScriptVersion, и version.txt одинаково; при только # исправлениях на шаре — достаточно поднять patch в version.txt (например 1.3.0.1). -$ScriptVersion = "2.1.6-SAC" +$ScriptVersion = "2.1.7-SAC" # Логи (все под InstallRoot) $LogFile = Join-Path $script:InstallRoot "Logs\login_monitor.log" @@ -135,6 +135,8 @@ $LastReportFile = Join-Path $script:InstallRoot "Logs\last_daily_report.txt" $EnableRDGatewayMonitoring = $true $RDGatewayLogName = "Microsoft-Windows-TerminalServices-Gateway/Operational" $RDGatewayEvents = @(302, 303) +# Дубликаты RDG 302 (User+Target+ExternalIP) в окне N с — один alert в SAC/Telegram. +$Rdg302NotifyDedupSeconds = 90 # Макс. возраст сохранённого курсора RD Gateway (мин): если файл старше — replay не делаем. $GatewayEventsLookbackMinutes = 60 # Security 4624/4625/4648: персистентный cursor + replay не старше N мин (медленный boot / поздний старт агента). @@ -3818,6 +3820,20 @@ function Test-RdgGatewayBenignErrorCode { return $false } +function Get-Rdg302NotifyDedupKey { + param( + [string]$Username, + [string]$InternalIP, + [string]$ExternalIP + ) + $userPart = Get-RdpLoginNotifyDedupUsernamePart -Username $Username + $target = if ($InternalIP) { [string]$InternalIP.Trim() } else { '-' } + if ([string]::IsNullOrWhiteSpace($target)) { $target = '-' } + $ext = if ($ExternalIP) { [string]$ExternalIP.Trim() } else { '-' } + if ([string]::IsNullOrWhiteSpace($ext)) { $ext = '-' } + return "rdg302|$userPart|$target|$ext" +} + function Get-RdgGatewaySacEventType { param( [Parameter(Mandatory = $true)][int]$EventId, @@ -4702,6 +4718,14 @@ function Start-LoginMonitor { Write-Log "Skip RDG 303: ephemeral channel (SessionDuration=0, User=$($ei.Username), Target=$($ei.InternalIP), ErrorCode=$($ei.ErrorCode))" continue } + if ($event.Id -eq 302) { + $dedupKey302 = Get-Rdg302NotifyDedupKey -Username $ei.Username ` + -InternalIP $ei.InternalIP -ExternalIP $ei.ExternalIP + if (Test-RdpMonitorNotifyDedup -Key $dedupKey302 -WindowSeconds $Rdg302NotifyDedupSeconds) { + Write-Log "Notify dedup RDG 302: User=$($ei.Username) Target=$($ei.InternalIP) Ext=$($ei.ExternalIP) (window ${Rdg302NotifyDedupSeconds}s)" + continue + } + } $msg = Format-RDGatewayEvent -EventID $event.Id ` -Username $ei.Username ` -ExternalIP $ei.ExternalIP ` diff --git a/version.txt b/version.txt index 6cf3433..0512b49 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -2.1.6-SAC +2.1.7-SAC