Ранее писал про простую, но довольно эффективную «защиту от брутфорсеров», но что делать если у вас нет роутера, на котором можно такую защиту построить?
Можно сделать «наколеночное» примитивное, но все таки работающее решение внутри самого сервера. Единственное ограничение — ОС на сервере должна быть минимум Windows Server 2012 R2.
Итак идея в следующем.
- в ОС Windows Server с версии 2012 неудачные попытки подключения в RDP-сессию стали отображаться в соответствующем журнале(EventID=140, Microsoft-Windows-RemoteDesktopServices-RdpCoreTS/Operational), с указанием IP подключающегося (в Server 2016 — еще лучше стало, там все в SECURITY лог пишется, и имя пользователя и IP — можно из одного события все данные брать).
- Делаем в Windows Firewall правило с именем «Block BAD-IP», в котором указываем, что хотим блокировать все соединения с неких IP (при создании правила внесите туда пару тестовых IP, 1.1.1.1 и 2.2.2.2 например). Это правило, вернее его список блокируемых IP мы будем в дальнейшем править скриптом
- Делаем задание в планировщике, которое стартует при возникновении этого события и запускает скрипт на Powershell. Тут все просто — создать новое задание, триггером указать «When a specific event is logged» и далее указать нужные реквизиты события, назначить Action т.п.
- Скрипт делает следующее:
- вычитывает из журнала все события с ID=140 за последние ну скажем 30 минут, получаем из них IP адреса «брутфорсеров».
- первый элемент массива — это очевидно адрес, на котором сработал скрипт, считаем сколько раз он присутствует в полученном массиве. Если больше порогового значения (например 5) — заносим его в соответствующее правило Windows Firewall
- Отправляет письмо с сообщением о событии
- PROFIT!
Ниже сам скрипт. Написан он второпях «на коленке», и наверняка может быть причесан и оптимизирован, тут я даже спорить не стану, если есть желание — меняйте на свое усмотрение.
# скрипт автоматически добавляет в уже существующее (!) правило Windows Firewall IP_адрес, с которого за последние 30 минут было больше 4 попыток входа на терминальный сервер с неправильным логином-паролем
#
# Сколько времени отступаем назад в минутах
$measureTime=(get-date)-(new-timespan -minute 30)
# Получаем массив(строго массив! даже если там только один адрес!) IP-адресов с которых идет брутфорс. В Windows Server 2012R2 это журнал событий Microsoft-Windows-RemoteDesktopServices-RdpCoreTS/Operational и сообщение с ID=140
[array]$IPs = Get-WinEvent -FilterHashtable @{Logname='Microsoft-Windows-RemoteDesktopServices-RdpCoreTS/Operational'; ID=140; StartTime=$measuretime} -ErrorAction SilentlyContinue | %{[regex]::match($_.message, "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b").value }
# Выясняем сколько раз содержится первый (тот на котором сработал скрипт) элемент массива в собственно полученном массиве адресов.
#Если этот элемент встречается там больше 4 раз - запускаем действие добавления в правило Firewall, и пишем письмо
#Если нет - просто пишем письмо про это и указываем, что вхождений пока мало
if (($Ips -match $Ips[0]).count -gt 4)
{
# получаем список адресов из правила
$oldList = Get-NetFirewallRule -DisplayName 'Block BAD-IP' | Get-NetFirewallAddressFilter
# обновляем список адресов
$newList = ($oldList.RemoteIP + $IPs[0])
# назначем новый список адресов в правило
Get-NetFirewallRule -DisplayName 'Block BAD-IP' | Get-NetFirewallAddressFilter | Set-NetFirewallAddressFilter -RemoteAddress $newList
Write-Host "Добавлен адрес: " + $Ips[0]
#region Mail
$smtpsrv = "smtp.yandex.ru"
$from = "user-mail@yandex.ru"
$to = "user-mail@yandex.ru", "user-mail@send.smsc.ru"
$subj = "ServiceRDP.AddedNewBad-IP-toFirewall. IP=" + $Ips[0]
$body = "`r`n"
$enc = [System.Text.Encoding]::UTF8
$usr = "user-mail@yandex.ru"
$pwd = ConvertTo-SecureString –String "verystrongpassword" –AsPlainText -Force
$creds = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList $usr, $pwd
#endregion Mail
Send-MailMessage $to $subj $body $smtpsrv -from $from -encoding $enc -credential $creds -useSSL
}
else
{
Write-host ("IP Адрес: " + $Ips[0] + " содержится в массиве только " + ($Ips -match $Ips[0]).count + " раз")
#region Mail
$smtpsrv = "smtp.yandex.ru"
$from = "user-mail@yandex.ru"
$to = "user-mail@yandex.ru"
$subj = "ServiceRDP.New Incorrect Username-password from IP=" + $Ips[0] + " Count=" + ($Ips -match $Ips[0]).count
$body = "`r`n"
$enc = [System.Text.Encoding]::UTF8
$usr = "user-mail@yandex.ru"
$pwd = ConvertTo-SecureString –String "verystrongpassword" –AsPlainText -Force
$creds = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList $usr, $pwd
#endregion Mail
Send-MailMessage $to $subj $body $smtpsrv -from $from -encoding $enc -credential $creds -useSSL
}
Примечания:
- В правиле Windows Firewall нужно чтобы было изначально пара адресов, иначе тот код что приведен выше не считает их списоком и ругается. Можно сам код поправить (мне лень), а можно просто внести изначально в правило пару адресов вида 1.1.1.1 и 2.2.2.2
- В скрипте естественно нужно поправить реквизиты отправки почты, указав свои. Кроме того, в случае когда адрес таки добавляется в Firewall-правило, я отправляю письмо также в шлюз Email2SMS, чтобы получить СМС об этом. Чтобы знать. Если просто происходит «срабатывания» от 1 до 4 раз, то СМС об этом получать не обязательно, это и сами пользователи могут ошибаться с паролем.
- Про сообщения генерируемые в логах при некорректных попытках входа можно подробно почитать тут Очень хорошая статья!
- У автора вышеуказанной статьи можно взять еще бесплатную утилиту, наглядно показывающую кто когда и как успешно подключался к RDP-Серверу. Называется RDPSoft RDS Log Viewer