Pull to refresh

ShieldPHP: многоуровневая защита от DDoS и брутфорс-атак для PHP-сайтов

Level of difficultyMedium

ShieldPHP — это модульная система безопасности для веб-сайтов на PHP, которая обеспечивает многоуровневую защиту от различных типов атак, включая DDoS, брутфорс и сканирование уязвимостей. Рассмотрим её технические особенности и принципы работы.

Архитектура системы

Система состоит из нескольких ключевых компонентов:

  1. security_monitor.php — основной модуль мониторинга, отвечающий за обнаружение и блокировку подозрительной активности

  2. admin.php — административный интерфейс с панелью управления для настройки и мониторинга

  3. recaptcha_unlock.php — механизм разблокировки с использованием reCAPTCHA

  4. cleanup.php — фоновая служба для очистки устаревших данных и оптимизации

  5. settings.php — конфигурационный файл с настройками безопасности

  6. check_404.php — обработчик 404-ошибок для выявления сканирования

Система поддерживает работу с Redis и MariaDB, автоматически выбирая оптимальный режим в зависимости от доступности и настроек.

Методы обнаружения атак

1. Контроль частоты запросов

phpprivate function checkIPRateLimitRedis() {
    if (!$this->redis) return false;
    
    try {
        $key = $this->prefix . "ip_request_rate:{$this->ip}";
        $now = time();
        
        // Если ключ не существует, создаем его с TTL
        if (!$this->redis->exists($key)) {
            $ttl = defined('REDIS_TTL_IP_REQUEST_RATE') ? REDIS_TTL_IP_REQUEST_RATE : 600;
            
            $hashData = array(
                'request_count' => 1,
                'first_request_time' => $now,
                'last_request_time' => $now
            );
            
            $this->redis->hMSet($key, $hashData);
            $this->redis->expire($key, $ttl);
            
            return false;
        }
        
        // Увеличиваем счетчик запросов
        $this->redis->hIncrBy($key, 'request_count', 1);
        $this->redis->hSet($key, 'last_request_time', $now);
        
        // Проверяем превышение лимита
        $request_count = (int)$this->redis->hGet($key, 'request_count');
        $first_time = (int)$this->redis->hGet($key, 'first_request_time');
        $time_diff = $now - $first_time;
        
        $window = defined('RATE_CHECK_WINDOW') ? RATE_CHECK_WINDOW : 30;
        $threshold = defined('RATE_THRESHOLD') ? RATE_THRESHOLD : 20;
        
        // Если лимит запросов превышен во временном окне
        if ($time_diff <= $window && $request_count > $threshold) {
            return true;
        }
        
        return false;
    } catch (Exception $e) {
        error_log("Ошибка проверки лимита IP: " . $e->getMessage());
        return false;
    }
}
private function checkIPRateLimitRedis() {
    if (!$this->redis) return false;
    
    try {
        $key = $this->prefix . "ip_request_rate:{$this->ip}";
        $now = time();
        
        // Если ключ не существует, создаем его с TTL
        if (!$this->redis->exists($key)) {
            $ttl = defined('REDIS_TTL_IP_REQUEST_RATE') ? REDIS_TTL_IP_REQUEST_RATE : 600;
            
            $hashData = array(
                'request_count' => 1,
                'first_request_time' => $now,
                'last_request_time' => $now
            );
            
            $this->redis->hMSet($key, $hashData);
            $this->redis->expire($key, $ttl);
            
            return false;
        }
        
        // Увеличиваем счетчик запросов
        $this->redis->hIncrBy($key, 'request_count', 1);
        $this->redis->hSet($key, 'last_request_time', $now);
        
        // Проверяем превышение лимита
        $request_count = (int)$this->redis->hGet($key, 'request_count');
        $first_time = (int)$this->redis->hGet($key, 'first_request_time');
        $time_diff = $now - $first_time;
        
        $window = defined('RATE_CHECK_WINDOW') ? RATE_CHECK_WINDOW : 30;
        $threshold = defined('RATE_THRESHOLD') ? RATE_THRESHOLD : 20;
        
        // Если лимит запросов превышен во временном окне
        if ($time_diff <= $window && $request_count > $threshold) {
            return true;
        }
        
        return false;
    } catch (Exception $e) {
        error_log("Ошибка проверки лимита IP: " . $e->getMessage());
        return false;
    }
}

2. Анализ паттернов запросов

Система использует различные методики для выявления подозрительных паттернов:

  • Проверка временных интервалов между запросами Анализ дисперсии интервалов позволяет определить автоматические запросы

phpprivate function checkTimingDispersion() {
    // Вычисляем интервалы между запросами
    $intervals = array();
    $timings = $_SESSION['request_timings'];
    $count = count($timings);
    
    // Вычисляем средний интервал
    $avg = array_sum($intervals) / count($intervals);
    
    // Вычисляем дисперсию
    $variance = 0;
    foreach ($intervals as $interval) {
        $variance += pow($interval - $avg, 2);
    }
    $variance /= count($intervals);
    
    // Минимальная ожидаемая дисперсия для трафика человека
    $min_variance = defined('TIMING_DISPERSION_MIN') ? TIMING_DISPERSION_MIN : 0.2;
    
    // Если очень низкая дисперсия, вероятно, это бот
    if ($variance < $min_variance && $avg < 5) {
        return true;
    }
    
    return false;
}
private function checkTimingDispersion() {
    // Вычисляем интервалы между запросами
    $intervals = array();
    $timings = $_SESSION['request_timings'];
    $count = count($timings);
    
    // Вычисляем средний интервал
    $avg = array_sum($intervals) / count($intervals);
    
    // Вычисляем дисперсию
    $variance = 0;
    foreach ($intervals as $interval) {
        $variance += pow($interval - $avg, 2);
    }
    $variance /= count($intervals);
    
    // Минимальная ожидаемая дисперсия для трафика человека
    $min_variance = defined('TIMING_DISPERSION_MIN') ? TIMING_DISPERSION_MIN : 0.2;
    
    // Если очень низкая дисперсия, вероятно, это бот
    if ($variance < $min_variance && $avg < 5) {
        return true;
    }
    
    return false;
}
  • Обнаружение множественных User-Agent с одного IP Позволяет выявить имитацию разных браузеров

  • Проверка согласованности Cookie и сессий Обнаруживает попытки подмены сессий и манипуляции с Cookie

  • Honeypot URL мониторинг Отслеживание попыток доступа к несуществующим, но часто сканируемым путям

phpprivate function checkHoneypotUrl() {
    // Список URL, которые обычные пользователи никогда не посещают, но боты сканируют
    $honeypot_urls = array(
        '/wp-login.php',
        '/administrator/',
        '/admin.php',
        '/wp-admin/',
        '/xmlrpc.php',
        '/.env',
        // ... и другие часто сканируемые пути
    );
    
    // Проверяем текущий URL
    $current_url = $_SERVER['REQUEST_URI'];
    
    foreach ($honeypot_urls as $honeypot) {
        if (strpos($current_url, $honeypot) !== false) {
            // Дополнительная проверка на отсутствие cookies/referer
            if (empty($_COOKIE) || empty($_SERVER['HTTP_REFERER'])) {
                return true;
            }
        }
    }
    
    return false;
}
private function checkHoneypotUrl() {
    // Список URL, которые обычные пользователи никогда не посещают, но боты сканируют
    $honeypot_urls = array(
        '/wp-login.php',
        '/administrator/',
        '/admin.php',
        '/wp-admin/',
        '/xmlrpc.php',
        '/.env',
        // ... и другие часто сканируемые пути
    );
    
    // Проверяем текущий URL
    $current_url = $_SERVER['REQUEST_URI'];
    
    foreach ($honeypot_urls as $honeypot) {
        if (strpos($current_url, $honeypot) !== false) {
            // Дополнительная проверка на отсутствие cookies/referer
            if (empty($_COOKIE) || empty($_SERVER['HTTP_REFERER'])) {
                return true;
            }
        }
    }
    
    return false;
}

Механизмы блокировки

Система предлагает несколько уровней блокировки:

  1. Прогрессивная блокировка Повышение времени блокировки с каждым повторным нарушением

phpswitch ($block_count) {
    case 2:
        $progressive_seconds = defined('BLOCK_TIME_SECOND') ? BLOCK_TIME_SECOND : 10800; // 3 часа
        break;
    case 3:
        $progressive_seconds = defined('BLOCK_TIME_THIRD') ? BLOCK_TIME_THIRD : 21600; // 6 часов
        break;
    case 4:
        $progressive_seconds = defined('BLOCK_TIME_FOURTH') ? BLOCK_TIME_FOURTH : 43200; // 12 часов
        break;
    // ...и так далее
}
switch ($block_count) {
    case 2:
        $progressive_seconds = defined('BLOCK_TIME_SECOND') ? BLOCK_TIME_SECOND : 10800; // 3 часа
        break;
    case 3:
        $progressive_seconds = defined('BLOCK_TIME_THIRD') ? BLOCK_TIME_THIRD : 21600; // 6 часов
        break;
    case 4:
        $progressive_seconds = defined('BLOCK_TIME_FOURTH') ? BLOCK_TIME_FOURTH : 43200; // 12 часов
        break;
    // ...и так далее
}
  1. Многоуровневая защита Применение различных методов блокировки:

    • Redis и MariaDB для хранения состояния блокировок

    • .htaccess для блокировки на уровне веб-сервера

    • ip.conf для блокировки через Nginx

    • iptables/ip6tables для блокировки на уровне ОС

    • API для интеграции с внешними системами защиты

  2. Троттлинг (замедление) вместо блокировки Постепенное увеличение задержки для подозрительных IP:

phppublic function applyThrottling($requestType = 'default', $increase = true) {
    // Вычисляем задержку: чем больше превышение, тем дольше задержка
    $overLimit = $count - $limit;
    $delayFactor = min(1, $overLimit / $limit); // От 0 до 1
    $result['delay'] = (int)($maxDelay * $delayFactor);
    
    // Если настроено, применяем задержку
    if (defined('THROTTLING_APPLY_DELAY') && THROTTLING_APPLY_DELAY) {
        $this->applyDelay($result['delay']);
    }
}
public function applyThrottling($requestType = 'default', $increase = true) {
    // Вычисляем задержку: чем больше превышение, тем дольше задержка
    $overLimit = $count - $limit;
    $delayFactor = min(1, $overLimit / $limit); // От 0 до 1
    $result['delay'] = (int)($maxDelay * $delayFactor);
    
    // Если настроено, применяем задержку
    if (defined('THROTTLING_APPLY_DELAY') && THROTTLING_APPLY_DELAY) {
        $this->applyDelay($result['delay']);
    }
}
  1. Автоматическая жесткая блокировка При превышении порога блокировок активируется автоматическая жесткая блокировка для защиты от массированных атак

phpprivate function checkAndApplyAutoHardBlock() {
    // Определяем порог количества блокировок
    $threshold = defined('AUTO_HARD_BLOCK_THRESHOLD') ? AUTO_HARD_BLOCK_THRESHOLD : 100;
    
    // Получаем текущее количество заблокированных IP
    $blocked_count = $this->getBlockedIPsCount();
    
    // Если количество блокировок не превышает порог, выходим
    if ($blocked_count <= $threshold) {
        return false;
    }
    
    // Логируем событие
    error_log("Превышен порог количества заблокированных IP ($blocked_count > $threshold). Применяем жесткую блокировку.");
    
    // Получаем наиболее активные заблокированные IP
    $blocked_ips = $this->getMostActiveBlockedIPs(50);
    
    // Применяем жесткую блокировку
    $this->applyHardBlockToAll($blocked_ips);
    
    return true;
}
private function checkAndApplyAutoHardBlock() {
    // Определяем порог количества блокировок
    $threshold = defined('AUTO_HARD_BLOCK_THRESHOLD') ? AUTO_HARD_BLOCK_THRESHOLD : 100;
    
    // Получаем текущее количество заблокированных IP
    $blocked_count = $this->getBlockedIPsCount();
    
    // Если количество блокировок не превышает порог, выходим
    if ($blocked_count <= $threshold) {
        return false;
    }
    
    // Логируем событие
    error_log("Превышен порог количества заблокированных IP ($blocked_count > $threshold). Применяем жесткую блокировку.");
    
    // Получаем наиболее активные заблокированные IP
    $blocked_ips = $this->getMostActiveBlockedIPs(50);
    
    // Применяем жесткую блокировку
    $this->applyHardBlockToAll($blocked_ips);
    
    return true;
}

Система разблокировки

Для обеспечения возможности разблокировки легитимных пользователей система предоставляет механизм с использованием reCAPTCHA:

php// Проверка reCAPTCHA
public function verifyRecaptcha($recaptcha_response) {
    if (empty($recaptcha_response)) {
        return false;
    }
    
    $url = 'https://www.google.com/recaptcha/api/siteverify';
    $data = array(
        'secret' => RECAPTCHA_SECRET_KEY,
        'response' => $recaptcha_response,
        'remoteip' => $this->ip
    );
    
    $options = array(
        'http' => array(
            'header' => "Content-type: application/x-www-form-urlencoded\r\n",
            'method' => 'POST',
            'content' => http_build_query($data)
        )
    );
    
    $context = stream_context_create($options);
    $result = file_get_contents($url, false, $context);
    
    if ($result === FALSE) {
        return false;
    }
    
    $response = json_decode($result, true);
    return isset($response['success']) && $response['success'] === true;
}
// Проверка reCAPTCHA
public function verifyRecaptcha($recaptcha_response) {
    if (empty($recaptcha_response)) {
        return false;
    }
    
    $url = 'https://www.google.com/recaptcha/api/siteverify';
    $data = array(
        'secret' => RECAPTCHA_SECRET_KEY,
        'response' => $recaptcha_response,
        'remoteip' => $this->ip
    );
    
    $options = array(
        'http' => array(
            'header' => "Content-type: application/x-www-form-urlencoded\r\n",
            'method' => 'POST',
            'content' => http_build_query($data)
        )
    );
    
    $context = stream_context_create($options);
    $result = file_get_contents($url, false, $context);
    
    if ($result === FALSE) {
        return false;
    }
    
    $response = json_decode($result, true);
    return isset($response['success']) && $response['success'] === true;
}

Страница разблокировки также отслеживает частоту посещений для предотвращения атак на саму систему разблокировки.

Система администрирования

Административная панель предоставляет следующие возможности:

  1. Просмотр заблокированных IP-адресов и причин блокировки

  2. Управление белым списком для исключения определенных IP

  3. Мониторинг частоты запросов и подозрительной активности

  4. Очистка дублирующихся правил брандмауэра

  5. Оперативная разблокировка IP-адресов вручную

  6. Настройка режимов работы системы

Отказоустойчивость и производительность

Система обеспечивает высокую надежность благодаря:

  1. Многоуровневому кешированию Информация о блокировках хранится в Redis, MariaDB и файловом кеше для обеспечения доступности даже при сбоях

  2. Автоматическому переключению между Redis и MariaDB При недоступности Redis система автоматически переключается на MariaDB:

php// Если Redis недоступен, получаем данные из MariaDB
if (!$this->useRedis || !$this->redis) {
    // Пытаемся подключиться к БД
    $this->connectDB();
    $db_available = $this->db ? true : false;
    
    // Если БД доступна, используем её
    if ($db_available) {
        // Проверка через БД
        if ($this->checkIPRateLimitInDatabase()) {
            $this->logRequest();
            $this->blockIP(3600, 'Превышен лимит запросов');
            $this->redirectToUnlockPage();
            exit;
        }
    }
    // Если и база недоступна, используем файловый режим
    else if ($this->checkIPRateLimitFile()) {
        $this->applyDirectBlockings($this->ip);
        $this->redirectToUnlockPage();
        exit;
    }
}
// Если Redis недоступен, получаем данные из MariaDB
if (!$this->useRedis || !$this->redis) {
    // Пытаемся подключиться к БД
    $this->connectDB();
    $db_available = $this->db ? true : false;
    
    // Если БД доступна, используем её
    if ($db_available) {
        // Проверка через БД
        if ($this->checkIPRateLimitInDatabase()) {
            $this->logRequest();
            $this->blockIP(3600, 'Превышен лимит запросов');
            $this->redirectToUnlockPage();
            exit;
        }
    }
    // Если и база недоступна, используем файловый режим
    else if ($this->checkIPRateLimitFile()) {
        $this->applyDirectBlockings($this->ip);
        $this->redirectToUnlockPage();
        exit;
    }
}
  1. Оптимизации для высоконагруженных систем

    • Контроль использования памяти Redis

    • Периодическая очистка и оптимизация таблиц

    • Возможность настройки вероятностных проверок для снижения нагрузки

  2. Система уведомления администратора Автоматическое информирование о срабатывании защиты:

phpprivate function sendAdminNotification($total_blocked, $threshold) {
    // Формируем текст письма
    $message = "Внимание! На сайте $site_name активирована автоматическая жесткая блокировка.\n\n";
    $message .= "Порог активации: $threshold IP-адресов\n";
    $message .= "Текущее количество блокировок: $total_blocked IP-адресов\n";
    $message .= "Метод блокировки: " . (defined('AUTO_HARD_BLOCK_ACTION') ? 
                strtoupper(AUTO_HARD_BLOCK_ACTION) : 'ALL') . "\n\n";
    $message .= "Проверьте панель администратора для получения подробной информации.\n";
    
    // Отправляем письмо
    $mail_sent = @mail($admin_email, $subject, $message, $headers);
}
private function sendAdminNotification($total_blocked, $threshold) {
    // Формируем текст письма
    $message = "Внимание! На сайте $site_name активирована автоматическая жесткая блокировка.\n\n";
    $message .= "Порог активации: $threshold IP-адресов\n";
    $message .= "Текущее количество блокировок: $total_blocked IP-адресов\n";
    $message .= "Метод блокировки: " . (defined('AUTO_HARD_BLOCK_ACTION') ? 
                strtoupper(AUTO_HARD_BLOCK_ACTION) : 'ALL') . "\n\n";
    $message .= "Проверьте панель администратора для получения подробной информации.\n";
    
    // Отправляем письмо
    $mail_sent = @mail($admin_email, $subject, $message, $headers);
}

Установка и интеграция

Для установки системы необходимо:

  1. Скопировать все файлы в каталог /dos/ на вашем веб-сервере

  2. Настроить параметры в файле settings.php

  3. Добавить строку

    require_once $_SERVER['DOCUMENT_ROOT'] . '/dos/security_monitor.php';

    в начало главного файла сайта

  4. Создать таблицы в базе данных или запустить скрипт cleanup.php с параметром --create-tables

  5. Настроить периодический запуск cleanup.php через cron

    crontab -e
    */15 * * * * curl -s -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36" https://mysite.com/dos/cleanup.php > /dev/null 2>&1
    

    Заключение

    ShieldPHP представляет собой комплексное решение для защиты веб-сайтов от различных типов атак. Благодаря многоуровневой архитектуре, система способна эффективно блокировать атаки даже при высокой нагрузке, обеспечивая при этом возможность легитимным пользователям разблокировать свои IP-адреса. Гибкая настройка и наличие административного интерфейса делают систему удобной в использовании для администраторов сайтов.

    Проект имеет открытый исходный код (лицензия MIT) и постоянно развивается. Подробная документация и инструкции по установке доступны на GitHub.

    Автор: Виталий Литвинов (murkir.pp.ua)

    Tags:
    Hubs:
    You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.