Перейти к содержимому

MOAB

* * * * * 1 Голосов

dDoS. Школа выживания


  • Войдите, чтобы ответить
Сообщений в теме: 10

#1 Spinne

Spinne

    Зануда™

  • Основатель
  • PipPipPipPipPip
  • 2 018 сообщений
3 525
  • Излесу, вестимо

Отправлено 15 Март 2023 - 03:24

Предыстория:

Есть у меня давний клиент, называть не буду (лишний нецелевой трафик ему сейчас совсем ни к чему), человека три-четыре с форума точно знают, о ком речь :) Клиент специфичный, но основная проблема в том, что он российский. Главным образом по этой причине он уже полгода живёт под dDoS. А я помогаю ему выжить. Так что могу поделиться впечатлениями и полезными советами.

Один в поле не воин

Первое, сразу же: даже не думайте, что справитесь в такой ситуации своими силами, правильно настроив сервер и набив огромный список IP в конфиг файрвола. Даже если у вас физический выделенный сервер, его вычислительные ресурсы и пропускная способность канала - величины конечные. Sapienti sat.
Опыт, если что, у меня уже был :) Кто был когда-то на MTSEO, могут вспомнить, как я вёл прямой репортаж со своей корриды, попутно прося советов. Атака была, прямо скажем, не слишком мощная, хостер крепкий (nic.ru), хостинг shared, но локальные конфиги nginx были к моим услугам. За ночь я перебанил чуть не пять шестых планеты подсетками, к утру ТП хостера углядела это побоище и приняла свои меры. Типа "пришёл лесник и"... На следующий день инцидент был уже исчерпан.

За широкой спиной

Сейчас каждый приличный хостер предлагает защиту. В данном случае хостера зовут FirstVDS, и предлагает он спрятаться за широкую спину своего партнёра DDOS Guard. Не сочтите за рекламу, да реклама тут и бесполезна: у каждого хостера свой партнёр по этой части, именно за его спиной вы при поддержке хостера и окажетесь.
Изображение
Небольшая иллюстрация. Видим, собственно, момент начала атаки и вполне закономерный результат. Синим цветом показан входящий трафик, красным исходящий (всё в GiB).
В самом начале VDS просто "погас", все его попытки отдавать трафик выглядели просто смехотворно (первый пик). Далее проблема была замечена, и я решил побороться за живучесть (масштаб не смутил, ага) :) Не буду долго растекаться, сделано было всё, что я мог сделать в рамках правки конфигов Линукса и сервисов. Одной из самых действенных мер оказалась настройка сервера MySQL с решительным затыканием очень прогрессивного паралитика по прозвищу Innodb (в настройках по умолчанию отжирает бездну памяти, пока не отвалится сервер БД).
После этого синее и красное почти сравнялись и что-то как-то заработало, харкая кровью, но следующий пик вновь отправил VDSку в аут. Вместо страниц пошли лаконичные системные сообщения, что SQL сервис куда-то унесён ветром. Поминутно строчить "systemctl restart mariadb.service" в еле дышащей консоли - так себе развлечение, да и техподдержка начала ненавязчиво подсказывать "что-то с вами неладно, похоже, ддосят вас". Поговорил с клиентом (платить-то ему), и мы быстро оказались за крепостной стеной DDOS Guard.

Рано радуетесь или Проблемы мелкого шрифта

Нет, вообще-то хостеры не виноваты, что мы не всё читаем заранее. И что мы не сразу оцениваем прочитанное - тоже не на их совести. Просто заметьте себе: при переходе на защищённый IP вы заодно оказываетесь на канале, который стоит дороже аренды сервера с парой Xeon'ов на борту (это если вы на colocation). Или не дороже самого начального VDS, но ширина канала порядка на три поменьше. И трафик сверх нормы сразу начинает иметь значение. В смысле, денежное. Которое мы заранее никогда не можем просчитать и прикинуть.
Да, если вы этого клиента привели по своей партнёрке, можете потирать руки, к вам потечёт приятный ручеёк от его переплат. Но ручаюсь, ему не очень понравится платить по 12-16 тыр в месяц там, где он привык платить не больше одной. Поэтому некоторые меры лучше принять и оказавшись "за широкой спиной". И самое первое - проверьте, не выложены ли на сайте какие-нибудь тяжёлые файлы для скачивания. Я вот поздно спохватился - на сайтах было кое-что выложено, и немалых размеров, но поначалу практически весь напор атакующих дебилов рвался на морду. Как видно на картинке, ситуация сперва изменилась к лучшему, а потом кто-то (не одни же дебилы атакуют!) просканировал сайты чем-то вроде Xenu и пошли обращения по всем найденным ссылкам, не только на html-страницы.
Когда презентацию в 30 с лишним мег начинают качать массово, это очень впечатляет. Файлы, конечно, не скачивали полностью (по логам я видел, что это скучное занятие обрывалось самое позднее на половине), но когда ddos'ят по всему набору найденных ссылок, это скачивание идёт не один раз в минуту и исходящий трафик растёт очень шустро.
Так что сразу уберите ссылки "скачать" до лучших времён. Или хорошенько поиграйтесь с JS, чтобы эти ссылки были видны только людям. Ноябрьский подъём на графике наглядно показывает разницу.

Защита от dDoS на php

Смешно? Да, согласен, очень смешно, когда флуд пытаются отсечь такими средствами на уровне движка. Но в данном случае я веду речь не о попытке остановить лавину совочком, а лишь о том, что никакой сервис защиты от dDoS не даст вам полной фильтрации трафика. Откровенный мусор, конечно, отправят в /dev/nul на дальних подступах, но немало "правдоподобного" HTTP-флуда дойдёт и до сервера, заставляя его впустую генерировать страницы и исходящий трафик.
Скажем так, до DDOS Guard'а был у сайта access_log HTTP чуть не в полгига, а стал в 150 мег, хотя в лучшие времена больше пяти мегабайт не бывало. Сайты у клиента - скромные визитки со скромным трафиком... были, до середины сентября прошлого года. А если бы не так скромно, что тогда? Так что мой Внутренний Перфекционист (ВП) задумался, что ещё с этим можно поделать.
Смотрим в логи - видим большую стаю дятлов, более-менее успешно притворяющихся браузерами. Характерные признаки понятны: кидают запросы раз за разом с максимально возможной частотой с одних и тех же IP, получают только html-код, из которого никаких прилинкованных объектов не запрашивают. Ни картинок, ни CSS, ни JS. Только то, что по ссылкам с a href=...
Из манеры поведения понятен и алгоритм их определения.
Берём, к примеру, запросы за интервал в 5 секунд. По скольким ссылкам нормальный посетитель за это время перейдёт? Вряд ли больше чем по двум - зашёл на одну страницу, быстро глянул, кликнул по ссылке и ушёл на другую. Значит, считаем, что если за 5 секунд кто-то отправил больше 2 запросов - это явно не человек. Для спокойствия берём норму в 3 запроса, после третьего отправляем IP в стоп-лист минут на 10.
И на любой запрос с IP-адресов из стоп-листа отвечаем отправкой статус-кода "304 Not Modified". Это мой ВП так решил.
Логично же - в ответ на повторный запрос любезно сообщить боту, что за прошедшие доли секунды запрошенный документ не изменялся. А отправлять тело документа в этом случае не позволяет Его Величество Протокол HTTP. Засим всего Вам хорошего, Ваше Неправдоподобие, будете проходить мимо - проходите. С ботами я всегда общаюсь строго в рамках протокола, как предписывают нормы дипломатии.
Ведём учёт запросов за 5 секунд в файле. Формат данных по вашему вкусу, а мне по вкусу формат CSV, в нём и сохранял. Данные:
- IP-адрес;
- время первого запроса с IP (проще всего таймштамп, выхваченный функцией time() - удобно секунды отсчитывать)
- порядковый номер запроса с этого IP за 5 секунд
Как только проходит третий запрос за интервал, IP-адрес заносится в файл стоп-листа вместе со временем занесения. Из списка "за 5 сек" его нужно убрать, он теперь штрафник.

Итого: делаем маленький скриптик, который:
- проверяет, есть ли этот IP в стоп-листе и не истекло ли время (10 минут отсидки). Если есть и время не вышло, сразу же посылает статус 304 и exit() - чтобы не тратить ресурсы зря.
- проверяет, есть ли этот IP в "5-секундном" списке. Если нет, то заносит. Если есть, то увеличивает счётчик запросов.
- Естественно, при каждом обращении к файлам списков нужно удалять из них устаревшие данные (для этого и нужны таймштампы занесения в список).
У любого движка сегодня есть "центральный" скрипт, на который и попадают все запросы. Вот в него и вписываем на самый верх include нашего скрипта-учётчика.

Лирическое отступление. Внешние Перфекционисты (а они здесь есть, я знаю) уже наверняка готовы к критике. Я о хранении данных в файлах, разумеется. Да, при такой плотности запросов коллизии случаются неизбежно, это я увидел в логе ошибок по сообщениям о пустых массивах данных. Но к моему удивлению коллизий было совсем немного, после них работа дятлорезки очень быстро восстанавливалась и в логах выстраивались стройные колонны статусов 304 :)
Однако, чтобы довести этот инструмент до ума, лучше использовать блоки shared memory вместо файлов, с ними и быстрее, и с блокировкой при записи проще. Так что сейчас переделываю с применением группы функций shmop_*().


Ещё немного добавим...

В качестве дополнительного критерия можно проверить, запрашивались ли за последние 10 минут с данного IP, к примеру, файлы CSS. Браузер-то их точно запросит, так что если "дятлом" оказался некий легальный прокси и CSS запрашивались, это позволит не банить его зря.
Делается это несложно. Предположим, внутри DOCUMENT_ROOT сайта есть директория /css и в ней лежит файл default.css, который задействован на каждой странице. И если мы его будем грузить не напрямую, а через php-скрипт, это нам позволит заодно и зафиксировать адрес, с которого запрашивали. Будем организовывать учёт запросов в самодельном лог-файле. Формат данных - CSV, разделитель - пробел, каждый адрес в своей строке, структура строки вот такая:
IP-address timestamp count
Назовём этот скрипт csslog.php и положим его прямо в директорию /css, код скрипта выглядит вот так:
<?
// куда складываем лог запросов CSS?
$logfile = $_SERVER['DOCUMENT_ROOT'].'/botlog/css.log';
// новое имя для default.css
$cssfile = "_default.css";
// фиксируем IP-адрес
$ip = $_SERVER['REMOTE_ADDR'];
// фиксируем время в виде таймштампа
$tst = time();

if (file_exists($logfile)) $ar = file($logfile); else $ar = array();
$lar = array();
foreach ($ar as $val) {
  $row = explode(' ',trim($val));
  if ($tst - intval($row[1]) < 600) {
	$lar[$row[0]] = $row;
	if ($row[0] == $ip) ++$lar[$row[0]][2];
  }
}
if (!isset($lar[$ip])) {
  $lar[$ip] = array(
	$ip,
	$tst,
	1
);
}
$str = '';
foreach ($lar as $val) {
  $str .= implode(' ',$val)."\n";
}
$fh = fopen($logfile, 'w');
fwrite($fh, $str);
fclose($fh);
header('Content-type: text/css');
readfile($cssfile);
?>
Что он должен делать? Он должен реагировать на запросы файла default.css - сперва засечь время запроса и IP-адрес, с которого запросили, потом считать и разобрать наш лог-файл, где мы такие запросы фиксируем (для этих логов делаем в корне сайта директорию /botlog), и пометить там, в который раз за последние 600 секунд с этого IP запрашивали CSS.
Заодно скрипт удаляет записи, которые старее 600 секунд и перезаписывает лог. После чего просто отправляет соответствующий HTTP-заголовок и вслед за ним тело CSS-файла.
Файл default.css переименовываем (в примере на _default.css), чтобы он не был доступен напрямую по имени. И организовываем перехват запросов к этому файлу, подсовывая вместо него наш скрипт.
Для этого в директории /css делаем файлик .htaccess с такой вот начинкой:
RewriteEngine on
RewriteBase /css/
RewriteRule ^default\.css$ csslog.php [L]
Этот пример - не догма, а руководство к действию. Можно таким способом проверять не CSS-файл, а файл какой-нибудь картинки или Java-скрипта - нужно, чтобы этот файл использовался на всех страницах, тогда проверка IP-адреса на "человечность" будет надёжной.

Итог

В конечном счёте удалось довести маразм до абсурда ситуацию до приемлемого уровня мерзости. Исходящий трафик сейчас ниже входящего, сайты людям видно, все системы VDS работают нормально.
Ник не менял, подпись поменяю позже. Ваш Зануда. Он же AHP-net, но это уже там

#2 uniks

uniks

    Почетный

  • Основатель
  • PipPipPipPipPip
  • 3 903 сообщений
3 709
  • ИзИркутск

Отправлено 15 Март 2023 - 09:10

Была у меня атака у них тоже, но благо кончилась сразу же, не пришлось переезжать на защиту.

#3 Serg_pnz

Serg_pnz

    Hanswurst

  • Старая гвардия
  • PipPipPipPipPip
  • 2 197 сообщений
1 890
  • Из*** гонец? Гонец из Пензы?... Нет – реальный гонец!

Отправлено 15 Март 2023 - 12:58

Spinne, вот Вас мне и нужно!
Во-первых, спасибо за статью!!

Ну и, собственно, задача. Нам надо пофиксить слишком частые запросы парсинга, которые кладут сервер с битриксом. Парсинг этот мы заказали себе сами, но индус всегда включает ботов на максимум и сайт ложится((
Напишите мне, пожалуйста, в личку или телеграмм https://t.me/Serge_pnz если принципиально готовы взяться за эту задачу. Не бесплатно, конечно же.

PS: надеюсь, что у Вас всё хорошо, давно не было видно на форуме...
Не все кальсоны с оторванными пуговицами – брюки. © Serg_pnz

#4 Spinne

Spinne

    Зануда™

  • Основатель
  • PipPipPipPipPip
  • 2 018 сообщений
3 525
  • Излесу, вестимо

TC Отправлено 15 Март 2023 - 15:20

Serg_pnz, приветствую.
Задача, конечно, в иной плоскости. Если я правильно понял, результаты этого парсинга нужны вам же, так что тупо отпихнуть лопатой бешеного бота, ничего ему не отдав – не выход. А отрегулировать бота вы не в состоянии. Единственный вывод, какой у меня есть – нужно делать своего бота, выбирая нужные данные прямо на сервере. Довольно странное занятие перекачивать сайт по HTTP целыми страницами, чтобы "выжать" информацию, которая у вас и так есть :)

PS сейчас всё хорошо. Признаться, было нехорошо, и долго, и дело не в модных вирусах, но я тварь живучая. Успел дожить до пенсии, растерять почти всю клиентуру, но среди оставшейся есть и немаленький магазин на Битриксе. По странному совпадению я для него как раз наваял (и продолжаю) немало сервисных скриптов с различными выборками, так что в принципе задача очень даже знакомая...
Ник не менял, подпись поменяю позже. Ваш Зануда. Он же AHP-net, но это уже там

#5 c4e8ece0

c4e8ece0

    Ниггер на лошади

  • Участник
  • PipPipPipPipPip
  • 5 431 сообщений
7 012
  • Изцирка

Отправлено 15 Март 2023 - 15:41

Ничего не понял, но очень интересно :lol: в смысле что за бизнесь такой, что не может себе позволить посидеть на мегабите в каком-нибудь qrator, но может несколько дней лежать

Просмотр сообщенияSerg_pnz сказал:

Нам надо пофиксить слишком частые запросы парсинга, которые кладут сервер с битриксом.
nginx + fpm в помощь :) nginx будет держать сколько надо запросов, а fpm в своём ритме их разбирать, главное не вылезать из оперативки при настройке кол-ва потоков и выделяемой на похапе память

Просмотр сообщенияSpinne сказал:

Смешно?
Ну ты шо, отетс. PHP 7.4+ идёт с включенным jit и по скорости близок уже к сям
"Они не могут ничего, у них лапки котят"
mine.organic

#6 Spinne

Spinne

    Зануда™

  • Основатель
  • PipPipPipPipPip
  • 2 018 сообщений
3 525
  • Излесу, вестимо

TC Отправлено 15 Март 2023 - 16:33

c4e8ece0, всё по схеме стадий принятия неизбежного. Сперва "может, это ненадолго", потом осознание, что "а может, и нет", вот он и сидит, но "просто пересесть" было, увы, недостаточно, без дополнительных мер этой ширины не хватало.

По скорости не спорю – смешон сам подход с попытками полностью отбить плотный dDoS средствами прикладного уровня. А с дочисткой оставшихся после ддос-гарда дятлов пых вполне уверенно справляется, даже в более ранней версии.
Ник не менял, подпись поменяю позже. Ваш Зануда. Он же AHP-net, но это уже там

#7 Serg_pnz

Serg_pnz

    Hanswurst

  • Старая гвардия
  • PipPipPipPipPip
  • 2 197 сообщений
1 890
  • Из*** гонец? Гонец из Пензы?... Нет – реальный гонец!

Отправлено 15 Март 2023 - 16:46

Spinne, рад за Вас!!
По моему вопросу. Ну он парсит - типа пробует ломать, дыры ищет. В целом дело даже не в индусе (его мы попросили снизить скорость обращений и вообще без нашего ведома больше не включать шайтан-машину)), а в том, что если кто-то захочет повторить его опыт, то сервер ляжет. Значит нужна защита, ну а ip индуса можно и в исключения добавить.

c4e8ece0, Вы сейчас с кем разговаривали?))) nginx, немцы, конгрес... nginx есть, больше не знаю.
Не все кальсоны с оторванными пуговицами – брюки. © Serg_pnz

#8 Spinne

Spinne

    Зануда™

  • Основатель
  • PipPipPipPipPip
  • 2 018 сообщений
3 525
  • Излесу, вестимо

TC Отправлено 15 Март 2023 - 17:09

Serg_pnz, разговор шёл не о немцах, а об индейцах :)
В смысле, чтобы шерифа не волновали проблемы индейцев, а точнее, толстого и неповоротливого Apache, убрать его совсем. А в качестве HTTP-сервера использовать один только nginx (сейчас он чаще всего стоит как фронт-прокси, а за ним толстый Апач). Я пробовал такую конфигурацию – по сравнению с "классическим" nginx+Apache это шустро просто фантастически. Но есть нюансы в предварительной настройке всего хозяйства. Как же без нюансов... ;)
Ник не менял, подпись поменяю позже. Ваш Зануда. Он же AHP-net, но это уже там

#9 angr

angr

    Мастер

  • S.E.Syndicate
  • PipPipPipPip
  • 819 сообщений
1 245

Отправлено 15 Март 2023 - 17:18

мы давно полность отказались от Apache, только nginx

#10 Drakon

Drakon

    Балбес

  • Основатель
  • PipPipPipPipPip
  • 2 120 сообщений
1 678
  • Изmsk

Отправлено 15 Март 2023 - 22:04

Spinne, дядяСлава :smile20:
недорогие и надежные vds - инструмент поднятия ТИЦ
монетизация с ссылок: тут и тут
...
успевает тот, кто не спешит (с)

#11 Spinne

Spinne

    Зануда™

  • Основатель
  • PipPipPipPipPip
  • 2 018 сообщений
3 525
  • Излесу, вестимо

TC Отправлено 15 Март 2023 - 23:30

Drakon, в наличии и в полном порядке :smile57:
Ник не менял, подпись поменяю позже. Ваш Зануда. Он же AHP-net, но это уже там



Похожие темы


Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 анонимных



© 2023 SMO&SEO форум «WEBIMHO» — продвижение и создание сайтов, интернет-маркетинг

По вопросам рекламы на форуме и цены на рекламу
Все материалы SEO форума разрешены к копированию только с установкой гиперактивной ссылки на webimho.ru,
тем, кто этого не сделает, мы оторвем руки и ноги и поменяем местами,
а когда выйдем из тюрьмы, опять оторвем и опять поменяем.


Россия, г. Москва
  • Top.Mail.Ru

Мы в соцсетях: twitter | вконтакте | facebook | livejournal