В общем нужно было этих ботов отлавливать и блокировать им доступ к сайту, сперва подумал об 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, когда список заблокированных вырос сайт начал свою штатную работу, а список блокированных с течением времени увеличивался все медленнее и в итоге совсем перестал расти - у атакующего закончились боты.
11 комментариев:
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 ктото применял? Крутая штука поидее....
Отправить комментарий