Подключение
Подключение PHP-модуля
Подключение PHP-модуля одной строкой: решение принимается до того, как сайт начнёт собирать страницу. Требования, установка, проверка.
Шаг 1. Скачайте модуль
Файл botban.php лежит на странице вашего сайта в личном кабинете.
Положите его в папку botban/ в корне сайта.
Модуль ни от чего не зависит и работает на PHP 7.0 и выше.
Шаг 2. Подключите
Вызов должен стоять в самом начале входного файла — до любого вывода и до подключения CMS:
<?php
if (is_file(__DIR__ . '/botban/botban.php')) {
try {
require_once __DIR__ . '/botban/botban.php';
BotBan::protect('bb_pk_...', 'bb_sk_...');
} catch (\Throwable $e) {
// Сбой модуля — сайт работает без защиты.
}
}
Проверка файла и try — страховка: код можно вставить раньше, чем загружен
сам модуль. Пока файла botban/botban.php нет на сервере или он загружен не
полностью, сайт работает как обычно, просто без защиты. Кабинет выдаёт код
именно в таком виде, уже с ключами вашего сайта.
Для WordPress это начало index.php в корне сайта, для Bitrix —
начало bitrix/php_interface/init.php или того же корневого
index.php.
Почему именно первой строкой
Модуль отдаёт ответ раньше, чем сайт начнёт формировать страницу. Бот не увидит ни контента, ни запросов к базе. Если поставить вызов позже, страница уже успеет сгенерироваться, и смысл потеряется.
Если вывод уже начался, модуль молча ничего не делает — сломать вёрстку он не может.
Шаг 3. Проверьте
Откройте сайт в браузере и загляните в журнал визитов в кабинете. Ваш визит должен там появиться в течение минуты.
Первый же корректный запрос от модуля подтверждает владение доменом: поставить модуль с верным ключом может только тот, у кого есть доступ к серверу.
Ловушка для краулеров
Невидимая ссылка, по которой человек не перейдёт никогда, а робот, собирающий все ссылки подряд, — обязательно. JS-скрипт и плагин WordPress ставят её сами. Если у вас только PHP-модуль, добавьте в подвал страниц:
<a href="/.bb-trap/x7k2p9" rel="nofollow" tabindex="-1" aria-hidden="true"
style="position:absolute;left:-9999px;top:0;width:1px;height:1px;overflow:hidden">.</a>
и строку Disallow: /.bb-trap/ в robots.txt, чтобы честные поисковики
её не трогали (они и так подтверждаются отдельно и в ловушку не
попадают). Первый переход по ловушке — тяжёлая улика, второй с того же
адреса — блокировка, адрес попадает в общую память нарушителей.
Статика и служебные пути
Запросы к картинкам, стилям, скриптам и шрифтам модуль не проверяет:
если сайт отдаёт миниатюры через PHP, страница с тридцатью картинками
иначе выглядела бы как шторм запросов от одного человека. Такие запросы
не считаются ни в частоте, ни в квоте, ни в журнале. Если статику всё же
нужно проверять, передайте 'check_assets' => true в параметрах
protect(). Пути, которые не нужно трогать вообще (обмен с 1С, вебхуки
оплаты, служебные скрипты), перечислите в 'skip_paths' => ['/bitrix/admin/1c_exchange.php']
— они не дойдут до нас совсем.
Работу внутри админки сайта — /wp-admin/…, /bitrix/admin/…, /admin/…
— BotBan не проверяет и не учитывает: сотрудник, который за час сохраняет
сотни товаров, не получит проверку, а его запросы не попадут ни в журнал,
ни в лимит визитов. Доступ туда закрывает сама CMS. Страницы входа в
админку (wp-login.php, /bitrix/admin/, адреса со словом login)
проверяются как обычно: на них подбирают пароли.
На своём сервере модуль может записывать адреса заблокированных программ
в файл для fail2ban — настройка 'ban_log' => '/var/log/botban/ban.log'
(с версии 1.4.9, по умолчанию выключено). Как это устроено и что туда
попадает — в статье «Список для файрвола и fail2ban».
Laravel Octane, RoadRunner, Swoole, FrankenPHP
Эти серверы держат приложение в памяти и обслуживают запросы одним и тем же
процессом. Вызов в index.php там не работает: файл выполняется один раз при
запуске воркера, а не на каждый запрос, и exit модуля остановил бы весь
воркер. Для таких сайтов в модуле с версии 1.4.11 есть метод BotBan::check().
Он ничего не выводит сам: возвращает ответ, а отдаёт его уже приложение.
В Laravel это middleware. Положите botban.php в папку botban/ в корне
проекта, ключи — в .env, а в config/services.php добавьте
'botban' => ['public' => env('BOTBAN_PUBLIC_KEY'), 'secret' => env('BOTBAN_SECRET_KEY')].
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class BotBanGate
{
public function handle(Request $request, Closure $next): Response
{
$result = null;
try {
require_once base_path('botban/botban.php');
// Под RoadRunner заголовки лежат не в массиве сервера, а отдельно.
$server = $request->server->all();
foreach ($request->headers->all() as $name => $values) {
$server['HTTP_'.strtoupper(str_replace('-', '_', $name))] = implode(', ', $values);
}
$server['REMOTE_ADDR'] = (string) $request->ip();
$server['REQUEST_METHOD'] = $request->getRealMethod();
$server['REQUEST_URI'] = $request->getRequestUri();
$server['HTTPS'] = $request->isSecure() ? 'on' : 'off';
$result = \BotBan::check(
(string) config('services.botban.public'),
(string) config('services.botban.secret'),
$server,
$request->cookies->all(),
[
'cache_dir' => storage_path('framework/botban'),
// Поля формы — для ловушки и повтора формы после проверки, файлы — только чтобы знать, что они есть.
'post' => $request->request->all(),
'files' => $request->files->all(),
],
);
$request->attributes->set('botban.finish', $result['finish']);
} catch (\Throwable) {
// Сбой модуля — сайт работает без защиты.
}
$response = $result !== null && $result['status'] !== null
? new Response($result['body'], $result['status'])
: $next($request);
// Set-Cookie — отдельными заголовками, остальное заменяет заголовки по умолчанию.
foreach ($result['headers'] ?? [] as [$name, $value]) {
$response->headers->set($name, $value, strcasecmp($name, 'Set-Cookie') !== 0);
}
return $response;
}
public function terminate(Request $request, Response $response): void
{
// Замер нагрузки, уборка кэша и обновление — после ответа посетителю.
$finish = $request->attributes->get('botban.finish');
if (is_callable($finish)) {
$finish();
}
}
}
Подключите его в bootstrap/app.php строкой
$middleware->append(BotBanGate::class) раньше своих глобальных middleware.
Встроенные к этому месту уже отработали, поэтому $request->ip() знает
настоящий адрес посетителя за прокси. А заголовки безопасности, которые ставит
приложение, на страницу проверки не попадут: её скрипт встроен в саму страницу,
и строгая политика CSP его бы остановила. Если приложение обслуживает
несколько доменов, а защищать нужно один, проверьте $request->getHost() в
начале handle().
Есть два отличия от обычного режима. Замедление в нём не применяется: воркер один на много посетителей, и усыпить его — значит задержать всех. Порядок заголовков модуль не передаёт, потому что RoadRunner собирает их в случайном порядке. Остальное работает так же: кэш, пропуск после проверки, страница блокировки с кнопкой «Я человек», замер нагрузки.
Отправка формы
Каждую отправку формы модуль с версии 1.4.12 проверяет заново, а не по запомненному решению: спамер часто открывает страницу «чистым» и потом шлёт заявки пачкой. Если отправку нужно проверить, модуль показывает страницу проверки и сам повторяет форму после неё: заявка человека не теряется, ему не нужно заполнять форму снова. Форму с файлами и фоновые запросы страницы (корзина, поиск, формы на скриптах) модуль в таком случае пропускает: пройти проверку там некому. Блокировка действует на любые отправки.
Содержимое формы модуль нам не передаёт. Он смотрит только на служебное поле ловушки, которое добавляет скрипт, и сообщает «заполнено» или «пусто».
Обновление модуля
Модуль обновляет себя сам, начиная с версии 1.2: когда сервер сообщает,
что вышла версия новее, модуль после ответа посетителю скачивает новый
файл с cdn.botban.ru, проверяет подпись нашим ключом (открытый ключ
зашит в сам модуль), версию и синтаксис, и только потом подменяет файл
атомарно, оставив копию botban.php.bak. Файл с неверной подписью не
будет записан никогда. Для этого папка botban/ должна быть доступна
на запись веб-серверу. Если записать файл нельзя, модуль продолжает
работать на прежней версии: защита не выключается, просто новые
исправления до сайта не доходят. Свежий файл всегда можно скачать со
страницы сайта в кабинете и заменить руками. Отключить самообновление
можно параметром 'auto_update' => false.
Обновлено 15 октября 2026
Не нашли ответа?
Напишите в поддержку из кабинета — отвечаем и дополняем документацию.
Подключить бесплатно