Захист nginx від DDoS атак. Захист web сервера від програм для ddos ​​атак Аналіз лог файлу web сервера для захисту від ddos

Веб-проекти часто стикаються з DDOS атаками. Сьогодні ми розглянемо один із базовий спосібзахисту від HTTP-Flood

Вступ:

Нещодавно на один із проектів мого знайомого відбулася атака, швидше за все, атакував недосвідчений хакер, оскільки атака велася з однієї ip адреси.

У ході аналізу логів було встановлено, що зловмисник намагається завантажити багато разів головну сторінкусервер намагається обробити ці запити і не може.

Для захисту від подібних атак ми будемо використовувати проксі сервер nginx і стандартний модуль ngx_http_limit_conn_module

Модуль ngx_http_limit_conn_module дозволяє обмежити кількість з'єднань за заданим ключем, зокрема, кількість з'єднань з однієї IP-адреси.

Враховуються в повному обсязі з'єднання, лише ті, у яких є запити, оброблювані сервером, і заголовок запиту вже прочитаний.

Інакше кажучи, ми можемо встановити обмеження на кількість запитів і підключень з однієї ip адреси. Цього вистачить для захисту від слабких та середніх HTTP-Flood атак.

Для встановлення обмеження ми будемо використовувати директиву limit_conn

Налаштування nginx для захисту від DDoS:

limit_conn:

limit_conn задає максимально допустиму кількість з'єднань з одного ip. У разі перевищення цього числа у відповідь на запит сервер поверне помилку 503 (Service Temporarily Unavailable).

Після отримання помилки 503, атакуючий перестане створювати корисне навантаження на сервер бази даних, наприклад MySQL, тим самим розвантаживши його.

Але перед тим як використовувати limit_conn для захисту від атак DDOS за допомогою nginx, ми повинні розібратися і встановити директиву limit_conn_zone

limit_conn_zone:

Синтаксис: limit_conn_zoneключ zone = назва : розмір;
Задає параметри зони пам'яті, що розділяється, яка зберігає стан для різних значень ключа. Стан, зокрема, містить поточну кількість з'єднань. Як ключ можна використовувати текст, змінні та їх комбінації. Запити з порожнім значенням ключа не враховуються.
Приклад використання:

Приклад використання

limit_conn_zone $binary_remote_addr zone=addr:10m;

Ця директива потрібна, щоб зберігати стан кожної ip адреси. Це важливо!Ця директива повинна йти в nginx.conf відразу після http (.

Приклад конфігурації nginx.conf для limit_conn_zone:

Приклад конфігурації

http ( limit_conn_zone $binary_remote_addr zone=addr:10m; ...

http (

limit_conn _ zone $ binary_remote_addr zone = addr : 10m;

. . .

Після встановлення директиви limit_conn_zone ми перейдемо до встановлення limit_conn

Синтаксис: limit_connзона число;

Зверніть увагу, що зону необхідно брати із зони, встановленої limit_conn_zone, у нашому випадку addr.

3-й параметр "число" позначає число одночасно відкритих з'єднань з одного IP адреси.

Для того, щоб обмежити трьома одночасними підключеннями для зони addr, необхідно написати такі:

limit_conn addr 3;

Приклад конфігурації для захисту від DDoS атак за допомогою nginx та limit_conn:

http ( limit_conn_zone $binary_remote_addr zone=addr:10m; ... server ( listen 80; ... location / ( limit_conn addr 3; ... ) ) )

http (

limit_conn _ zone $ binary_remote_addr zone = addr : 10m;

Якийсь час тому я написав докладну статтю про встановлення та налаштування web серверана базі останніх версій. Там я згадав, що це перша стаття з циклу нотаток про веб-сервер. Сьогодні я розповім як простими та підручними засобами захиститися від простих ddosатак.

Відразу зроблю застереження щодо слова ddos, яке тут не зовсім доречне, але я не придумав, як ще популярно пояснити про що йдеться. Від повноцінної атаки ddos ​​ви не зможете захиститися в рамках налаштування веб сервера. У вас просто буде забито весь канал і сервер перестане відповідати. Якщо потужності сервера недостатньо для обробки та фільтрації вхідних запитів, він ляже, щоб ви там не робили. Для повноцінного захисту від ddos ​​потрібні повноцінні кошти, які коштують відчутні фінансові витрати. Докладніше з теорією читайте в окремій статті.

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

Я наведу поради щодо захисту від простих атак ботів або якихось дрібних шкідників та капосників, які без належних дій з вашого боку можуть покласти ваш сайт чи сервер без особливих проблем. Ось простий приклад. Є не дуже слабкий, на борту якого 2 ярди, 8 гігів оперативи та ssd диск.

Сервер налаштований за моєю попередньою статтею, посилання на яку привів на початку. На сервері розгорнуть wordpress сайт із деяким вмістом. І є у нас шкідник, який на своєму сервері запускає простий тест від apache на продуктивність веб-сервера:

# ab -c 50 -n 30000 "https://hl.zeroxzed.ru/"

Усього лише 50 паралельних потоків. Що ми бачимо на своєму веб-сервері:

Не надто приємна картина. Сервер завантажено на 100%. І хоча він нормально опрацьовує запити і загалом коректно працює. Навіть не дуже гальмує, але все одно погано. А якщо буде 3 сервери та по 100 потоків на кожному? Немає жодних проблем навіть на тест взяти у різних хостерів по віртуальній машиніі запускати на них подібні штуки, імітуючи ддос атаку.

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

Захист від ddos ​​за допомогою iptables

Для захисту від найпростішої атакими будемо використовувати firewall iptables, модуль ядра ipsetдля зберігання великих списків ip та самописні скрипти. По фаєрволу дивіться мою статтю - . Тут я не на цьому зупинятимуся.

Питання налаштування ipset я докладно розглядав у своїй статті. Раджу подивитися матеріал, оскільки він безпосередньо пов'язаний із цією статтею та доповнює її.

Отже, приступимо до створення нашого простого захисту від dos атаки з великою кількістю підключень з одного IP адреси. Для початку перевіримо команду, яка покаже нам кількість підключень із кожної ip адреси:

# netstat-ntu | awk "(print $5)" | grep -vE "(Address | servers | 127.0.0.1)" | cut-d: -f1 | sort | uniq-c | sort -n | sed "s/^[ \t]*//"

Ось він, порушник нашого спокою, намагається організувати дос атаку на наш сервер. Тепер намалюємо скрипт, який блокуватиме всіх, хто встановлює понад 50 одночасних з'єднань з сайтом.

#!/bin/sh netstat -ntu | awk "(print $5)" | grep -vE "(Address | servers | 127.0.0.1)" | cut-d: -f1 | sort | uniq-c | sort -n | sed "s/^[ \t]*//" | awk "(if ($1 > 50) print$2)" > /root/ddos/much_conn.txt sleep 3 list=$(cat /root/ddos/much_conn.txt) для ipnet в $list до ipset -A much_conn $ipnet done

В принципі, коментувати тут особливо нема чого. Беремо список підключень, який щойно вивели, у ньому порівнюємо першу колонку, якщо вона більша за 50, то результат другої колонки, де записана ip адреса, передаємо у файл.

Далі читаємо цей файл і додаємо всі ip адреси з нього до списку ipset під назвою much_conn. Попередньо його треба створити. Докладно про це я розповідав у статті, на яку звів посилання вище, але повторю ще раз тут:

# ipset -N much_conn iphash

Подивитися вміст списку можна командою:

# ipset -L much_conn

Тепер потрібно додати до iptables правило, за яким блокуватимуться всі підключення із зазначеного списку ipset.

# iptables -A INPUT -m set --match-set much_conn src -j DROP

Про всяк випадок попереджаю, щоб ви перевірили свій доступ до консолі сервера, перш ніж налаштовувати правила iptables. Будь-яке буває, можна просто помилитися, скопіювати та вставити не те, що потрібно.

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

Єдиний момент, про який я хочу сказати. Сам я не перевіряв, скільки підключень відкривають пошукові роботи, коли приходять на сайт. Я підозрюю, що явно не 50 і навіть не 30, але, напевно, я не перевіряв. Загалом будьте обережні, коли використовуєте цей засіб.

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

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

Є хоч і не дуже витончене, але просте вирішення цієї проблеми. Створити список ipset із заданим часом життя запису за допомогою timeout. Наприклад, ось так:

Ipset -N much_conn iphash timeout 3600

У даному випадкузапис із забаненим ip у списку ipset буде зберігатися протягом 3600 секунд або 60 хвилин.

Потрібно розуміти, що в даному прикладіз 1 ip адресою використовувати ipset немає сенсу, можна відразу банити засобами самого iptables. Ipset потрібен лише тоді, коли цей список хоча б у сотні рядків. Якщо там кілька десятків адрес, вистачить і одного iptables.

Аналіз лог файлу web-сервера для захисту від ddos

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

Банити будемо теж через iptables, а список адрес для бана будемо витягувати з логів веб-сервера. Для цього у вас має бути включене логування запитів до веб-сервера. Наприклад, у nginx за це відповідає таке налаштування віртуального хоста:

Access_log /web/sites/hl.zeroxzed.ru/log/access.log main;

Ми не будемо щоразу аналізувати весь лог файл. Ця операція сама по собі сильно навантажуватиме веб сервер. Візьмемо останні 1000 рядків з лог файлу і порахуємо кількість підключень з одного IP з типовим вмістом, наприклад запит головної сторінки за протоколом http 1.0, «GET/HTTP/1.0». Якщо ви помітите іншу постійну ознаку ботнета, який вас атакує, використовуйте його. Це може бути один і той же user agent або щось ще. Припустимо, якщо атакуючий буде довбати у вразливе місце, то це буде адреса цієї сторінки.

# tail -1000 /web/sites/hl.zeroxzed.ru/log/ssl-access.log | egrep "GET/HTTP/1.0" | awk "(print $1)" | sort-n | uniq -c

Результатом цієї команди буде приблизно такий перелік.

У цьому випадку я використав трохи іншу умову і просто вивів список усіх тих, хто стукався на головну сторінку. Але вже тут порушника, якого можна забанити.

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

#!/bin/sh tail -1000 /web/sites/hl.zeroxzed.ru/log/ssl-access.log | egrep "GET/HTTP/1.0" | awk "(print $1)" | sort-n | uniq-c | sort-n | tail-n100 | awk "(if ($1 > 50) print $2)" > /root/ddos/much_gets.txt sleep 3 list=$(cat /root/ddos/much_gets.txt) для ipnet в $list до ipset -A much_gets $ipnet done

Тут робимо те саме, що й раніше. Ті, хто зробили понад 50 однакових запитів по нашій масці на останні 1000 рядків у лог файлі, відправляються в бан.

Звертаю увагу на рядок, за яким ви фільтруватимете запити. У цьому випадку я показав лише приклад. Не треба брати і застосовувати у тому вигляді, як я показую. Я демонструю технічні можливості та підхід. Налаштовувати та калібрувати систему вам потрібно у себе за місцем. Важливо це розуміти та не застосовувати рішення бездумно. Буде лише шкода.

Не забудьте створити окремий список ipset і додати окреме правило ipables. Можна використовувати вже існуючий список та додане правило з попереднього прикладу, але я рекомендую все поділяти. Так зручніше для подальшого аналізу.

Під час атаки ddos ​​додаєте це правило в cron і виконуєте кожну хвилину. Після завершення атаки скрипт можна вимкнути. В принципі, можна й на постійку залишати, але тут треба добре подумати і прикинути, як воно має виглядати. Головний принцип – не нашкодити.

Банім ботів з неправильним referer

194.67.215.242 - - "POST /index.php HTTP/1.1" 200 913 " g0dfw4p1.ru" "Mozilla/5.0 (Windows NT 6.0; rv:34.0) Gecko/20100101 Firefox/34.0" "-"

Коректне поле referer має містити або http, https, або бути порожнім. Все, що інакше, можна сміливо блокувати чи повертати статус помилки. Додаємо приблизно таку конструкцію в конфігурацію віртуального хоста, розділ server().

If ($http_referer !~* ^($|http://|https://)) ( return 403; )

Після цього перевірте конфігурацію nginx та перечитайте її.

# nginxt -t # nginx -s reload

Якщо ви дістаєте якийсь бот з конкретним referer, можна забанити саме його. Для цього можна доповнити умову або змінити. Наприклад, ось так:

If ($http_referer = "https://bots.ru/dostanim_tebya.html") ( return 403; )

На додаток, можна всіх цих роботів за допомогою простого скрипту банити на iptables, як у прикладах вище. До речі, їх можна банити відразу, розбираючи http запити ще до того, як вони потраплятимуть до nginx, наприклад, за допомогою ngrep, але це складніше завдання. Не всі це вміють робити, там є нюанси, а з nginx знайомі усі. Не складе труднощів реалізувати даний метод.

Захист від ддос за допомогою модулів nginx - limit_conn та limit_req

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

Сенс даних модулів у тому, що один може обмежити одночасну кількість дозволених з'єднань із сайтом, а інший – кількість з'єднань в одиницю часу.

Я обмежу у своєму прикладі кількість одночасних підключень до сайту з одного ip числом 50, а кількість одночасних запитів до динамічного контенту не більше 2-х на секунду. При цьому буде дозволено сплеск ( burst) запитів до 5-ти. Поясню, як розуміти цей сплеск, тому що сам не відразу зрозумів, що саме він означає.

Якщо у нас йде перевищення кількості встановлених запитів за секунду, то їх виконання затримується, і вони вишиковуються в чергу на виконання із зазначеною швидкістю. Розмір цієї черги і дорівнює значенню сплеску. Усі запити, яким не вистачить місця у черзі, будуть завершені помилково. Тобто, якщо запитів буде 4 в секунду, то 2 виконаються відразу і ще 2 встануть у чергу. А якщо буде 10, то 2 виконаються відразу, 5 стануть у чергу на виконання по 2 штуки в секунду, а решта буде завершена з помилкою.

Виходячи з цих умов, обмеження на підключення необхідно встановити в контексті server, а доступ до динамічного контенту у відповідному location. При цьому опис зон, які будуть використовувати директиви, потрібно розташувати в http.

Ось приклад конфігу nginx для реалізації встановлених обмежень з метою захисту від атак атак.

Http ( ... limit_conn_zone $binary_remote_addr zone=perip:10m; limit_req_zone $binary_remote_addr zone=dynamic:10m rate=2r/s; ... server ( ... limit_conn perip 50; ... location ~ \.php$ ( ... limit_req zone = динамічний burst = 5 nodelay; ... ) ) )

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

та запис у лозі з помилками:

2017/11/30 15:25:26 9773#9773: *51482 limiting requests, excess: 5.664 by zone "dynamic", client: 195.91.248.43, server: hl.zeroxzed.ru, request: "G. ", host: "hl.zeroxzed.ru", referrer: "https://hl.zeroxzed.ru/2013/03/15/featured-image-vertical/"

Ліміт на кількість підключень можете перевірити тією ж утилітою ab, Про яку я розповів у вступі.

017/11/30 15:38:56 9773#9773: *53938 limiting connections by zone "perip", client: 94.142.141.246, server: hl.zeroxzed.ru, request: "GET /wp-content/uploads/20 /03/the-dark-knight-rises.jpg HTTP/1.0", host: "hl.zeroxzed.ru"

Тільки не забувайте, що тест потрібно запускати не на конкретну сторінку, тоді ви потрапите на обмеження виконання динамічного контенту, а щось інше. Наприклад, як у моєму прикладі, на картинку.

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

Висновок

Я розглянув найбільш прості способидля захисту web сервера від не менш простих ddos ​​атак, які більше схожі на пустощі. Серйозна атака, яка просто заллє весь сервер сервера, навіть не помітить наших захистів. Але мені доводилося переконуватися в ефективності цих способів у відображенні деяких атак.

Існує досі величезна кількість веб-серверів, які взагалі ніяк не захищені навіть від утиліти ab:) Я знаю про що говорю, тому що мені трапляються в роботу такі сервери. І є так само багато всяких ботів і простих програм, які можна знайти на просторах інтернету та побалуватись, завалюючи сайти, які не готові до навантажень взагалі.

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

Суть захисту в тому, що за допомогою nginx видаємо користувачеві певну cookies, а потім редиректим на сторінку, що запитується. Якщо бот не розуміє кукісів чи редиректів, він відвалюється. Нормальні користувачі нічого не помічають. Можливо, пізніше я окремо розповім про цей спосіб і доповню статтю. А поки що все. Буду радий зауваженням по суті у статтях.

Онлайн курс з Linux

Якщо у вас є бажання навчитися будувати та підтримувати високодоступні та надійні системи, рекомендую познайомитись з онлайн-курсом «Адміністратор Linux»в OTUS. Курс не для новачків, для вступу потрібні базові знання з мереж та встановлення Linuxна віртуалку. Навчання триває 5 місяців, після чого успішні випускники курсу зможуть пройти співбесіду у партнерів. Що дасть вам цей курс:
  • Знання архітектури Linux.
  • Освоєння сучасних методів та інструментів аналізу та обробки даних.
  • Вміння підбирати конфігурацію під необхідні завдання, керувати процесами та забезпечувати безпеку системи.
  • Володіння основними робочими інструментами системного адміністратора.
  • Розуміння особливостей розгортання, настроювання та обслуговування мереж, побудованих на базі Linux.
  • Здатність швидко вирішувати проблеми, що виникають, і забезпечувати стабільну і безперебійну роботу системи.
Перевірте себе на вступному тесті і дивіться докладніше програму.

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

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

Правильні інгредієнти

Сувора правда така, що багато сайтів може покласти будь-хто, скориставшись атакою Slowloris, що наглухо вбиває Apache, або влаштувавши так званий SYN-флуд за допомогою ферми віртуальних серверів, піднятих за хвилину в хмарі Amazon EC2. Всі наші подальші поради щодо захисту від DDoS самотужки ґрунтуються на наступних важливих умовах.

1. Відмовитися від Windows Server

Практика підказує, що сайт, який працює на вінді (2003 або 2008 – неважливо), у разі DDoS приречений. Причина невдачі криється в винтовому мережевому стеку: коли з'єднань стає дуже багато, то сервер неодмінно починає погано відповідати. Ми не знаємо чому Windows Serverу таких ситуаціях працює настільки жахливо, але стикалися з цим не раз і не два. З цієї причини мова в цій статті йтиме про засоби захисту від DDoS-атак у разі, коли сервер крутиться на Linux. Якщо ви щасливий власник щодо сучасного ядра (починаючи з 2.6), то як первинний інструментарій будуть виступати утиліти iptables та ipset (для швидкого додавання IP-адрес), за допомогою яких можна оперативно забанити ботів. Ще один ключ до успіху - правильно приготовлений мережевий стек, про що ми також говоритимемо далі.

2. Розлучитися з Apache

Друге важлива умова- Відмова від Apache. Якщо у вас, не рівна година, стоїть Apache, то як мінімум поставте перед ним проксі, що кешує - nginx або lighttpd. Apache "вкрай важко віддавати файли, і, що ще гірше, він на фундаментальному рівні (тобто невиправно) вразливий для небезпечної атаки Slowloris, що дозволяє завалити сервер мало не з мобільного телефона. Для боротьби з різними видами Slowloris користувачі Apache придумали спочатку патч Anti-slowloris.diff, потім mod_noloris, потім mod_antiloris, mod_limitipconn, mod_reqtimeout... Але якщо ви хочете спокійно спати ночами, простіше взяти HTTP-сервер, невразливий для Slowloris на рівні. Тому всі наші подальші рецепти ґрунтуються на припущенні, що на фронтенді використовується nginx.

Відбиваємось від DDoS

Що робити, коли прийшов DDoS? Традиційна техніка самооборони – почитати лог-файл HTTP-сервера, написати патерн для grep (що відловлює запити ботів) та забанити всіх, хто під нього підпаде. Ця методика спрацює... якщо пощастить. Ботнети бувають двох типів, обидва небезпечні, але по-різному. Один цілком приходить на сайт миттєво, інший поступово. Перший вбиває все й одразу, зате в логах з'являється весь повністю, і якщо ви їх проgrepаєте та забаните всі IP-адреси, то ви – переможець. Другий ботнет укладає сайт ніжно та обережно, але банити вам його доведеться, можливо, протягом доби. Будь-якому адміністратору важливо розуміти: якщо планується боротися grep'ом, то треба бути готовим присвятити боротьбі з атакою кілька днів. Нижче поради про те, куди можна заздалегідь підкласти соломки, щоб не так боляче було падати.

3. Використовувати модуль testcookie

Мабуть, найголовніший, найдієвіший і оперативніший рецепт цієї статті. Якщо на ваш сайт приходить DDoS, то максимально дієвим способомдати відсіч може стати модуль testcookie-nginx, розроблений хабракористувачем @kyprizel. Ідея проста. Найчастіше роботи, що реалізують HTTP-флуд, досить тупі і не мають механізмів HTTP cookie та редиректу. Іноді трапляються просунутіші - такі можуть використовувати cookies і обробляти редиректи, але майже ніколи DoS-бот не несе в собі повноцінного JavaScript-движка (хоча це зустрічається все частіше і частіше). Testcookie-nginx працює як швидкий фільтр між ботами та бекендом під час L7 DDoS-атаки, що дозволяє відсіювати сміттєві запити. Що входить до цих перевірок? Чи вміє клієнт виконувати HTTP Redirect, чи підтримує JavaScript, чи він браузер, за який себе видає (оскільки JavaScript скрізь різний і якщо клієнт каже, що він, скажімо, Firefox, то ми можемо це перевірити). Перевірка реалізована за допомогою кукісів з використанням різних методів:

  • "Set-Cookie" + редирект за допомогою 301 HTTP Location;
  • «Set-Cookie» + редирект з допомогою HTML meta refresh;
  • довільним шаблоном, причому можна використовувати JavaScript.

Щоб уникнути автоматичного парсингу, перевіряюча кукіса може бути зашифрована за допомогою AES-128 і пізніше розшифрована на клієнтській стороні JavaScript. У новій версії модуля з'явилася можливість встановлювати кукісу через Flash, що також дозволяє ефективно відсіяти ботів (які Flash зазвичай не підтримують), але, правда, і блокує доступ для багатьох легітимних користувачів (фактично всіх мобільних пристроїв). Примітно, що використовувати testcookie-nginx вкрай просто. Розробник, зокрема, наводить кілька зрозумілих прикладів використання (на різні випадки атаки) із семплами конфігів для nginx.

Крім переваг, у testcookie є і недоліки:

  • ріже всіх роботів, у тому числі Googlebot. Якщо ви плануєте залишити testcookie на постійній основі, переконайтеся, що ви не пропадете з пошукової видачі;
  • створює проблеми користувачам з браузерами Links, w3m та їм подібними;
  • не рятує від роботів, оснащених повноцінним браузерним двигуном з JavaScript.

Словом, testcookie_module не є універсальним. Але від ряду речей, таких як, наприклад, примітивні інструментарії Java і C#, він допомагає. Таким чином ви відсікаєте частину загрози.

4. Код 444

Метою DDoS'єрів часто стає найбільш ресурсомістка частина сайту. Типовий приклад – пошук, який виконує складні запити до бази. Звичайно, цим можуть користуватися зловмисники, зарядивши відразу кілька десятків тисяч запитів до пошукового двигуна. Що ми можемо вдіяти? Час відключити пошук. Нехай клієнти не зможуть шукати потрібну інформацію вбудованими засобами, але весь основний сайт залишатиметься в працездатному стані доти, поки ви не знайдете корінь всіх проблем. Nginx підтримує нестандартний код 444, який дозволяє просто закрити з'єднання і нічого не віддавати у відповідь:

Location /search ( return 444; )

Таким чином, можна, наприклад, оперативно реалізувати фільтрацію по URL. Якщо ви впевнені, що запити до location /search приходять тільки від ботів (наприклад, ваша впевненість полягає в тому, що на вашому сайті взагалі немає розділу /search), ви можете встановити на сервер пакет ipset і забанити ботів простим shell-скриптом:

Ipset-N ban iphash tail-f access.log | while read LINE; do echo "$LINE" | \ cut -d "" -f3 | cut -d " " -f2 | grep -q 444 && ipset -A ban "$(L%% *)";

Якщо формат лог-файлів нестандартний (не combined) або потрібно банити за іншими ознаками, ніж статус відповіді, може знадобитися замінити cut на регулярне вираження.

5. Банім з геопризнаку

Нестандартний код відповіді 444 може стати у нагоді ще й для оперативного бана клієнтів з геоознаки. Ви можете жорстко обмежити окремі країни, від яких відчуваєте незручність. Скажімо, навряд чи інтернет-магазин фотоапаратів з Ростова-на-Дону має багато користувачів в Єгипті. Це не дуже гарний спосіб(прямо скажемо - огидний), оскільки дані GeoIP неточні, а лихварі іноді літають до Єгипту на відпочинок. Але якщо вам втрачати нічого, то дотримуйтесь інструкцій:

  1. Підключіть до nginx GeoIP-модуль (wiki.nginx.org/HttpGeoipModule).
  2. Виведіть інформацію про геоприв'язку в access log.
  3. Далі, модифікувавши наведений вище шелл-скрипт, проgrepайте accesslog nginx'а і додайте відфутболених за географічною ознакою клієнтів у бан.

Якщо, наприклад, боти здебільшого були з Китаю, це може допомогти.

6. Нейронна мережа (PoC)

Нарешті, ви можете повторити досвід хабракористувача @SaveTheRbtz, який взяв нейронну мережу PyBrain, запхав у неї лог і проаналізував запити (habrahabr.ru/post/136237). Метод робочий, хоч і не універсальний:). Але якщо ви дійсно знаєте нутрощі свого сайту – а ви, як системний адміністратор, повинні, – то у вас є шанси, що в найбільш трагічних ситуаціях такий інструментарій на основі нейронних мереж, навчання та заздалегідь зібраної інформації вам допоможе. У цьому випадку дуже корисно мати access.log до початку DDoS"а, тому що він описує практично 100% легітимних клієнтів, а отже, відмінний dataset для тренування нейронної мережі. Тим більше очима в лозі боти видно не завжди.

Діагностика проблеми

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

7. Юзайте профайлер та відладчик

Для найпоширенішої платформи створення веб-сайтів – PHP + MySQL – вузьке місце можна шукати за допомогою наступних інструментів:

  • профайлер Xdebug покаже, на які виклики програма витрачає найбільше часу;
  • вбудований налагоджувач APD та налагоджувальний висновок у лог помилок допоможуть з'ясувати, який саме код виконує ці виклики;
  • в більшості випадків собака заритий у складності та великоваговості запитів до бази даних. Тут допоможе вбудована в двигун бази даних SQL-директива explain.

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

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

8. Аналізуйте помилки

Проаналізуйте обсяг трафіку, час відповіді сервера кількість помилок. Для цього дивіться логі. У nginx час відповіді сервера фіксується у лозі двома змінними: request_time та upstream_response_time. Перша – це повний часвиконання запиту, включаючи затримки мережі між користувачем і сервером; друга повідомляє, скільки бекенд (Apache, php_fpm, uwsgi...) виконував запит. Значення upstream_response_time надзвичайно важливе для сайтів з великою кількістю динамічного контенту та активним спілкуванням фронтенду з базою даних, їх не можна нехтувати. Як формат лога можна використовувати такий конфіг:

Log_format xakep_log "$remote_addr - $remote_user [$time_local] " ""$request" $status $body_bytes_sent " ""$http_referer" "$http_user_agent" $request_time \ $upstream_response_time";

Це combined-формат із доданими полями таймінгу.

9. Відстежуйте кількість запитів на секунду

Також подивіться на кількість запитів за секунду. У разі nginx ви можете приблизно оцінити цю величину наступною shell-командою (змінна ACCESS_LOG містить шлях до журналу запитів nginx у combined-форматі):

Echo $(($(fgrep -c "$(env LC_ALL=C date --date=@$(($(date \ +%s)-60)) +%d/%b/%Y:%H: %M)" "$ACCESS_LOG")/60))

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

10. Не забувайте про tcpdump

Багато хто забуває, що tcpdump - це шалений засіб діагностики. Я наведу кілька прикладів. У грудні 2011-го виявили баг в ядрі Linux, коли воно відкривало TCP-з'єднання при виставлених прапорах TCP-сегменту SYN і RST. Першим багрепорт відправив саме системний адміністратор з Росії, чий ресурс був атакований цим методом - атакуючі дізналися про вразливість раніше, ніж весь світ. Йому, мабуть, така діагностика допомогла. Інший приклад: у nginx є одна не дуже приємна властивість - він пише в балку тільки після повної відпрацювання запиту. Бувають ситуації, коли сайт лежить, нічого не працює і нічого немає. Все тому, що всі запити, які в Наразізавантажують сервер, що ще не виконалися. Tcpdump допоможе тут.

Він настільки хороший, що я радив людям не використовувати бінарні протоколи до того, як вони переконаються, що все гаразд, - адже текстові протоколи налагоджувати tcpdump"ом легко, а бінарні - ні. Однак сніффер хороший як засіб діагностики - як засіб підтримки production"а він страшний. Він легко може втратити відразу кілька пакетів та зіпсувати вам історію користувача. Дивитися його висновок зручно, і він стане в нагоді для ручної діагностики та бана, але намагайтеся нічого критичного на ньому не засновувати. Інший улюблений багатьма засіб «погріпати запити» - ngrep - взагалі за замовчуванням намагається запросити в районі двох гігабайт пам'яті, що несвопується, і тільки потім починає зменшувати свої вимоги.

11. Атака чи ні?

Як відрізнити DDoS-атаку, наприклад, від ефекту рекламної кампанії? Це питання може здатися смішним, але ця тема не менш складна. Бувають досить курйозні випадки. В одних добрих хлопців, коли вони напружилися і ґрунтовно прикрутили кешування, сайт зліг на пару днів. З'ясувалося, що протягом кількох місяців цей сайт непомітно датамайнили якісь німці і до оптимізації кешування сторінки сайту у цих німців з усіма картинками вантажилися досить довго. Коли сторінка почала видаватися з кешу миттєво, бот, який не мав ніяких тайм-аутів, теж почав збирати їх миттєво. Тяжко довелося. Випадок особливо складний тому, що якщо ви самі змінили налаштування (включили кешування) і сайт після цього перестав працювати, то хто, на вашу і начальницьку думку, винен? Ось ось. Якщо ви спостерігаєте різке зростання кількості запитів, подивіться, наприклад, у Google Analytics, хто приходив на якісь сторінки.

Тюнінг веб-сервера

Які є ще ключові моменти? Звичайно, ви можете поставити «умолчальний» nginx і сподіватися, що у вас все буде гаразд. Однак добре завжди не буває. Тому адміністратор будь-якого сервера повинен присвятити чимало часу тонкому налаштуванню та тюнінгу nginx.

12. Лімітуємо ресурси (розміри буферів) у nginx

Про що треба пам'ятати насамперед? Кожен ресурс має ліміт. Насамперед це стосується оперативної пам'яті. Тому розміри заголовків і всіх буферів потрібно обмежити адекватними значеннями на клієнта і на сервер цілком. Їх обов'язково потрібно прописати у конфізі nginx.

  • client_header_buffer_size_ _ Задає розмір буфера для читання заголовка запиту клієнта. Якщо рядок запиту або поле заголовка запиту не поміщаються повністю в цей буфер, виділяються буфери більшого розміру, що задаються директивою large_client_header_buffers.
  • large_client_header_buffersЗадає максимальне число та розмір буферів для читання великого заголовка запиту клієнта.
  • client_body_buffer_sizeЗадає розмір буфера для читання запиту клієнта. Якщо тіло запиту більше заданого буфера, все тіло запиту чи лише його частина записується в тимчасовий файл.
  • client_max_body_sizeЗадає максимально допустимий розмір тіла запиту клієнта, що вказується в полі Content-Length заголовка запиту. Якщо розмір більше заданого, клієнту повертається помилка 413 (Request Entity Too Large).

13. Налаштовуємо тайм-аути в nginx

Ресурсом є час. Тому наступним важливим кроком має стати установка всіх тайм-аутів, які знову ж таки дуже важливо акуратно прописати в налаштуваннях nginx.

  • reset_timedout_connection on;Допомагає боротися із сокетами, що зависли у фазі FIN-WAIT.
  • client_header_timeoutЗадає тайм-аут під час читання заголовка запиту клієнта.
  • client_body_timeoutЗадає тайм-аут під час читання тіла запиту клієнта.
  • keepalive_timeoutЗадає тайм-аут, протягом якого keep-alive з'єднання з клієнтом не буде закрито сервером. Багато хто боїться задавати тут великі значення, але ми не впевнені, що цей страх виправданий. Опціонально можна виставити значення тайм-ауту в заголовку HTTP Keep-Alive, але Internet Explorerзнаменитий тим, що ігнорує це значення
  • send_timeoutЗадає тайм-аут під час передачі відповіді клієнту. Якщо після цього клієнт нічого не прийме, з'єднання буде закрито.

Відразу питання: які параметри буферів та тайм-аутів правильні? Універсального рецепта тут немає, у кожній ситуації вони свої. Але є перевірений підхід. Потрібно виставити мінімальні значення, за яких сайт залишається у працездатному стані (у мирний час), тобто сторінки віддаються та запити обробляються. Це визначається лише тестуванням – як із десктопів, так і з мобільних пристроїв. Алгоритм пошуку значень кожного параметра (розмір буфера або тайм-ауту):

  1. Виставляємо математично мінімальне значенняпараметра.
  2. Запускаємо прогін тестів сайту.
  3. Якщо весь функціонал сайту працює без проблем – параметр визначено. Якщо ні – збільшуємо значення параметра та переходимо до п. 2.
  4. Якщо значення параметра перевищило навіть значення за промовчанням, це привід для обговорення в команді розробників.

У ряді випадків ревізія даних параметрів повинна призводити до рефакторингу/редизайну сайту. Наприклад, якщо сайт не працює без трихвилинних AJAX long polling запитів, то потрібно не тайм-аут підвищувати, а long polling замінювати на щось інше - ботнет у 20 тисяч машин, що висить на запитах по три хвилини, легко вб'є дешевий середньостатистичний сервер.

14. Лімітуємо з'єднання в nginx (limit_conn та limit_req)

Nginx також має можливість лімітувати з'єднання, запити і так далі. Якщо ви не впевнені в тому, як поведеться певна частина вашого сайту, то в ідеалі вам потрібно протестувати її, зрозуміти скільки запитів вона витримає, і прописати це в конфігурації nginx. Одна річ, коли сайт лежить і ви здатні прийти та підняти його. І зовсім інша справа - коли він ліг настільки, що сервер пішов у swap. У цьому випадку найчастіше простіше перезавантажитись, ніж дочекатися його тріумфального повернення.

Припустимо, що на сайті є розділи з назвами /download і /search. При цьому ми:

  • не хочемо, щоб боти (або люди з надто ретивими рекурсивними download-менеджерами) забили нам таблицю TCP-з'єднань своїми закачуваннями;
  • не хочемо, щоб боти (або залітні краулери пошукових систем) вичерпали обчислювальні ресурси СУБД безліччю пошукових запитів.

Для цього пригодиться конфігурація такого виду:

Http ( limit_conn_zone $binary_remote_addr zone=download_c:10m; limit_req_zone $binary_remote_addr zone=search_r:10m \ rate=1r/s; server ( location /download/ ( limit_conn download_c 1; # Інша конфігурація search_r burst = 5; # Інша конфігурація location ) ) )

Зазвичай має пряме значення встановити обмеження limit_conn і limit_req для locations, у яких перебувають дорогі до виконання скрипти (у прикладі вказаний пошук, і це неспроста). Обмеження необхідно вибирати, керуючись результатами навантажувального та регресійного тестування, а також здоровим глуздом.

Зверніть увагу на параметр 10m у прикладі. Він означає, що на розрахунок даного ліміту буде виділено словник з буфером 10 мегабайт і ні мегабайтом більше. У цій конфігурації це дозволить відстежувати 320 000 TCP-сесій. Для оптимізації займаної пам'яті як ключ у словнику використовується змінна $binary_remote_addr, яка містить IP-адресу користувача в бінарному вигляді і займає менше пам'яті, ніж звичайна строкова змінна $remote_addr. Потрібно зауважити, що другим параметром до директиви limit_req_zone може бути не тільки IP, але й будь-яка інша змінна nginx, доступна в даному контексті, - наприклад, у випадку, коли ви не хочете забезпечити більш щадний режим для проксі, можна використовувати $binary_remote_addr$http_user_agent або $binary_remote_addr$http_cookie_myc00kiez - але використовувати такі конструкції потрібно з обережністю, оскільки, на відміну від 32-бітного $binary_remote_addr, ці змінні можуть бути істотно більшої довжини і декларовані вами «10m» можуть раптово закінчитися.

Тренди в DDoS

  1. Безперервно зростає потужність атак мережного та транспортного рівня. Потенціал середньостатистичної атаки типу SYN-флуд досяг уже 10 мільйонів пакетів на секунду.
  2. Особливий попит останнім часом мають атаки на DNS. UDP-флуд валідними DNS-запитами зі spoof'ленними IP-адресами джерела - це одна з найпростіших у реалізації та складних у плані протидії атак. Багато великих російських компаній (у тому числі хостингів) відчували останнім часом проблеми в результаті атак на їхні DNS-сервери. Чим далі, тим таких атак буде більше, а їхня потужність зростатиме.
  3. Судячи з зовнішніх ознак, більшість ботнетів управляється не централізовано, а у вигляді пірингової мережі. Це дає зловмисникам можливість синхронізувати дії ботнета в часі - якщо раніше керуючі команди поширювалися по ботнету в 5 тисяч машин за десятки хвилин, то тепер рахунок йде на секунди, а ваш сайт може несподівано випробувати миттєве зростання кількості запитів.
  4. Частка роботів, оснащених повноцінним браузерним двигуном з JavaScript, все ще невелика, але безперервно зростає. Таку атаку складніше відбити вбудованими підручними засобами, тому Саморобкіни повинні з побоюванням стежити за цим трендом.

готуємо ОС

Крім тонкого налаштування nginx, потрібно подбати про налаштування мережевого стекасистеми. Щонайменше - відразу включити net.ipv4.tcp_syncookies в sysctl, щоб разом захистити себе від атаки SYN-floodневеликого розміру.

15. Тюним ядро

Зверніть увагу на більш просунуті налаштування мережної частини (ядра) знову ж таки за тайм-аутами та пам'яті. Є більш важливі та менш важливі. Насамперед треба звернути увагу на:

  • net.ipv4.tcp_fin_timeoutЧас, який сокет проведе у TCP-фазі FIN-WAIT-2 (очікування FIN/ACK-сегмента).
  • net.ipv4.tcp_(,r,w)memРозмір приймального буфера сокетів TCP. Три значення: мінімум, значення за замовчуванням та максимум.
  • net.core.(r,w)mem_maxТе ж саме для не TCP буферів.

При каналі в 100 Мбіт/с значення за умовчанням якось годяться; але якщо у вас є хоча б гігабіт в секунду, то краще використовувати щось на кшталт:

Sysctl -w net.core.rmem_max=8388608 sysctl -w net.core.wmem_max=8388608 sysctl -w net.ipv4.tcp_rmem="4096 87380 8388608" sysctl4m 8388608" sysctl - w net.ipv4.tcp_fin_timeout=10

16. Ревізія /proc/sys/net/**

Ідеально вивчити всі параметри /proc/sys/net/**. Потрібно подивитися, наскільки вони відрізняються від дефолтних, і зрозуміти, наскільки вони адекватно виставлені. Linux-розробник (або системний адміністратор), який знається на роботі підвладного йому інтернет-сервісу і бажає його оптимізувати, повинен з цікавістю прочитати документацію всіх параметрів мережевого стека ядра. Можливо, він знайде там специфічні для свого сайту змінні, які допоможуть не лише захистити сайт від зловмисників, а й прискорити його роботу.

Не боятися!

Успішні DDoS-атаки день у день гасять e-commerce, стрясають ЗМІ, з одного удару відправляють у нокаут найбільші платіжні системи. Мільйони інтернет-користувачів втрачають доступ до критичної інформації. Загроза насущна, тому потрібно зустрічати її у всеозброєнні. Виконайте домашню роботу, не бійтеся та тримайте голову холодною. Ви не перший і не останній, хто зіткнеться з DDoS-атакою на свій сайт, і у ваших силах, керуючись своїми знаннями та здоровим глуздом, звести наслідки атаки до мінімуму.

Розгорнемо два сервери: Frontend (виконуватиме роль фільтруючого сервера: nginx, iptables, naxsi\modsecurity, fail2ban etc) і Backend (захищений веб-додаток). У цій статті буде описано практично приклади фільтрації шкідливого трафіку засобами Frontend-сервера.

1. Оптимізуємо ОС

Насамперед оптимізуємо ОС на сервері Frontend під великі навантаження. Відредагуємо файл /etc/sysctl.conf:

## Оптимізація ОЗУ
kernel.shmmax = ХХХ
kernel.shmall = ХХХ

## Оптимізація підсистеми виведення повідомлень
kernel.msgmnb = 65536
kernel.msgmax = 65536

## Оптимізація роботи зі SWAP
vm.swappiness = 10
vm.dirty_ratio = 40
vm.dirty_background_ratio = 5

## Оптимізація підсистеми роботи з файлами ("Too many open files fix")
fs.file-max = 2097152

## Оптимізація мережної підсистеми
net.ipv4.ip_forward = 1
net.core.somaxconn = 65535
net.netfilter.nf_conntrack_max = 10000000
net.netfilter.nf_conntrack_tcp_loose = 0
net.netfilter.nf_conntrack_tcp_timeout_established = 1800
net.netfilter.nf_conntrack_tcp_timeout_close = 10
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 10
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 20
net.netfilter.nf_conntrack_tcp_timeout_last_ack = 20
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 20
net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 20
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 10
net.ipv4.tcp_congestion_control = hybla
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.ip_no_pmtu_disc = 1
net.ipv4.route.flush = 1
net.ipv4.route.max_size = 8048576
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.tcp_mem = 65536 131072 262144
net.ipv4.udp_mem = 65536 131072 262144
net.ipv4.tcp_rmem = 4096 87380 33554432
net.ipv4.udp_rmem_min = 16384
net.ipv4.tcp_wmem = 4096 87380 33554432
net.ipv4.udp_wmem_min = 16384
net.ipv4.tcp_max_tw_buckets = 1440000
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_max_orphans = 400000
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_rfc1337 = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_synack_retries = 1
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_fack = 1
net.ipv4.tcp_ecn = 2
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 60
net.ipv4.tcp_keepalive_probes = 10
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.rp_filter = 1

Значення параметрів kernel.shmmax та kernel.shmall розраховуються, виходячи з обсягу ОЗУ. Для підрахунку можна скористатися скриптом:

#!/bin/bash # simple shmsetup script page_size=`getconf PAGE_SIZE` phys_pages=`getconf _PHYS_PAGES` shmall=`expr $phys_pages / 2` shmmax=`expr $shmall \* $page_size` echo kernel. kernel.shmall = $shmall

Ці параметри дозволять оптимізувати роботу системи під високі навантаження. Застосування змін здійснюється командою "sysctl -p" або перезавантаження системи.

2. Iptables

Фільтруємо атаки на мережному транспортному рівні з використанням iptables:

## Блокування INVALID-пакетів
iptables -A INPUT -i eth0 -m conntrack --ctstate INVALID -j DROP
## Блокування нових пакетів, які не мають прапора SYN
iptables -A INPUT -i eth0 -p tcp ! --syn-m conntrack --ctstate NEW-j DROP
## Блокування нестандартних значень MSS
iptables -A INPUT -i eth0 -p tcp -m conntrack -ctstate NEW -m tcpmss! --mss 536:65535 -j DROP
## Блокування фрагментованих пакетів
iptables -A INPUT -i eth0 -f -j DROP
## Блокування пакетів з неправильними прапорами TCP
iptables -A INPUT -i eth0 -p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE-j DROP
iptables -A INPUT -i eth0 -p tcp --tcp-flags FIN,SYN FIN,SYN-j DROP
iptables -A INPUT -i eth0 -p tcp --tcp-flags SYN,RST SYN,RST-j DROP
iptables -A INPUT -i eth0 -p tcp --tcp-flags SYN,FIN SYN,FIN-j DROP
iptables -A INPUT -i eth0 -p tcp --tcp-flags FIN,RST FIN,RST-j DROP
iptables -A INPUT -i eth0 -p tcp --tcp-flags FIN,ACK FIN-j DROP
iptables -A INPUT -i eth0 -p tcp --tcp-flags ACK,URG URG -j DROP
iptables -A INPUT -i eth0 -p tcp --tcp-flags ACK,FIN FIN -j DROP
iptables -A INPUT -i eth0 -p tcp --tcp-flags ACK,PSH PSH -j DROP
iptables -A INPUT -i eth0 -p tcp --tcp-flags ALL ALL -j DROP
iptables -A INPUT -i eth0 -p tcp --tcp-flags ALL NONE -j DROP
iptables -A INPUT -i eth0 -p tcp --tcp-flags ALL FIN, PSH, URG -j DROP
iptables -A INPUT -i eth0 -p tcp --tcp-flags ALL SYN,FIN,PSH,URG-j DROP
iptables -A INPUT -i eth0 -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
## Захист від сканування портів
iptables -N port-scanning
iptables -A port-scanning -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s --limit-burst 2 -j RETURN
iptables -A port-scanning -j DROP

Обмежимо кількість з'єднань з веб-сервером:

Iptables -A INPUT -i eth0 -o eth1 -p tcp --syn -m multiport --dports 80,443 -m connlimit --connlimit-above 30 --connlimit-mask 32 -j DROP
iptables -A INPUT -i eth0 -o eth1 -p tcp -m multiport --dports 80,443 -j ACCEPT

Правила обмежать кількість сесій до 30 в секунду для кожної зовнішньої адреси. Значення підбирається індивідуально, залежно від типу веб-програми. Як правило, значення 30 для connlimit-above буде достатньо.

3. Nginx

3.1 Блокуємо надмірні звернення

Налаштуємо Nginx на Frontend-сервері так, щоб обмежити надлишкові звернення до сервера. Відредагуємо файл vhost:

# nano /etc/nginx/sited-enabled/frontend

Limit_req_zone$binary_remote_addrzone=сайт:10m rate=10r/s;
server (
listen 80;
server_name сайт;
...
}
location / (
proxy_pass ...
...
limit_req zone=сайт burst=20;
limit_req_log_level error;
limit_req_status 503;
...
}

Таким чином Nginx проксируватиме звернення клієнтів на Backend-сервер не частіше, ніж 10 запитів в секунду (параметр rate). Надлишкові звернення накопичуватимуться у черзі та проксуватимуться у міру звільнення «пулу» звернень. Якщо кількість звернень перевищить значення 20 (параметр burst), nginx на Frontend почне віддавати 503 помилку до того часу, поки «пул» не почне вивільнятися.

3.2 Блокуємо підозрілі юзерагенти

Заблокуємо юзерагенти, які, як правило, не використовують легітимні користувачі:

# nano /etc/nginx/nginx.conf

Map $http_user_agent $bad_useragent (
include /etc/nginx/bad_useragents;
}

# nano /etc/nginx/bad_useragents

~*nmap 1;
~*nikto1 1;
~*wikto 1;
~*sf 1;
~*sqlmap 1;
~*bsqlbf 1;
~*acunetix 1;
~*havij 1;
~*appscan 1;
~*wpscan 1;
~*mj12bot 1;
~*ApacheBench 1;
~*WordPress 1;
~*DirBuster 1;
~*perl 1;
~*PhpStorm 1;
~*python 1;
~*w3af 1;
~*WhatWeb 1;
~*Arachni 1;
~*XSpider 1;
~*Hydra 1;
~*Evasions 1;
~*OpenVas 1;
~*visionutils 1;
~*Synapse 1;
~*HTTP_Request2 1;
~*GuzzleHttp 1;
~*Paros 1;
~*Synapse 1;
~*Python-urllib 1;

Окремо варто звернути увагу на user-agent WordPress. Якщо веб-додаток, що захищається, не використовує CMS WordPress, або ж функціонал «track-back» і «ping-back» не планується використовувати (швидше за все), то блокування запитів з даним user-agent дозволить перекрити атаки, що використовують особливості реалізації такого функціоналу в WordPress. вивчити особливості таких атак можна.

Реалізація таких простих правил дозволить забезпечити якісний захист від DDoS-атак веб-сайту з мінімальними витратами.

PS:Переконайтеся, що інші сервіси на Frontend-сервері добре захищені та не дозволять зловмиснику отримати віддалений доступ(наприклад, SSH або FTP).

UPD:Як альтернатива можна спробувати Nemesida WAF Free - повністю безкоштовний, представлений у вигляді динамічного модуля Nginx, встановлюється та оновлюється з репозиторію, не вимагає компіляції, підключається за кілька хвилин до вже встановленого Nginx. waf.pentestit.ru/about/2511

У нашому блозі на Хабрі ми пишемо не тільки про розвиток нашого хмарного проекту 1cloud, але й розповідаємо про те, як вирішувати ті чи інші технологічні завдання. Влітку 2015 року в блозі проекту NGINX з'явився матеріал про те, як за його допомогою можна протистояти DDoS-атакам. Нотатка видалася нам цікавою, тому ми наводимо тут її основні моменти.

Що таке DDoS?

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

Стандартна схема у цій справі – «замучити» систему такою кількістю нових з'єднань та запитів, щоб мережа перестала справлятися з їхнім потоком, або стала настільки повільною, що з нею неможливо працювати.

Технічні характеристики DDoS-атаки

На прикладному рівні DDoS-атака проводиться спеціальними програмами(ботами), які можуть використовувати вразливість у конкретній системі. Наприклад, система, яка не заточена під керування великим числом паралельних з'єднань, може бути виведена з ладу шляхом створення великої кількості таких коннектів. В активному стані їх можна підтримувати, іноді посилаючи через них невеликі обсяги трафіку. Інший варіант – завалювати систему великою кількістю запитів чи робити ці запити досить тяжкими. Адже йдеться не про актуальні з'єднання, тому через боти дуже легко відправляти величезну кількість запитів і швидко створювати безліч нових з'єднань.

Нижче наведено технічні характеристики DDoS-атак, якими їх можна розпізнати, і, враховуючи які, з ними впоратися:

  • Трафік зазвичай йде з фіксованого числа IP-адрес, призначених для атаки. В результаті кожна така адреса виробляє ненормальну кількість з'єднань та запитів, не характерну для реального користувача. Довідка: Не завжди подібний розклад свідчить про проведення DDoS-атаки. Подібні ж дії можна спостерігати при використанні forward (анонімного) проксі, тому що його IP-адреса на сервері служить для ідентифікації будь-якого користувача, якого він обслуговує. Однак, кількість заходів та запитів від анонімного проксі буде в рази меншою, ніж при атаці.
  • Оскільки йдеться про боти, що виробляють трафік, сервер, що «перегріває», інтенсивність цього трафіку набагато вища, ніж здатний виробляти реальний користувач.
  • Заголовок клієнтської програми User-Agent іноді відображається у нестандартній конфігурації.
  • Іноді атаку можна розпізнати за заголовком Referer.

Можливості NGINX та NGINX Plus щодо боротьби з DDoS-атаками

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

Limit_req_zone $binary_remote_addr zone=one:10m rate=30r/m; server ( ... location /login.html ( limit_req zone=one; ... ) )
Директива limit_req_zone формує загальну зону пам'яті one для зберігання встановленої кількості запитів по заданому ключу. У цьому випадку це клієнтська IP-адреса ($binary_remote_addr). Директива limit_req у блоці /login.html надсилає до цієї зони пам'яті.

Обмеження кількості з'єднань
Ви можете накласти обмеження на кількість з'єднань, які можуть виходити від однієї IP-адреси клієнта. Знову ж таки оцінивши їх значення, характерне для реального користувача. Наприклад, ви можете встановити не більше 10 заходів із одного IP в область /store вашого сайту.

Limit_conn_zone $binary_remote_addr zone=addr:10m; server ( ... location /store/ ( limit_conn addr 10; ... ) )
Як і в попередньому прикладі, директива limit_conn_zone формує загальну зону пам'яті add для зберігання запитів за заданим ключем – клієнтською IP-адресою $binary_remote_addr . limit_conn у тілі /store відсилає до цієї зони пам'яті та встановлює обмеження 10 з'єднаннями з кожного IP клієнта.

Закриття повільних з'єднань
Ви можете закрити з'єднання, які надсилають дані надто рідко, що може бути ознакою того, що їхня головна мета – бути відкритими протягом тривалого часу та перешкоджати новим з'єднанням. Цей тип програми для атаки називають Slowloris. Директива client_body_timeout контролює час очікування NGINX між записами клієнта. Директива client_header_timeout робить те саме для заголовків. За замовчуванням в обох випадках встановлюється 60 секунд. У наступному прикладі цей інтервал встановлюється на 5 секунд.

Server ( client_body_timeout 5s; client_header_timeout 5s; ... )

Внесення IP-адрес до «чорного списку»
Якщо ви розпізнали IP, що використовуються для атаки, ви можете внести їх до «чорного списку» за допомогою директиви deny, NGINX і NGINX Plus більше не реагуватиме на запити з цих адрес. Наприклад, якщо ви з'ясували, що атака йде з області 123.123.123.1 через адресу 123.123.123.16:

Location / ( deny 123.123.123.0/28; ... )
Якщо таких адрес кілька:

Location / ( deny 123.123.123.3; deny 123.123.123.5; deny 123.123.123.7; ... )

Створення дозволеного списку IP-адрес
Допустимо, доступ до вашого сайту або додатку відкритий для заздалегідь відомого діапазону IP-адрес. Ви можете прописати його за допомогою директив allow та deny. Наприклад, ви можете надати доступ лише адресам локальної мережі.

Location / (allow 192.168.1.0/24; deny all; ... )
IP-адреси, які не відповідають умовам встановленого діапазону, будуть заблоковані.

Кешування для запобігання стрибкам трафіку
Ви можете налаштувати NGINX та NGINX Plus, щоб вони поглинали стрибки трафіку під час атаки через кешування та пропис його параметрів, вони ігноруватимуть зворотні запити. Це можна зробити такими варіантами:

Параметр оновлення в proxy_cache_use_stale повідомляє NGINX, що коли йому необхідно провести оновлення застарілих об'єктів у кеші, йому слід надсилати лише один запит і тримати відкритим доступдо таких об'єктів для клієнтів, доки оновлення з внутрішніх серверів не отримано.

Key defined by the proxy_cache_key зазвичай складається із вбудованих варіацій (default key , $scheme$proxy_host$request_uri має три варіації). Якщо значення включає $query_string , то атака, що надсилає рідкісні рядки запитів, може призвести до надмірного кешування. Не рекомендується включати цей варіант у ключ, якщо в цьому немає потреби.

Блокування запитів
Ви можете налаштувати NGINX та NGINX Plus для блокування наступних видів запитів:
  • Запити до певної URL-адреси, яка може бути під загрозою.
  • Запити, де заголовки User-Agent мають значення, що не відповідає звичайному трафіку клієнта.
  • Запити, в яких заголовки Referer можуть бути визначені як пов'язані з атакою.
  • Запити, у яких інші заголовки здаються підозрілими.
Наприклад, якщо ви вирішили, що атака націлена на URL /foo.php, можете заблокувати всі запити до сторінки:

Location /foo.php ( deny all; )
Якщо ви з'ясували, що запити DDoS-атаки мають значення foo або bar у заголовках User Agent, можете заблокувати їх:

Location / ( if ($http_user_agent ~* foo|bar) ( return 403; ) ... )
За таким самим принципом можна працювати з іншими заголовками, які мають значення, що вказують на загрозу атаки.

Обмеження з'єднань до внутрішніх серверів
NGINX і NGINX Plus можуть одночасно керуватися з великою кількістю з'єднань, ніж дозволяють собі внутрішні сервери. За допомогою NGINX Plus можна обмежити кількість з'єднань до кожного з внутрішніх серверів. Допустимо, ви бажаєте обмежити кількість підключень до двох внутрішніх серверів групи, що обслуговує сайт, числом 200:

Upstream website ( server 192.168.100.1:80 max_conns=200; server 192.168.100.2:80 max_conns=200; queue 10 timeout=30s; )
Параметр max_conns встановлює для кожного сервера максимальну кількість з'єднань, відкритих NGINX Plus. Директива queue обмежує кількість запитів у черзі, якщо всі сервери групи перевищили свій ліміт. У цьому рядку прописано час перебування запиту у черзі – 30 секунд.

Range-Based-атаки
Існує варіант атаки, при якому заголовок функції Range відправляється з дуже великим значенням, що може призвести до переповнення буфера. Для того щоб дізнатися, як за допомогою NGINX і NGINX Plus справлятися з цим типом атаки, радимо почитати.
Як керуватися з великими завантаженнями
DDoS-атаки зазвичай ведуть до критичного підвищення рівня завантаження. Почитати про те, як навчити NGINX та NGINX Plus та ОС справлятися з цією проблемою, можна .

Виявлення DDoS-атаки

Досі ми обговорювали, як можна використовувати NGINX та NGINX Plus, щоб пом'якшити наслідки DDoS-атаки. Але чи можна за допомогою цих серверів виявити саму атаку? Модуль NGINX Plus Status надає детальні метричні показники трафіку, розподіленого по внутрішніх серверах. Цей інструмент дозволяє розпізнати ненормальний стан трафіку. NGINX Plus має функцію панелі керування сторінкою сайту, де відображаються графіки поточного стану роботи системи (приклад можна подивитися тут: demo.nginx.com/status.html). Ті ж показники доступні через API, їх можна вбудувати у власну або сторонню систему моніторингу, і відстежувати в часі зміни трафіку, попереджаючи незвичайні його стани.

Резюме

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

Ви можете допомогти і переказати трохи коштів на розвиток сайту