Защита nginx сервера от ботов.
no system is safe

Посмотрите на скриншот выше. Любой администратор, увидев этот скриншот поймет - это наглые боты, которые что-то делают, таким образом нагружая сервер. Поэтому, надо заняться уборкой ботов.
Это будет сделано при помощи двух вещей -(nginx ultimate bad bot blocker и fail2ban. Начнем с fail2ban. Машина, на которой производились действия - Debian Wheezy.
Установка и настройка fail2ban
Одна из функций fail2ban - чтение логов и проверка их по выражению. Если выражение совпадает - тогда с что-то происходит. Это мы и будем использовать.
Для начала, установим fail2ban:
sudo apt install fail2ban
После установки fail2ban уже автоматически работает, но нужно произвести некоторые настройки.
В первую очередь, нужно создать локальный конфиг. Создатели рекомендуют это сделать, так как он подключается автоматически и имеет высший приоритет.
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Открываем файл любым любимым вами редактором (в моём случае - nano) и приступаем к настройке
sudo nano /etc/fail2ban/jail.local [DEFAULT] ignoreip = 127.0.0.1/8 bantime = 600 findtime = 600 maxretry = 3 banaction = iptables-multiport action = %(action_)s
Ignoreip указывает на ip-адреса или диапазоны, которые следует игнорировать. Можно писать несколько через пробел.
bantime указывает на время бана в секундах, а findtime - интервал времени в секундах, в течении которого будет определяться активность.
maxretry - количество попыток в течении findtime, после которой будет применены действия.
После этого, там же, добавляем вот такие правила:
[nginx-noscript] enabled = true port = http,https filter = nginx-noscript logpath = /var/log/nginx/access.log maxretry = 6 [nginx-badbots] enabled = true port = http,https filter = nginx-badbots logpath = /var/log/nginx/access.log maxretry = 2 [nginx-noproxy] enabled = true port = http,https filter = nginx-noproxy logpath = /var/log/nginx/access.log maxretry = 2 [nginx-noconnect] enabled = true port = http,https filter = nginx-noconnect logpath = /var/log/nginx/access.log maxretry = 2
Как понятно выше, true - это включенное или выключенное правило. logpath - всего-то путь к логу. Также, maxretry можно не указывать - он будет браться из того, что написано было выше.
После всего этого, нам нужно добавить фильтры. Переходим в директорию /etc/fail2ban/filter.d/.
Создание фильтра batbots самое простое. Просто скопируем его с apache-badbots. Данный фильтр банит по юзерагенту.
sudo cp apache-badbots.conf nginx-badbots.conf
Следующим, настроим фильтр nginx-noscript.
nano nginx-noscript.conf [Definition] failregex = ^<HOST> -.*GET.*(\.php|\.asp|\.exe|\.pl|\.cgi|\.scgi) ignoreregex =
Данный фильтр банит те ip, которые обращаются за файлами с расширением php, asp, exe, pl, cgi, scgi. Если вам что-то из этого нужно - просто удалите расширение.
Фильтр, который поймал у меня больше всего ботов - nginx-noproxy. Создадим и его.
nano nginx-noproxy.conf [Definition] failregex = ^<HOST> -.*GET http.* ignoreregex =
Последним у нас будет фильтр, который я долго хотел не писать и решить проблему с ним при помощи самого nginx. Но проблема оказалась нерешаемая, поэтому, вот конфиг фильтра nginx-noconnect:
[Definition] failregex = ^<HOST> -.*CONNECT ignoreregex =
Так как я не использую метод CONNECT, а вот боты его частенько любят, мы просто баним всех, кто его использует.
Перезагрузим fail2ban:
fail2ban-client restart
Проверяем его статус:
fail2ban-client status

У меня еще включено пару специфических фильтров, но вывод должен состоять из количества включенных фильтров и их названия. Теперь посмотрим статус фильтра:
fail2ban-client status nginx-noconnect

199 забаненных ip, довольно круто! И это всего за пол часа работы. Дальше - лучше!
NGINX ultimate bad bot blocker
Тут очень глупо описывать процесс установки, так как он описан в репозитории. Сам репозиторий находится вот здесь:
https://github.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/
Заикнусь лишь про установку с https и авторедиректом. Дело в том, что при запросе, бот будет получать сообщение с кодом 301 "Перемещено навсегда"(так как он пытается зайти по http). Поэтому, нам нужно ловить запрос ДО того, как будет редирект. Приведу на примере конфига одного виртуалхоста:
server {
# Конфигурация SSL
listen 443 ssl http2;
root /var/www/yourdomain.com;
server_name yourdomain.com www.yourdomain.com;
charset UTF-8;
access_log /var/log/nginx/yourdomain.com-access.log;
error_log /var/log/nginx/yourdomain.com-error.log;
/etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/yourdomain.com/chain.pem;
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:128m;
ssl_session_tickets off;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
ssl_prefer_server_ciphers on;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
ssl_stapling on;
ssl_stapling_verify on;
# ДОБАВЛЯЕМ НАСТРОЙКИ BAD BOT BLOCKER СЮДА
include /etc/nginx/bots.d/blockbots.conf;
include /etc/nginx/bots.d/ddos.conf;
# Сюда можно вставить что-то ещё
#Конец настройки ssl
}
server {
# Теперь мы редиректим траффик с 80 порта на 443
listen 80;
server_name yourdomain.com www.yourdomain.com;
# ДОБАВЛЯЕМ СЮДА НАСТРОЙКИ!!!
include /etc/nginx/bots.d/blockbots.conf;
include /etc/nginx/bots.d/ddos.conf;
return 301 https://yourdomain.com$request_uri;
}