Слова «защита от DDoS» на витринах хостингов звучат как решение всех проблем, но закрывают только один класс атак. Сервер падает не только от гигабитных потоков мусора, но и от сотни запросов в секунду к странице поиска — и от этого никакая сетевая фильтрация не спасёт. Разберём, какие бывают атаки, что закрывает дата-центр, что остаётся на вас, и как настроить сервер так, чтобы он пережил и атаку, и честный всплеск посещаемости после рекламы.
Два класса атак
Объёмные (L3/L4)
На сервер льют поток мусорного трафика — UDP-пакеты, SYN-флуд, отражённые DNS- и NTP-ответы, — чтобы забить канал или исчерпать таблицу соединений. Счёт идёт на гигабиты и миллионы пакетов в секунду. Сервер здесь бессилен: если канал забит до вашей машины, никакая её настройка не поможет. Защищаться от таких атак может только сеть — провайдер, дата-центр или внешний фильтрующий сервис.
Прикладные (L7)
Атака выглядит как обычные запросы к сайту. Тысяча запросов в секунду к поиску, к корзине, к форме восстановления пароля — к любой странице, которая каждый раз лезет в базу. Трафика мало, пакеты легитимные, для сетевого фильтра это просто посетители. А сервер лежит, потому что каждый такой запрос стоит 50–200 мс процессорного времени и десятки обращений к базе.
На практике небольшие и средние проекты гораздо чаще сталкиваются со вторым классом: он дешевле для атакующего и не требует ботнета — хватает пары арендованных машин и скрипта. Хорошая новость: от него вы защищаетесь сами, и это бесплатно.
Что закрывает дата-центр
Большинство дата-центров фильтрует объёмные атаки на уровне сети: аномальный трафик отбрасывается до того, как дойдёт до виртуальной машины, и никаких настроек с вашей стороны не требует. Для этого нужны широкие каналы площадки — фильтрующей системе есть где принять и отбросить лишнее. Какие именно атаки и до какого объёма фильтруются на конкретной площадке, лучше уточнить в поддержке провайдера до того, как это станет срочным.
Если проект в конфликтной нише — игровые серверы, конкурентная e-commerce, политика, криптовалюта — и атаки уже случались, базовой фильтрации может не хватить. Тогда нужен внешний сервис: прокси с фильтрацией вроде Cloudflare (есть бесплатный тариф, закрывающий большую часть L3/L4 и базовый L7) или специализированная защита с выделенным IP.
Что остаётся на вас: пять мер против L7
1. Ограничение частоты запросов
Nginx умеет считать запросы с одного адреса и отвечать ошибкой 429 тем, кто превышает порог. В блоке http:
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s; limit_req_zone $binary_remote_addr zone=heavy:10m rate=1r/s;
И в конфигурации сайта:
location / {
limit_req zone=general burst=20 nodelay;
...
}
location ~ ^/(search|login|wp-login\.php|cart) {
limit_req zone=heavy burst=5;
...
}
Десять запросов в секунду с одного IP — много для человека и мало для скрипта. Тяжёлые страницы получают отдельный, более строгий лимит. Проверьте, что не отрезали легитимных пользователей за общим NAT, например из офиса или мобильного оператора, — при необходимости поднимите burst.
2. Ограничение числа соединений
limit_conn_zone $binary_remote_addr zone=addr:10m; limit_conn addr 20;
Не больше 20 одновременных соединений с одного адреса. Защищает от медленных атак вроде Slowloris, которые держат соединения открытыми, исчерпывая пул рабочих процессов.
3. Кэширование
Главная мера, и против атак, и против всплесков. Страница, отданная из кэша Nginx, стоит микросекунды и не трогает ни PHP, ни базу. Для WordPress и других CMS fastcgi_cache на 1–5 минут для анонимных посетителей снимает 80–95% нагрузки; атака на главную или каталог становится незаметной. Кэш не спасёт страницы, которые по определению динамические — поиск, корзина, личный кабинет, — поэтому для них и нужны лимиты из пункта 1.
4. Блокировка по поведению
fail2ban читает логи и блокирует адреса, которые ведут себя как атака: много ошибок 404 подряд, частые обращения к wp-login.php, превышение лимитов Nginx. Базовая установка — apt install fail2ban, дальше включаются готовые фильтры nginx-limit-req, nginx-botsearch, sshd. Блокировка происходит на уровне firewall, то есть заблокированный адрес вообще перестаёт доходить до веб-сервера.
5. Капча на дорогих операциях
Регистрация, восстановление пароля, отправка форм, поиск — всё, что запускает тяжёлую логику или письмо. Невидимая капча почти не мешает людям и полностью останавливает скрипты.
Атака или просто много посетителей
Внешне всё одинаково: сайт тормозит, процессор в потолке. Разница в логах.
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
Если сверху десяток адресов с тысячами запросов каждый — это атака или агрессивный бот, и помогут лимиты и блокировка. Если запросы равномерно распределены по тысячам адресов и идут на разные страницы — это честный всплеск, например после рекламы или публикации в крупном канале. Тогда блокировать нечего, нужен кэш и, возможно, ресурсы.
Посмотреть, на какие страницы идёт нагрузка:
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
Как понять, что пора увеличить тариф
Защита и кэш не решают проблему, если серверу реально не хватает ресурсов для честной нагрузки. Три сигнала:
- Память:
free -mпоказывает активно используемый swap. Система вытесняет данные на диск, и дальше тормозит всё. Это первый параметр для апгрейда. - Процессор: load average выше числа ядер часами, а не минутами. Разовые пики нормальны, постоянная очередь — нет.
- Диск: в
topпоказательwa(ожидание ввода-вывода) устойчиво выше 10–20%. Узкое место в хранилище; на NVMe это встречается заметно реже, чем на SSD.
Если упираетесь в диск — переезжайте в локацию с NVMe: Финляндия, Нидерланды, Чехия. Если в процессор на однопоточных задачах — HI-CPU на Ryzen. Если в память — просто следующий тариф: переход без переноса данных. Как считать, сколько нужно, — в статье «Как выбрать тариф VPS»; когда пора уже на физический сервер — в разборе «VPS или выделенный сервер».
Medium в Финляндии, NVMe — $20/мес Medium в Нидерландах, NVMe — $20/мес
Что сделать заранее
- Включить кэширование для анонимных посетителей.
- Настроить
limit_reqиlimit_connв Nginx, строже — на тяжёлых страницах. - Поставить fail2ban с фильтрами для Nginx и SSH.
- Закрыть всё лишнее в firewall: наружу только 80, 443 и SSH.
- Уточнить у провайдера, что фильтруется на уровне сети.
- Настроить мониторинг с уведомлением — узнать об атаке через минуту, а не через час.
- Если проект в рискованной нише — заранее подключить Cloudflare или аналог: во время атаки переключать DNS уже поздно, записи обновляются минутами и часами.
Если сайт всё-таки упал — порядок диагностики в статье «Что делать, если сайт упал».
