Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як застосунок можна покласти без мережевої DDoS-атаки і як обмежити дорогі запити в Laravel?

Щоб зупинити застосунок, не потрібні мільйони запитів: досить кількох, кожен з яких змушує сервер робити величезну роботу. Захист від мережевих атак (CDN, WAF) тут не допомагає - запити виглядають цілком легітимно.

Типові «дорогі» запити:

Вектор Приклад
необмежена пагінація GET /api/orders?per_page=1000000
важкі фільтри й сортування сортування за колонкою без індексу, LIKE '%...%' по мільйонах рядків
великі тіла запитів JSON на сотні мегабайтів, масив з мільйоном елементів
файли гігабайтні завантаження, zip-бомба, «бомба декомпресії» в зображенні (крихітний PNG, що розпаковується в гігабайти пікселів)
регулярні вирази катастрофічний бектрекінг на рядку від користувача (ReDoS)
дорогі операції без ліміту генерація PDF, експорт, виклик LLM чи платного API на кожен запит
хешування дуже довгі паролі з дорогим алгоритмом хешування

Захист у Laravel:

// пагінація: верхня межа
$perPage = min($request->integer('per_page', 20), 100);

// валідація розмірів і кількостей
$request->validate([
    'items' => ['required', 'array', 'max:100'],
    'items.*.sku' => ['required', 'string', 'max:64'],
    'avatar' => ['image', 'max:2048', 'dimensions:max_width=4000,max_height=4000'],
    'password' => ['required', 'string', 'max:128'],
]);
  • сортування й фільтри лише зі списку дозволених колонок (які мають індекси);
  • обмеження частоти для дорогих маршрутів окремо: RateLimiter::for('exports', fn (Request $r) => Limit::perMinute(3)->by($r->user()->id));
  • важка робота - у черзі, з окремим пулом воркерів, щоб експорт не забирав процеси вебзапитів;
  • тайм-аути: statement_timeout / max_execution_time для бази, тайм-аути HTTP-клієнта до сторонніх сервісів.

Межі на рівні інфраструктури:

  • client_max_body_size у Nginx, post_max_size і upload_max_filesize у PHP - тіло відкидається ще до Laravel;
  • memory_limit і max_execution_time - щоб один запит не з'їв увесь сервер;
  • кількість воркерів PHP-FPM - обмежений ресурс: повільні запити займають їх, і решта користувачів чекає в черзі.

Неочевидні місця:

  • розпакування архівів - перевіряти сумарний розмір і кількість файлів під час розпакування, а не за розміром архіву;
  • зображення - перевіряти розміри в пікселях до обробки, а не лише розмір файлу;
  • GraphQL і вкладені include в API - обмеження глибини й складності запиту.

Перевірка: у тестах навмисно надсилати граничні значення (per_page=100000, масив на 10 000 елементів) і очікувати 422, а не 500 і не хвилину очікування.

Докладніше в документації: OWASP API4:2023 Unrestricted Resource Consumption

Схожі питання