zoolok/laravel-ip-blocker

Laravel package for blocking suspicious IP addresses (anti-spam/anti-scanner). Supports nginx and Apache log parsing.

Maintainers

Package info

github.com/zoolok/laravel-ip-blocker

pkg:composer/zoolok/laravel-ip-blocker

Transparency log

Statistics

Installs: 10

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.5.0 2026-08-01 08:42 UTC

This package is auto-updated.

Last update: 2026-08-01 08:42:39 UTC


README

Latest Version PHP Version Laravel Version

Блокировка подозрительных IP-адресов для Laravel. Поддерживает nginx и Apache.

Возможности

  • Middleware — отслеживает подозрительные ответы, проверяет блокировку, возвращает 403
  • Парсинг логов — читает access.log (nginx combined, Apache common/combined)
  • Автоопределение формата — определяет nginx или Apache по первой строке файла
  • Обнаружение сканеров — по User-Agent и путям даже при ответе 200 (ExchangeScanner, zgrab и т.п.)
  • Автоматическая блокировка — анализирует подозрительную активность и блокирует IP
  • Генерация deny-конфига — создаёт nginx deny или Apache Require not ip конфигурацию
  • Ежедневный отчёт — email-рассылка со статистикой блокировок
  • MoonShine 3.x / 4.x — опциональный админ-ресурс для просмотра блокировок
  • Инкрементальный парсинг — запоминает позицию в логе для последующих проходов

Требования

  • PHP ^8.1
  • Laravel ^10.0|^11.0|^12.0|^13.0
  • MoonShine ^3.0|^4.0 (только для интеграции с админ-панелью)
  • nginx или Apache (для генерации deny-конфигов)

Установка

composer require zoolok/laravel-ip-blocker

Публикация конфига и миграций (опционально):

php artisan vendor:publish --tag=ip-blocker-config
php artisan vendor:publish --tag=ip-blocker-migrations
php artisan migrate

Быстрый старт

1. Подключите Middleware

В bootstrap/app.php (Laravel 11+) или Http/Kernel.php:

// Глобально — на все запросы
->withMiddleware(function (Middleware $middleware) {
    $middleware->append(\Zoolok\IpBlocker\Http\Middleware\TrackSuspiciousIps::class);
})

// Или на группу роутов
Route::middleware('suspicious-ip')->group(function () {
    // ...
});

2. Настройте конфиг

IP_BLOCKER_LOG_PATH=/var/log/nginx/access.log
IP_BLOCKER_LOG_FORMAT=auto
IP_BLOCKER_SERVER_TYPE=nginx
IP_BLOCKER_DENY_PATH=/etc/nginx/conf.d/blocked-ips.conf
IP_BLOCKER_RELOAD_CMD="nginx -s reload"

3. Запустите парсинг логов (опционально)

Middleware фиксирует только новые 4xx-запросы с момента установки, поэтому база suspicious_requests изначально пуста. Чтобы сразу анализировать историю, заполните её из существующего access.log:

php artisan ip:parse-log

Опции:

  • --path — путь к лог-файлу (переопределяет конфиг)
  • --format — формат (auto, nginx-combined, apache-common, apache-combined)
  • --dry-run — только вывод, без сохранения в БД
  • --from-beginning — парсить с начала файла (игнорировать сохранённую позицию)
  • --block — после парсинга сразу запустить ip:block (удобно для cron)

4. Заблокируйте подозрительные IP

php artisan ip:block

Опции:

  • --ip — заблокировать конкретный IP
  • --reason — причина блокировки
  • --dry-run — показать, кто будет заблокирован, без блокировки
  • --force — пропустить подтверждение
  • --no-nginx — не генерировать deny-конфиг

Автоматизация (cron / планировщик)

Для автоматической защиты по логам используйте связку ip:parse-log --block:

*/5 * * * * php /path/to/artisan ip:parse-log --block --no-interaction

Пакет запоминает позицию в логе, поэтому каждый запуск обрабатывает только новые строки, а затем --block анализирует и блокирует нарушителей. Middleware при этом продолжает работать независимо: он фиксирует запросы в реальном времени и возвращает 403 уже заблокированным IP, но сам блокировки не создаёт — за это отвечает только ip:block. Записи одного и того же запроса могут попасть в suspicious_requests дважды (через middleware и через парсинг лога), это не мешает блокировке.

Встроенный планировщик

Пакет может сам регистрировать задачу ip:parse-log --block в Laravel-планировщике — отдельный cron не нужен. Достаточно включить в конфиге (или .env):

IP_BLOCKER_SCHEDULER_ENABLED=true
# IP_BLOCKER_SCHEDULER_SCHEDULE=*/5 * * * *   # по умолчанию каждые 5 минут

При этом у Laravel должен быть запущен планировщик:

* * * * * php /path/to/artisan schedule:run

Задача использует withoutOverlapping(), чтобы параллельные запуски не пересекались.

Интеграция с MoonShine

Пакет предоставляет готовый ресурс для админ-панели MoonShine для просмотра заблокированных IP. Совместим с MoonShine 3.x и 4.x. Ресурс автоматически регистрируется, когда включён в конфиге:

IP_BLOCKER_MOONSHINE_ENABLED=true

Если в вашем приложении меню админ-панели формируется вручную (переопределён метод menu() в лейауте), добавьте пункт меню автоматически:

php artisan ip:install-moonshine

Команда сама найдёт активный лейаут MoonShine (по конфигу moonshine.layout), добавит use-импорт ресурса и пункт меню «Заблокированные IP». Команда идемпотентна — повторный запуск ничего не дублирует. Для принудительной перевставки используйте --force.

Поддерживаемые форматы логов

Формат Конфиг Пример
nginx combined nginx-combined 192.168.1.1 - - [10/Jul/2026:13:55:36 +0000] "GET /admin HTTP/1.1" 404 123 "-" "curl/7.68.0"
Apache common apache-common 192.168.1.1 - - [10/Jul/2026:13:55:36 +0000] "GET /admin HTTP/1.1" 404 123
Apache combined apache-combined 192.168.1.1 - - [10/Jul/2026:13:55:36 +0000] "GET /admin HTTP/1.1" 404 123 "-" "curl/7.68.0"
Автоопределение auto Пробует nginx-combined → apache-combined → apache-common

Переменные окружения

Переменная По умолчанию Описание
IP_BLOCKER_LOG_PATH /var/log/nginx/access.log Путь к лог-файлу
IP_BLOCKER_LOG_FORMAT auto Формат лога
IP_BLOCKER_LOG_LEVEL debug Уровень логирования
IP_BLOCKER_ANALYSIS_WINDOW 5 Окно анализа (минуты)
IP_BLOCKER_MAX_404 10 Порог 404 для блокировки
IP_BLOCKER_MAX_REQUESTS 100 Порог запросов для блокировки
IP_BLOCKER_MAX_UNIQUE_URLS 20 Порог уникальных URL
IP_BLOCKER_BLOCK_DURATION 60 Длительность блокировки (минуты)
IP_BLOCKER_SERVER_TYPE nginx Тип веб-сервера (nginx/apache)
IP_BLOCKER_DENY_PATH /etc/nginx/conf.d/blocked-ips.conf Путь для deny-конфига
IP_BLOCKER_RELOAD_CMD nginx -s reload Команда перезагрузки сервера
IP_BLOCKER_REPORT_EMAIL Email для отчётов
IP_BLOCKER_MOONSHINE_ENABLED false Включить MoonShine-ресурс
IP_BLOCKER_RETENTION_DAYS 30 Дней хранить записи
IP_BLOCKER_SCHEDULER_ENABLED false Авторегистрация ip:parse-log --block в планировщике
IP_BLOCKER_SCHEDULER_SCHEDULE */5 * * * * Cron-выражение для задачи парсинга

Обнаружение сканеров (по User-Agent и путям)

По умолчанию пакет отслеживает запросы со статусом 4xx/5xx. Но сканеры (ExchangeScanner, zgrab, японские IoT-сканеры и т.п.) часто получают ответ 200 — например, когда SPA-приложение отдаёт index.html на любой путь. Такие запросы раньше не попадали в базу и IP не блокировался.

Начиная с v1.3.0 запрос считается подозрительным, если:

  • статус >= 400, или
  • User-Agent совпадает с шаблоном из ip-blocker.suspicious.user_agents, или
  • путь URL совпадает с шаблоном из ip-blocker.suspicious.paths

Шаблоны User-Agent — регистронезависимые подстроки с подстановкой *. Шаблоны путей поддерживают wildcard-синтаксис Str::is() (например /owa*). Списки настраиваются в опубликованном конфиге config/ip-blocker.php:

'suspicious' => [
    'user_agents' => ['*exchangescanner*', '*zgrab*', '*sqlmap*'],
    'paths' => ['/owa*', '/ews*', '/cgi-bin*', '/wp-admin*'],
],

Тестирование

composer test

Лицензия

MIT