Блокировка IP выполняющих перебор паролей к RDP серверам

Текст: 

На RDP сервера выставленные в Интернет, как мухи на лакомство, сразу слетаются переборщики паролей. Расплодились они невероятно и безобидный перебор очень часто превращается в приличный DDoS. Внятные специалисты сейчас же мне скажут, что это не кошерно - сервера в Интернете, ламерство какое-то, если не сказать грубее. Кто же так делает?! Как кричал попугай в одном детском стишке: " Только бездельники, только растяпы!".

И они правы, сделайте VPN и все будет OK.

Но как оказалось, кроме банков, операторов мобильной связи и госучреждений, короче говоря людей больших и состоятельных, на свете существует множество маленьких фирм и фирмочек. Для которых организация и поддержка VPN инфраструктуры - удовольствие неподъемное. Сам факт появления RDP сервера для клиентов - уже событие. А тут еще нужен производительный роутер, нужно организовать поддержку пользователей. Потому как для большинства из них максимально сложное поведение - это щелкнуть на готовом RDP-ярлычке и скопировать пароль. А поставить и настроить VPN клиент...

Итак, небольшая фирма с RDP сервером наружу.

Первый признак работы сканеров - большое количество неудачных событий 4625 (An account failed to log on) в которых указаны различные распространенные имена пользователей.

Тут пора позаботится чтобы пароль действительно не подобрали. Для этого нужен комплекс мер: имена пользователей не должны быть стандартными, пароль должен быть сложным, количество неудачных попыток входа для пользователя должно быть ограничено. Как минимум нужно настроить в групповой локальной или доменной политике следующие параметры:

Computer Configuration\Security Settings\Local Policies\Account Policies\Password Policy

Minimum password length = 9
Password must meet complexity requirements = Enabled

Computer Configuration\Security Settings\Local Policies\Account Policies\Account Lockout Policy

Account lockout threshold = 5
Reset account lockout counter after = 30
Account lockout duration = 30

Так же необходимо выставить параметры безопасности на уровне RDP:

Computer Configuration\Policies\Administrative Templates\Windows Components\Remote Desktop Services\Remote Desktop Session Host\Security

Require secure RPC communication = Enabled
Require use of specific security layer for remote (RDP) connections = SSL
Require user authentication for remote connections by using Network Level Authentication = Enabled
Set client connection encryption level = High

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

Это хорошо, но не снимает нагрузку на сервер из-за обработки неуспешных аутентификаций. При интенсивном переборе вероятна ситуация в которой вместе с паразитными запросами будут отбрасываться и попытки входа реальных пользователей. Которые будут получать отказы на вход через RDP, несмотря на правильно введенные логин и пароль.

Признаком данной ситуации станут события 5817 "Netlogon has failed an additional 129 authentication requests in the last 30 minutes. The requests timed out before they could be sent to domain controller \\server.ourdomain.local in domain OURDOMAIN."

Первый испробованный "метод защиты" - изменение стандартного RDP-порта 3389 на нестандартный. Настройки находятся в реестре:

KEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp\PortNumber

для применения нужен рестарт сервера.

Как оказалось сканеры успешно обрабатывают данную ситуацию и через день-два новый порт уже вовсю используется.

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

Явно, нужен некий сетевой экран умеющий делать инспекцию пакетов на уровне приложения. Но такие устройства и их поддержка явно выходят за рамки бюджета маленькой фирмы.

На линуксе существует утилита fail2ban парсящая логи и блокирующая на уровне firewall адреса с которых происходит много неуспешных попыток входа. Попробуем написать что-то подобное под Windows Server используя Powershell.

Определим переменные:

# количество неуспешных попыток за единицу времени при которых IP блокируется
# с единицей времени определимся ниже
$ban_treshold = 5

# продолжительность блокировки в часах
$ban_duration = 24

# инициализируем массивы в которых будут добавляться IP для блокировки
$ip2ban = @()
$ip2ban_str = @()

В нашем случае с параметром групповой политики Require use of specific security layer for remote (RDP) connections = SSL и включенным NLA события 4625 не будут содержать IP источника. И для Server 2008, чтобы видеть в событиях 4625 источник перебора прийдется ставить менее защишенный security layer = RDP.

Server 2012 более продвинутый, можно использовать настройки SSL+NLA и при этом ориентироваться на события 140 ( A connection from the client computer with an IP address of xxx.xxx.xxx.xxx failed because the user name or password is not correct. ) в Applications and Services Logs. Не путайте с NTFS событиями 140 ( The system failed to flush data to the transaction log. ) появляющимися в логе System.

# получаем события
$evt140 = Get-WinEvent -ProviderName Microsoft-Windows-RemoteDesktopServices-RdpCoreTS|?{$_.id -eq 140}

# пишем в лог
"--- Get-WinEvent $ban_date_str" >> $log_file

# группируем события по IP, фильтруем по количеству определенному в ban_treshold и записываем в массив
$ip2ban = $evt140.properties.value|Group-Object|?{$_.count -ge $ban_treshold}|select name,count

# пишем в лог IP определенные для блокировки и для информации количество попыток
$ip2ban|%{ "#block_ip "+$_.name+" "+$_.count >> $log_file }

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

# проверяем что список IP не пустой
if($ip2ban.count -gt 0){

# очищаем лог
  get-winevent -ListLog Microsoft-Windows-RemoteDesktopServices-RdpCoreTS/Operational| % { [System.Diagnostics.Eventing.Reader.EventLogSession]::GlobalSession.ClearLog($_.LogName) }
  $ip2ban|%{$ip2ban_str+=$_.name.tostring()}

# создаем правило firewall
  New-NetFirewallRule -DisplayName "RDP_DYN_BAN_$ban_date_str" -Enabled "True" -Profile Any -Direction Inbound -Action Block -RemoteAddress $ip2ban_str -Protocol TCP

# пишем в лог имя созданного правила
  "--- New-NetFirewallRule RDP_DYN_BAN_$ban_date_str" >> $log_file
}

Дело пошло - правила начинают накапливаться, чтобы их не стало сильно много будем удалять правила которые старше ban_duration.

# читаем текущие правила
$current_frs = Get-NetFirewallRule -DisplayName RDP_DYN_BAN*

$current_frs|%{

# переводим строковое имя правила в datetime
  $date_frs=[datetime]::parseexact($_.displayname, 'RDP_DYN_BAN_ddMMyyyy_HHmmss',$null)

# если разница в часах больше ban_duration удаляем правило
  if( ((get-date) - $date_frs).totalhours -ge $ban_duration ){
    "--- Remove-NetFirewallRule -Displayname "+$_.displayname  >> $log_file
    $_|Remove-NetFirewallRule -Confirm:$false
  }
}

Осталось настроить запуск скрипта в планировщике, например каждый час или 30 минут. Это и будет единицей времени для ban_treshold определенной нами в скрипте.

В идеале скрипт нужно доработать, должны создаваться не правила для firewall операционной системы, а командные файлы на сетевое оборудование, чтобы вредные пакеты даже не попадали внутрь сети.

Скрипт в чистом виде без комментариев.

Добавить комментарий.

Filtered HTML

  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Доступны HTML теги: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Строки и параграфы переносятся автоматически.

Plain text

  • HTML-теги не обрабатываются и показываются как обычный текст
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Строки и параграфы переносятся автоматически.
CAPTCHA
Этот вопрос задается для того, чтобы выяснить, являетесь ли Вы человеком или представляете из себя автоматическую спам-рассылку.
CAPTCHA на основе изображений
Введите символы, которые показаны на картинке.