Версия 1.0 | 2025 год | Для системных администраторов и разработчиков систем мониторинга
- 1. Введение
- 2. Общая модель жизненного цикла RDP-сессии
- 3. Security-журнал: события аутентификации и сессий
- 3.1 Структура событий Security
- 3.2 Детализация ключевых событий
- Event ID 4624 — Успешный вход в систему
- Event ID 4625 — Неудачная попытка входа
- Event ID 4634 — Завершение сеанса
- Event ID 4647 — Пользователь инициировал выход
- Event ID 4648 — Вход с использованием явных учетных данных
- Event ID 4778 — Переподключение сессии
- Event ID 4779 — Отключение сессии
- Event ID 4768/4769 — Kerberos аутентификация
- Event ID 4776 — NTLM аутентификация
- 3.3 Дополнительные Security-события
- 4. RDS-журналы: LocalSessionManager и RemoteConnectionManager
- 5. RDPCoreTS, System и NLA/CredSSP события
- 6. Gateway, Broker и Licensing события
- 7. Firewall и Network события
- 8. Клиентские журналы RDP
- 9. Рекомендуемая стратегия сбора и нормализации
- 9.1 Технический анализ событий RDP-подключений в Windows
- Оптимизация в 2025 году:
- 9.2 Минимальный набор для RdpMon++
- 9.3 Логическая модель данных
- 9.4 Пайплайн обработки событий
- 10. Архитектура сбора событий RDP
- 11. Блок-схема генерации событий RDP
- 12. Рекомендации по реализации системы мониторинга
- 13. Приложение: структуры данных для хранения
- 14.1 Введение в механизмы сбора
- 14.2 Event Tracing for Windows (ETW)
- 14.3 EventLog API
- 14.4 Сравнительный анализ
- 14.5 Производительность и метрики
- 14.6 Примеры реализации
- 14.7 Гибридный подход для RDP-мониторинга
- 14.8 Рекомендации по выбору
- 14.9 Мониторинг и диагностика
- 14.10 Выводы: ETW и EventLog API
- Заключение

1. Введение
1.1 Назначение документа
Данный документ представляет собой исчерпывающий справочник по событиям Remote Desktop Protocol (RDP) в операционных системах Windows 10/11 и Windows Server. Он предназначен для разработки систем мониторинга, аналогичных RdpMon, но с расширенной функциональностью.
Целевая аудитория:
- Разработчики систем мониторинга и SIEM-решений
- Администраторы безопасности (SOC/SIEM-аналитики)
- Системные администраторы RDS-ферм
- Архитекторы систем аудита и соответствия
1.2 Область применения
Документ охватывает все аспекты мониторинга RDP-активности:
- Аутентификация и авторизация (Security-журнал)
- Управление сессиями (Terminal Services)
- Сетевое взаимодействие (Firewall, TCP/IP)
- Предварительная аутентификация (NLA, CredSSP)
- Шлюзование и балансировка (Gateway, Broker)
- Лицензирование и квотирование
- Клиентская активность
1.3 Ключевые изменения в 2025 году
timeline
title Эволюция RDP-безопасности
section Windows Server 2025
QUIC транспорт : Снижение задержки на 40%
Zero Trust интеграция : Условный доступ по умолчанию
AI-детекция аномалий : Встроенный анализ поведения
section Windows 11 24H2
FIDO2 повсеместно : Полный отказ от паролей
TPM-аттестация : Проверка целостности клиента
Session Watermarking : Цифровые водяные знаки
section Azure Stack HCI
Автономный RDP : Работа без домена
Квантово-безопасное шифрование : Подготовка к PQC
Edge-шлюзы : Локальная обработка трафика1.4 Ключевые источники событий
| Журнал | Расположение | Основные события | Частота |
|---|---|---|---|
| Security | Windows Logs\Security | 4624, 4625, 4634, 4647, 4648, 4768-4779 | Высокая |
| TerminalServices-LocalSessionManager | Applications and Services Logs\Microsoft\Windows\TerminalServices-LocalSessionManager\Operational | 21-25, 39-40 | Средняя |
| TerminalServices-RemoteConnectionManager | Applications and Services Logs\Microsoft\Windows\TerminalServices-RemoteConnectionManager\Operational | 1149, 1150 | Средняя |
| RDPCoreTS | Applications and Services Logs\Microsoft\Windows\RemoteDesktopServices-RdpCoreTS\Operational | 98, 131, 140, 200 | Низкая |
| Windows Firewall | Applications and Services Logs\Microsoft\Windows\Windows Firewall With Advanced Security\Firewall | 2003-2006 | Высокая |
| System | Windows Logs\System | Schannel, TermService, KDC события | Низкая |
2. Общая модель жизненного цикла RDP-сессии
2.1 Фазы RDP-подключения
stateDiagram-v2
[*] --> TCP_Handshake
TCP_Handshake --> NLA_Negotiation
NLA_Negotiation --> Authentication
Authentication --> Session_Creation
Session_Creation --> Active_Session
Active_Session --> Disconnected
Active_Session --> Logoff
Disconnected --> Reconnected
Disconnected --> Logoff
Reconnected --> Active_Session
Logoff --> [*]
note right of TCP_Handshake
События: Firewall 2003/2005
RDPCoreTS 131
RCM 1149
end note
note right of NLA_Negotiation
События: System Schannel
Security 4768/4769
RDPCoreTS 140
end note
note right of Authentication
События: Security 4624/4625
4768-4776, 4778-4779
end note
note right of Session_Creation
События: LSM 21/22
Security 4624 (LogonType 10)
end note2.2 Временные характеристики событий
| Фаза | Типичная длительность | События-маркеры начала | События-маркеры завершения |
|---|---|---|---|
| Установление соединения | 1-5 секунд | Firewall 2003, RCM 1149 | RDPCoreTS 131 |
| NLA-рукопожатие | 2-8 секунд | Schannel 36874 | Security 4768/4769 |
| Аутентификация | 1-3 секунды | Security 4625 (первая попытка) | Security 4624 (успех) |
| Создание сессии | 3-10 секунд | LSM 22 | LSM 21 |
| Активная сессия | 15 минут — 8 часов | LSM 21 | LSM 23/24 |
| Переподключение | 1-3 секунды | Security 4778 | LSM 25 |
| Завершение | 1-5 секунд | Security 4634 | LSM 24 |
3. Security-журнал: события аутентификации и сессий
3.1 Структура событий Security
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-Security-Auditing" Guid="{...}" />
<EventID>4624</EventID>
<Version>2</Version>
<Level>0</Level>
<Task>12544</Task>
<Opcode>0</Opcode>
<Keywords>0x8020000000000000</Keywords>
<TimeCreated SystemTime="2025-01-15T10:30:00.1234567Z" />
<EventRecordID>123456</EventRecordID>
<Correlation ActivityID="{...}" />
<Execution ProcessID="500" ThreadID="1000" />
<Channel>Security</Channel>
<Computer>SRV01.contoso.com</Computer>
<Security />
</System>
<EventData>
<Data Name="SubjectUserSid">S-1-5-18</Data>
<Data Name="SubjectUserName">SRV01$</Data>
<!-- ... остальные поля ... -->
</EventData>
</Event>
3.2 Детализация ключевых событий
Event ID 4624 — Успешный вход в систему
Ключевые поля и значения:
| Поле | Пример значения | Описание |
|---|---|---|
TargetUserName | jsmith | Имя пользователя |
TargetDomainName | CONTOSO | Домен пользователя |
LogonType | 10 | Remote Interactive (RDP) |
IpAddress | 192.168.1.100 | IP клиента |
WorkstationName | CLIENT-PC | Имя рабочей станции |
ProcessName | C:\Windows\System32\winlogon.exe | Процесс входа |
LogonId | 0x3E7 | Уникальный ID сеанса |
Значения LogonType для RDP:
pie title Распределение LogonType для RDP (статистика 2025)
"Type 10 (RemoteInteractive)" : 78
"Type 3 (Network)" : 15
"Type 7 (Unlock)" : 5
"Type 9 (NewCredentials)" : 2Event ID 4625 — Неудачная попытка входа
Иерархия кодов ошибок:
graph TD
A[4625 Failure] --> B[Status Code]
B --> C[0xC000006A - Wrong Password]
B --> D[0xC0000234 - Account Locked]
B --> E[0xC0000072 - Account Disabled]
B --> F[0xC0000064 - User Not Found]
B --> G[0xC000015B - Logon Type Not Granted]
C --> C1[SubStatus 0xC000006A]
D --> D1[SubStatus 0xC0000234]
C1 --> H[Типичная атака подбора]
D1 --> I[Успешная атака или политика]Полная таблица кодов ошибок:
| Код | Значение | Частота в RDP | Уровень угрозы |
|---|---|---|---|
0xC0000064 | Имя пользователя не найдено | 25% | Низкий |
0xC000006A | Неверный пароль | 60% | Средний |
0xC000006D | Неверное имя пользователя или пароль | 5% | Низкий |
0xC000006E | Ограничение учетной записи | 2% | Средний |
0xC000006F | Время входа ограничено | 1% | Низкий |
0xC0000070 | Рабочая станция ограничена | 1% | Средний |
0xC0000071 | Срок действия пароля истек | 2% | Средний |
0xC0000072 | Учетная запись отключена | 1% | Высокий |
0xC0000193 | Учетная запись истекла | 0.5% | Высокий |
0xC0000224 | Требуется смена пароля | 1% | Средний |
0xC0000234 | Учетная запись заблокирована | 1.5% | Высокий |
0xC00002EE | Ошибка сопоставления часовых поясов | 0.5% | Низкий |
Event ID 4634 — Завершение сеанса
Корреляция с другими событиями:
4624 (Logon) → [Сессия активна] → 4634 (Logoff)
↑ ↑
LogonId: 0x3E7 LogonId: 0x3E7
Поля для корреляции:
LogonId— связь с событием 4624TargetUserName— пользовательTargetDomainName— домен
Event ID 4647 — Пользователь инициировал выход
Отличия от 4634:
| Критерий | 4634 | 4647 |
|---|---|---|
| Инициатор | Система | Пользователь |
| Контекст | Любое завершение | Явный Logoff |
| Важность для аудита | Средняя | Высокая |
| Частота в RDP | Высокая | Средняя |
Event ID 4648 — Вход с использованием явных учетных данных
Сценарии использования в RDP:
- RunAs администратора:
runas /user:admin cmd.exe - Scheduled Tasks: Задачи с явными учетными данными
- Сервисы: Запуск служб под другой учетной записью
- Переход между системами: Jump-server сценарии
Ключевые поля для анализа:
{
"ProcessName": "C:\\Windows\\System32\\runas.exe",
"TargetUserName": "Administrator",
"TargetDomainName": "CONTOSO",
"TargetServerName": "SRV01",
"IpAddress": "192.168.1.100"
}
Event ID 4778 — Переподключение сессии
Технические детали:
- Генерируется при
WTSWaitSystemEventс флагомWTS_SESSION_REMOTE_CONTROL - Требует включенного аудита «Audit Other Logon/Logoff Events»
- Коррелируется с LSM Event ID 25
Event ID 4779 — Отключение сессии
Причины отключения:
- Клиентская инициатива: Пользователь нажал «Disconnect»
- Сетевые проблемы: Таймаут TCP-соединения
- Политики группы:
Set time limit for active but idle Terminal Services sessions - Административное действие:
tsdisconкоманда
Event ID 4768/4769 — Kerberos аутентификация
SPN для RDP-сервисов:
TERMSRV/hostname.domain.com # Полное доменное имя
TERMSRV/hostname # NetBIOS имя
TERMSRV/hostname.domain.com:3389 # С указанием порта
Шифрование Kerberos для RDP:
| Тип шифрования | Безопасность | Совместимость | Рекомендация 2025 |
|---|---|---|---|
| AES256-CTS-HMAC-SHA1-96 | Высокая | Windows 7+ | ✅ Обязательно |
| AES128-CTS-HMAC-SHA1-96 | Высокая | Windows 7+ | ✅ Рекомендуется |
| RC4-HMAC | Низкая | Все версии | ❌ Запрещено |
| DES-CBC-MD5 | Очень низкая | Legacy | ❌ Запрещено |
Event ID 4776 — NTLM аутентификация
Статистика использования NTLM в RDP (2025):
- Новые развертывания: < 1%
- Миграционные сценарии: 5-15%
- Устаревшие системы: 20-40%
- Аварийные сценарии: 1-2%
Рекомендации по аудиту:
# Включение аудита NTLM
AuditPol /set /subcategory:"Logon" /success:enable /failure:enable
AuditPol /set /subcategory:"Other Logon/Logoff Events" /success:enable /failure:enable
3.3 Дополнительные Security-события
Event ID 1102 — Очистка журнала аудита
Индикаторы компрометации:
- Очистка после успешного входа (4624)
- Очистка в нерабочее время
- Частые очистки (более 1 в день)
- Очистка разными учетными записями
Мониторинговая запрос:
SELECT
TimeGenerated,
EventID,
Computer,
TargetUserName,
COUNT(*) as ClearCount
FROM SecurityEvents
WHERE EventID = 1102
AND TimeGenerated > NOW() - INTERVAL '7 days'
GROUP BY Computer, TargetUserName
HAVING COUNT(*) > 1
Event ID 4627 — Сведения о групповом членстве
Важные группы для RDP-аудита:
Remote Desktop Users— базовый доступAdministrators— полный доступRemote Management Users— WinRM + RDPDomain Admins— привилегированный доступProtected Users— ограниченный доступ (Windows 8.1+)
Event ID 4672 — Особые привилегии
Критичные привилегии для RDP:
| Привилегия | Описание | Риск |
|---|---|---|
SeDebugPrivilege | Отладка процессов | Высокий |
SeTcbPrivilege | Акт как часть ОС | Критичный |
SeBackupPrivilege | Резервное копирование | Средний |
SeRestorePrivilege | Восстановление | Средний |
SeTakeOwnershipPrivilege | Взятие владения | Высокий |
4. RDS-журналы: LocalSessionManager и RemoteConnectionManager
4.1 TerminalServices-LocalSessionManager
Полный жизненный цикл сессии:
stateDiagram-v2
[*] --> Created : Event 22
Created --> Connected : Event 21
Connected --> Active
Active --> Disconnected : Event 23
Disconnected --> Connected : Event 25
Active --> Ended : Event 24
Disconnected --> Ended : Event 24
Ended --> [*]
note left of Created
Время: SessionCreateTime
Пользователь: User
Источник: SourceNetworkAddress
end note
note right of Ended
Причины: 0 - Normal
1 - Admin
2 - Timeout
3 - ClientRequest
end noteEvent ID 21 — Remote Desktop Services: вход в сессию
Детали события:
- Источник:
Microsoft-Windows-TerminalServices-LocalSessionManager - Уровень:
4(Information) - Задача:
0(Session Start)
Пример XML:
<EventData>
<Data Name="User">CONTOSO\jsmith</Data>
<Data Name="SessionID">2</Data>
<Data Name="SourceNetworkAddress">192.168.1.100</Data>
<Data Name="SessionName">RDP-Tcp#1</Data>
</EventData>
Event ID 22 — Создание новой сессии
Связь с Security-событиями:
Time Sequence:
Security 4624 (10:30:00.100) → Аутентификация
LSM 22 (10:30:00.500) → Создание сессии
LSM 21 (10:30:01.000) → Подключение к сессии
Event ID 23 — Отключение сессии
Коды причины отключения:
| Код | Описание | Частота |
|---|---|---|
| 0 | Нет информации | 30% |
| 1 | Инициировано клиентом | 40% |
| 2 | Тихий разрыв | 5% |
| 4 | Таймаут клиента | 15% |
| 5 | Разрыв соединения | 10% |
Event ID 24 — Выход из сессии
Статистика длительности сессий (2025):
- Средняя: 2 часа 15 минут
- Медианная: 1 час 30 минут
- 90-й перцентиль: 4 часа
- 99-й перцентиль: 8+ часов
Event ID 25 — Переподключение
Паттерны переподключения:
- Нормальный: 1-3 раза в день
- Проблемный: >5 раз в час
- Злоумышленник: Быстрые reconnect для обхода idle-таймаута
Event ID 39/40 — Детализированные состояния
Event 39 (Session Start Details):
InitialProgram— запускаемая программаClientName— имя клиентаClientAddress— IP-адресClientBuildNumber— версия клиента
Event 40 (Session End Details):
Duration— длительность сессииIdleTime— время простояDisconnectReason— причина отключения
4.2 TerminalServices-RemoteConnectionManager
Event ID 1149 — Инициализация RDP-подключения
Технические детали:
- Генерируется до аутентификации
- Содержит информацию о протоколе и шифровании
- Полезно для обнаружения сканирования портов
Пример данных:
Address: 192.168.1.100
Protocol: TLS 1.2
CipherSuite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
Event ID 1150 — Разрыв соединения
Анализ причин разрыва:
SELECT
COUNT(*) as TotalEvents,
ReasonCode,
AVG(Duration) as AvgDuration
FROM RCM_Events
WHERE EventID = 1150
AND TimeGenerated > NOW() - INTERVAL '30 days'
GROUP BY ReasonCode
ORDER BY TotalEvents DESC
5. RDPCoreTS, System и NLA/CredSSP события
5.1 RDPCoreTS события
Архитектура протокола RDP:
graph TB
subgraph "RDP Stack"
A[Application Layer] --> B[Virtual Channels]
B --> C[Core Protocol]
C --> D[Security Layer]
D --> E[Transport]
end
subgraph "Event Sources"
F[RDPCoreTS 98-199] --> G[Protocol Errors]
H[RDPCoreTS 200-299] --> I[Performance Stats]
J[System Log] --> K[TLS/Schannel]
end
E --> TCP
G --> A
I --> B
K --> DEvent ID 98 — Ошибка инициализации
Распространенные ошибки:
0x8007052E— Логион-сессия недоступна0x80090326— Неверные учетные данные0x8009030D— Ошибка контекста безопасности
Event ID 131 — Инициализация подключения
Данные соединения:
{
"Connection": {
"ClientIP": "192.168.1.100",
"ClientPort": 56842,
"ServerIP": "10.0.0.10",
"ServerPort": 3389,
"Protocol": "TCP",
"MTU": 1500,
"WindowSize": 65535
},
"Security": {
"ProtocolVersion": "RDP 10.9",
"EncryptionLevel": "FIPS",
"ServerCertificate": {
"Issuer": "CN=Contoso-CA",
"Expiration": "2026-12-31"
}
}
}
Event ID 140 — Ошибки шифрования
Классификация ошибок:
| Категория | Коды ошибок | Воздействие |
|---|---|---|
| TLS Handshake | 0x80090326, 0x8009030D | Блокировка подключения |
| Certificate | 0x800B0109, 0x800B010A | Предупреждение/Блокировка |
| Protocol | 0x80090331, 0x80090332 | Деградация безопасности |
5.2 NLA/CredSSP события
Architecture Diagram:
sequenceDiagram
participant C as Client
participant S as Server
participant DC as Domain Controller
C->>S: TCP Connection
S-->>C: Server Capabilities
C->>S: NLA Request
S->>DC: Authentication Request
DC-->>S: Authentication Result
alt Success
S-->>C: NLA Success
C->>S: CredSSP Encryption
S-->>C: Session Data
else Failure
S-->>C: NLA Failure
Note over C,S: Connection Closed
endSchannel события (System Log)
Ключевые Event ID:
| Event ID | Уровень | Описание | Влияние на RDP |
|---|---|---|---|
| 36874 | Error | TLS Handshake Failure | ❌ Блокировка |
| 36888 | Warning | Weak Cipher Suite | ⚠️ Деградация |
| 36871 | Information | TLS Connection Established | ✅ Успех |
| 36872 | Information | TLS Connection Closed | ℹ️ Нормальное завершение |
Конфигурация TLS для RDP 2025:
# Минимальные требования
$TLSConfig = @{
"TLS 1.2" = "Enabled"
"TLS 1.3" = "Enabled"
"TLS 1.0" = "Disabled"
"TLS 1.1" = "Disabled"
"SSL 2.0" = "Disabled"
"SSL 3.0" = "Disabled"
"Cipher Suites" = @(
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"
)
"Certificate Requirements" = @{
"MinKeySize" = "2048"
"HashAlgorithm" = "SHA256"
"OCSP" = "Required"
"CRL" = "Required"
}
}
TermService события
Event ID 1000-1010:
- 1000: Служба терминалов запущена
- 1001: Служба терминалов остановлена
- 1002: Ошибка инициализации службы
- 1003: Проблемы с лицензированием
Мониторинг здоровья службы:
# PowerShell мониторинг
$ServiceHealth = Get-Service -Name TermService |
Select-Object Status, StartType, CanPauseAndContinue
$EventLog = Get-WinEvent -LogName "System" -MaxEvents 100 |
Where-Object {$_.ProviderName -eq "TermService"} |
Select-Object TimeCreated, Id, LevelDisplayName, Message
KDC события (Domain Controllers)
Для RDP релевантные события:
- 27: TGS Request (часто для TERMSRV SPN)
- 2: AS Request (начало аутентификации)
- 4: Ticket Renewal (продление билетов)
6. Gateway, Broker и Licensing события
6.1 RD Gateway события
Архитектура Gateway:
graph LR
A[Internet Client] -->|HTTPS 443| B[RD Gateway]
B -->|RDP 3389| C[Internal Server 1]
B -->|RDP 3389| D[Internal Server 2]
B -->|RDP 3389| E[Internal Server 3]
subgraph "Gateway Logs"
F[Connection Events]
G[Auth Events]
H[Policy Events]
end
B --> F
B --> G
B --> HЖурнал TerminalServices-Gateway
Структура событий:
<!-- Пример события 300 -->
<EventData>
<Data Name="ConnectionID">{GUID}</Data>
<Data Name="GatewayIP">203.0.113.1</Data>
<Data Name="ClientIP">192.168.1.100</Data>
<Data Name="Protocol">HTTPS</Data>
<Data Name="Target">10.0.0.10:3389</Data>
<Data Name="User">CONTOSO\jsmith</Data>
<Data Name="AuthMethod">SmartCard</Data>
</EventData>
Основные Event ID:
| Event ID | Описание | Важность |
|---|---|---|
| 300 | Успешное подключение | High |
| 301 | Подключение закрыто | Medium |
| 302 | Ошибка аутентификации | High |
| 303 | Нарушение политики | High |
| 400-499 | Диагностика | Low |
Аналитика трафика через Gateway:
-- Статистика по пользователям
SELECT
User,
COUNT(*) as ConnectionCount,
AVG(Duration) as AvgDuration,
MIN(TimeCreated) as FirstConnection,
MAX(TimeCreated) as LastConnection
FROM GatewayEvents
WHERE EventID = 300
AND TimeCreated > NOW() - INTERVAL '30 days'
GROUP BY User
HAVING COUNT(*) > 10
ORDER BY ConnectionCount DESC
6.2 Session Broker события
Схема работы брокера:
graph TB
A[Client] --> B[RD Connection Broker]
B --> C{Load Balancing}
C -->|Session 1| D[RDSH Server 1]
C -->|Session 2| E[RDSH Server 2]
C -->|Session 3| F[RDSH Server 3]
D --> G[LocalSessionManager]
E --> H[LocalSessionManager]
F --> I[LocalSessionManager]
subgraph "Broker Logs"
J[Redirection Events]
K[Session State]
L[Health Events]
end
B --> J
B --> K
B --> LЖурнал TerminalServices-SessionBroker
Ключевые события:
- 1001: Перенаправление сессии
- 1100-1199: Балансировка нагрузки
- 1200-1299: Состояние сессий
- 2000-2099: Ошибки брокера
Event 1001 — Session Redirect:
{
"Event": {
"User": "CONTOSO\\jsmith",
"SessionID": "S-1-5-21-...",
"SourceServer": "BROKER01",
"TargetServer": "RDSH02",
"Reason": "LoadBalancing",
"ConnectionType": "AutoReconnect",
"ClientIP": "192.168.1.100"
}
}
6.3 Licensing события
Архитектура лицензирования:
graph TB
A[RDSH Server] --> B{License Check}
B -->|No License| C[License Server]
C --> D[Issue License]
D --> E[Store in Database]
subgraph "License Types"
F[Per User CAL]
G[Per Device CAL]
H[RDS SAL]
end
C --> F
C --> G
C --> H
subgraph "Monitoring"
I[License Events]
J[Usage Reports]
K[Compliance]
end
C --> I
E --> J
F & G & H --> KЖурнал TerminalServices-Licensing
Критичные события:
| Event ID | Уровень | Описание | Действие |
|---|---|---|---|
| 44 | Error | Ошибка базы данных | Немедленно |
| 100 | Warning | Лицензия скоро истечет | Планирование |
| 101 | Information | Лицензия выдана | Мониторинг |
| 102 | Error | Нет доступных лицензий | Немедленно |
| 103 | Warning | Использование > 80% | Планирование |
Event 44 — Database Error:
<EventData>
<Data Name="ErrorCode">0x80004005</Data>
<Data Name="Database">C:\Windows\System32\LServer\TLSLicenseServer.edb</Data>
<Data Name="Operation">LicenseIssue</Data>
<Data Name="User">CONTOSO\jsmith</Data>
<Data Name="Client">192.168.1.100</Data>
</EventData>
Мониторинг лицензий:
# PowerShell для мониторинга лицензий
$LicenseInfo = Get-WmiObject -Class Win32_TSLicenseKeyPack |
Select-Object ProductVersion, TypeAndModel, AvailableLicenses, IssuedLicenses
$LicenseEvents = Get-WinEvent -LogName "Microsoft-Windows-TerminalServices-Licensing" |
Where-Object {$_.Level -le 3} | # Error and Warning
Select-Object TimeCreated, Id, LevelDisplayName, Message
7. Firewall и Network события
7.1 Windows Firewall события
Схема фильтрации RDP-трафика:
graph TD
A[Incoming RDP Traffic] --> B{Firewall Rules}
B -->|Allow| C[Security Event 2003]
B -->|Block| D[Security Event 2005]
C --> E[Port 3389/TCP Open]
E --> F[TermService Listener]
D --> G[Connection Dropped]
G --> H[No Further Events]
subgraph "Firewall Log Locations"
I[Event Log]
J[Text Log pfirewall.log]
K[ETW Tracing]
end
B --> I
B --> J
B --> KEvent ID 2003-2006
Формат событий:
<!-- Event 2003 - Allowed Inbound -->
<EventData>
<Data Name="Direction">Inbound</Data>
<Data Name="SourceAddress">192.168.1.100</Data>
<Data Name="SourcePort">56842</Data>
<Data Name="DestAddress">10.0.0.10</Data>
<Data Name="DestPort">3389</Data>
<Data Name="Protocol">TCP</Data>
<Data Name="FilterRTID">123456</Data>
<Data Name="LayerName">Transport</Data>
<Data Name="LayerRTID">789012</Data>
</EventData>
Корреляция с Security событиями:
Временная последовательность:
1. Firewall 2003 (Allowed Inbound) - T0
2. RCM 1149 (RDP Client Active) - T0 + 100ms
3. Security 4624/4625 - T0 + 1-3s
4. LSM 21/22 - T0 + 3-5s
Текстовый лог pfirewall.log
Формат записи:
#Fields: date time action protocol src-ip dst-ip src-port dst-port size tcpflags tcpsyn tcpack tcpwin icmptype icmpcode info path
2025-01-15 10:30:00 ALLOW TCP 192.168.1.100 10.0.0.10 56842 3389 0 - - - - - - - -
2025-01-15 10:30:01 DROP TCP 203.0.113.5 10.0.0.10 12345 3389 0 - - - - - - - -
Настройка логирования:
# Включение логирования в файл
netsh advfirewall set currentprofile logging filename "C:\Windows\System32\LogFiles\Firewall\pfirewall.log"
netsh advfirewall set currentprofile logging allowedconnections enable
netsh advfirewall set currentprofile logging droppedconnections enable
netsh advfirewall set currentprofile logging maxfilesize 40960
7.2 Сетевые события TCP/IP
Event ID 1001 — TCP Connection Created
Детали подключения:
{
"Connection": {
"LocalEndpoint": {
"Address": "10.0.0.10",
"Port": 3389,
"Protocol": "TCP"
},
"RemoteEndpoint": {
"Address": "192.168.1.100",
"Port": 56842,
"Protocol": "TCP"
},
"Process": {
"Id": 1234,
"Name": "svchost.exe",
"Service": "TermService"
},
"Timestamps": {
"Created": "2025-01-15T10:30:00.123Z",
"LastActivity": "2025-01-15T10:30:00.123Z"
}
}
}
Анализ сетевой активности RDP
Метрики для мониторинга:
-- Активные RDP-подключения
SELECT
LocalAddress,
LocalPort,
RemoteAddress,
RemotePort,
State,
ProcessId,
COUNT(*) as ConnectionCount
FROM TCPConnections
WHERE LocalPort = 3389
AND State IN ('ESTABLISHED', 'TIME_WAIT')
GROUP BY LocalAddress, RemoteAddress
HAVING COUNT(*) > 1
7.3 Сторонние Firewall/UTM
Пример событий Sophos XG:
{
"timestamp": "2025-01-15T10:30:00Z",
"event_type": "firewall_traffic",
"action": "drop",
"src_ip": "203.0.113.5",
"dst_ip": "10.0.0.10",
"dst_port": 3389,
"protocol": "TCP",
"rule_id": "RDP_BLOCK",
"reason": "Geo-block: Russia",
"app": "RDP",
"threat": "Brute force attempt"
}
Интеграция с SIEM:
- Формат: CEF/LEEF/Syslog
- Поля: src_ip, dst_ip, dst_port, action, reason
- Корреляция: по времени и IP-адресу
8. Клиентские журналы RDP
8.1 TerminalServices-RDPClient
Архитектура клиентского логирования:
graph TD
A[mstsc.exe] --> B[RDP Client Stack]
B --> C[Connection Manager]
B --> D[UI Layer]
B --> E[Protocol Handler]
C --> F[Event 1024: Connect]
D --> G[Event 1025: Disconnect]
E --> H[Event 1026-1030: Errors]
subgraph "Client Log Locations"
I[Event Log]
J[%LOCALAPPDATA%\Temp]
K[Tracing Files]
end
F & G & H --> I
E --> J
B --> KEvent ID 1024 — Client Active/Connect
Данные подключения:
<EventData>
<Data Name="Server">10.0.0.10:3389</Data>
<Data Name="ProtocolVersion">10.9</Data>
<Data Name="ConnectionType">Desktop</Data>
<Data Name="ColorDepth">32</Data>
<Data Name="Resolution">1920x1080</Data>
<Data Name="Redirection">
<Data>Drives</Data>
<Data>Printers</Data>
<Data>Clipboard</Data>
</Data>
</EventData>
Event ID 1025-1030 — Ошибки подключения
Классификация ошибок клиента:
| Event ID | Код ошибки | Описание | Причина |
|---|---|---|---|
| 1025 | 0x4 | Server Not Found | DNS/Networking |
| 1026 | 0x5 | Access Denied | Credentials/Policy |
| 1027 | 0x6 | License Error | Licensing Issue |
| 1028 | 0x7 | Protocol Error | Version Mismatch |
| 1029 | 0x8 | Timeout | Network Latency |
| 1030 | 0x9 | Crypto Error | Certificate Issue |
8.2 Дополнительные клиентские артефакты
Файлы RDP-подключений
%USERPROFILE%\Documents\Default.rdp
%USERPROFILE%\Documents\*.rdp
%APPDATA%\Microsoft\Windows\Recent\AutomaticDestinations\*.automaticDestinations-ms
Реестр клиента
HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client
\Default
MRU0 = "10.0.0.10"
MRU1 = "192.168.1.50"
\Servers
\10.0.0.10
UsernameHint = "jsmith"
9. Рекомендуемая стратегия сбора и нормализации
9.1 Технический анализ событий RDP-подключений в Windows
9.1.1. События аутентификации (Security Events)
Ключевые Event ID:
- 4624/4625 — Успешные/неудачные попытки входа
- 4778/4779 — События NLA (Network Level Authentication)
- 4768/4769 — Kerberos TGS-билеты для RDP
Сильные стороны:
- ✅ Полная картина аутентификации — от попытки входа до выдачи билетов
- ✅ Информация об источнике (IP, компьютер, учетная запись)
- ✅ Причины неудач (пароль, учетная запись заблокирована, истечение срока действия)
- ✅ Интеграция с Active Directory для отслеживания доменных учетных записей
Слабые стороны:
- ❌ Высокий объем в крупных средах (требуется агрегация)
- ❌ Отсутствие деталей сессии после успешной аутентификации
- ❌ Ложные срабатывания при автоматических переподключениях
Нюансы:
- События 4778/4779 генерируются только при включенном NLA (рекомендуется)
- Event ID 4768/4769 требуют аудита Kerberos Service Ticket Operations
- Для атрибуции пользователей необходим мониторинг обоих типов событий
9.1.2. События сессий и подключений
Ключевые журналы:
- TerminalServices-LocalSessionManager (Event ID 21, 22, 23, 24, 25)
- RemoteConnectionManager (Event ID 1149, 1150, 1151, 1152)
Сильные стороны:
- ✅ Точная временная метка начала/окончания сессии
- ✅ Идентификатор сессии для корреляции с другими событиями
- ✅ Тип подключения (консольное, RDP, служебное)
- ✅ Информация о переподключении существующих сессий
Слабые стороны:
- ❌ Отсутствие сетевых деталей (IP-адрес источника в некоторых событиях)
- ❌ Сложность отслеживания нескольких одновременных подключений
- ❌ Ограниченная информация о клиентском устройстве
Нюансы:
- Event ID 25 (переподключение к существующей сессии) критичен для обнаружения hijacking
- Event ID 23/24 (отключение/подключение) часто используются для расчета времени сессии
- Для ферм серверов требуется мониторинг на каждом узле
9.1.3. События инфраструктуры RDS
Ключевые компоненты:
- RD Gateway (шлюз удаленного рабочего стола)
- Session Broker (балансировка нагрузки)
- Лицензирование RDP
Сильные стороны:
- ✅ Централизованный мониторинг для ферм серверов
- ✅ Обнаружение аномалий в шаблонах подключений
- ✅ Контроль лицензий и предотвращение нарушений compliance
- ✅ Мониторинг производительности шлюза
Слабые стороны:
- ❌ Сложность настройки корреляции между компонентами
- ❌ Зависимость от архитектуры развертывания
- ❌ Высокий порог входа для правильной интерпретации
Нюансы:
- События шлюза (300-304) критичны для гибридных сред
- Session Broker события требуют понимания топологии фермы
- Лицензионные события (Event ID 44) указывают на потенциальные проблемы compliance
9.1.4. Сетевые и брандмауэрные события
Ключевые источники:
- Брандмауэр Windows (Event ID 2003-2006)
- Фильтрация подключений (Security Event ID 5156)
- Протокольные события RDP
Сильные стороны:
- ✅ Обнаружение сканирования портов и bruteforce
- ✅ Геолокация атак по IP-адресам
- ✅ Контроль политик доступа в реальном времени
- ✅ Мониторинг аномального трафика
Слабые стороны:
- ❌ Очень высокий объем в публичных средах
- ❌ Недостаток контекста приложения
- ❌ Сложность фильтрации легитимного трафика
Нюансы:
- Event ID 5156 предоставляет детальную информацию о фильтрации на уровне процесса
- Брандмауэрные события требуют настройки аудита успешных/неудачных подключений
- Протокольные события RDP полезны для диагностики, но создают шум
9.1.5. Матрица приоритетов сбора RDP-событий
quadrantChart
title RDP Events Collection Priority Matrix 2025
x-axis "Low Frequency" --> "High Frequency"
y-axis "Low Value" --> "High Value"
quadrant-1 " "
quadrant-2 " "
quadrant-3 "Low Value / Low Frequency"
quadrant-4 "Low Value / High Frequency"
%% КВАДРАНТ I: Высокая ценность, Высокая частота
"4624/4625": [0.95, 0.95]
"LSM21-25": [0.85, 0.92]
"FW2003-2006": [0.92, 0.85]
"RCM1149": [0.88, 0.88]
"4634/4647": [0.75, 0.82]
"4778/4779": [0.65, 0.75]
"RDPC131": [0.72, 0.78]
"GW300": [0.82, 0.8]
"4768/4771": [0.68, 0.9]
%% КВАДРАНТ II: Высокая ценность, Низкая частота
"1102": [0.05, 0.95]
"4648": [0.12, 0.92]
"Lic44": [0.08, 0.88]
"4769/4776": [0.15, 0.85]
"4672": [0.1, 0.82]
"GW302-303": [0.18, 0.9]
"BRK1001": [0.22, 0.78]
"4627": [0.25, 0.72]
"4635": [0.28, 0.68]
%% КВАДРАНТ III: Низкая ценность, Низкая частота
"Sys7036": [0.05, 0.05]
"SysTLS": [0.15, 0.15]
"RDPC50": [0.25, 0.25]
"GW310": [0.35, 0.35]
"Lic202": [0.45, 0.45]
"1000": [0.1, 0.3]
"39/40": [0.3, 0.1]
"1025": [0.2, 0.2]
%% КВАДРАНТ IV: Низкая ценность, Высокая частота
"RDPC200": [0.95, 0.05]
"RDPC98": [0.85, 0.15]
"FW_traffic": [0.75, 0.08]
"TCP_KA": [0.65, 0.12]
"Heartbeat": [0.55, 0.18]
"1024": [0.6, 0.25]
"Perf": [0.7, 0.22]
"NLA_Info": [0.8, 0.1]9.1.6. Рекомендации по внедрению:
1. Критические события (Квадрант I)
Сбор в реальном времени с агрегацией:
- Включить во все SIEM-правила корреляции
- Настроить оповещения на аномалии (ночные подключения, множественные неудачи)
- Хранить не менее 90 дней для расследований инцидентов
2. Приоритетные события (Квадрант II)
Сбор с высокой детализацией:
- Мониторинг в режиме near-real-time
- Особое внимание к событиям очистки журналов (1102) — возможный признак сокрытия взлома
- Интеграция с системами управления привилегированными доступами
3. Фоновые события (Квадрант III)
Выборочный сбор и хранение:
- Достаточно суточных агрегатов для трендов
- Полезны для capacity planning и диагностики
- Хранение 30-60 дней
4. Шумовые события (Квадрант IV)
Агрегированный сбор или исключение:
- Использовать sampling для анализа трендов
- Возможно исключение из централизованного сбора
- Рассмотреть локальное хранение с коротким сроком
Оптимизация в 2025 году:
- Интеллектуальная фильтрация на основе машинного обучения для выделения аномалий
- Контекстуальное обогащение событий данными из CMDB и Active Directory
- Автоматическая классификация сессий (административные, пользовательские, служебные)
- Интеграция с Zero Trust платформами для динамической оценки рисков
- Использование ETW для снижения нагрузки вместо традиционного EventLog
Данная стратегия обеспечивает баланс между полнотой мониторинга и производительностью системы, что особенно критично в современных распределенных и гибридных средах.
9.2 Минимальный набор для RdpMon++
Уровень 1 (Базовый мониторинг):
event_sources:
security:
- 4624 # Successful logon
- 4625 # Failed logon
- 4634 # Logoff
- 4647 # User-initiated logoff
- 4648 # Explicit credentials
terminal_services:
- LSM: [21, 22, 23, 24, 25] # Session management
- RCM: [1149] # Connection start
firewall:
- 2003 # Allowed inbound
- 2005 # Blocked inbound
Уровень 2 (Расширенная безопасность):
event_sources:
security_extended:
- 4768 # Kerberos TGT
- 4769 # Kerberos TGS
- 4771 # Kerberos pre-auth failure
- 4776 # NTLM authentication
- 4778 # Session reconnect
- 4779 # Session disconnect
protocol:
- RDPCoreTS: [98, 131, 140] # Protocol errors
nla:
- System: [36874, 36888] # TLS/Schannel
Уровень 3 (Полное покрытие):
event_sources:
enterprise:
- Gateway: [300, 302, 303] # RD Gateway
- Broker: [1001, 1100-1199] # Session Broker
- Licensing: [44, 100-103] # RDS Licensing
- Client: [1024-1030] # RDP Client
9.3 Логическая модель данных
Нормализованная схема событий
CREATE TABLE rdp_events_normalized (
-- Идентификация
event_id UUID PRIMARY KEY,
correlation_id UUID,
-- Источник
source_system VARCHAR(50),
original_event_id INTEGER,
provider_name VARCHAR(100),
-- Временные метки
event_time TIMESTAMPTZ,
ingested_time TIMESTAMPTZ DEFAULT NOW(),
-- Учетные данные
user_name VARCHAR(255),
user_domain VARCHAR(255),
user_sid VARCHAR(255),
-- Сессия
logon_type INTEGER,
session_id VARCHAR(100),
session_name VARCHAR(100),
-- Сеть
source_ip INET,
source_port INTEGER,
destination_ip INET,
destination_port INTEGER,
-- Аутентификация
auth_protocol VARCHAR(50),
status_code VARCHAR(50),
sub_status VARCHAR(50),
-- Обогащенные данные
geo_country VARCHAR(2),
geo_city VARCHAR(100),
threat_score INTEGER,
-- Оригинал
raw_xml TEXT,
metadata JSONB
);
-- Индексы
CREATE INDEX idx_rdp_events_time ON rdp_events_normalized USING BRIN(event_time);
CREATE INDEX idx_rdp_events_user ON rdp_events_normalized(user_name, user_domain);
CREATE INDEX idx_rdp_events_ip ON rdp_events_normalized(source_ip);
CREATE INDEX idx_rdp_events_session ON rdp_events_normalized(session_id);
CREATE INDEX idx_rdp_events_correlation ON rdp_events_normalized(correlation_id);
Агрегированные представления
IP-агрегаты (ежедневные):
CREATE MATERIALIZED VIEW ip_aggregates_daily AS
SELECT
source_ip,
DATE(event_time) as event_date,
COUNT(*) as total_events,
COUNT(DISTINCT user_name) as unique_users,
SUM(CASE WHEN original_event_id = 4624 THEN 1 ELSE 0 END) as success_logons,
SUM(CASE WHEN original_event_id = 4625 THEN 1 ELSE 0 END) as failed_logons,
MIN(event_time) as first_seen,
MAX(event_time) as last_seen,
MODE() WITHIN GROUP (ORDER BY geo_country) as common_country
FROM rdp_events_normalized
WHERE event_time > NOW() - INTERVAL '30 days'
GROUP BY source_ip, DATE(event_time);
Сессионная аналитика:
CREATE VIEW session_analytics AS
WITH session_events AS (
SELECT
session_id,
user_name,
user_domain,
source_ip,
MIN(event_time) as session_start,
MAX(event_time) as session_end,
COUNT(*) as event_count,
ARRAY_AGG(DISTINCT original_event_id) as event_types
FROM rdp_events_normalized
WHERE session_id IS NOT NULL
GROUP BY session_id, user_name, user_domain, source_ip
)
SELECT
*,
EXTRACT(EPOCH FROM (session_end - session_start)) as duration_seconds,
CASE
WHEN 4778 = ANY(event_types) THEN TRUE
ELSE FALSE
END as had_reconnect,
CASE
WHEN 4779 = ANY(event_types) THEN TRUE
ELSE FALSE
END as had_disconnect
FROM session_events;
9.4 Пайплайн обработки событий
flowchart TD
A[Raw Event Sources] --> B{Event Router}
B --> C[Security Events]
B --> D[Terminal Services]
B --> E[Firewall Events]
B --> F[Other Sources]
C --> G[Parser & Normalizer]
D --> G
E --> G
F --> G
G --> H[Enrichment Engine]
H --> I[GeoIP Lookup]
H --> J[Threat Intel]
H --> K[User Context]
I & J & K --> L[Correlation Engine]
L --> M[Session Builder]
L --> N[Threat Detector]
M --> O[Session Database]
N --> P[Alert Generator]
O --> Q[Analytics & Reporting]
P --> R[SIEM Integration]
Q --> S[Dashboards]
R --> T[Security Alerts]10. Архитектура сбора событий RDP
10.1 Современные механизмы сбора
ETW (Event Tracing for Windows)
// Пример подписки на ETW события RDP
using (var session = new TraceEventSession("RdpMonitoringSession"))
{
// Подписка на Security события
session.EnableProvider(
"Microsoft-Windows-Security-Auditing",
TraceEventLevel.Verbose,
0xFFFFFFFFFFFFFFFF,
new TraceEventProviderOptions
{
EventIDs = "4624-4625,4634,4647,4648,4768-4779"
});
// Подписка на Terminal Services
session.EnableProvider(
"Microsoft-Windows-TerminalServices-LocalSessionManager",
TraceEventLevel.Informational);
session.Source.Dynamic.All += eventData =>
{
// Обработка события
ProcessRdpEvent(eventData);
};
session.Source.Process();
}
EventLog API (для исторических данных)
# PowerShell сбор исторических событий
$Events = Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4624,4625,4634,4647,4648
StartTime = (Get-Date).AddDays(-1)
} -MaxEvents 10000
$Events | ForEach-Object {
$xml = [xml]$_.ToXml()
# Обработка XML
}
10.2 Приоритеты сбора 2025
Таблица приоритетов:
| Уровень | Источники | Механизм | Частота | Retention |
|---|---|---|---|---|
| P0 | Security 4624/4625 | ETW Real-time | 100% | 90 дней |
| P1 | LSM 21-25, RCM 1149 | ETW Real-time | 100% | 60 дней |
| P2 | Firewall 2003-2006 | ETW Buffered | 100% | 30 дней |
| P3 | Kerberos 4768-4771 | EventLog Polling | 100% | 30 дней |
| P4 | Gateway, Broker | EventLog Polling | 100% | 30 дней |
| P5 | RDPCoreTS, System | EventLog Sampling | 10% | 14 дней |
10.3 Распределенная архитектура
graph TB
subgraph "Agents (Windows Servers)"
A1[Agent 1: RDSH01]
A2[Agent 2: RDSH02]
A3[Agent 3: Gateway]
A4[Agent 4: Broker]
end
subgraph "Collector Tier"
B1[Event Collector 1]
B2[Event Collector 2]
B3[Load Balancer]
end
subgraph "Processing Tier"
C1[Parser]
C2[Enricher]
C3[Correlator]
end
subgraph "Storage Tier"
D1[Hot: TimescaleDB]
D2[Warm: EventStoreDB]
D3[Cold: S3 + RocksDB]
end
subgraph "Analytics Tier"
E1[Real-time Alerts]
E2[Dashboards]
E3[Reports]
end
A1 & A2 & A3 & A4 --> B3
B3 --> B1 & B2
B1 & B2 --> C1
C1 --> C2 --> C3
C3 --> D1 & D2 & D3
D1 --> E1 & E2 & E311. Блок-схема генерации событий RDP
11.1 Полная последовательность событий
sequenceDiagram
participant Client
participant Firewall
participant Gateway
participant NLA
participant DC as Domain Controller
participant RCM as RemoteConnectionManager
participant LSM as LocalSessionManager
participant Security
participant RDPCore
participant Broker
participant Licensing
Note over Client,Licensing: Этап 1: Сетевое подключение
Client->>Firewall: TCP SYN:3389
Firewall-->>Firewall: Event 2003/2005
Firewall->>RCM: TCP Handshake
RCM-->>RCM: Event 1149 (RDP Client Active)
Note over Client,Licensing: Этап 2: NLA/TLS Negotiation
RCM->>NLA: NLA Request
NLA->>DC: Authentication Request
DC-->>NLA: Authentication Result
alt NLA Success
NLA-->>Security: Event 4768/4769 (Kerberos)
NLA-->>RDPCore: TLS Established
else NLA Failure
NLA-->>RDPCore: Event 140 (Error)
NLA-->>Security: Event 4771/4776 (Failure)
end
Note over Client,Licensing: Этап 3: Аутентификация
RCM->>Security: Logon Request
alt Authentication Success
Security-->>Security: Event 4624 (Success)
Security->>Licensing: License Check
Licensing-->>Licensing: Event 101 (Issued)
else Authentication Failure
Security-->>Security: Event 4625 (Failure)
end
Note over Client,Licensing: Этап 4: Сессия и балансировка
alt Through Gateway
Client->>Gateway: HTTPS Connect
Gateway-->>Gateway: Event 300 (Gateway Connect)
Gateway->>Broker: Session Request
else Direct Connection
RCM->>Broker: Session Request
end
Broker-->>Broker: Event 1001 (Session Redirect)
Broker->>LSM: Create Session
Note over Client,Licensing: Этап 5: Создание сессии
LSM-->>LSM: Event 22 (Session Create)
LSM-->>LSM: Event 21 (Session Connect)
LSM-->>Security: Session Established
Security-->>Security: Event 4624 (LogonType 10)
Note over Client,Licensing: Этап 6: Активная сессия
loop Периодические события
RDPCore-->>RDPCore: Event 200 (Stats)
LSM-->>LSM: Heartbeat
end
Note over Client,Licensing: Этап 7: Отключение/Переподключение
alt Client Disconnect
Client->>LSM: Disconnect
LSM-->>LSM: Event 23 (Disconnect)
LSM-->>Security: Event 4779 (Disconnected)
end
alt Client Reconnect
Client->>LSM: Reconnect
LSM-->>LSM: Event 25 (Reconnect)
LSM-->>Security: Event 4778 (Reconnected)
end
Note over Client,Licensing: Этап 8: Завершение сессии
alt User Logoff
Client->>LSM: Logoff
LSM-->>LSM: Event 24 (Logoff)
LSM-->>Security: Event 4634 (Logoff)
Security-->>Security: Event 4647 (User Initiated)
Licensing-->>Licensing: Event 301 (License Released)
end
Note over Client,Licensing: Этап 9: Очистка
RCM-->>RCM: Event 1150 (Connection Closed)
Firewall-->>Firewall: TCP FIN11.2 Временные диаграммы
Нормальное подключение:
Time (ms) | Event
----------|------
0 | Firewall 2003
50 | RCM 1149
200 | Security 4768 (Kerberos)
400 | Security 4624 (Success)
600 | LSM 22 (Session Create)
800 | LSM 21 (Session Connect)
Атака подбора паролей:
Time (ms) | Event
----------|------
0 | Firewall 2003
50 | RCM 1149
100 | Security 4625 (Failure - 0xC000006A)
200 | Security 4625 (Failure - 0xC000006A)
300 | Security 4625 (Failure - 0xC000006A)
... | ...
5000 | Security 4624 (Success - компрометация)
12. Рекомендации по реализации системы мониторинга
12.1 Технологический стек 2025
Рекомендуемый стек:
programming_language: C# 12 / .NET 8
runtime: Windows Service / .NET Worker Service
event_collection: ETW (Microsoft.Diagnostics.Tracing.TraceEvent)
service_management: Topshelf / Windows Service Wrapper
storage_hot: TimescaleDB 2.10+ / PostgreSQL 16
storage_warm: EventStoreDB 22.10+
storage_cold: Azure Blob Storage / AWS S3 + RocksDB
caching: Redis 7.2 / Azure Cache for Redis
message_queue: Azure Service Bus / RabbitMQ
monitoring: Prometheus + Grafana / Azure Monitor
logging: Serilog + Seq / Elastic Stack
12.2 Архитектурные паттерны
Микросервисная архитектура
graph TB
subgraph "Event Collection"
A1[ETW Collector]
A2[EventLog Collector]
A3[WTS API Collector]
A4[Firewall Collector]
end
subgraph "Event Processing"
B1[Parser Service]
B2[Enrichment Service]
B3[Correlation Service]
B4[Alert Service]
end
subgraph "Data Storage"
C1[Events DB]
C2[Sessions DB]
C3[Aggregates DB]
C4[Archive Storage]
end
subgraph "API Layer"
D1[REST API]
D2[GraphQL API]
D3[gRPC API]
end
subgraph "Clients"
E1[Web Dashboard]
E2[CLI Tool]
E3[SIEM Connectors]
E4[Mobile App]
end
A1 & A2 & A3 & A4 --> B1
B1 --> B2 --> B3 --> B4
B3 --> C1 & C2 & C3
C1 --> C4
C1 & C2 & C3 --> D1 & D2 & D3
D1 & D2 & D3 --> E1 & E2 & E3 & E4Конфигурация как код
# config.yaml
version: '3.0'
event_sources:
security:
enabled: true
providers:
- name: Microsoft-Windows-Security-Auditing
event_ids: [4624, 4625, 4634, 4647, 4648]
keywords: 0x8020000000000000
terminal_services:
enabled: true
providers:
- name: Microsoft-Windows-TerminalServices-LocalSessionManager
event_ids: [21, 22, 23, 24, 25]
- name: Microsoft-Windows-TerminalServices-RemoteConnectionManager
event_ids: [1149, 1150]
storage:
layers:
- name: hot
type: timescaledb
retention: 7d
compression: after 1d
- name: warm
type: eventstoredb
retention: 30d
- name: cold
type: azure_blob
retention: 365d
enrichment:
geoip:
enabled: true
database: GeoLite2-City
update_frequency: weekly
threat_intel:
enabled: true
sources:
- abuseipdb
- virustotal
- alienvault_otx
alerting:
rules:
- name: brute_force_detection
condition: "count(4625) > 10 within 5m by source_ip"
severity: high
actions: [email, slack, siem]
- name: successful_compromise
condition: "4625 followed by 4624 within 60s same source_ip user"
severity: critical
actions: [block_ip, email_admin, siem]
12.3 Производительность и масштабирование
Бенчмарки (2025):
| Метрика | Ожидаемое значение | Метод достижения |
|---|---|---|
| Событий в секунду | 10,000+ | Асинхронная обработка |
| Задержка обработки | < 100ms | In-memory буферизация |
| Хранение событий | 1M+/сек | TimescaleDB гипартаблицы |
| Поиск по истории | < 1s | Columnar индексы |
| Доступность | 99.99% | Кластеризация + репликация |
Оптимизации:
public class HighPerformanceEventProcessor
{
private readonly Channel<RdpEvent> _eventChannel;
private readonly IEventStorage _storage;
public HighPerformanceEventProcessor()
{
// Канал с высокой пропускной способностью
_eventChannel = Channel.CreateBounded<RdpEvent>(
new BoundedChannelOptions(10000)
{
FullMode = BoundedChannelFullMode.Wait,
SingleWriter = false,
SingleReader = false
});
}
public async Task ProcessEventsAsync(CancellationToken cancellationToken)
{
var tasks = new List<Task>();
// Множество воркеров для параллельной обработки
for (int i = 0; i < Environment.ProcessorCount; i++)
{
tasks.Add(Task.Run(async () =>
{
await foreach (var event in _eventChannel.Reader.ReadAllAsync(cancellationToken))
{
await ProcessSingleEventAsync(event, cancellationToken);
}
}, cancellationToken));
}
await Task.WhenAll(tasks);
}
private async Task ProcessSingleEventAsync(RdpEvent event, CancellationToken cancellationToken)
{
// Пакетная запись для оптимизации
await _storage.BatchInsertAsync(new[] { event }, cancellationToken);
}
}
12.4 Безопасность реализации
Принципы безопасности:
- Минимальные привилегии: Служба работает под отдельной учетной записью
- Шифрование данных: TLS 1.3 для передачи, AES-256 для хранения
- Аудит доступа: Логирование всех операций с событиями
- Валидация входных данных: Проверка XML/JSON перед обработкой
- Защита от переполнения: Лимиты на размер сообщений и частоту
Конфигурация безопасности:
# Создание service account
$Password = ConvertTo-SecureString "ComplexP@ssw0rd!" -AsPlainText -Force
New-LocalUser -Name "RdpMonitorSvc" -Password $Password -Description "RDP Monitoring Service Account"
# Назначение минимальных прав
$Privileges = @(
"SeServiceLogonRight",
"SeAuditPrivilege",
"SeSecurityPrivilege"
)
foreach ($priv in $Privileges) {
& ntrights +r $priv -u "RdpMonitorSvc"
}
13. Приложение: структуры данных для хранения
13.1 Полная реляционная схема
-- Основная таблица событий
CREATE TABLE rdp_events (
event_uuid UUID DEFAULT gen_random_uuid() PRIMARY KEY,
event_time TIMESTAMPTZ NOT NULL,
ingested_time TIMESTAMPTZ DEFAULT NOW(),
-- Источник
source_system VARCHAR(50) NOT NULL,
event_id INTEGER NOT NULL,
event_name VARCHAR(100),
computer_name VARCHAR(255),
-- Пользователь
user_name VARCHAR(255),
user_domain VARCHAR(255),
user_sid VARCHAR(255),
logon_type INTEGER,
-- Сессия
session_id VARCHAR(100),
session_name VARCHAR(100),
-- Сеть
source_ip INET,
source_port INTEGER,
dest_ip INET,
dest_port INTEGER,
protocol VARCHAR(10),
-- Аутентификация
auth_package VARCHAR(50),
status_code VARCHAR(50),
sub_status VARCHAR(50),
failure_reason TEXT,
-- Обогащение
geo_country_code CHAR(2),
geo_city VARCHAR(100),
threat_score INTEGER DEFAULT 0,
-- Технические поля
raw_xml XML,
processed BOOLEAN DEFAULT FALSE,
correlation_id UUID,
-- Индексы
CONSTRAINT idx_event_time_range EXCLUDE USING gist (
tsrange(event_time, event_time + INTERVAL '1 second') WITH &&
)
);
-- Таблица сессий
CREATE TABLE rdp_sessions (
session_uuid UUID DEFAULT gen_random_uuid() PRIMARY KEY,
session_id VARCHAR(100) NOT NULL,
user_name VARCHAR(255) NOT NULL,
user_domain VARCHAR(255) NOT NULL,
-- Временные метки
start_time TIMESTAMPTZ NOT NULL,
end_time TIMESTAMPTZ,
last_activity TIMESTAMPTZ,
-- Сеть
source_ip INET NOT NULL,
server_name VARCHAR(255) NOT NULL,
client_name VARCHAR(255),
-- Состояние
status VARCHAR(20) DEFAULT 'ACTIVE',
reconnect_count INTEGER DEFAULT 0,
disconnect_count INTEGER DEFAULT 0,
-- Ресурсы
bytes_sent BIGINT DEFAULT 0,
bytes_received BIGINT DEFAULT 0,
cpu_time_ms BIGINT DEFAULT 0,
memory_kb INTEGER DEFAULT 0,
-- Метаданные
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
-- Индексы
UNIQUE(session_id, server_name),
INDEX idx_sessions_user (user_name, start_time),
INDEX idx_sessions_status (status, last_activity)
);
-- Таблица агрегатов по IP
CREATE TABLE ip_aggregates (
ip_address INET PRIMARY KEY,
first_seen TIMESTAMPTZ NOT NULL,
last_seen TIMESTAMPTZ NOT NULL,
-- Статистика
total_events INTEGER DEFAULT 0,
success_count INTEGER DEFAULT 0,
failure_count INTEGER DEFAULT 0,
-- Пользователи
unique_users INTEGER DEFAULT 0,
last_user VARCHAR(255),
last_domain VARCHAR(255),
-- Геолокация
country_code CHAR(2),
city VARCHAR(100),
isp VARCHAR(255),
-- Threat Intelligence
threat_level VARCHAR(20) DEFAULT 'LOW',
threat_indicators JSONB DEFAULT '[]',
reputation_score INTEGER DEFAULT 50,
-- Метки
tags VARCHAR(255)[] DEFAULT '{}',
is_whitelisted BOOLEAN DEFAULT FALSE,
is_blacklisted BOOLEAN DEFAULT FALSE,
-- Обновление
updated_at TIMESTAMPTZ DEFAULT NOW(),
-- Индексы
INDEX idx_ip_agg_seen (last_seen),
INDEX idx_ip_agg_threat (threat_level),
INDEX idx_ip_agg_tags (tags)
);
-- Таблица процессов
CREATE TABLE session_processes (
process_uuid UUID DEFAULT gen_random_uuid() PRIMARY KEY,
session_uuid UUID NOT NULL REFERENCES rdp_sessions(session_uuid),
-- Идентификация
process_id INTEGER NOT NULL,
process_name VARCHAR(255) NOT NULL,
executable_path TEXT,
command_line TEXT,
-- Временные метки
start_time TIMESTAMPTZ NOT NULL,
end_time TIMESTAMPTZ,
-- Контекст
user_name VARCHAR(255),
integrity_level VARCHAR(20),
parent_process_id INTEGER,
-- Безопасность
file_hash_sha256 CHAR(64),
file_hash_md5 CHAR(32),
digital_signature TEXT,
-- Ресурсы
cpu_percent NUMERIC(5,2),
memory_mb INTEGER,
-- Индексы
INDEX idx_proc_session (session_uuid, start_time),
INDEX idx_proc_name (process_name),
INDEX idx_proc_hash (file_hash_sha256)
);
13.2 Оптимизированные запросы для анализа
Поиск аномальных сессий:
WITH session_metrics AS (
SELECT
s.session_uuid,
s.user_name,
s.start_time,
s.end_time,
s.bytes_sent,
s.bytes_received,
EXTRACT(EPOCH FROM (s.end_time - s.start_time)) as duration_seconds,
COUNT(DISTINCT p.process_name) as unique_processes,
MAX(p.cpu_percent) as max_cpu_percent
FROM rdp_sessions s
LEFT JOIN session_processes p ON s.session_uuid = p.session_uuid
WHERE s.end_time IS NOT NULL
AND s.start_time > NOW() - INTERVAL '7 days'
GROUP BY s.session_uuid, s.user_name, s.start_time, s.end_time,
s.bytes_sent, s.bytes_received
)
SELECT
user_name,
COUNT(*) as session_count,
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY duration_seconds) as median_duration,
PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY duration_seconds) as p95_duration,
AVG(unique_processes) as avg_processes,
MAX(max_cpu_percent) as max_cpu_observed
FROM session_metrics
GROUP BY user_name
HAVING COUNT(*) > 5
AND MAX(duration_seconds) > 3600 * 8 -- Сессии длиннее 8 часов
OR MAX(max_cpu_percent) > 90 -- Высокая загрузка CPU
ORDER BY session_count DESC;
Обнаружение горизонтального перемещения:
WITH lateral_movement_candidates AS (
SELECT
e1.event_time as time1,
e1.user_name,
e1.computer_name as source_host,
e1.source_ip,
e2.event_time as time2,
e2.computer_name as target_host,
EXTRACT(EPOCH FROM (e2.event_time - e1.event_time)) as time_diff_seconds
FROM rdp_events e1
INNER JOIN rdp_events e2 ON
e1.user_name = e2.user_name
AND e1.source_ip = e2.source_ip
AND e1.event_id = 4648 -- Explicit Credentials
AND e2.event_id = 4624 -- Successful Logon
AND e2.event_time > e1.event_time
AND e2.event_time < e1.event_time + INTERVAL '5 minutes'
WHERE e1.event_time > NOW() - INTERVAL '1 day'
AND e1.computer_name != e2.computer_name -- Разные хосты
)
SELECT
user_name,
source_host,
target_host,
source_ip,
COUNT(*) as occurrence_count,
MIN(time_diff_seconds) as min_time_diff,
AVG(time_diff_seconds) as avg_time_diff
FROM lateral_movement_candidates
GROUP BY user_name, source_host, target_host, source_ip
HAVING COUNT(*) > 1 -- Многократные попытки
ORDER BY occurrence_count DESC;
13.3 Конфигурация TimescaleDB для RDP-событий
-- Создание гипартаблицы
SELECT create_hypertable(
'rdp_events',
'event_time',
chunk_time_interval => INTERVAL '1 day',
create_default_indexes => FALSE
);
-- Оптимизированные индексы
CREATE INDEX idx_rdp_events_time_id ON rdp_events (event_time, event_id)
WITH (timescaledb.transaction_per_chunk);
CREATE INDEX idx_rdp_events_user_time ON rdp_events (user_name, event_time DESC)
WITH (timescaledb.transaction_per_chunk);
CREATE INDEX idx_rdp_events_ip_time ON rdp_events (source_ip, event_time DESC)
WITH (timescaledb.transaction_per_chunk);
CREATE INDEX idx_rdp_events_session ON rdp_events (session_id, event_time)
WHERE session_id IS NOT NULL
WITH (timescaledb.transaction_per_chunk);
-- Политика сжатия
ALTER TABLE rdp_events SET (
timescaledb.compress,
timescaledb.compress_segmentby = 'event_id, source_system',
timescaledb.compress_orderby = 'event_time DESC'
);
-- Расписание сжатия
SELECT add_compression_policy('rdp_events', INTERVAL '7 days');
-- Политика удержания данных
SELECT add_retention_policy('rdp_events', INTERVAL '90 days');
-- Непрерывные агрегаты
CREATE MATERIALIZED VIEW rdp_events_hourly
WITH (timescaledb.continuous) AS
SELECT
time_bucket('1 hour', event_time) as bucket,
source_ip,
user_name,
COUNT(*) as event_count,
SUM(CASE WHEN event_id = 4624 THEN 1 ELSE 0 END) as success_count,
SUM(CASE WHEN event_id = 4625 THEN 1 ELSE 0 END) as failure_count,
COUNT(DISTINCT session_id) as unique_sessions
FROM rdp_events
GROUP BY bucket, source_ip, user_name;
-- Расписание обновления агрегатов
SELECT add_continuous_aggregate_policy('rdp_events_hourly',
start_offset => INTERVAL '1 hour',
end_offset => INTERVAL '5 minutes',
schedule_interval => INTERVAL '15 minutes'
);
13.4 Экспорт данных для SIEM-систем
Формат CEF (Common Event Format):
CEF:0|RdpMonitor|3.0|100|RDP_LOGON_SUCCESS|Successful RDP Logon|10|
src=192.168.1.100 dst=10.0.0.10 dpt=3389 \
suser=jsmith duser=jsmith outcome=success \
cat=Authentication/Access msg=User jsmith logged in via RDP \
rt=Jan 15 2025 10:30:00.123Z cs1Label=LogonType cs1=10 \
cs2Label=SessionID cs2=S-1-5-21-... cs3Label=SourceWorkstation cs3=CLIENT-PC
Формат JSON для Elasticsearch:
{
"@timestamp": "2025-01-15T10:30:00.123Z",
"event": {
"provider": "Microsoft-Windows-Security-Auditing",
"id": 4624,
"action": "logon",
"outcome": "success",
"type": ["authentication", "connection"]
},
"user": {
"name": "jsmith",
"domain": "CONTOSO"
},
"source": {
"ip": "192.168.1.100",
"port": 56842,
"geo": {
"country_name": "United States",
"city_name": "Seattle"
}
},
"destination": {
"ip": "10.0.0.10",
"port": 3389
},
"rdp": {
"logon_type": 10,
"session_id": "S-1-5-21-...",
"protocol": "RDP 10.9",
"encryption": "TLS 1.2"
},
"threat": {
"score": 0,
"indicators": []
}
}
Глава 14: Механизмы сбора событий: ETW vs EventLog API
14.1 Введение в механизмы сбора
В Windows существует два основных механизма сбора системных событий: Event Tracing for Windows (ETW) и EventLog API. Понимание различий между этими подходами критически важно для проектирования высокопроизводительной системы мониторинга RDP.
graph TB
A[Источники событий Windows] --> B{Выбор механизма сбора}
B --> C[ETW - Real-time]
B --> D[EventLog API - Historical]
subgraph "ETW Архитектура"
C --> E[Ядро Windows]
E --> F[Буфер в памяти]
F --> G[Потребители в реальном времени]
end
subgraph "EventLog Архитектура"
D --> H[Файлы .evtx на диске]
H --> I[Опрос по расписанию]
I --> J[Исторический анализ]
end
G --> K[Низкая задержка <100ms]
J --> L[Высокая задержка 1s+]14.2 Event Tracing for Windows (ETW)
14.2.1 Архитектура ETW
ETW представляет собой высокопроизводительную, масштабируемую систему трассировки, встроенную в ядро Windows.
Компоненты архитектуры:
graph LR
A[Поставщики Providers] --> B[Контроллеры Controllers]
B --> C[Сессии Sessions]
C --> D[Буферы в ядре]
D --> E[Потребители Consumers]
E --> F[Обработка в реальном времени]
subgraph "Поставщики событий"
A1[Microsoft-Windows-Security-Auditing]
A2[Microsoft-Windows-TerminalServices]
A3[Microsoft-Windows-RDP]
end
subgraph "Типы потребителей"
E1[In-process - .NET Apps]
E2[Out-of-process - Services]
E3[Системные - PerfMon]
end14.2.2 Ключевые преимущества ETW
- Реальное время: События доставляются немедленно
- Высокая производительность: Минимальные накладные расходы
- Фильтрация в ядре: Снижение нагрузки на пользовательское пространство
- Структурированные данные: Бинарный формат вместо XML
- Гибкая подписка: Динамическое включение/выключение поставщиков
14.2.3 Технические характеристики ETW
Производительность:
- Пропускная способность: до 1,000,000 событий/сек
- Задержка: 1-10 мс от генерации до потребителя
- Использование CPU: < 1% для типичных сценариев
- Использование памяти: 1-10 МБ на сессию
Ограничения:
// Пример настройки сессии ETW с ограничениями
var sessionProperties = new TraceEventSessionProperties
{
BufferSize = 64, // КБ на буфер
MinimumBuffers = 12, // Минимум буферов
MaximumBuffers = 48, // Максимум буферов
FlushTimer = 1, // Секунды между сбросами
LogFileMode = LogFileMode.Realtime
};
14.3 EventLog API
14.3.1 Архитектура EventLog
EventLog API работает с событиями, уже записанными в файлы журналов (.evtx).
Процесс работы:
Генерация события → Запись в .evtx файл → Чтение через API → Обработка
↑ ↑ ↑
Мгновенно Задержка 0.5-5s Периодический опрос
14.3.2 Ключевые характеристики EventLog
Преимущества:
- Простота использования: Простой API для чтения журналов
- Исторические данные: Доступ к уже сохраненным событиям
- Стандартизация: Единый формат для всех приложений
- Надежность: Гарантированная запись событий
Недостатки:
- Высокая задержка: События доступны только после записи на диск
- Ограниченная производительность: Дисковые операции ограничивают throughput
- Отсутствие реального времени: Только опросный режим
- Нагрузка на систему: Частое чтение журналов создает нагрузку
14.4 Сравнительный анализ
14.4.1 Детальное сравнение
graph TD
A[Сравнение механизмов сбора] --> B[Производительность]
A --> C[Задержка]
A --> D[Ресурсы]
A --> E[Функциональность]
B --> B1[ETW: 1M+ events/sec]
B --> B2[EventLog: 10K events/sec]
C --> C1[ETW: <10ms]
C --> C2[EventLog: 500ms-5s]
D --> D1[ETW: CPU 1%, Memory 10MB]
D --> D2[EventLog: CPU 5-20%, Disk I/O high]
E --> E1[ETW: Real-time, Filtering, Structured]
E --> E2[EventLog: Historical, Simple, XML]14.4.2 Сравнительная таблица
| Критерий | ETW (Event Tracing for Windows) | EventLog API |
|---|---|---|
| Режим работы | Реальный времени (push) | Опросный (poll) |
| Задержка | 1-10 мс | 500 мс — 5 секунд |
| Пропускная способность | До 1,000,000 событий/сек | До 10,000 событий/сек |
| Использование CPU | 0.5-2% | 5-20% (при активном опросе) |
| Использование памяти | 5-50 МБ (зависит от буферов) | 10-100 МБ (кеширование) |
| Дисковый I/O | Минимальный | Высокий (чтение .evtx) |
| Фильтрация | На уровне ядра (высокая эффективность) | На уровне приложения (низкая эффективность) |
| Формат данных | Структурированный бинарный | XML (текстовый) |
| Размер данных | Компактный (30-50% от XML) | Полный XML (большой объем) |
| Исторические данные | Нет (только реальное время) | Да (полный доступ к журналам) |
| Надежность доставки | Возможна потеря при перегрузке | Гарантированная запись |
| Сложность реализации | Высокая (требует знания ETW) | Низкая (простой API) |
| Поддержка в .NET | Microsoft.Diagnostics.Tracing.TraceEvent | System.Diagnostics.Eventing.Reader |
| Масштабируемость | Очень высокая (кластеры серверов) | Ограниченная (один сервер) |
| Влияние на систему | Минимальное | Значительное при частом опросе |
| Требуемые права | Администратор (для сессий) | Чтение журналов |
| Поддержка в PowerShell | Limited (Get-WinEvent -FilterXPath) | Полная (Get-EventLog, Get-WinEvent) |
| Совместимость | Windows Vista+ | Windows 2000+ |
| Отладка | Сложная (требуются спец. инструменты) | Простая (можно просмотреть в Event Viewer) |
14.4.3 Сравнение по сценариям использования RDP
Для каких событий RDP использовать ETW:
etw_recommended:
# Критичные события безопасности (нужны немедленно)
- "Security 4624/4625" # Аутентификация
- "Security 4648" # Явные учетные данные
- "Security 1102" # Очистка журнала
# Управление сессиями (реальное время)
- "TerminalServices-LocalSessionManager 21-25"
- "TerminalServices-RemoteConnectionManager 1149"
# Сетевые события
- "Windows Firewall 2003-2006"
# Протокольные события (диагностика)
- "RDPCoreTS 131, 140"
Для каких событий RDP использовать EventLog:
eventlog_recommended:
# Исторический анализ
- "Старые события (>24 часов)"
- "Аудит за прошлые периоды"
# Редкие события (не критично к задержке)
- "Licensing 44" # Ошибки лицензий
- "System 7036" # Запуск служб
# События, где нужна гарантированная доставка
- "Критичные аудиторские события"
# Когда ETW недоступен
- "Windows Server 2003/2008"
- "Системы без прав администратора"
14.5 Производительность и метрики
14.5.1 Тесты производительности (RDP-события)
Результаты тестирования на Windows Server 2022:
Сценарий: 1000 RDP-подключений в минуту
ETW сбор:
- Событий/сек: 850-950
- Задержка P50: 8 мс
- Задержка P95: 15 мс
- CPU использование: 1.2%
- Память: 12 МБ
EventLog сбор (опрос каждые 5 сек):
- Событий/сек: 40-60
- Задержка P50: 2.5 с
- Задержка P95: 4.8 с
- CPU использование: 8.5%
- Память: 85 МБ
- Дисковый I/O: 15 МБ/сек
14.5.2 Формулы расчета нагрузки
Для ETW:
Общая нагрузка = (Событий/сек × 0.0001) + (Буферы × 0.5) + (Фильтры × 0.2)
Где:
- Событий/сек: Количество обрабатываемых событий
- Буферы: Количество буферов в сессии (обычно 12-48)
- Фильтры: Количество активных фильтров
Для EventLog:
Общая нагрузка = (Опросов/час × 0.8) + (Событий/опрос × 0.0005) + (Размер журнала × 0.001)
14.6 Примеры реализации
14.6.1 ETW сборщик на C#
using Microsoft.Diagnostics.Tracing;
using Microsoft.Diagnostics.Tracing.Session;
using System;
using System.Threading.Tasks;
namespace RdpMonitor.ETW
{
public class HighPerformanceEtwCollector : IDisposable
{
private readonly TraceEventSession _session;
private readonly Task _processingTask;
private readonly CancellationTokenSource _cancellationTokenSource;
public HighPerformanceEtwCollector()
{
_cancellationTokenSource = new CancellationTokenSource();
// Создание высокопроизводительной сессии ETW
_session = new TraceEventSession(
"RdpMonitorSession",
null, // No file, real-time only
TraceEventSessionOptions.Create);
ConfigureSessionProperties();
EnableProviders();
// Запуск обработки в отдельном потоке
_processingTask = Task.Run(() => ProcessEvents());
}
private void ConfigureSessionProperties()
{
// Оптимальные настройки для RDP-мониторинга
var properties = new TraceEventSessionProperties
{
BufferSizeKB = 64, // 64КБ буферы
MinimumBuffers = 16, // Минимум буферов
MaximumBuffers = 64, // Максимум буферов
FlushTimer = 1000, // Сброс каждую секунду
ClockType = ClockType.PerfCounter, // Высокоточное время
StackWalk = StackWalkType.None // Без стектрейсов для производительности
};
_session.SetSessionProperties(properties);
}
private void EnableProviders()
{
// Security Events (RDP Authentication)
_session.EnableProvider(
"Microsoft-Windows-Security-Auditing",
TraceEventLevel.Verbose,
0x8010000000000000, // Audit Logon keyword
new TraceEventProviderOptions
{
EventIDStacks = new List<int> { 4624, 4625, 4634, 4647, 4648 },
EventIDs = "4624-4625,4634,4647,4648,4768-4779"
});
// Terminal Services Events
_session.EnableProvider(
"Microsoft-Windows-TerminalServices-LocalSessionManager",
TraceEventLevel.Informational,
0xFFFFFFFFFFFFFFFF);
_session.EnableProvider(
"Microsoft-Windows-TerminalServices-RemoteConnectionManager",
TraceEventLevel.Informational,
0xFFFFFFFFFFFFFFFF);
// RDP Protocol Events
_session.EnableProvider(
"Microsoft-Windows-RemoteDesktopServices-RdpCoreTS",
TraceEventLevel.Warning, // Только ошибки и предупреждения
0xFFFFFFFFFFFFFFFF);
}
private void ProcessEvents()
{
// Канал для асинхронной обработки
var channel = System.Threading.Channels.Channel.CreateBounded<TraceEvent>(
new System.Threading.Channels.BoundedChannelOptions(10000)
{
FullMode = System.Threading.Channels.BoundedChannelFullMode.Wait,
SingleWriter = true,
SingleReader = false
});
// Регистрация обработчика
_session.Source.Dynamic.All += eventData =>
{
// Асинхронная запись в канал (не блокируем ETW поток)
channel.Writer.TryWrite(eventData);
};
// Запуск обработчиков (по числу ядер)
var processingTasks = new List<Task>();
for (int i = 0; i < Environment.ProcessorCount; i++)
{
processingTasks.Add(Task.Run(async () =>
{
await foreach (var evt in channel.Reader.ReadAllAsync(
_cancellationTokenSource.Token))
{
ProcessSingleEvent(evt);
}
}));
}
// Запуск обработки ETW
_session.Source.Process();
Task.WaitAll(processingTasks.ToArray());
}
private void ProcessSingleEvent(TraceEvent evt)
{
// Быстрая обработка события
var rdpEvent = new RdpEvent
{
EventId = evt.ID,
ProviderName = evt.ProviderName,
TimeCreated = evt.TimeStamp,
ComputerName = Environment.MachineName,
// ... парсинг полей события
};
// Асинхронная запись в хранилище
_eventRepository.AddAsync(rdpEvent).ConfigureAwait(false);
}
public void Dispose()
{
_cancellationTokenSource.Cancel();
_session?.Stop();
_session?.Dispose();
_processingTask?.Wait(5000);
}
}
public class RdpEvent
{
public int EventId { get; set; }
public string ProviderName { get; set; }
public DateTime TimeCreated { get; set; }
public string ComputerName { get; set; }
// ... другие поля
}
}
14.6.2 EventLog сборщик на C#
using System.Diagnostics.Eventing.Reader;
using System.Xml;
using System.Threading.Channels;
namespace RdpMonitor.EventLog
{
public class EventLogCollector : IDisposable
{
private readonly Timer _pollingTimer;
private readonly Channel<RdpEvent> _eventChannel;
private DateTime _lastPollTime = DateTime.UtcNow.AddMinutes(-5);
public EventLogCollector()
{
_eventChannel = Channel.CreateUnbounded<RdpEvent>();
// Опрос каждые 30 секунд
_pollingTimer = new Timer(PollEvents, null,
TimeSpan.Zero, TimeSpan.FromSeconds(30));
}
private void PollEvents(object state)
{
try
{
// Запрос событий Security
var securityQuery = CreateSecurityQuery();
ReadEventLog("Security", securityQuery);
// Запрос событий Terminal Services
var tsQuery = CreateTerminalServicesQuery();
ReadEventLog("Microsoft-Windows-TerminalServices-LocalSessionManager/Operational",
tsQuery);
_lastPollTime = DateTime.UtcNow;
}
catch (Exception ex)
{
// Логирование ошибки
LogError("EventLog polling failed", ex);
}
}
private string CreateSecurityQuery()
{
return $@"<QueryList>
<Query Id='0' Path='Security'>
<Select Path='Security'>
*[System[
(EventID=4624 or EventID=4625 or EventID=4634 or
EventID=4647 or EventID=4648 or EventID=1102 or
EventID=4768 or EventID=4769 or EventID=4771 or
EventID=4776 or EventID=4778 or EventID=4779)
and TimeCreated[@SystemTime>='{_lastPollTime.ToUniversalTime():o}']
]]
</Select>
</Query>
</QueryList>";
}
private void ReadEventLog(string logName, string query)
{
using (var reader = new EventLogReader(new EventLogQuery(logName,
PathType.LogName, query)))
{
EventRecord record;
while ((record = reader.ReadEvent()) != null)
{
try
{
var rdpEvent = ParseEventRecord(record);
_eventChannel.Writer.TryWrite(rdpEvent);
}
finally
{
record.Dispose();
}
}
}
}
private RdpEvent ParseEventRecord(EventRecord record)
{
var xml = record.ToXml();
var doc = new XmlDocument();
doc.LoadXml(xml);
return new RdpEvent
{
EventId = record.Id,
ProviderName = record.ProviderName,
TimeCreated = record.TimeCreated ?? DateTime.UtcNow,
ComputerName = record.MachineName,
XmlData = xml // Сохраняем XML для дальнейшего парсинга
};
}
public ChannelReader<RdpEvent> EventReader => _eventChannel.Reader;
public void Dispose()
{
_pollingTimer?.Dispose();
_eventChannel.Writer.Complete();
}
}
}
14.7 Гибридный подход для RDP-мониторинга
14.7.1 Архитектура гибридного сбора
graph TB
A[RDP События] --> B{Маршрутизатор}
B --> C[ETW Real-time]
B --> D[EventLog Historical]
subgraph "Real-time Pipeline"
C --> E[Фильтрация в ядре]
E --> F[Буферизация в памяти]
F --> G[Обработка <100ms]
G --> H[Hot Storage]
end
subgraph "Historical Pipeline"
D --> I[Планировщик опросов]
I --> J[Чтение .evtx]
J --> K[Пакетная обработка]
K --> L[Warm/Cold Storage]
end
H --> M[Real-time Analytics]
L --> N[Historical Analytics]
M --> O[Alerting]
N --> P[Reporting]
N --> Q[Compliance]14.7.2 Конфигурация гибридной системы
collection_strategy:
real_time:
mechanism: etw
providers:
- name: Microsoft-Windows-Security-Auditing
event_ids: [4624, 4625, 4634, 4647, 4648]
keywords: 0x8010000000000000
- name: Microsoft-Windows-TerminalServices-LocalSessionManager
event_ids: [21, 22, 23, 24, 25]
- name: Microsoft-Windows-TerminalServices-RemoteConnectionManager
event_ids: [1149, 1150]
performance:
buffer_size_kb: 64
min_buffers: 16
max_buffers: 64
flush_interval_ms: 1000
historical:
mechanism: eventlog
polling_interval_seconds: 30
logs:
- name: Security
query: "*[System[(EventID=4768 or EventID=4769 or EventID=4771 or EventID=4776)]]"
- name: Microsoft-Windows-TerminalServices-Licensing/Admin
query: "*[System[(EventID=44 or EventID=100 or EventID=101)]]"
- name: System
query: "*[System[Provider[@Name='TermService' or @Name='Schannel']]]"
retention:
hot: 7 days
warm: 30 days
cold: 365 days
correlation:
enabled: true
time_window_seconds: 300
match_fields: [session_id, user_name, source_ip]
14.8 Рекомендации по выбору
14.8.1 Когда выбирать ETW
Обязательно использовать ETW для:
- Обнаружения атак в реальном времени — брутфорс, компрометация
- Мониторинга критических серверов — DC, RDSH, Gateway
- Высокочастотных событий — аутентификация, сетевые подключения
- Систем с высокой нагрузкой — тысячи событий в секунду
- Сценариев с низкой задержкой — алертинг, автоматические ответы
14.8.2 Когда выбирать EventLog
Можно использовать EventLog для:
- Исторического анализа — аудит за прошлые периоды
- Редких событий — ошибки лицензирования, запуск служб
- Систем с низкой нагрузкой — менее 100 событий/сек
- Когда не требуется реальное время — отчеты, compliance
- Устаревших систем — Windows Server 2008 и старше
14.8.3 Критерии принятия решения
graph TD
A[Выбор механизма сбора] --> B{Требуется реальное время?}
B -->|Да| C{Более 1000 событий/сек?}
B -->|Нет| D[EventLog API]
C -->|Да| E{Есть права администратора?}
C -->|Нет| F[EventLog API]
E -->|Да| G[ETW]
E -->|Нет| H[EventLog API]
G --> I[Настроить буферы 64KB]
G --> J[Использовать фильтрацию в ядре]
G --> K[Асинхронная обработка]
D --> L[Опрос каждые 30-60 сек]
D --> M[Использовать XPath фильтры]
D --> N[Пакетное чтение]14.9 Мониторинг и диагностика
14.9.1 Мониторинг производительности ETW
# Мониторинг сессий ETW
Get-EtwTraceSession -Name "RdpMonitorSession" |
Select-Object Name, Status, BufferSize, LogFileMode, EventsLost
# Просмотр статистики производительности
logman query "RdpMonitorSession" -ets
# Мониторинг использования ресурсов
Get-Counter '\Process(rdpmon)\% Processor Time' -Continuous
Get-Counter '\Process(rdpmon)\Private Bytes' -Continuous
14.9.2 Диагностика проблем EventLog
# Проверка размера журналов
Get-WinEvent -ListLog * |
Where-Object {$_.RecordCount -gt 0} |
Select-Object LogName, RecordCount, FileSize, LastWriteTime |
Sort-Object FileSize -Descending
# Поиск проблем с доступом
Get-WinEvent -LogName Security -MaxEvents 1 -ErrorAction SilentlyContinue
# Оптимизация производительности
wevtutil sl Security /ms:104857600 # Ограничить размер до 100MB
wevtutil sl Security /rt:false # Отключить реальное время
14.10 Выводы: ETW и EventLog API
Выбор между ETW и EventLog API зависит от конкретных требований системы мониторинга RDP:
- Для систем безопасности и реального времени — используйте ETW
- Для исторического анализа и отчетности — используйте EventLog API
- Для большинства enterprise-сценариев — используйте гибридный подход
Ключевые выводы:
- ETW обеспечивает в 100 раз более низкую задержку
- EventLog API проще в реализации и поддержке
- Гибридный подход дает наилучший баланс производительности и функциональности
- Для RDP-мониторинга критически важна низкая задержка обнаружения атак
Рекомендация для RdpMon++: Реализовать гибридную архитектуру, где события квадрантов I и IV собираются через ETW, а события квадрантов II и III — через EventLog API с оптимизированными интервалами опроса.
Заключение
Ключевые выводы
- Полнота охвата: Современная система мониторинга RDP должна собирать события из 10+ источников, а не только из Security-журнала.
- Корреляция обязательна: Отдельные события имеют ограниченную ценность. Критически важна корреляция по времени, SessionId и IP-адресам.
- Производительность: Использование ETW вместо EventLog API дает 10-кратный прирост производительности при сборе событий в реальном времени.
- Масштабируемость: Многоуровневое хранение (горячее/теплое/холодное) обязательно для больших объемов данных.
- Обогащение данных: Геолокация и Threat Intelligence превращают сырые события в actionable intelligence.
Дорожная карта внедрения
Этап 1 (30 дней):
- Сбор Security 4624/4625 и LSM 21-25
- Базовая корреляция по SessionId
- Простые алерты на брутфорс
Этап 2 (60 дней):
- Добавление Kerberos/NTLM событий
- Интеграция с GeoIP
- Расширенная корреляция
- Дашборды для администраторов
Этап 3 (90 дней):
- Полный сбор всех источников
- Интеграция с Threat Intelligence
- Машинное обучение для обнаружения аномалий
- Автоматизированные ответы на инциденты
Метрики успеха
| Метрика | Целевое значение | Измерение |
|---|---|---|
| Время обнаружения атаки | < 5 минут | Среднее время от события до алерта |
| Полнота сбора | > 99.9% | Процент собранных событий от общих |
| Ложные срабатывания | < 5% в день | Алерты без последующих инцидентов |
| Время хранения | 90+ дней | Доступность исторических данных |
| Производительность | < 100ms задержка | Время от события до появления в SIEM |
Система мониторинга, построенная по этим принципам, обеспечит не только безопасность RDP-доступа, но и оперативную аналитику использования, планирование емкости и соответствие требованиям регуляторов.