security 23 марта 2026 10 мин чтения ...
ЕС
Евгений Семёнов
Генеральный директор ООО АйТи Фреш · 15+ лет в IT

Аудит RDP-подключений к Windows Server: кто, когда и откуда

rdp-connection-audit

RDP — это подарок для атакующих. Порт 3389 сканируют круглосуточно, брутфорс идёт непрерывно, а сотрудники иногда заходят на серверы в три часа ночи — и поди разберись, зачем. Мы в своей практике разбирали инциденты, где взлом обнаруживался спустя недели после того, как он случился. SIEM решает проблему, но это отдельный бюджет, отдельное внедрение и отдельная головная боль.

В этой статье покажем, как закрыть базовые задачи аудита RDP-подключений без сторонних инструментов — только штатный журнал событий Windows и PowerShell. Кто заходил на сервер? С какого IP? В половину третьего ночи или в рабочее время? Сколько раз промахнулся паролем? Ответы на все эти вопросы можно получить за несколько минут.

Какие события фиксирует Windows при RDP-сессии

Windows пишет всё. Security Event Log фиксирует каждое RDP-соединение в виде цепочки событий с конкретными Event ID. Если знаешь, какие именно идентификаторы за что отвечают, — читать этот журнал не сложнее, чем лог nginx.

Совет: Для RDP наиболее информативна пара 4624 (вход) + 4634/4647 (выход). По разнице временных меток можно рассчитать продолжительность сессии.

Включение аудита входов в систему

Вот с чем мы регулярно сталкиваемся у клиентов: расширенный аудит входов оказывается частично отключён — прямо из коробки. Прежде чем писать запросы к журналу, проверьте, что нужные политики вообще активны.

Текущие настройки аудита смотрим командой:

auditpol /get /subcategory:"Logon"
auditpol /get /subcategory:"Logoff"

Если в столбце Inclusion Setting не стоит Success and Failure — включите аудит вручную:

# Включить аудит успешных и неудачных входов
auditpol /set /subcategory:"Logon" /success:enable /failure:enable
auditpol /set /subcategory:"Logoff" /success:enable /failure:enable

В доменной среде это удобнее делать через GPO: Computer Configuration → Windows Settings → Security Settings → Advanced Audit Policy Configuration → Logon/Logoff. Один раз настроили — разъехалось на все машины.

Важно: Не включайте аудит на уровне Default Domain Policy — это создаст избыточную нагрузку на журнал всех рабочих станций. Применяйте политику только к OU с серверами.

Быстрая проверка: кто заходил по RDP сегодня

Самый ходовой запрос — список всех успешных RDP-входов за последние 24 часа. Запускаем PowerShell от имени администратора:

$StartTime = (Get-Date).AddHours(-24)

Get-WinEvent -FilterHashtable @{
    LogName   = 'Security'
    Id        = 4624
    StartTime = $StartTime
} | Where-Object {
    $_.Properties[8].Value -eq 10
} | Select-Object TimeCreated,
    @{Name='User';    Expression={$_.Properties[5].Value}},
    @{Name='Domain';  Expression={$_.Properties[6].Value}},
    @{Name='SourceIP';Expression={$_.Properties[18].Value}},
    @{Name='LogonType';Expression={$_.Properties[8].Value}} |
Sort-Object TimeCreated -Descending |
Format-Table -AutoSize

На выходе получите таблицу: время входа, имя пользователя, домен, IP-адрес источника. Хотите покликать мышкой — замените Format-Table на Out-GridView, откроется графическое окно с фильтрацией.

Анализ неудачных попыток входа (брутфорс)

Event ID 4625 — это то, что первым делом смотришь при подозрении на брутфорс. Один IP, 400 попыток за три минуты — картина знакомая. Видели такое даже на серверах клиентов с нестандартным портом RDP: боты находят и их.

# Топ IP-адресов по числу неудачных попыток за последние 7 дней
$StartTime = (Get-Date).AddDays(-7)

Get-WinEvent -FilterHashtable @{
    LogName   = 'Security'
    Id        = 4625
    StartTime = $StartTime
} | Select-Object @{
    Name       = 'SourceIP'
    Expression = {$_.Properties[19].Value}
}, @{
    Name       = 'User'
    Expression = {$_.Properties[5].Value}
} | Group-Object SourceIP |
Select-Object Name, Count |
Sort-Object Count -Descending |
Select-Object -First 20 |
Format-Table -AutoSize

IP из Нигерии, Бразилии или Сингапура на сервере московской бухгалтерии — уже достаточный повод для блокировки, не дожидаясь разбора полётов. Логины несуществующих пользователей — туда же. Баним на брандмауэре сразу.

Внимание: У Get-WinEvent есть ограничение: при очень большом журнале запрос может занять несколько минут. Используйте параметр -MaxEvents для ограничения выборки при первичной диагностике.

Полная история сессий с продолжительностью

Для расследования инцидентов «кто и сколько просидел в системе» одного события входа мало. Сопоставляем 4624 и 4634/4647 по LogonID — и видим реальную продолжительность каждой сессии:

# Сбор входов RDP
$logons = Get-WinEvent -FilterHashtable @{
    LogName = 'Security'; Id = 4624
} | Where-Object {
    $_.Properties[8].Value -eq 10
} | Select-Object TimeCreated,
    @{Name='LogonID';  Expression={$_.Properties[7].Value}},
    @{Name='User';     Expression={$_.Properties[5].Value}},
    @{Name='SourceIP'; Expression={$_.Properties[18].Value}}

# Сбор выходов
$logoffs = Get-WinEvent -FilterHashtable @{
    LogName = 'Security'; Id = @(4634, 4647)
} | Select-Object TimeCreated,
    @{Name='LogonID';Expression={$_.Properties[3].Value}}

# Сопоставление по LogonID
$result = foreach ($logon in $logons) {
    $logoff = $logoffs | Where-Object {
        $_.LogonID -eq $logon.LogonID
    } | Select-Object -First 1

    [PSCustomObject]@{
        User      = $logon.User
        SourceIP  = $logon.SourceIP
        LogonTime = $logon.TimeCreated
        LogoffTime= if ($logoff) {$logoff.TimeCreated} else {'Сессия активна'}
        Duration  = if ($logoff) {
            ($logoff.TimeCreated - $logon.TimeCreated).ToString('hh\:mm\:ss')
        } else {'—'}
    }
}

$result | Sort-Object LogonTime -Descending | Format-Table -AutoSize

Мониторинг подозрительных входов в реальном времени

PowerShell умеет подписываться на новые события журнала безопасности и реагировать на них в реальном времени. Скрипт ниже выводит оповещение в консоль при каждом новом RDP-входе — удобно гонять на мониторинговой машине:

# Мониторинг новых RDP-входов в реальном времени
$query = @"

  
    
  

"@

$watcher = New-Object System.Diagnostics.Eventing.Reader.EventLogWatcher(
    (New-Object System.Diagnostics.Eventing.Reader.EventLogQuery(
        "Security",
        [System.Diagnostics.Eventing.Reader.PathType]::LogName,
        $query
    ))
)

$watcher.add_EventRecordWritten({
    param($sender, $e)
    $ev = $e.EventRecord
    $user = $ev.Properties[5].Value
    $ip   = $ev.Properties[18].Value
    $time = $ev.TimeCreated
    Write-Host "[$time] НОВЫЙ RDP-ВХОД: $user с IP $ip" -ForegroundColor Red
})

$watcher.Enabled = $true
Write-Host "Мониторинг запущен. Нажмите Ctrl+C для остановки."
while ($true) { Start-Sleep -Seconds 5 }
Совет: Вместо вывода в консоль можно отправлять уведомления по email через Send-MailMessage или HTTP-хук в Telegram.

Отправка отчёта по RDP-входам на email

На практике удобнее всего — автоматический отчёт на почту каждое утро. Пишем скрипт, кидаем в Планировщик задач, забываем. Утром в ящике уже лежит сводка за прошедшие сутки:

# Параметры почты
$SmtpServer = "smtp.yourcompany.ru"
$SmtpPort   = 587
$From       = "monitoring@yourcompany.ru"
$To         = "admin@yourcompany.ru"
$Credential = Get-Credential  # или задайте PSCredential вручную

# Формируем отчёт за прошедшие сутки
$StartTime = (Get-Date).Date.AddDays(-1)
$EndTime   = (Get-Date).Date

$events = Get-WinEvent -FilterHashtable @{
    LogName   = 'Security'
    Id        = 4624
    StartTime = $StartTime
    EndTime   = $EndTime
} | Where-Object { $_.Properties[8].Value -eq 10 } |
    Select-Object TimeCreated,
        @{Name='User';     Expression={$_.Properties[5].Value}},
        @{Name='SourceIP'; Expression={$_.Properties[18].Value}}

$failed = (Get-WinEvent -FilterHashtable @{
    LogName   = 'Security'
    Id        = 4625
    StartTime = $StartTime
    EndTime   = $EndTime
} -ErrorAction SilentlyContinue).Count

$body = "RDP-отчёт за $(Get-Date $StartTime -Format 'dd.MM.yyyy')`n`n"
$body += "Успешных входов: $($events.Count)`n"
$body += "Неудачных попыток: $failed`n`n"
$body += ($events | Format-Table -AutoSize | Out-String)

Send-MailMessage -SmtpServer $SmtpServer -Port $SmtpPort `
    -From $From -To $To `
    -Subject "RDP-аудит $(hostname) — $(Get-Date -Format 'dd.MM.yyyy')" `
    -Body $body -Encoding UTF8 -Credential $Credential -UseSsl

Добавление скрипта в Планировщик задач

Чтобы отчёт уходил без участия человека, регистрируем PowerShell-скрипт как задачу Windows:

# Создание задачи планировщика — запуск каждый день в 08:00
$Action  = New-ScheduledTaskAction -Execute "powershell.exe" `
    -Argument "-NonInteractive -ExecutionPolicy Bypass -File C:\Scripts\rdp-report.ps1"

$Trigger = New-ScheduledTaskTrigger -Daily -At "08:00"

$Settings = New-ScheduledTaskSettingsSet `
    -ExecutionTimeLimit (New-TimeSpan -Minutes 10) `
    -RunOnlyIfNetworkAvailable

Register-ScheduledTask -TaskName "RDP Daily Report" `
    -Action $Action -Trigger $Trigger -Settings $Settings `
    -RunLevel Highest -User "SYSTEM"
Совет: Используйте учётную запись SYSTEM или выделенный сервисный аккаунт с правами на чтение Security Event Log. Обычному пользователю читать этот журнал запрещено.

Автоматическая блокировка атакующих IP через Windows Firewall

Если с одного IP прилетело больше N неудачных попыток — блокируем автоматически, не ждём, пока кто-то это заметит вручную. Скрипт запускаем по расписанию, например каждые 15 минут:

# Пороговое значение — количество неудачных попыток за час
$Threshold = 15
$StartTime = (Get-Date).AddHours(-1)

# Получаем IP-адреса превысившие порог
$attackers = Get-WinEvent -FilterHashtable @{
    LogName   = 'Security'
    Id        = 4625
    StartTime = $StartTime
} | Select-Object @{
    Name = 'SourceIP'; Expression = {$_.Properties[19].Value}
} | Group-Object SourceIP |
    Where-Object { $_.Count -ge $Threshold } |
    Select-Object -ExpandProperty Name |
    Where-Object { $_ -notmatch '^(10\.|192\.168\.|172\.(1[6-9]|2\d|3[01])\.)' }

foreach ($ip in $attackers) {
    $ruleName = "Block-RDP-Bruteforce-$ip"
    if (-not (Get-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue)) {
        New-NetFirewallRule -DisplayName $ruleName `
            -Direction Inbound -Protocol TCP -RemoteAddress $ip `
            -Action Block -Profile Any
        Write-Host "Заблокирован IP: $ip (попыток: $($attackers.Count))" -ForegroundColor Yellow
    }
}

Регулярное выражение в условии Where-Object исключает из блокировки локальные адреса (RFC 1918) — без этого есть шанс случайно заблокировать собственных пользователей внутри сети, что мы однажды и сделали в тестовой среде.

Осторожно: Перед запуском в production обязательно протестируйте скрипт в тестовой среде. Ошибочная блокировка диапазона IP может отрезать легитимных пользователей от сервера.

Просмотр журнала через Event Viewer: ручной способ

PowerShell недоступен или просто нужно быстро глянуть пару событий? Обычный Просмотр событий тоже справится:

  1. Откройте eventvwr.msc (Win+R).
  2. Перейдите в Журналы Windows → Безопасность.
  3. Нажмите Фильтровать текущий журнал (правая панель).
  4. В поле Идентификаторы событий введите: 4624,4625,4634,4647,4778,4779.
  5. Нажмите OK — журнал отфильтруется по нужным событиям.

Нужно посмотреть журнал на удалённой машине — не надо никуда идти. Прямо из Event Viewer: Действие → Подключиться к другому компьютеру. Работает, пока открыт нужный порт и есть права.

Совет: Сохраните созданный фильтр как Настраиваемое представление — тогда не придётся каждый раз вводить Event ID заново.

Экспорт журнала в CSV для долгосрочного хранения

Журнал событий Windows хранит не так много, как хотелось бы. По умолчанию размер ограничен, старые записи перезаписываются новыми — и вот вы уже потеряли данные за прошлый месяц. Если в вашей компании есть требования ИБ или нужно хранить историю RDP-доступа дольше пары недель, экспортируйте события в CSV-файлы:

# Экспорт всех RDP-событий за месяц в CSV
$MonthStart = (Get-Date -Day 1).Date
$ExportPath = "C:\Logs\RDP-Audit-$(Get-Date -Format 'yyyy-MM').csv"

Get-WinEvent -FilterHashtable @{
    LogName   = 'Security'
    Id        = @(4624, 4625, 4634, 4647, 4778, 4779)
    StartTime = $MonthStart
} | Select-Object TimeCreated, Id,
    @{Name='User';     Expression={$_.Properties[5].Value}},
    @{Name='Domain';   Expression={$_.Properties[6].Value}},
    @{Name='SourceIP'; Expression={
        if ($_.Id -eq 4625) {$_.Properties[19].Value}
        else                {$_.Properties[18].Value}
    }},
    @{Name='LogonType';Expression={$_.Properties[8].Value}},
    Message |
Export-Csv -Path $ExportPath -Encoding UTF8 -NoTypeInformation

Write-Host "Экспортировано в: $ExportPath"

Этот скрипт мы добавляем в планировщик с запуском первого числа каждого месяца. Ротацию настраиваем так, чтобы на диске лежало не больше 12 архивов — то есть ровно год истории. Места занимает немного, зато при разборе инцидентов не придётся кусать локти.

Итог: минимальный набор инструментов для RDP-аудита

Если коротко — без SIEM и сторонних агентов вы вполне получаете полноценный аудит RDP-доступа. Только встроенные возможности Windows, ничего лишнего:

Все скрипты легко адаптируются под вашу среду. Поменяли пороговые значения, список серверов, реквизиты почтового сервера — и готово. Если серверов уже десятки, я бы посмотрел в сторону централизованного сбора событий через Windows Event Forwarding (WEF). Когда же инфраструктура продолжает расти — стоит попробовать лёгкий SIEM. Wazuh, например, разворачивается куда проще, чем принято думать.

Официальная документация: Microsoft Learn — Windows Server, Microsoft Learn — PowerShell

Часто задаваемые вопросы

Что такое Аудит RDP-подключений к Windows Server: кто, когда и откуда?

Аудит RDP-подключений к Windows Server: кто, когда и откуда — это важный аспект системного администрирования, который позволяет настроить и оптимизировать работу IT-инфраструктуры. В данной статье подробно рассматриваются все ключевые моменты.

Как правильно настроить Аудит RDP-подключений к Windows Server: кто, когда и откуда?

Для корректной настройки Аудит RDP-подключений к Windows Server: кто, когда и откуда необходимо следовать пошаговой инструкции, представленной в статье выше. Важно учитывать особенности вашей инфраструктуры и требования безопасности.

Какие типичные ошибки возникают при работе с Аудит RDP-подключений к Windows Server: кто, когда и откуда?

Наиболее частые ошибки при работе с Аудит RDP-подключений к Windows Server: кто, когда и откуда: некорректная конфигурация, недостаточные права доступа и несовместимость версий. Рекомендуем обратиться к специалистам ITFresh для профессиональной настройки.

Нужна помощь специалистов?

ООО «АйТи Фреш» возьмёт это на себя

Не хватает времени или своих специалистов — мы настроим, оптимизируем и возьмём вашу IT-инфраструктуру на постоянное сопровождение. Работаем с юридическими лицами в Москве и регионах. Собственный дата-центр, команда из 8 серверов Dell Xeon Platinum 8280 на базе МТС.

15+лет опыта
25+клиентов
40Gсвоя сеть
24/7поддержка

Комментарии