DDoS-стресс-тест нужен не для того, чтобы любой ценой уронить сайт. Правильно проведённая проверка показывает, при какой нагрузке сервис начинает замедляться, какой компонент первым исчерпывает ресурсы, срабатывает ли защита и сохраняются ли критические функции.
Я не начинаю такую проверку с мощного потока в рабочую систему. Сначала запускаю небольшую нагрузку на тестовом стенде, проверяю метрики и автоматическую остановку, затем постепенно повышаю интенсивность. Полноценную имитацию сетевой DDoS-атаки заказываю у специализированного подрядчика и заранее согласовываю с облачной платформой, оператором связи и поставщиком защиты.
Материал предназначен для легального тестирования собственных систем или инфраструктуры, на проверку которой получено письменное разрешение. Соблюдайте законы своей страны, особенно России, договоры с операторами и правила облачных платформ. Инструкции нельзя применять для атак на чужие ресурсы, нарушения работы сервисов, взлома, слежки или несанкционированного доступа.
Что на самом деле проверяет DDoS-стресс-тест
DDoS расшифровывается как Distributed Denial of Service, то есть «распределённый отказ в обслуживании». Во время реальной атаки множество устройств одновременно отправляет трафик на сайт, приложение или сетевое оборудование. Цель атакующего состоит в том, чтобы занять канал, исчерпать соединения, перегрузить серверы или заставить приложение выполнять слишком дорогие операции.
Обычная нагрузочная проверка устроена иначе. Она воспроизводит действия легитимных пользователей и отвечает на вопрос, сколько посетителей сервис способен обслужить без заметного ухудшения работы. DDoS-симуляция дополнительно проверяет защитные системы и реакцию команды.
| Проверка | Что происходит | Что узнаёт команда |
|---|---|---|
| Обычная нагрузка | Пользователи открывают страницы и вызывают API | Справляется ли система с нормальным трафиком |
| Пиковая нагрузка | Число запросов резко возрастает | Успевают ли запуститься дополнительные серверы |
| Длительная нагрузка | Повышенный поток сохраняется несколько часов | Есть ли утечки памяти и накопление очередей |
| Стресс-тест | Нагрузка постепенно выходит за расчётный предел | Где начинается деградация и как проходит восстановление |
| DDoS-симуляция | Создаётся контролируемый вредоносный трафик | Работают ли фильтрация, оповещения и план реагирования |
Сетевые атаки направлены на канал связи, маршрутизаторы, межсетевые экраны и балансировщики. Прикладные атаки обращаются к сайту или API и заставляют приложение выполнять работу. Например, один запрос к статическому изображению почти не нагружает сервер, а запрос сложного отчёта может обратиться к нескольким базам данных и занять процессор на секунды.
Поэтому число запросов в секунду само по себе мало что говорит. Тысяча лёгких запросов может оказаться безопаснее десяти тяжёлых. Сценарий должен повторять реальные операции и учитывать стоимость каждой операции для инфраструктуры.
Как подготовить тест и ограничить ущерб
Перед запуском я составляю небольшой план. В документе перечисляю проверяемые адреса, допустимую нагрузку, время проведения, ответственных сотрудников и условия немедленной остановки.
- Подтверждаю, что домены, IP-адреса и облачные ресурсы принадлежат заказчику теста.
- Проверяю правила хостинга, облачной платформы, CDN и оператора связи.
- Создаю отдельные учётные записи и тестовые данные.
- Отключаю реальные платежи, SMS, письма, заказы и другие действия с последствиями.
- Ограничиваю максимальное число запросов, длительность и количество генераторов.
- Настраиваю внешнюю проверку главной страницы, входа и критических функций.
- Назначаю сотрудника, который может остановить тест независимо от автора сценария.
- Проверяю, как быстро система восстанавливается после снятия нагрузки.
Нагрузка должна расти ступенями. Например, сначала 5 запросов в секунду, затем 10, 20 и 30. После каждого повышения команда смотрит на задержку, ошибки, состояние базы данных, очередей и серверов. Следующая ступень начинается только после стабилизации показателей.
Когда тест нужно остановить
| Признак | Пример ограничения | Действие |
|---|---|---|
| Внутренние ошибки сервера | Более 1% ответов с кодом 5xx | Прекратить повышение нагрузки |
| Медленные ответы | 95% запросов не укладываются в 800 мс | Зафиксировать предел и снизить поток |
| База данных | Пул соединений заполнен более чем на 90% | Немедленно остановить тест |
| Очередь заданий | Очередь продолжает расти при постоянной нагрузке | Прекратить создание новых заданий |
| Критическая функция | Не работает вход, оплата или основной API | Запустить аварийную остановку |
| Расходы | Превышен согласованный бюджет | Остановить автоматическое масштабирование |
Значения в таблице приведены как пример. Для каждого сервиса пороги выбирают по соглашению об уровне обслуживания и требованиям бизнеса. Задержка в одну секунду может быть допустима для каталога, но неприемлема для торговой системы или платёжного подтверждения.
Что такое k6 и зачем он нужен в таком тесте
k6 представляет собой бесплатный инструмент с открытым исходным кодом для нагрузочного тестирования сайтов и программных интерфейсов. Программу разработала команда Grafana Labs. k6 запускается из командной строки, читает сценарий из файла и создаёт заданное число HTTP-запросов.
Сценарии пишутся на JavaScript. Глубоко знать язык для простого теста не требуется. В файле достаточно указать адрес, скорость запросов, продолжительность ступеней и допустимые показатели.
Я использую k6 в примере по четырём причинам.
- Сценарий хранится в обычном текстовом файле и легко проверяется перед запуском.
- Нагрузку можно повышать постепенно, а не включать сразу на полную мощность.
- k6 считает задержки, ошибки и пропущенные запросы.
- Программа умеет остановить тест при превышении заданного порога.
k6 не является сервисом для проведения DDoS-атак. Один экземпляр программы проверяет главным образом прикладной уровень, то есть сайт или API. k6 не заменяет распределённые генераторы, центр очистки трафика и согласованную проверку сетевой защиты.
Что делает пример ниже
Сценарий отправляет запросы на страницу каталога. Нагрузка начинается с двух запросов в секунду, затем возрастает до 5, 10, 20 и 30 запросов. В конце поток снижается до пяти запросов, чтобы команда увидела, возвращается ли система в нормальное состояние.
Код также следит за двумя показателями. Доля неожиданных ошибок не должна превышать 1%, а 95% запросов должны выполняться быстрее 800 миллисекунд. При нарушении любого условия k6 останавливает тест.
import http from 'k6/http';
import { check } from 'k6';
if (!__ENV.TARGET || !__ENV.TEST_TOKEN) {
throw new Error('Нужно указать TARGET и TEST_TOKEN');
}
const acceptableStatuses = http.expectedStatuses(
{ min: 200, max: 399 },
429
);
export const options = {
discardResponseBodies: true,
scenarios: {
controlled_test: {
executor: 'ramping-arrival-rate',
startRate: 2,
timeUnit: '1s',
preAllocatedVUs: 20,
maxVUs: 100,
stages: [
{ target: 5, duration: '2m' },
{ target: 10, duration: '3m' },
{ target: 20, duration: '3m' },
{ target: 30, duration: '3m' },
{ target: 5, duration: '2m' }
],
gracefulStop: '20s'
}
},
thresholds: {
http_req_failed: [
{
threshold: 'rate<0.01',
abortOnFail: true,
delayAbortEval: '30s'
}
],
http_req_duration: [
{
threshold: 'p(95)<800',
abortOnFail: true,
delayAbortEval: '30s'
}
],
dropped_iterations: ['count==0'],
checks: ['rate>0.99']
}
};
export default function () {
const response = http.get(
`${__ENV.TARGET}/api/catalog?load_test=1`,
{
headers: {
'X-Load-Test': __ENV.TEST_TOKEN,
'User-Agent': 'authorized-k6-test'
},
responseCallback: acceptableStatuses,
timeout: '3s'
}
);
check(response, {
'Сервер вернул контролируемый ответ': (r) =>
(r.status >= 200 && r.status < 400) ||
r.status === 429
});
}
Первая строка подключает модуль для отправки HTTP-запросов. Вторая подключает функцию проверки ответов. Блок options описывает нагрузку и условия остановки, а функция default содержит действие, которое повторяют виртуальные пользователи.
startRate: 2 задаёт начальную скорость. Запись target: 30 означает, что к концу соответствующей ступени k6 должен запускать 30 проходов сценария в секунду. В приведённом примере один проход содержит один запрос, поэтому число проходов примерно совпадает с числом запросов.
preAllocatedVUs задаёт число заранее подготовленных виртуальных пользователей. Виртуальный пользователь не является реальным человеком или отдельным компьютером. Так k6 называет исполнителя, который запускает сценарий и ждёт ответ сервера.
maxVUs ограничивает максимальное число таких исполнителей. Ограничение защищает машину с k6 от бесконтрольного роста потребления памяти и процессора.
http_req_failed показывает долю неудачных HTTP-запросов. Условие rate<0.01 разрешает менее 1% ошибок. Параметр abortOnFail требует остановить тест при превышении порога.
http_req_duration измеряет время ответа. Запись p(95)<800 означает, что не менее 95% запросов должны завершиться быстрее 800 миллисекунд. Речь идёт не о среднем времени, а о задержке большей части запросов.
dropped_iterations показывает, смог ли сам генератор создать запланированную нагрузку. Если показатель больше нуля, k6 не успел запустить часть проходов. В такой ситуации результат может описывать предел тестовой машины, а не предел проверяемого сервиса.
Код 429 означает «слишком много запросов». Такой ответ обычно возвращает ограничитель частоты запросов. Сервер не упал, а сознательно отказался принимать лишнюю нагрузку. Однако большое количество ответов 429 всё равно указывает, что часть пользователей не получает услугу.
Как запустить сценарий
Сначала устанавливают k6 по инструкции для своей операционной системы. Затем код сохраняют в файл safe-load.js. Перед запуском указывают адрес тестового стенда и специальный токен, который помогает отличить проверочные запросы в журналах.
Для Linux и macOS команда выглядит так.
TARGET=https://staging.example.com
TEST_TOKEN=replace-with-secret
k6 run safe-load.js
В Windows PowerShell переменные задаются отдельно.
$env:TARGET = "https://staging.example.com"
$env:TEST_TOKEN = "replace-with-secret"
k6 run safe-load.js
Адрес staging.example.com нужно заменить адресом собственного тестового стенда. Значения 5, 10, 20 и 30 запросов в секунду приведены только для демонстрации. Нельзя копировать их в продакшен без расчёта обычной нагрузки и проверки на стенде.
Заголовок X-Load-Test помогает найти тестовый трафик в журналах и на графиках. При этом WAF не должен автоматически пропускать запросы с таким заголовком. Иначе проверка обойдёт защиту, которую команда собиралась оценить.
Что чаще всего ломается во время проверки
Первым ограничением далеко не всегда становится процессор веб-сервера. Приложение может работать нормально, пока не закончится пул соединений с базой данных. После исчерпания пула новые запросы начинают ждать, задержка растёт, клиенты повторяют обращения и усиливают перегрузку.
Повторные запросы создают особенно неприятный эффект. Пользователь отправляет запрос, не получает ответ за установленное время и повторяет попытку. Прокси и внутренние сервисы делают то же самое. Один исходный запрос превращается в несколько, хотя свободных ресурсов уже не осталось.
Автоматическое масштабирование тоже не гарантирует защиту. Облачная платформа запускает новые экземпляры приложения, но каждый экземпляр открывает соединения с базой данных, обращается к кэшу и читает очередь. В результате перегрузка просто перемещается на следующий компонент, а расходы продолжают расти.
Отдельный риск создают журналы событий. При большом числе ошибок приложение, WAF и балансировщик начинают записывать больше данных. Система сбора журналов может занять диск, сеть или память раньше самого приложения. На время теста нужно ограничить повторяющиеся записи и проверить свободное место.
CDN также не решает проблему автоматически. Кэшируемые файлы CDN отдаёт со своих узлов, но динамические запросы доходят до исходного сервера. Если настоящий IP-адрес сервера сохранился в старой DNS-записи или на забытом поддомене, атакующий сможет обратиться к нему напрямую в обход CDN.
После остановки генератора тест ещё не закончен. База данных продолжает выполнять запросы, очередь разгребает накопившиеся задания, а дополнительные серверы выключаются не сразу. Я считаю проверку завершённой только после возвращения задержек, очередей, соединений и расхода ресурсов к исходному уровню.
Когда собственного теста уже недостаточно
k6 подходит для проверки сайта, API, базы данных и прикладных ограничений. Программа не воспроизводит полноценную распределённую атаку на сетевой канал. Для проверки защиты от потоков TCP, UDP, SYN и других сетевых сценариев нужен специализированный подрядчик.
Перед такой проверкой подрядчик должен письменно зафиксировать источники трафика, цели, время, максимальную мощность, аварийную остановку и ответственных сотрудников. Облачные платформы устанавливают собственные ограничения. Например, действующая политика AWS разрешает DDoS-симуляции только при соблюдении установленных условий и ограничений по мощности, числу запросов и используемому поставщику.
Разрешение на обычный поиск уязвимостей не всегда разрешает DDoS-симуляцию. Перед каждым тестом нужно заново проверять правила облака, хостинга, оператора и защитного сервиса. Старое письмо или условия из предыдущего проекта могут уже не действовать.
Хороший результат DDoS-стресс-теста не звучит как «сайт невозможно уронить». Такая гарантия нереалистична. Итог должен содержать измеримый предел нагрузки, первое узкое место, время срабатывания защиты, доступность критических функций и продолжительность восстановления.
Начинать лучше с небольшого сценария k6 на тестовом стенде. Затем можно провести ограниченную проверку рабочей системы с заранее заданными порогами остановки. Полноценную сетевую симуляцию следует передать согласованному подрядчику. Главная цель состоит не в рекордном потоке, а в понимании границ инфраструктуры без незапланированного простоя.
Что такое DDoS-стресс-тестирование?
DDoS-стресс-тестирование проверяет, как инфраструктура, приложение и защитные сервисы ведут себя при контролируемой вредоносной или аномально высокой нагрузке. Задача теста не в том, чтобы уронить сайт, а в том, чтобы определить предел мощности, найти узкие места и проверить план реагирования.
Чем DDoS-тест отличается от обычного нагрузочного тестирования?
Нагрузочный тест обычно воспроизводит поведение реальных пользователей и проверяет производительность приложения. DDoS-тест дополнительно моделирует намеренно неэффективный, распределённый или объёмный трафик, чтобы проверить CDN, WAF, rate limiting, центр очистки, сетевой канал и действия дежурной команды.
Можно ли проводить DDoS-стресс-тест в продакшене?
Ограниченный тест в продакшене допустим после проверки сценария на стенде, согласования с владельцами инфраструктуры и настройки жёстких стоп-условий. Начинать с максимальной нагрузки нельзя. Интенсивность повышают небольшими ступенями, постоянно контролируя задержки, ошибки, очереди, базу данных и доступность критических функций.
Нужно ли согласовывать DDoS-тест с облачным провайдером?
Да. Правила AWS, Azure, Cloudflare, хостинговых компаний и операторов связи различаются. Некоторые платформы разрешают только определённые сценарии, требуют использовать одобренного подрядчика или заранее уведомлять службу безопасности. Разрешение на обычный пентест не всегда распространяется на DDoS-симуляцию.
Какие инструменты подходят для DDoS-стресс-теста?
k6, JMeter, Gatling и Locust подходят для контролируемой HTTP-нагрузки и проверки уровня L7. Крупные сетевые сценарии L3 и L4 требуют специализированной платформы, распределённых генераторов и согласованного провайдера DDoS-симуляций. Один сервер с генератором не воспроизводит полноценную распределённую атаку.
Какие метрики нужно контролировать во время теста?
Нужно отслеживать p95 и p99 задержки, долю 5xx и 429, таймауты, число соединений, загрузку процессора и памяти, CPU throttling, глубину очередей, пул подключений к базе данных, cache hit ratio, скорость масштабирования и стоимость ресурсов. Средняя задержка часто скрывает проблемы небольшой, но значимой части запросов.
Какие стоп-условия нужны для безопасного тестирования?
Тест останавливают при недоступности критического маршрута, превышении допустимой доли ошибок, резком росте p95 или p99, заполнении пула базы данных, неконтролируемом росте очереди или превышении бюджета. Пороговые значения устанавливают до запуска, а не подбирают после получения результата.
Защитит ли автоматическое масштабирование от DDoS?
Autoscaling помогает при легитимном росте трафика, но не заменяет DDoS-защиту. Дополнительные экземпляры приложения могут исчерпать соединения базы данных, перегрузить очередь, превысить квоту внешнего API и резко увеличить облачный счёт. Вредоносные запросы выгоднее блокировать на CDN, WAF или в центре очистки.
Почему CDN не всегда защищает от DDoS?
CDN хорошо обрабатывает кэшируемый контент, но динамические API и уникальные запросы часто доходят до исходного сервера. Защиту также можно обойти, если реальный IP origin-сервера раскрыт через старую DNS-запись, поддомен, сертификат или почтовую инфраструктуру. Origin должен принимать соединения только от сетей CDN или центра очистки.
Как понять, что анти-DDoS-защита действительно работает?
Нужно сопоставить показатели генераторов, CDN, WAF, центра очистки, балансировщиков и origin-серверов. При успешной фильтрации вредоносный поток блокируется до приложения, критические пользовательские маршруты остаются доступными, а нагрузка на базу данных и серверы не растёт пропорционально входящему трафику.
Почему ответы 429 нельзя считать обычными ошибками?
Код 429 показывает, что rate limiter контролируемо ограничил поток запросов. Такой ответ защищает приложение от исчерпания ресурсов, поэтому не равен внутренней ошибке 5xx. Однако большое число ответов 429 означает, что часть пользователей не получает услугу, поэтому долю ограничений нужно измерять отдельно.
Когда DDoS-тест можно считать завершённым?
Тест завершается не сразу после остановки генераторов. Нужно дождаться, пока разгрузятся очереди, завершатся запросы к базе данных, восстановится кэш, уменьшится число экземпляров и все метрики вернутся к исходному уровню. Время полного восстановления входит в результаты испытания.
