В общем нужно было этих ботов отлавливать и блокировать им доступ к сайту, сперва подумал об iptables и ConfigServer Firewall (csf), но хостинг был внутри OpenVZ, а это означало невозможность использования более 120 правил, а так же невозможность установки модулей ядра и вообще каких либо изменений опций ядра. Потому стандартные подходы для решения проблемы сразу отпадали.
А время шло, и переписываться с тех поддежкой хостинга небыло времени, а платить огромные суммы за защиту от такой примитивной атаки небыло никакого желания.
Решение пришло в голову неожиданно, при перечитывании man ip, вспомнить зачем я его читал затрудняюсь, но решение было
Решением было добавление маршрута проблемного IP в blackhole. В следствие чего пакеты от этих адресов будут молча отбрасываться (the rule prescribes to silently drop the packet.).
Сперва конфигурируем nginx:
... worker_rlimit_nofile 200000; events { worker_connections 1024; use epoll; } .... http { # Документ по умолчанию index index.html index.htm index.php; ## # Basic Settings ## sendfile on; send_timeout 5; tcp_nopush on; tcp_nodelay on; keepalive_timeout 30 15; types_hash_max_size 2048; server_tokens off; client_header_timeout 15; client_body_timeout 15; # лимитируем для зоны one 10 конектов в 1 сек. limit_req_zone $binary_remote_addr zone=one:16m rate=10r/s; #В ситуации когда сервер записал в сокет данные, но клиент не хочет # их забирать, после таймаута по закрытию соединения в ядре # данные будут держаться еще несколько минут. В nginx если директи ва # для принудительного сброса всех данных после закрытия по таймаут у. reset_timedout_connection on; include /etc/nginx/mime.types; default_type application/octet-stream; ## # Logging Settings ## access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; gzip on; gzip_disable "msie6"; ... server { listen ip.ip.ip.ip:80; server_name my.site; open_file_cache max=100000 inactive=40s; open_file_cache_valid 60s; open_file_cache_min_uses 2; open_file_cache_errors on; #это значит что законектится с лимитом в 3 подключения за 1 сек можно 3 раза, а дальше 503 ошибка. Что и пишется в лог access. limit_req zone=one burst=10; # Default locations config. include conf.std; ... } ... }Файлик /etc/nginx/conf.std:
####### STANDART # redirect server error pages to the static page /50x.html error_page 500 502 503 504 /50x.html; location = /50x.html { root /var/www/nginx-dist; } # deny access to .htaccess files, if Apache's document root # concurs with nginx's one location ~ /\.ht { deny all; } location ~ /\< { deny all; }С конфигурацией nginx все, теперь скрипты.
Добавляем в файл /etc/crontab строки:
# parse nginx logs and ban bad ip via nullroute * * * * * root /root/ddos/parse_nginx.log.sh >/root/ddos/parse_nginx.log.log 2>&1Содержимое скрипта /root/ddos/parse_nginx.log.sh:
#!/bin/sh ADMINS_IP='ip.ip.ip.ip' echo $(date) echo '--- запускаем систему парсинга nginx лога---' echo ' ищем ботов' cat /var/log/nginx/access.log \ | grep -E -e 'HTTP/1.(0|1)" (400|403|405|499|503)' -e '] "-" 400 0 "-" "-"' \ | awk '{print $1}' \ | sort -nr | uniq -c \ | awk '{if($1>10)print $1" "$2}' \ > /root/ddos/banlist.txt cat /var/log/nginx/error.log \ | grep -E '(limiting requests|limiting connections)' \ | awk -F"client: " '{print $2}' \ | awk -F"," '{print $1}' \ | sort -nr | uniq -c \ | awk '{if($1>10)print $1" "$2}' \ >> /root/ddos/banlist.txt # get unique ip cat /root/ddos/banlist.txt \ | grep -v $ADMINS_IP \ | uniq | sort -nr \ > /root/ddos/banlist_uniq.txt echo '------ очищаем tmp file бана-' cat /dev/null > /root/ddos/banlist.txt echo ' создаем DROP правила для 50 самых агрессивных ботов' awk '{print $2}' /root/ddos/banlist_uniq.txt \ | uniq | head -n 150 > /root/ddos/banlist.txt #т.к. iptables полнейшее УГ, особенно внутри OpenVZ, баним ip вот таким извращенским методом... через nullroute #ip route flush type blackhole for ip in $(cat /root/ddos/banlist.txt); do ip route add blackhole ${ip}/32 done #echo 'записываем злобных ботов в csf.deny' #cat /etc/csf/csf.deny >> /root/ddos/banlist.txt #cat /root/ddos/banlist.txt \ # | uniq | sort -nr \ # > /etc/csf/csf.deny #echo 'csf релоад, внесение в iptables ботов' #/usr/sbin/csf -r sleep 5 echo '-- делаем ротацию лога--------' test -x /usr/sbin/logrotate || exit 0 /usr/sbin/logrotate /etc/logrotate.conf echo '=====злобные боты в списке бана=====' sleep 1Для мониторинга состояния сервера используем такой скрипт:
#!/bin/sh while :; do netstat_str=$(netstat -an) echo -n 'SYN_RECV: ' echo "$netstat_str" | grep 80 | grep SYN_RECV | wc -l echo -n 'TIME_WAIT: ' echo "$netstat_str" | grep 80 | grep TIME_WAIT | wc -l echo -n 'FIN_WAIT: ' echo "$netstat_str" | grep 80 | grep FIN_WAI1 | wc -l echo -n 'ESTABLISHED: ' echo "$netstat_str" | grep 80 | grep ESTABLISHED | wc -l echo -n 'BLOCKED_IP to Black-route: ' ip route list | grep blackhole | sort | wc -l sleep 2 echo '------------------------- for stop this script Press Ctrl+C' doneЕще понадобится настроить ротацию логов, приводим файл /etc/logrotate.d/nginx к такому виду:
/var/log/nginx/*.log { size 1M missingok rotate 52 compress delaycompress notifempty create 0640 www-data adm sharedscripts prerotate if [ -d /etc/logrotate.d/httpd-prerotate ]; then \ run-parts /etc/logrotate.d/httpd-prerotate; \ fi; \ endscript postrotate [ ! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.pid` endscript }Еще я использовал встроенные средства iptables для борьбы с DDoS:
#!/bin/sh iptables -F iptables -N syn_flood iptables -A INPUT -p tcp --syn -j syn_flood iptables -A syn_flood -m limit --limit 100/s --limit-burst 150 -j RETURN iptables -A syn_flood -j DROP
Данный скрипт спокойно блокировал DDoS примерно в 10 000 ботов, при этом сайт был полностью доступен и атака вообще не чувствовалась.
Прошу обратить внимание на то, что скрипт запускается раз в минуту, и блокирует ip адреса по заданным критериям в скрипте /root/ddos/parse_nginx.log.sh. В моем случае атака была "вялой" и одной минуты вполне хватало для сбора ip адресов ботов. В первые минуты сайт "туго" работал, но спустя минут 10, когда список заблокированных вырос сайт начал свою штатную работу, а список блокированных с течением времени увеличивался все медленнее и в итоге совсем перестал расти - у атакующего закончились боты.
10.000 ботов?
ОтветитьУдалитьв OpenVZ?
да еще и арендованом?
И что не завалили? Аплинк у вас чтоли 10G и ядро хитрое? Со штатным ядром и таким количеством атакующих трудно не то что логику борьбы на уровне фаервола/сервиса настраивать, а просто держать канал... простая арифметика, что будет если каждый из 10.000 ботов пульнет в ваш сервак по 100kB/s трафика (по барабану какого)?
Боты не давали трафик, они делали запросы и уходили, этого хватало, чтобы сайт загибался.
ОтветитьУдалитьДа и как бот сможет мне отправлять трафик, если я его не принимаю? :)
Вы то его не принимаете ... но канал у вас зашейпленый провайдером и фиксированный - например 100 мегабит/cек
ОтветитьУдалитьШлем вам от каждого бота по 100кбит/сек. UDP пакетов и что будет с вашим каналом 100мбит? Правильно, принимай не принимай эти пакеты, а труба забита (читай канал) "левым трафиком". Сервис при этом может даже работать, но не имея канала (его забили под завязку боты своими UDP-шками) к вам не сможет придти ни один клиент :)
Такчто вам либо повезло с атакой либо вы приврали с количеством ботов :) Знаю не по наслышке, недавно выгребал DDoS с количеством ботов около 1000 - они уложили канал 175 мбит в потолок и их цель была достигнута - сервер с мира было видно с потерями 90-95%, соответственно до сервисов достучаться было уже крайне проблематично (можно сказать что сервисы были недоступны)
Про UDP согласен, канал ляжет, но статья-то именно про Syn-Flood, который возможен только на уровне TCP протокола, трафик там копеечный и сильно не мешал работе сайта, тем более, что запросы делались не так часто, а вот когда они добирались до веб сервера, то ему становилось плохо, он упорно ждал ответа от клиентов(ботов), которые молчали как партизаны, в результате чего нормальные клиенты не могли попасть на сайт. Что касается цифр ботов, то они реальные. Список пополнялся ~50-200 ip.
ОтветитьУдалитьВидимо зря я не упомянул в статье о других видах атак, и что эта статья от них не спасет, а только от вялой TCP SYN-Flood атаки :)
Согласен по поводу син флуда
ОтветитьУдалитьМои боты были "круче"
Если они блочились фаерволом - сразу переключались на UDP flood
Бывает и так :(
А как теперь разбанить ипы.
ОтветитьУдалитьОчевидно же ip route delete ip.ip.ip.ip.
ОтветитьУдалитьПодробнее man ip, раздел про ip route :)
Этот комментарий был удален автором.
ОтветитьУдалитьСпсибо разобрался сам как удалить правила из ip route
ОтветитьУдалитьЯ немного пределал под ipset, так надежней 5к записей без какой либо нагрузки на CPU
Это вам повезло, что у вас там есть ipset:) и кстати блокировка через blackhole маршрут тоже обходится без какой либо нагрузки на CPU.
ОтветитьУдалитьА TARPIT в iptables ктото применял? Крутая штука поидее....
ОтветитьУдалить