Fail2ban для Windows: какие есть реальные аналоги
Fail2ban под Windows не существует. Как выглядит самописный вариант на PowerShell, где именно он ломается и что на самом деле дают альтернативы.
Почему этот вопрос возникает снова и снова
На Linux fail2ban — рефлекторный ответ на подбор паролей: он читает лог, сопоставляет строки отказов с регулярным выражением и добавляет правило фаервола для адреса, перешедшего порог. Он маленький, он стандартный, и он есть в каждом руководстве по харденингу за последние пятнадцать лет.
Администраторы, переходящие на Windows, ищут тот же инструмент и не находят ничего. Fail2ban — это Python плюс iptables, и под Windows он не работает ни в каком осмысленном виде: там нет syslog для чтения и нет iptables для записи. У Windows вместо этого есть журнал безопасности и Windows Firewall — те же два ингредиента, только не соединённые между собой.
Поэтому вопрос на самом деле не «как поставить fail2ban на Windows». Он звучит так: «что соединяет событие 4625 с правилом фаервола, и сколько из этого мне придётся построить самому».
Самописный вариант и его цена
Ответ «сделай сам» — это плановая задача на PowerShell. Каркас действительно короткий: вот чтение отказов за последние десять минут, группировка по источнику и блокировка всего, что превысило порог.
$Threshold = 10
$RuleName = 'Block-BruteForce'
$offenders = Get-WinEvent -FilterHashtable @{
LogName='Security'; Id=4625; StartTime=(Get-Date).AddMinutes(-10)
} -ErrorAction SilentlyContinue |
ForEach-Object { ([xml]$_.ToXml()).Event.EventData.Data |
Where-Object Name -eq 'IpAddress' | Select-Object -ExpandProperty '#text' } |
Where-Object { $_ -and $_ -ne '-' } |
Group-Object | Where-Object Count -ge $Threshold | Select-Object -ExpandProperty Name
$rule = Get-NetFirewallRule -DisplayName $RuleName -ErrorAction SilentlyContinue
if (-not $rule) {
New-NetFirewallRule -DisplayName $RuleName -Direction Inbound -Action Block `
-RemoteAddress $offenders | Out-Null
} else {
$existing = ($rule | Get-NetFirewallAddressFilter).RemoteAddress
$rule | Set-NetFirewallRule -RemoteAddress @($existing + $offenders | Select-Object -Unique)
}Где скрипт начинает протекать
Эти тридцать строк заблокируют реальных атакующих уже сегодня. Разрыв между ними и тем, что можно оставить работать на год, состоит из неромантичных проблем, и каждая обнаруживается только в бою:
- Вы заблокируете себя. В коде выше нет белого списка. В первый же раз, когда у вашего офисного адреса случится плохой день — классика: сохранённые устаревшие учётные данные, повторяющиеся в цикле, — вы окажетесь снаружи сервера, к которому есть доступ только по RDP.
- Отдельных адресов мало. Ботнеты перебирают диапазон. Блокировка 203.0.113.47 даёт вам час до старта .48. Блокировка /24 обрывает серию, но корректно вычислять и объединять CIDR-диапазоны заметно сложнее, чем показано выше.
- Окно опроса теряет события. Запуск раз в десять минут либо пропускает всплеск, укладывающийся в одно окно, либо считает его дважды на границе. Под нагрузкой журнал безопасности ротируется быстрее вашего интервала, и события исчезают до того, как вы их прочтёте.
- Никто не сообщит, что защита встала. Плановые задачи падают молча — после перезагрузки, после смены пароля учётки, от которой они запускаются, после обновления политики PowerShell. Вы узнаёте через месяцы, что защита не отрабатывала с марта.
- Порт RDP может быть не 3389. Если его переносили, скрипт всё ещё блокирует источник, но никто не проверяет, какие порты должно закрывать правило, а FTP и MS SQL не покрыты вовсе.
- Баны не переживают пересборку. Состояние живёт в фаерволе одной машины. Восстановите из образа — и все атакующие, о которых вы узнали, забыты.
Что Windows даёт из коробки
В этом контексте обычно рекомендуют две встроенные возможности, и стоит быть точным насчёт того, что делает каждая.
Политика блокировки учётных записей отключает запись после N неудач. Против RDP, смотрящего в интернет, это скорее уязвимость, чем защита: имя учётной записи выбирает атакующий, значит кто угодно может по желанию заблокировать вашего Administrator откуда угодно. Разумная мера для внутренних учёток и плохая — на периметре.
Network Level Authentication требует аутентификации клиента до создания сессии. Она действительно снижает стоимость каждой попытки и убирает класс доэкплуатационных уязвимостей, и её надо включать. Число попыток она не уменьшает, потому что боты аутентифицируются всё равно — плохо и бесконечно.
Ни то, ни другое не соединяет журнал событий с фаерволом. Именно это соединение и даёт fail2ban, и в поставке Windows его нет.
Варианты рядом друг с другом
По соотношению затрат и результата:
- PowerShell-скрипт — бесплатно, полный контроль, примерно день на написание и постоянное обязательство поддерживать. Годится для одного сервера, на который вы часто смотрите. Отказывает молча.
- VPN или RDP-шлюз перед сервером — самое сильное решение и самое дорогое в эксплуатации. Если до VPN может дотянуться каждый пользователь — используйте его и не читайте дальше. В большинстве парков есть подрядчики и телефоны, для которых это так и не случается.
- Белый список IP на фаерволе — отлично, когда набор легитимных адресов мал и постоянен, и непригодно в ту минуту, когда кто-то работает из гостиницы.
- Управляемый агент — установщик, белый список, наполняемый до того, как что-то будет заблокировано, баны подсетей, автоопределение портов и консоль, показывающая, работает ли защита. К этой категории относится RDP Protector.
Что управляемый агент добавляет к скрипту
Две вещи, которых у скрипта не может быть, как бы хорошо вы его ни написали.
Первая — эксплуатационная база: ваш адрес в белом списке с момента установки, одно сводное правило фаервола вместо тысяч, порты, определённые по реестру и слушающим сокетам, баны, переживающие перезагрузку, и панель, которая отвечает на вопрос «оно вообще живо» — а это и есть тот отказ, который реально кусается.
Вторая не строится в одиночку вообще. Каждый защищённый сервер пополняет общую базу репутации, поэтому адрес, атаковавший кого-то вчера, уже заблокирован, когда дойдёт до вас. Скрипт на одном сервере может учиться только на атаках по этому серверу.
Решение при этом по-прежнему принимается локально на агенте, так что защита не зависит от доступности облака: если связь пропала, продолжает работать локальная политика.
FAQ
- Можно ли реально запустить fail2ban на Windows?
- Полезным образом — нет. Fail2ban зависит от Python и iptables и от чтения текстовых логов в стиле syslog; в Windows нет ни iptables, ни syslog, а отказы аутентификации лежат в бинарном журнале безопасности. Запуск под WSL защищает окружение WSL, а не RDP хостовой Windows. Нужен инструмент, построенный на Get-WinEvent и Windows Firewall.
- Достаточно ли PowerShell-скрипта для одного сервера?
- Для одного сервера, который вы администрируете ежедневно и проверяете, — да, тридцать строк выше заблокируют реальных атакующих. Заложите день на добавление белого списка, работы с подсетями и проверки живости и примите, что отказывает такая схема молча: плановые задачи перестают запускаться после перезагрузок и смены паролей, никого об этом не уведомляя.
- Почему одно правило фаервола лучше, чем правило на каждый IP?
- Windows Firewall обрабатывает правила последовательно и справляется с несколькими правилами, содержащими большие списки адресов, куда лучше, чем с тысячами мелких. Правила на каждый адрес — стандартный способ, которым такие скрипты умирают: пару недель всё прекрасно, потом обработка правил начинает стоить минут, а консоль управления становится непригодной.
- Заменяет ли блокировка на фаерволе сложные пароли?
- Нет — она убирает объём, а не требование. Сложные пароли и NLA останавливают те попытки, которые прошли; блокировка на фаерволе не даёт им дойти до Windows вообще, что защищает процессор, журнал аудита и вашу способность найти в нём реальные события. Нужно и то, и другое.
