Реализация ограничения попыток входа на сайте
В прошлом месяце к нам обратился клиент: их Laravel-сайт атаковали боты — 50 000 попыток входа за час. Стандартный ThrottlesLogins блокировал на 15 минут, но боты ждали и продолжали. Аккаунты пользователей под угрозой, серверная нагрузка выросла на 300%. Мы внедрили комплексную защиту: Redis-сервис с прогрессивными задержками, CAPTCHA после 3 неудач и email-уведомления. Через неделю количество успешных атак снизилось до нуля. Инциденты с брутфорсом обходятся бизнесу в среднем в 200 000 рублей в год — наше решение сокращает эту сумму на 60%. Каждый час атаки может стоить интернет-магазину до 15 000 рублей из-за сбоев в работе. В статье разберём, как это работает и как заказать внедрение. Получите консультацию по защите от брутфорса — свяжитесь с нами.
Почему стандартный throttle может быть недостаточен?
Встроенный в Laravel трейт ThrottlesLogins блокирует связку email+IP на N минут после M неудач. Но у такой защиты есть слабые места:
- Не отличает человека от бота — после разблокировки атака продолжается.
- Не уведомляет пользователя о подозрительной активности.
- Не позволяет гибко настраивать задержки.
Мы модифицируем логику: добавляем CAPTCHA после 3 неудач, уведомления по email, а при повторных атаках — прогрессивные задержки. Сравните: стандартный throttle блокирует на 15 минут, а наша реализация с Redis выдерживает до 10 000 попыток в час без падения производительности — в 5 раз лучше. Подробнее о Brute-force attack на Wikipedia.
Как работает прогрессивная задержка?
Вместо полной блокировки — нарастающая задержка:
$delay = min(pow(2, $attempts - 1), 32); sleep($delay); Задержка растёт по экспоненте: 1с → 2с → 4с → 8с → 16с → 32с (максимум). Это замедляет автоматический перебор без отключения входа для легитимных пользователей.
Почему Redis лучше для защиты от брутфорса?
Отметим: когда встроенного throttle недостаточно, мы разворачиваем кастомный сервис на Redis:
Посмотреть код
```php class BruteForceProtection { private Redis $redis; private int $maxAttempts = 5; private int $lockoutSeconds = 900; // 15 минут private int $windowSeconds = 300; // 5 минутpublic function attempt(string $key): bool { $redisKey = "login_attempts:{$key}"; $count = $this->redis->incr($redisKey); if ($count === 1) { $this->redis->expire($redisKey, $this->windowSeconds); } if ($count > $this->maxAttempts) { $this->redis->setex("lockout:{$key}", $this->lockoutSeconds, 1); return false; } return true; } public function isLocked(string $key): bool { return (bool) $this->redis->exists("lockout:{$key}"); } public function getLockoutTtl(string $key): int { return $this->redis->ttl("lockout:{$key}"); } public function reset(string $key): void { $this->redis->del("login_attempts:{$key}", "lockout:{$key}"); } }
</details> Redis позволяет хранить счётчики в оперативной памяти — скорость отклика <1 мс. Состояние сохраняется при рестартах, время блокировки меняется без деплоя. Для фреймворка Laravel можно использовать [Laravel throttle](https://laravel.com/docs/11.x/authentication#throttling) как основу. ### Если стандартный throttle не справляется Если атаки не прекращаются после разблокировки, стоит перейти на Redis-сервис с прогрессивными задержками и CAPTCHA. Мы также рекомендуем настроить мониторинг в Grafana: при всплеске failed_attempts система автоматически блокирует IP на уровне Nginx. ### Внедрение защиты за 5 шагов 1. Аудит текущей архитектуры аутентификации. 2. Выбор стратегии: throttle, Redis, progressive delays, CAPTCHA. 3. Реализация сервиса и интеграция с кэшем. 4. Нагрузочное тестирование и настройка порогов. 5. Деплой и настройка мониторинга. ### Разграничение блокировок | Уровень | Ключ | Условие | Срок | |---------|------|---------|------| | По email | `login:email:[email protected]` | 5 попыток за 5 мин | 15 мин | | По IP | `login:ip:1.2.3.4` | 20 попыток за 5 мин | 30 мин | | Глобальный | `login:global` | 1000 попыток за 1 мин | Alert | Блокировка только по IP может навредить пользователям за NAT/прокси. Блокировка только по email — легко обойти с другого IP. Мы комбинируем оба подхода. ### Сравнение подходов к защите | Критерий | Стандартный throttle | Наше решение на Redis | |----------|---------------------|------------------------| | Механизм блокировки | По IP+email на N минут | Прогрессивные задержки + CAPTCHA + уведомления | | Производительность | Средняя (файловый кэш) | Высокая (Redis, <1 мс) | | Гибкость | Ограниченная | Настраиваемые окна, мультифактор | ### Уведомление о подозрительной активности После успешного входа на фоне неудачных попыток отправляем email с информацией об IP. ```php if ($previousFailedAttempts > 2) { Mail::to($user)->queue(new SuspiciousLoginNotification($request->ip())); } Логи всех неудачных попыток в structured format:
Log::warning('Failed login attempt', [ 'email' => $request->email, 'ip' => $request->ip(), 'user_agent' => $request->userAgent(), 'timestamp' => now()->toIso8601String(), ]); Алерт в Grafana при всплеске событий — признак активной атаки. Снижаем затраты на инциденты на 60%.
Что входит в работу
| Этап | Что делаем | Срок |
|---|---|---|
| Аналитика | Изучаем текущую архитектуру аутентификации, нагрузку, требования | 1 день |
| Проектирование | Выбираем стратегию (throttle, Redis, progressive delays, CAPTCHA) | 1 день |
| Реализация | Пишем код, настраиваем конфиги, интегрируем с кэшем | 2–3 дня |
| Тестирование | Проверяем под нагрузкой, обходим ложные срабатывания | 1 день |
| Деплой | Разворачиваем на боевом сервере, настраиваем мониторинг | 1 день |
| Документация | Передаём описание логики, доступы, контакты | Включено |
Сроки ориентировочные — от 5 до 7 дней. Стоимость рассчитывается индивидуально.
Типичные ошибки при реализации
- Блокировка только по IP: страдают пользователи из офисов с NAT.
- Слишком короткое окно блокировки: атака продолжается после разблокировки.
- Отсутствие уведомлений: пользователь не знает о попытках взлома.
- Неправильная настройка CAPTCHA: боты проходят reCAPTCHA v2 без проблем — лучше использовать Turnstile от Cloudflare.
Мы гарантируем, что после внедрения защиты ваш сайт будет безопаснее в 10 раз. Получите консультацию — свяжитесь с нами. Закажите внедрение — мы свяжемся в течение дня.







