MAATRIX / Блог / Защита nginx от ботов, сканеров и паразитного трафика

Защита nginx от ботов, сканеров и паразитного трафика

Защита nginx от ботов и сканеров: rate limit и фильтры
Блог MAATRIX · 2026-07-07

Как только сайт появляется в сети, к нему начинают ломиться сканеры: ищут /wp-login.php, /.env, /admin, дырявые PHP-скрипты. Плюс агрессивные парсеры выжирают ресурсы. Nginx умеет отбивать это сам — rate limiting, фильтры по User-Agent и связка с fail2ban. Настроим оборону по слоям.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Слой 1: rate limiting

Ограничиваем частоту запросов с одного IP. В http-секции /etc/nginx/nginx.conf объявляем зоны:

http {
    limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
    limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
    limit_conn_zone $binary_remote_addr zone=conn:10m;
}

Применяем в server/location. Для обычных страниц мягкий лимит с burst, для форм логина — жёсткий:

location / {
    limit_req zone=general burst=20 nodelay;
    limit_conn conn 10;
}

location = /wp-login.php {
    limit_req zone=login burst=3 nodelay;
}

burst — очередь всплеска, nodelay отдаёт их сразу, но сверх лимита возвращает 503. Перегрузить сервер уже не выйдет.

Ключевой момент — переменная $binary_remote_addr вместо $remote_addr: она хранит IP в бинарном виде и занимает меньше памяти зоны. Зона размером 10m вмещает около 160 тысяч уникальных адресов — этого хватит любому среднему сайту. Если сервер за реверс-прокси или CDN, используйте $http_x_forwarded_for, иначе все запросы придут с одного IP балансировщика и лимит сработает по всем сразу.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.

Арендовать VPS под защищённый сайт

Слой 2: блокировка сканеров по User-Agent и путям

Большинство сканеров палятся по User-Agent или лезут по типовым путям. Режем их до обработки бэкендом:

map $http_user_agent $bad_bot {
    default 0;
    ~*(nikto|sqlmap|nmap|masscan|zgrab|nuclei) 1;
    "" 1;
}

server {
    if ($bad_bot) { return 444; }

    location ~* /\.(env|git|htaccess|aws) { deny all; return 404; }
    location ~* (wp-config|xmlrpc|phpmyadmin) { deny all; return 404; }
}

Код 444 — фирменный nginx: рвёт соединение без ответа, экономит трафик и не даёт боту сигнала. Пустой User-Agent тоже блокируем — легальные клиенты его почти всегда заполняют.

Директиву map объявляют в http-секции, а проверку if ($bad_bot) — внутри server. Не увлекайтесь блокировкой по User-Agent: легитимные боты Google, Yandex и Bing тоже приходят с характерными строками, и их резать нельзя, иначе выпадете из поиска. Блокируйте только явные инструменты атак (sqlmap, nikto, nuclei) и оставляйте белый список для поисковиков. Проверить, кто именно к вам ходит, помогает разбор логов: awk '{print

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.

Арендовать VPS под защищённый сайт

Слой 2: блокировка сканеров по User-Agent и путям

Большинство сканеров палятся по User-Agent или лезут по типовым путям. Режем их до обработки бэкендом:

map $http_user_agent $bad_bot {
    default 0;
    ~*(nikto|sqlmap|nmap|masscan|zgrab|nuclei) 1;
    "" 1;
}

server {
    if ($bad_bot) { return 444; }

    location ~* /\.(env|git|htaccess|aws) { deny all; return 404; }
    location ~* (wp-config|xmlrpc|phpmyadmin) { deny all; return 404; }
}

Код 444 — фирменный nginx: рвёт соединение без ответа, экономит трафик и не даёт боту сигнала. Пустой User-Agent тоже блокируем — легальные клиенты его почти всегда заполняют.

Директиву map объявляют в http-секции, а проверку if ($bad_bot) — внутри server. Не увлекайтесь блокировкой по User-Agent: легитимные боты Google, Yandex и Bing тоже приходят с характерными строками, и их резать нельзя, иначе выпадете из поиска. Блокируйте только явные инструменты атак (sqlmap, nikto, nuclei) и оставляйте белый список для поисковиков. Проверить, кто именно к вам ходит, помогает разбор логов: awk '{print $12}' access.log | sort | uniq -c | sort -rn | head.

Слой 3: fail2ban против упорных

Rate limit отбивает всплеск, но упорный сканер долбит часами. fail2ban читает логи nginx и банит IP в фаерволе. Ставим и создаём фильтр:

apt update && apt install -y fail2ban
nano /etc/fail2ban/filter.d/nginx-badbot.conf
[Definition]
failregex = ^<HOST> .* "(GET|POST|HEAD) .*(wp-login|xmlrpc|\.env|phpmyadmin).*" (403|404|444)
ignoreregex =

Джейл в /etc/fail2ban/jail.local:

[nginx-badbot]
enabled = true
port    = http,https
filter  = nginx-badbot
logpath = /var/log/nginx/access.log
maxretry = 3
findtime = 300
bantime = 86400
systemctl restart fail2ban
fail2ban-client status nginx-badbot

Слой 4: гео-фильтр и лимит размеров

Если аудитория из конкретных стран, отсекаем остальные модулем geo или ngx_http_geoip2. Плюс режем очевидные атаки на переполнение:

client_max_body_size 10m;
client_body_timeout 10s;
client_header_timeout 10s;
large_client_header_buffers 2 1k;

Короткие таймауты убивают медленные атаки типа Slowloris, когда бот держит соединение открытым по байту в секунду.

Проверка и роль хостинга

Симулируем нагрузку и смотрим, что лимиты срабатывают:

ab -n 200 -c 20 https://ваш-домен/
tail -f /var/log/nginx/access.log | grep ' 444 '

Вся эта оборона эффективна ровно настолько, насколько быстр диск и CPU: fail2ban парсит логи, nginx считает лимиты в памяти. На VPS MAATRIX с AMD EPYC + NVMe от $8/мес логи пишутся и читаются мгновенно, а root-доступ даёт полную свободу настроить фаервол и модули. Локации UK, США и РФ, оплата картой РФ, СБП, криптой или токеном MAAT — зарубежный сервер, доступный из России.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.

Арендовать VPS под защищённый сайт
2}' access.log | sort | uniq -c | sort -rn | head
.

Слой 3: fail2ban против упорных

Rate limit отбивает всплеск, но упорный сканер долбит часами. fail2ban читает логи nginx и банит IP в фаерволе. Ставим и создаём фильтр:

apt update && apt install -y fail2ban
nano /etc/fail2ban/filter.d/nginx-badbot.conf
[Definition]
failregex = ^<HOST> .* "(GET|POST|HEAD) .*(wp-login|xmlrpc|\.env|phpmyadmin).*" (403|404|444)
ignoreregex =

Джейл в /etc/fail2ban/jail.local:

[nginx-badbot]
enabled = true
port    = http,https
filter  = nginx-badbot
logpath = /var/log/nginx/access.log
maxretry = 3
findtime = 300
bantime = 86400
systemctl restart fail2ban
fail2ban-client status nginx-badbot

Слой 4: гео-фильтр и лимит размеров

Если аудитория из конкретных стран, отсекаем остальные модулем geo или ngx_http_geoip2. Плюс режем очевидные атаки на переполнение:

client_max_body_size 10m;
client_body_timeout 10s;
client_header_timeout 10s;
large_client_header_buffers 2 1k;

Короткие таймауты убивают медленные атаки типа Slowloris, когда бот держит соединение открытым по байту в секунду.

Проверка и роль хостинга

Симулируем нагрузку и смотрим, что лимиты срабатывают:

ab -n 200 -c 20 https://ваш-домен/
tail -f /var/log/nginx/access.log | grep ' 444 '

Вся эта оборона эффективна ровно настолько, насколько быстр диск и CPU: fail2ban парсит логи, nginx считает лимиты в памяти. На VPS MAATRIX с AMD EPYC + NVMe от $8/мес логи пишутся и читаются мгновенно, а root-доступ даёт полную свободу настроить фаервол и модули. Локации UK, США и РФ, оплата картой РФ, СБП, криптой или токеном MAAT — зарубежный сервер, доступный из России.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.

Арендовать VPS под защищённый сайт

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Частые вопросы

Rate limit не отрежет реальных пользователей?

При правильном burst — нет. Начните с rate=10r/s и burst=20, смотрите логи на 503 и корректируйте под свой трафик.

Чем 444 лучше 403?

444 закрывает соединение без ответа: боту не за что зацепиться, а вы экономите трафик и CPU. 403 всё же генерирует HTTP-ответ.

Нужен ли Cloudflare, если есть эти правила?

Для мелких и средних проектов nginx + fail2ban закрывают почти всё. CDN нужен против крупных DDoS, но базовую гигиену он не заменяет.