Bot Fight Mode

Bot Fight Mode не пускает на сайт автоматический трафик: краулеров, которых вы не звали, сканеры уязвимостей, скрипты, headless-браузеры и инструменты, которые круглые сутки запрашивают /.env и /wp-login.php у каждого сервера в интернете. Каждый запрос оценивается по User-Agent, адресу, URL и поведению.

Включается в настройках сайта: вкладка Дополнительно, раздел Bot Fight Mode. Заблокированные запросы получают 404 (или вашу собственную страницу блокировки).

Категории ботов

Категория По умолчанию Примеры
ИИ-краулеры и ассистенты вкл. GPTBot, ChatGPT-User, ClaudeBot, CCBot, PerplexityBot, Bytespider, Amazonbot, meta-externalagent и неизвестные краулеры «…bot»
SEO-краулеры вкл. AhrefsBot, SemrushBot, MJ12bot, DotBot, BLEXBot, DataForSeoBot
Сканеры уязвимостей вкл. sqlmap, Nikto, Nuclei, WPScan, masscan, zgrab, Censys, Shodan
Скрипты и headless-браузеры вкл. curl, wget, python-requests, Go, Java, okhttp, HeadlessChrome, Puppeteer, Playwright, Selenium
Запросы без User-Agent вкл. всё, что вообще не отправляет User-Agent
Поисковые роботы выкл. Googlebot, Bingbot, YandexBot, Baiduspider, DuckDuckBot, Applebot
Боты превью ссылок выкл. Telegram, WhatsApp, Facebook, X (Twitter), Discord, Slack, LinkedIn

User-Agent с типичными для краулеров словами («SomethingBot/1.0», «crawler», «spider», контактная ссылка +https://), который не совпадает ни с одним известным именем, считается неизвестным ботом. Его блокируют, если заблокированы «ИИ-краулеры и ассистенты» или «SEO-краулеры».

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

Мониторинг и RSS-читалки не попадают ни под одно правило

Мониторы доступности и RSS-читалки обычно подключаете вы сами, и многие из них присылают User-Agent, похожий на бота. UptimeRobot, Pingdom, StatusCake, Better Uptime (Better Stack), Feedly, Inoreader, NewsBlur и Feedbin не входят ни в одну категорию. Чтобы всё же заблокировать какой-то из них, добавьте его имя в собственный список (см. ниже).

Собственный список

Также блокировать User-Agent, содержащие: одна запись на строку, без учёта регистра, до 200 записей. Любой User-Agent, в котором есть одна из записей, блокируется. Этот список проверяется раньше всех остальных правил User-Agent, поэтому он ловит и мониторы, и ботов, разрешённых по категории.

Строгая проверка браузера

По умолчанию выключена. Когда она включена, запрос, чей User-Agent не совпадает ни с одним известным ботом, должен выглядеть как настоящий браузер: присылать заголовки Accept и Accept-Language и User-Agent, начинающийся с Mozilla/5.0. Любой современный браузер так и делает, а многие парсеры копируют User-Agent браузера и забывают про остальные заголовки. Проверка может заблокировать редкие старые браузеры и некоторые необычные клиенты, поэтому сначала опробуйте её на сайте, статистику которого вы смотрите.

Известные боты, которых вы разрешили (например, поисковики), эту проверку пропускают.

Генерируемый robots.txt

Если включён параметр Отдавать robots.txt, запрещающий заблокированных ботов (включён по умолчанию), сайт без собственного robots.txt получает сгенерированный. В нём весь сайт закрыт для заблокированных вами ИИ-краулеров, SEO-краулеров и поисковиков под их официальными именами в robots.txt, путь-ловушка скрыт от всех остальных, а прочее разрешено. Краулеры, которые соблюдают robots.txt, после этого перестают заходить; остальных всё равно блокирует защита.

Если у сайта есть собственный robots.txt, он отдаётся как есть, и ничего не генерируется.

Поиск уязвимых файлов

Банить IP, ищущие уязвимости (включено по умолчанию) банит посетителя, который запрашивает путь, нужный только атакующему, если такого файла на вашем сайте нет:

  • секреты и репозитории: /.env, /.git/..., /.svn/, /.aws/, /.ssh/, /.docker/, .sql, .bak, .old, .swp, .htpasswd, docker-compose.yml, credentials.yml;
  • скрипты, которые пробуют сканеры: /wp-login.php, /wp-config.php, /xmlrpc.php, /phpinfo.php, /info.php, /shell.php, /cmd.php, /adminer.php, /c99.php, /wso.php, /filemanager.php и похожие имена;
  • известные пути приложений: /wp-admin/, /wp-json/, /phpmyadmin/, /cgi-bin/, /actuator, /server-status, /vendor/phpunit, /etc/passwd;
  • выход за пределы каталога через .. (браузер сам раскрывает .., его отправляют только инструменты).

Существующий файл никогда не считается пробой: если у вас есть /info.php, запрашивать его можно.

Одного расширения скрипта для бана мало. На сайт, переехавший с PHP или другой платформы, продолжают приходить посетители по старым ссылкам на /contact.php, /index.php или /downloads/setup.sh, и бан по расширению отрезал бы ваших же читателей. Проверяются только те имена, которые действительно пробуют сканеры; сканер, перебирающий много других имён, ловит обнаружение сканирования.

Пробы, атаки в URL, поддельные краулеры и путь-ловушка используют одно время бана: Бан, минут в Bot Fight Mode, по умолчанию 60 (от 0 до 10 080; при 0 запрос отклоняется без бана).

Запросы кроме GET

Блокировать запросы кроме GET (включено по умолчанию). Статическому сайту нужны только GET, HEAD и OPTIONS. POST, PUT, DELETE, PROPFIND и другие методы на статическом сайте присылают автоматические инструменты, поэтому такие запросы отклоняются (без бана).

Сайты с обработчиком PHP или Node.js принимают формы и вызовы API. Там разрешены ещё POST, PUT, PATCH и DELETE, а отклоняются только необычные методы вроде PROPFIND или TRACE.

Атаки в URL

Блокировать атаки в URL (включено по умолчанию) ищет SQL-инъекции, межсайтовый скриптинг, выход за пределы каталога, обёртки php://, Log4Shell (${jndi:...}), инъекции в шаблоны и команды shell в пути и в каждом параметре запроса. Закодированные и дважды закодированные формы (%2e%2e, %252e) и SQL-комментарии вместо пробелов (UNION/**/SELECT) перед проверкой раскодируются.

У правил три уровня, чтобы живого человека никогда не забанили за то, что он ввёл:

  • За несомненную атаку посетитель получает бан. Сюда относятся SQL-синтаксис вокруг слов (' or '1'='1, UNION SELECT после кавычки, sleep(5) после кавычки), <script>, обработчик событий, срабатывающий сам (onerror=), ${jndi:, .. в пути, ../, добирающийся до /etc или /proc, и сразу три уровня вверх (../../../).
  • То, что похоже на атаку, но могло прийти от человека, отклоняется, причём только этот запрос: поиск {{7*7}}, ссылка вида ?next=../page, текст etc/passwd в параметре, onclick=foo().
  • Обычный текст не совпадает ни с одним правилом: слова вроде select ... from в адресе статьи, «Sleep (2009)», {{name}} или $(...) из jQuery.

Параметры поиска (q, s, search, query, keyword, term, find и ещё несколько) проверяются мягче: тот, кто ищет в вашей документации php:// или <div onclick=...>, скорее всего читатель. В параметре поиска к бану приводит только несомненный эксплойт; однострочники shell и составные SQL-запросы там отклоняются без бана.

Лимиты, которые нельзя обойти заполнением

Каждое правило работает за линейное время, поэтому специально составленный URL не замедлит сервер. Путь и каждый параметр запроса проверяются отдельно, до 4 КБ каждый. Чтобы атаку нельзя было спрятать за заполнителем, запрос отклоняется (без бана), если:

  • путь или один из параметров длиннее 4 КБ,
  • в нём больше 200 параметров,
  • или строка запроса длиннее 64 КБ.

Обнаружение сканирования

Банить IP, сканирующие файлы (включено по умолчанию) ловит инструменты перебора каталогов вроде gobuster, ffuf и dirbuster: посетитель, собравший много ответов 404 за короткое время, получает бан. По умолчанию порог 25 отсутствующих путей за 60 секунд (настраивается: от 3 до 10 000 путей, от 5 до 3600 секунд).

Отсутствующая картинка, таблица стилей, скрипт, шрифт или source map считается за 0,1 промаха. Читатель, открывший старую страницу с 30 битыми картинками, наберёт 3 промаха, что намного ниже порога.

Сайты на PHP и Node.js

На сайте с динамическим обработчиком некоторые пути, похожие на пробы, могут оказаться настоящими маршрутами: WordPress отдаёт /wp-json/ и /wp-admin/ из своего кода. Поэтому на сайтах PHP и Node.js:

  • известные пути приложений (/wp-admin/, /wp-json/, /phpmyadmin/, /cgi-bin/ и остальные из этого списка) пробами не считаются. Секреты (/.env, /.git), имена скриптов сканеров (/shell.php, /phpinfo.php) и выход за пределы каталога по-прежнему считаются;
  • формы и API (POST, PUT, PATCH, DELETE) разрешены, как описано выше;
  • путь, который отдали бы правила .htaccess, считается существующим.

Сканирование всё равно ловится, потому что обнаружение сканирования считает ответы 404, которые возвращает PHP.

Проверка краулеров и списки IP

Ещё три переключателя Bot Fight Mode смотрят на адрес, а не на User-Agent: Проверять краулеров по IP (включено по умолчанию), Блокировать этих краулеров и по IP и Использовать публичные списки блокировки IP. Они описаны на странице Проверенные краулеры и публичные списки IP. У параметра Путь-ловушка своя страница: Путь-ловушка.