DDoS на допомогу: як ми проводимо стрес- та навантажувальні тести

DDoS на допомогу: як ми проводимо стрес- та навантажувальні тести

Компанія Variti розробляє захист від ботів та DDoS-атак, а також проводить стрес- та навантажувальне тестування. На конференції HighLoad++ 2018 ми розповідали, як убезпечити ресурси від різноманітних атак. Якщо коротко: ізолюйте частини системи, використовуйте хмарні сервіси та CDN та регулярно оновлюйтесь. Але без спеціалізованих компаній із захистом ви все одно не впораєтеся 🙂

Перед прочитанням тексту можете ознайомитись з короткими тезами на сайті конференції.
А якщо ви не любите читати або просто хочете переглянути відео, запис нашої доповіді нижче під спойлером.

Відеозапис доповіді

Багато компаній вже вміють робити тести навантаження, але не всі роблять стрес-тестування. Деякі наші замовники думають, що їх сайт невразливий, тому що у них є highload система, і вона добре захищає від атак. А ми показуємо, що це не зовсім правда.
Зрозуміло, що перед проведенням тестів ми отримуємо дозвіл від замовника, з підписом та печаткою, і з нашою допомогою DDoS-атаку зробити ні на кого не можна. Тестування проводиться у вибраний замовником час, коли відвідуваність його ресурсу мінімальна, а проблеми з доступом не вплинуть на клієнтів. Крім того, оскільки в процесі тестування завжди може піти щось не так, ми маємо постійний контакт із замовником. Це дозволяє не лише повідомляти про досягнуті результати, а й щось змінювати під час тестування. При завершенні тестування ми завжди складаємо звіт, в якому вказуємо на виявлені недоліки та надаємо рекомендації щодо усунення слабких місць сайту.

Як ми працюємо

Під час проведення тестування ми емулюємо ботнет. Оскільки ми працюємо з клієнтами, які не розташовуються в наших мережах, то для того, щоб тест не закінчився на першій хвилині через спрацьовування лімітів або захисту, ми подаємо навантаження не з одного IP, а з власної підмережі. Плюс, для створення значного навантаження ми маємо свій досить потужний тестовий сервер.

Постулати

Багато – не значить добре
Чим меншим навантаженням ми зможемо довести ресурс до відмови, тим краще. Якщо вдасться зробити так, що сайт припинить функціонувати від одного запиту за секунду, або навіть від одного запиту за хвилину, це чудово. Тому що за законом підлості користувачі чи зловмисники випадково потраплять саме до цієї вразливості.

Часткова відмова краще, ніж повна
Ми завжди радимо робити системи гетерогенними. Причому розділяти їх варто саме фізично, а не лише контейніризації. У разі фізичного поділу, навіть якщо на сайті щось відмовить, то велика ймовірність, що він не припинить роботу повністю, і у користувачів збережеться доступ хоча б до частини функціоналу.

Правильна архітектура - основа стійкості
Відмовостійкість ресурсу та його здатність витримувати атаки та навантаження повинні закладатися на етапі проектування, фактично на етапі малювання перших блок-схем у блокноті. Тому що, якщо закрадаються фатальні помилки, виправити їх надалі можна, але дуже складно.

Хорошим має бути не тільки код, а й конфіг
Багато хто думає, що хороша команда розробки – це гарантія відмовостійкості сервісу. Хороша команда розробки справді необхідна, але має бути ще й хороша експлуатація, хороший DevOps. Тобто потрібні фахівці, які правильно конфігурують Linux та мережу, правильно напишуть конфіги в nginx, налаштують ліміти та інше. В іншому випадку ресурс добре працюватиме тільки на тесті, а в продакшені в якийсь момент все зламається.

Відмінності навантажувального та стрес-тестування
Навантаження тестування дозволяє виявити межі функціонування системи. Стрес-тестування спрямоване на пошук слабких місць системи та використовується для того, щоб цю систему зламати та подивитися, як вона поводитиметься у процесі відмови тих чи інших частин. При цьому характер навантаження зазвичай залишається невідомим для замовника до початку стрес-тестування.

Відмінні риси L7 атак

Види навантаження ми зазвичай ділимо на навантаження на рівні L7 та L3&4. L7 - це навантаження на рівні програми, найчастіше під нею розуміють тільки HTTP, ми ж маємо на увазі будь-яке навантаження на рівні протоколу TCP.
У L7 атак є певні риси. По-перше, вони приходять безпосередньо у додаток, тобто відобразити їх мережевими засобами навряд чи вдасться. Такі атаки задіяють логіку, і за рахунок цього дуже ефективно і за невеликого трафіку споживають ЦПУ, пам'ять, диск, базу даних та інші ресурси.

HTTP Flood

У разі будь-якої атаки навантаження простіше створити, ніж обробити, і у випадку з L7 це теж правильно. Трафік атаки не завжди просто відрізнити від легітимного, і найчастіше це вдається зробити за частотністю, але якщо все сплановано грамотно, то з логів зрозуміти, де атака, а де легітимні запити, неможливо.
Як перший приклад розглянемо атаку HTTP Flood. З графіка видно, що зазвичай такі атаки дуже потужні, у прикладі нижче пікова кількість запитів перевищувала 600 тисяч за хвилину.

DDoS на допомогу: як ми проводимо стрес- та навантажувальні тести

HTTP Flood – це найпростіший спосіб створити навантаження. Зазвичай для нього береться якийсь інструмент тестування навантаження, наприклад, ApacheBench, і задаються запит і мета. За такого простого підходу велика ймовірність нарватися на кешування сервера, але його легко оминути. Наприклад, додавши випадкові рядки на запит, що змусить сервер постійно віддавати свіжу сторінку.
Також не варто забувати про user-agent у процесі створення навантаження. Багато user-agent популярних інструментів тестування фільтруються системними адміністраторами, і в такому разі навантаження може просто не дійти до бекенда. Значно покращити результат можна, вставляючи в запит більш менш валідний заголовок з браузера.
При всій простоті атаки HTTP Flood мають свої недоліки. По-перше, для створення навантаження потрібні великі потужності. По-друге, такі атаки дуже легко виявляються, особливо якщо йдуть з однієї адреси. У результаті запити відразу ж починають фільтруватися або системними адміністраторами, або навіть на рівні провайдера.

Що шукати

Щоб знизити кількість запитів на секунду і при цьому не втратити ефективності, потрібно проявити трохи фантазії та дослідити сайт. Так, навантажувати можна як канал чи сервер, а й окремі частини програми, наприклад, бази даних чи файлові системи. Також можна пошукати місця на сайті, які роблять великі обчислення: калькулятори, сторінки з підбором продуктів та інше. Нарешті часто буває, що на сайті є якийсь php-скрипт, який генерує сторінку з кількох сотень тисяч рядків. Такий скрипт також значною мірою навантажує сервер і може стати мішенню для атаки.

Де шукати

Коли ми скануємо ресурс перед проведенням тестування, то перш за все дивимося, звичайно, на сам сайт. Ми шукаємо всілякі поля введення, важкі файли — загалом усе, що може створити проблеми ресурсу та уповільнює його роботу. Тут допомагають банальні засоби розробки в Google Chrome та Firefox, що показують час відповіді сторінки.
Також ми скануємо піддомени. Наприклад, є якийсь онлайн-магазин, abc.com, і він має піддомен admin.abc.com. Швидше за все це адмінка з авторизацією, але якщо в неї пустити навантаження, то вона може створити проблеми для основного ресурсу.
Сайт може мати піддомен api.abc.com. Швидше за все це ресурс для мобільних додатків. Програму можна знайти в App Store або Google Play, поставити спеціальну точку доступу, препарувати API та зареєструвати тестові облікові записи. Проблема в тому, що часто люди думають, що все, що захищене авторизацією, є невразливим для атак на відмову в обслуговуванні. Начебто авторизація це найкраща CAPTCHA, але це не так. Зробити 10-20 тестових акаунтів просто, а створивши їх, ми отримуємо доступ до складного та неприхованого функціоналу.
Звичайно, ми дивимося на історію, на robots.txt і WebArchive, ViewDNS, шукаємо старі версії ресурсу. Іноді буває так, що розробники викотили, скажімо, mail2.yandex.net, а стара версія mail.yandex.net залишилася. Цей mail.yandex.net перестає підтримуватись, на нього не відводяться ресурси розробки, але він продовжує споживати базу даних. Відповідно, за допомогою старої версії можна ефективно задіяти ресурси бекенда і всього того, що стоїть за версткою. Звичайно, так відбувається не завжди, але з подібним ми стикаємося досить часто.
Звичайно, ми препаруємо всі параметри запиту, структуру cookie. Можна, скажімо, запулити в JSON масив усередині cookie якесь значення, створити велику вкладеність і змусити ресурс працювати нерозумно довго.

Навантаження у пошук

Перше, що спадає на думку при дослідженні сайту, це навантажити базу даних, оскільки пошук є майже у всіх, і майже у всіх він, на жаль, захищений погано. Чомусь розробники не приділяють пошуку достатньо уваги. Але тут є одна рекомендація - не варто робити однотипні запити, тому що можна зіткнутися з кешування, як і у випадку з HTTP flood.
Робити випадкові запити до бази даних теж завжди ефективно. Набагато краще створити список ключових слів, які стосуються пошуку. Якщо повертатися наприклад інтернет-магазину: припустимо, сайт торгує автомобільною гумою і дозволяє задавати радіус шин, тип машини та інші параметри. Відповідно комбінації релевантних слів змусять базу даних працювати у набагато складніших умовах.
Крім того, варто використовувати пагінацію: пошуку набагато складніше віддати передостанню сторінку видачі, ніж першу. Тобто за допомогою пагінації можна трохи урізноманітнити навантаження.
На прикладі нижче показуємо навантаження у пошук. Видно, що з першої секунди тесту на швидкості десять запитів на секунду сайт ліг і не відповідав.

DDoS на допомогу: як ми проводимо стрес- та навантажувальні тести

Якщо пошуку немає?

Якщо пошуку немає, то це не означає, що сайт не містить інших вразливих полів введення. Таким полем може бути авторизація. Зараз розробники люблять робити складні хеші, щоб захистити базу логінів від атаки по таблицях райдужних. Це добре, але такі хеші споживають великі ресурси CPU. Великий потік хибних авторизацій призводить до відмови процесора, і, як наслідок, на виході сайт перестає працювати.
Присутність на сайті різноманітних форм для коментарів та зворотного зв'язку – це привід відправити туди дуже великі тексти або просто створити масовий флуд. Іноді сайти приймають вкладені файли, у тому числі у форматі gzip. У такому випадку ми беремо файл розміром 1Тб, за допомогою gzip стискаємо його до декількох байт або кілобайт і відправляємо на сайт. Далі він розархівується та виходить дуже цікавий ефект.

API відпочинку

Хотілося б приділити трохи уваги таким популярним нині сервісам, як Rest API. Захистити API Rest набагато складніше, ніж звичайний сайт. Для Rest API не працюють навіть банальні способи захисту від перебору паролів та іншої нелегітимної активності.
Rest API дуже просто зламати, тому що він звертається безпосередньо до бази даних. При цьому висновок такого сервісу з ладу спричиняє досить тяжкі наслідки для бізнесу. Справа в тому, що на Rest API зазвичай зав'язаний не лише головний сайт, а й мобільний додаток, якісь внутрішні бізнес-ресурси. І якщо це все падає, то ефект набагато сильніший, ніж у випадку виходу з ладу простого сайту.

Навантаження на важкий контент

Якщо нам пропонують тестувати якийсь звичайний односторінковий додаток, лендинг, сайт-візитку, які не мають складного функціоналу, ми шукаємо важкий контент. Наприклад, великі картинки, які віддає сервер, бінарні файли, pdf-документацію, ми намагаємося все це викачувати. Такі тести добре вантажать файлову систему та забивають канали, і тому ефективні. Тобто навіть якщо ви не покладете сервер, завантажуючи великий файл на невеликих швидкостях, ви просто заб'єте канал цільового сервера і тоді настане відмова в обслуговуванні.
На прикладі такого тесту видно, що на швидкості 30 RPS сайт перестав відповідати, або видавав 500 помилки сервера.

DDoS на допомогу: як ми проводимо стрес- та навантажувальні тести

Не варто забувати і про налаштування серверів. Часто можна зустріти, що людина купила віртуалку, поставила туди Apache, налаштувала все за замовчуванням, розташувала php-додаток, і нижче можна побачити результат.

DDoS на допомогу: як ми проводимо стрес- та навантажувальні тести

Тут навантаження йшло в корінь і становило лише 10 RPS. Ми зачекали 5 хвилин і сервер впав. До кінця, правда, невідомо, чому він упав, але є припущення, що він просто об'ївся пам'яті, і тому перестав відповідати.

Wave based

В останні рік-два досить популярними стали хвильові атаки. Це пов'язано з тим, що багато організацій купують ті чи інші залозки для захисту від DDoS, які вимагають певного часу накопичення статистики для початку фільтрації атаки. Тобто вони не фільтрують атаку в перші 30-40 секунд, тому що накопичують дані та навчаються. Відповідно в ці 30-40 секунд на сайт можна запустити стільки, що ресурс лежатиме тривалий час, доки не розгребуться всі запити.
У разі атаки нижче був інтервал 10 хвилин, після чого прилетіла нова, видозмінена порція атаки.

DDoS на допомогу: як ми проводимо стрес- та навантажувальні тести

Тобто захист навчився, запустив фільтрацію, але прилетіла нова, зовсім інша порція атаки, і захист знову розпочав навчання. Фактично, фільтрація перестає працювати, захист стає неефективним, і сайт недоступний.
Для хвильових атак характерні дуже високі значення на піку, вона може досягати ста тисяч або мільйона запитів за секунду, у випадку з L7. Якщо говорити про L3&4, то там можуть бути сотні гігабіт трафіку, або, відповідно, сотні mpps, якщо рахувати в пакетах.
Проблема таких атак у синхронізації. Атаки йдуть з ботнету, і для того, щоб створити дуже великий разовий пік, потрібен високий рівень синхронізації. І ця координація не завжди виходить: іноді на виході виходить якийсь параболічний пік, який виглядає досить шкода.

Не HTTP єдиним

Крім HTTP на рівні L7, ми любимо експлуатувати інші протоколи. Як правило, у звичайного веб-сайту, тим більше у звичайного хостингу, стирчать назовні поштові протоколи і MySQL. Поштові протоколи схильні до навантажень меншою мірою, ніж бази даних, але їх теж можна навантажувати досить ефективно і на виході отримувати перевантажений CPU на сервері.
Ми цілком реально за допомогою вразливості SSH 2016 досягали успіху. Зараз ця вразливість майже у всіх виправлена, але це не означає, що в SSH не можна подавати навантаження. Можна, можливо. Просто подається величезне навантаження авторизацій, SSH з'їдає майже весь CPU на сервері і далі веб-сайт складається вже від одного-двох запитів на секунду. Відповідно, ці один-два запити по логах ніяк не можна відрізнити від легітимного навантаження.
Залишаються актуальними і безліч з'єднань, які ми відкриваємо на серверах. Раніше цим грішив Apache, зараз цим фактично грішить і nginx, оскільки він часто налаштовується дефолтом. Кількість з'єднань, які nginx може тримати відкритими, лімітована, відповідно ми відкриваємо цю кількість з'єднань, нове з'єднання nginx вже не приймає, і на виході сайт не працює.
Наш тестовий кластер має достатній CPU, щоб атакувати SSL handshake. В принципі, як показує практика, ботнети також іноді люблять це робити. З одного боку, зрозуміло, що без SSL не обійтись, тому що видача Google, ранжування, безпека. З іншого боку, SSL, на жаль, має проблему з CPU.

L3&4

Коли ми говоримо про атаку на рівнях L3&4, ми говоримо, як правило, про атаку на рівні каналу. Таке навантаження майже завжди відмінне від легітимного, якщо це не атака SYN-flood. Проблема SYN-flood атак для засобів захисту полягає у великому обсязі. Максимальна величина L3&4 складала 1,5-2 Тбіт/с. Такий трафік дуже складно обробити навіть великим компаніям, включаючи Oracle та Google.
SYN та SYN-ACK — це пакети, які використовуються для встановлення з'єднання. Тому SYN-flood і складно відрізнити від легітимного навантаження: незрозуміло, це SYN, який прийшов на встановлення з'єднання або частину флуду.

UDP-флуд

Зазвичай зловмисники не мають тих потужностей, які є у нас, тому для організації атак може використовуватися ампліфікація. Тобто зловмисник сканує інтернет і знаходить або вразливі або неправильно налаштовані сервери, які, наприклад, у відповідь на один SYN-пакет, відповідають трьома SYN-ACK. Підробляючи адресу джерела з адреси цільового сервера, можна з допомогою одного пакета збільшити потужність, скажімо, втричі, і перенаправити трафік на жертву.

DDoS на допомогу: як ми проводимо стрес- та навантажувальні тести

Проблема ампліфікацій полягає в їхньому складному виявленні. З останніх прикладів можна навести гучний випадок з вразливим мемкаченим. Плюс, зараз з'явилося безліч пристроїв IoT, IP-камер, які теж в основному налаштовані по дефолту, і по дефолту вони неправильно налаштовані, тому через такі пристрої зловмисники і роблять атаки найчастіше.

DDoS на допомогу: як ми проводимо стрес- та навантажувальні тести

Непростий SYN-flood

SYN-flood, напевно, найцікавіший вид із усіх атак з погляду розробника. Проблема в тому, що найчастіше системні адміністратори використовують для захисту блокування IP. Причому блокуванням по IP страждають не лише сисадміни, які діють за скриптами, а й, на жаль, деякі системи захисту, які купуються за великі гроші.
Такий метод може стати катастрофою, адже якщо зловмисники підмінять IP-адреси, то компанія заблокує власну підмережу. Коли Firewall заблокує власний кластер, на виході руйнуватимуться зовнішні взаємодії, і ресурс зламається.
Причому досягти блокування власної мережі нескладно. Якщо в офісі клієнта є WI-Fi-мережа, або якщо працездатність ресурсів вимірюється за допомогою різних моніторингів, то ми беремо IP-адресу цієї системи моніторингу або офісного Wi-Fi клієнта і використовуємо його як джерело. На виході ресурс начебто доступний, але цільові IP-адреси заблоковані. Так, може бути заблокована Wi-Fi-мережа конференції HighLoad, де презентується новий продукт компанії, — і це тягне за собою певні бізнес- та економічні витрати.
Під час тестування ми не можемо використовувати ампліфікацію через memcached якимись зовнішніми ресурсами, тому що є домовленості щодо подачі трафіку тільки в дозволені IP-адреси. Відповідно ми використовуємо ампліфікацію через SYN та SYN-ACK, коли на відправку одного SYN система відповідає двома-трьома SYN-ACK, і на виході атака множиться у два-три рази.

Інструменти

Один з основних інструментів, яким ми користуємося для навантаження на рівні L7, – Yandex-tank. Зокрема, як гармата використовується фантом, плюс є кілька скриптів для генерації патронів та аналізу результатів.
Для аналізу мережного трафіку використовується Tcpdump, для аналізу сервера Nmap. Для створення навантаження на рівні L3&4 використовується OpenSSL та трохи власної магії з бібліотекою DPDK. DPDK - це бібліотека від Intel, яка дозволяє працювати з мережевим інтерфейсом, минаючи стек Linux, і тим самим підвищує ефективність. Звичайно, DPDK ми використовуємо не тільки на рівні L3&4, але і на рівні L7, тому що вона дозволяє створювати дуже високий потік навантаження, в межах кількох мільйонів запитів на секунду з однієї машини.
Також ми використовуємо певні трафік-генератори та спеціальні інструменти, які пишемо під специфічні тести. Якщо згадати вразливість під SSH, то наведеним вище набором вона може бути проескпулатирована. Якщо ми атакуємо поштовий протокол, беремо поштові утиліти або просто пишемо на них скрипти.

Висновки

Як підсумки хотілося б сказати:

  • Крім класичного тесту навантаження потрібно обов'язково проводити і стрес-тестування. У нас є реальний приклад, коли субпідрядник партнера провів лише тестування навантаження. Воно показало, що ресурс витримує штатне навантаження. Але потім з'явилося позаштатне навантаження, відвідувачі сайту почали трохи інакше використати ресурс, — і на виході субпідрядник ліг. Таким чином, шукати вразливості варто навіть якщо ви вже захищені від DDoS-атак.
  • Необхідно ізолювати одні частини системи від інших. Якщо у вас є пошук, його треба винести на окремі машини, тобто навіть не в докер. Бо якщо відмовить пошук чи авторизація, то хоч щось продовжить працювати. У випадку з інтернет-магазином користувачі продовжать знаходити товари за каталогом, переходити з агрегатора, купувати, якщо вони вже авторизовані, або авторизуватись через OAuth2.
  • Не варто нехтувати всілякими хмарними сервісами.
  • Використовуйте CDN не лише для оптимізації мережевих затримок, але й як засіб захисту від атак на вичерпання каналу та просто флуду у статику.
  • Необхідно використовувати спеціалізовані послуги захисту. Від L3&4 атак на рівні каналу самі ви не захиститеся, тому що у вас, швидше за все, немає достатнього каналу. Від L7 атак ви теж навряд чи відіб'єтеся, оскільки вони бувають дуже великими. Плюс пошук маленьких атак це все-таки прерогатива спеціальних сервісів, спеціальних алгоритмів.
  • Регулярно оновлюйтесь. Це стосується не лише ядра, а й SSH daemon, особливо якщо вони у вас відкриті назовні. В принципі, оновлювати треба взагалі все, тому що відстежувати ті чи інші вразливості самостійно ви навряд чи зможете.

Джерело: habr.com

Додати коментар або відгук