Ошибка RDP: как разблокировать учётную запись Windows (PowerShell)

Опубликовано Обновлено 6 мин. чтения

Заблокированная учётная запись Windows при входе по RDP обычно означает автоматизированную атаку. Скрипт PowerShell снимает блокировку, показывает IP-адреса источников и настраивает политику блокировки.

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

В этом руководстве показано, как разблокировать учётную запись, выяснить, какие IP-адреса вызывают блокировки, и изменить или отключить политику блокировки. Всё это делает один скрипт PowerShell, без ручной работы в редакторе групповых политик.

Почему учётная запись Windows блокируется при входе по RDP?

Windows считает неудачные попытки входа и блокирует учётную запись, как только достигнут заданный порог. Сама по себе такая защита полезна, но превращается в проблему, как только порт RDP открыт в интернет: автоматические боты круглосуточно перебирают пароли и блокируют именно ту учётную запись, под которой вы собираетесь работать.

Поведение определяют три значения:

  • Порог блокировки: число неудачных попыток до блокировки
  • Длительность блокировки: минуты, в течение которых учётная запись остаётся заблокированной
  • Окно наблюдения: минуты, за которые суммируются неудачные попытки

Запуск PowerShell от имени администратора

Откройте Windows PowerShell от имени администратора. Для этого щёлкните в меню «Пуск» правой кнопкой мыши по пункту «Windows PowerShell» и выберите «Запуск от имени администратора». Без повышенных прав скрипт не сможет ни разблокировать учётную запись, ни изменить политику.

Скрипт: разблокировка учётной записи и поиск атакующих

В разделе «Настройки» укажите имя учётной записи и нужные значения, после чего вставьте скрипт в PowerShell:

#Requires -RunAsAdministrator

# KernelHost: разблокировка заблокированной учётной записи Windows RDP и поиск причины
# Выполнять в Windows PowerShell от имени администратора.

# ----------------------------------------------------------------------------
#  Настройки: измените их под своё окружение
# ----------------------------------------------------------------------------
$Username = 'Administrator'   # локальная учётная запись, которую нужно разблокировать

$ApplyPolicy      = $true     # $false, если политику блокировки менять не нужно
$LockoutThreshold = 10        # неудачных попыток до блокировки (0 = ОТКЛЮЧИТЬ блокировку)
$LockoutDuration  = 15        # минут, в течение которых запись остаётся заблокированной
$LockoutWindow    = 15        # минут, за которые считаются неудачные попытки
# ----------------------------------------------------------------------------

# 1) Показать текущую политику блокировки
Write-Host "`n=== 1) Текущая политика блокировки ===" -ForegroundColor Cyan
net accounts | Select-String 'Lockout|Sperr'

# 2) Разблокировать учётную запись
Write-Host "`n=== 2) Разблокировка учётной записи '$Username' ===" -ForegroundColor Cyan
try {
    $user = [ADSI]"WinNT://$env:COMPUTERNAME/$Username,user"
    if ($user.InvokeGet('IsAccountLocked')) {
        $user.InvokeSet('IsAccountLocked', $false)
        $user.SetInfo()
        Write-Host "  Учётная запись '$Username' была заблокирована и теперь РАЗБЛОКИРОВАНА." -ForegroundColor Green
    } else {
        Write-Host "  Учётная запись '$Username' не заблокирована." -ForegroundColor Yellow
    }
} catch {
    Write-Warning "  Не удалось разблокировать учётную запись '$Username': $($_.Exception.Message)"
}

# 3) Необязательно: изменить или отключить политику блокировки
if ($ApplyPolicy) {
    Write-Host "`n=== 3) Установка политики блокировки ===" -ForegroundColor Cyan
    if ($LockoutThreshold -eq 0) {
        net accounts /lockoutthreshold:0 | Out-Null
        Write-Host "  Блокировка учётных записей ОТКЛЮЧЕНА (порог 0)." -ForegroundColor Yellow
        Write-Warning "  На сервере, доступном из интернета, это НЕ рекомендуется."
    } else {
        net accounts /lockoutthreshold:$LockoutThreshold /lockoutduration:$LockoutDuration /lockoutwindow:$LockoutWindow | Out-Null
        Write-Host "  Порог=$LockoutThreshold  Длительность=$LockoutDuration мин  Окно=$LockoutWindow мин" -ForegroundColor Green
    }
}

# 4) Кто вызывает блокировки? (источники RDP-атак)
Write-Host "`n=== 4a) Последние события блокировки (Security-ID 4740) ===" -ForegroundColor Cyan
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4740} -MaxEvents 10 -ErrorAction SilentlyContinue |
    ForEach-Object {
        $x = [xml]$_.ToXml()
        [pscustomobject]@{
            Время                 = $_.TimeCreated
            ЗаблокированнаяЗапись = ($x.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetUserName' }).'#text'
            Источник              = ($x.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetDomainName' }).'#text'
        }
    } | Format-Table -AutoSize

Write-Host "=== 4b) Самые частые IP-адреса источников неудачных входов за последние 24 ч (Security-ID 4625) ===" -ForegroundColor Cyan
$since = (Get-Date).AddHours(-24)
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625; StartTime=$since} -ErrorAction SilentlyContinue |
    ForEach-Object {
        ([xml]$_.ToXml()).Event.EventData.Data |
            Where-Object { $_.Name -eq 'IpAddress' } | Select-Object -ExpandProperty '#text'
    } |
    Where-Object { $_ -and $_ -ne '-' } |
    Group-Object | Sort-Object Count -Descending | Select-Object -First 10 |
    Format-Table Count, @{N='IP-источника'; E={$_.Name}} -AutoSize

Что делает скрипт по шагам

  1. Через net accounts он показывает текущую политику блокировки учётных записей, то есть порог, длительность блокировки и окно наблюдения.
  2. Он разблокирует учётную запись, указанную в $Username, через поставщик каталога WinNT. Для локальных учётных записей это аналог Unlock-ADAccount.
  3. Он изменяет политику, если $ApplyPolicy имеет значение $true. Со значениями по умолчанию блокировка становится менее агрессивной, а с $LockoutThreshold = 0 вы отключаете её полностью.
  4. Он выводит последние события блокировки (код события 4740), а также самые частые IP-адреса источников неудачных входов за последние 24 часа (код события 4625). Именно с этих адресов атакуют ваш RDP-доступ.

Замечание о языке: на немецкоязычной Windows команда net accounts выводит значения под немецкими названиями, поэтому скрипт выше фильтрует и по «Lockout», и по «Sperr». В русской локализации подписи выглядят иначе (например, «Пороговое значение блокировки»), так что добавьте в фильтр ещё и «блокиров».

Локальная учётная запись или доменная?

Скрипт работает с локальной учётной записью, то есть с типичным случаем на отдельно стоящем VPS или root-сервере. Если речь идёт о доменной учётной записи или вы работаете на контроллере домена, снимайте блокировку иначе:

Unlock-ADAccount -Identity <имя-пользователя>

Изменение или отключение порога блокировки

Значение $LockoutThreshold = 0 полностью отключает защиту блокировкой. На сервере, доступном из интернета, мы этого не советуем: без блокировки атакующий может перебирать сколько угодно паролей. Разумнее умеренный порог, например 10 неудачных попыток, в сочетании с мерами из следующего раздела.

Устранение причины: постоянная защита RDP

Заблокированная учётная запись — это только симптом. Настоящая причина в том, что доступ по RDP открыт всему интернету. Следующие четыре меры устраняют проблему в корне.

Ограничение RDP собственным IP-адресом

Это самая действенная мера. Если RDP доступен только с вашего собственного адреса, все автоматизированные атаки уходят в никуда:

# Разрешить входящие RDP-подключения только с собственного IP-адреса
Set-NetFirewallRule -DisplayName 'Remote Desktop - User Mode (TCP-In)' -RemoteAddress '203.0.113.5'

Указанное отображаемое имя действует в англоязычной Windows. В локализованных версиях, в том числе в русской, оно выглядит иначе. Существующие правила и их точные названия выводит команда Get-NetFirewallRule -DisplayGroup 'Удаленный рабочий стол'.

Блокировка отдельного IP-адреса атакующего

Для адресов, которые выдаёт шаг 4b скрипта, создайте отдельное запрещающее правило:

New-NetFirewallRule -DisplayName 'Block RDP attacker 203.0.113.9' -Direction Inbound -Action Block -RemoteAddress '203.0.113.9'

Это помогает против отдельных настойчивых источников, но не заменяет ограничение доступа вашим собственным IP-адресом, потому что атакующие постоянно берут новые адреса.

Смена порта RDP

Если RDP больше не слушает стандартный порт 3389, обычные массовые сканирования вашу службу просто не найдут. Как сменить порт без перезагрузки сервера, показано в нашем руководстве Смена RDP-порта в Windows без перезагрузки сервера.

Надёжный пароль и проверка подлинности на уровне сети

Используйте длинный случайный пароль и оставьте включённой проверку подлинности на уровне сети (Network Level Authentication, NLA). NLA требует аутентификации ещё до того, как будет установлен сеанс, и таким образом заранее отсекает большую часть автоматизированных попыток.

Частые вопросы

Почему учётная запись Windows блокируется при входе по RDP?
Windows блокирует учётную запись, как только достигнуто заданное в политике число неудачных попыток входа. На сервере с открытым в интернет портом RDP такую блокировку почти всегда вызывают автоматизированные атаки.
Как долго учётная запись остаётся заблокированной?
Столько, сколько задано в длительности блокировки, чаще всего 15 или 30 минут. После этого вход снова возможен. Скриптом из этого руководства блокировку можно снять сразу.
Стоит ли полностью отключать блокировку учётных записей?
На сервере, доступном из интернета, лучше не стоит. Без блокировки атакующий может перебирать сколько угодно паролей. Разумнее умеренный порог около 10 попыток вместе с правилом файрвола, которое ограничивает RDP вашим собственным IP-адресом.
Как узнать, какие IP-адреса блокируют мою учётную запись?
Событие с кодом 4740 в журнале безопасности фиксирует сами блокировки, а событие 4625 — неудачные входы вместе с IP-адресом источника. Скрипт из этого руководства разбирает оба автоматически.
Скрипт не разблокирует мою учётную запись, в чём причина?
Скрипт работает с локальной учётной записью. Для доменной учётной записи или на контроллере домена используйте вместо него Unlock-ADAccount. Кроме того, проверьте, действительно ли PowerShell запущен от имени администратора.

Windows Server Windows RDP Удалённый рабочий стол PowerShell Блокировка учётной записи Brute-force Безопасность сервера