Защита nginx от DDoS атак. Вычисляем DDOS на сервере Внесение IP-адресов в «черный список»

Рассмотрим защиту веб-сервера ngix работающей на операционной системе Ubuntu (в принципе - любой Linux).

Существует два типа DoS/DDoS-атак основанных на идее флуда, то есть заваливания жертвы огромным количеством пакетов.

Флуд бывает разным: ICMP-флуд, SYN-флуд, UDP-флуд и HTTP-флуд. Современные DoS-боты могут использовать все эти атаки одновременно, поэтому следует заранее позаботиться об адекватной защите от каждой из них.

  • ICMP-флуд
  • Примитивный метод забивания полосы пропускания и создания нагрузок на сетевой стек через монотонную посылку запросов ICMP ECHO (пинг). Он обнаруживается с помощью анализа потоков трафика в обе стороны: во время атаки типа ICMP-флуд они практически идентичны. Практически безболезненный способ абсолютной защиты основан на отключении ответов на запросы ICMP ECHO:

    сохраним и применим:

    sudo sysctl -p
  • SYN-флуд
  • Один из распространенных способов не только забить канал связи, но и ввести сетевой стек операционной системы в такое состояние, когда он уже не сможет принимать новые запросы на подключение.
    Основан на попытке инициализации большого числа одновременных TCP-соединений через посылку SYN-пакета с несуществующим обратным адресом. После нескольких попыток отослать ответный ACK-пакет на недоступный адрес большинство систем ставят неустановленное соединение в очередь. И только после n-ой попытки закрывают соединение.
    Так как поток ACK-пакетов очень велик, вскоре очередь оказывается заполненной, и ядро дает отказ на попытки открыть новое соединение.
    Наиболее умные DoS-боты еще и анализируют систему перед началом атаки, чтобы слать запросы только на открытые жизненно важные порты. Идентифицировать такую атаку просто: достаточно попробовать подключиться к одному из сервисов.

    Оборонительные мероприятия обычно включают в себя:
    Увеличение очереди "полуоткрытых" TCP-соединений,
    Уменьшение времени удержания "полуоткрытых" соединений,
    Включение механизма TCP syncookies,
    Ограничение максимального числа "полуоткрытых» соединений с одного IP к конкретному порту"

  • UDP-флуд
  • Обычный метод захламления полосы пропускания. Основан на бесконечной посылке UDP-пакетов на порты различных UDP-сервисов. Легко устраняется за счет отрезания таких сервисов от внешнего мира и установки лимита на количество соединений в единицу времени к DNS-серверу на стороне шлюза:

    iptables -I INPUT -p udp --dport 53 -j DROP -m iplimit --iplimit-above 1

    Скорей всего придётся пересобрать ядро. Но это уже сами.......

  • HTTP-флуд
  • Один из самых популярных на сегодняшний день способов флуда. Основан на бесконечной посылке GET запросов на 80-ый порт с целью загрузить web-сервер настолько, чтобы он оказался не в состоянии обрабатывать все остальные запросы.
    Бывает, что целью флуда становится не корень web-сервера, а один из скриптов, выполняющих ресурсоемкие задачи или работающий с базой данных. В любом случае, индикатором начавшейся атаки будет служить аномально быстрый рост логов web-сервера.
    Методы борьбы с HTTP-флудом включают в себя настройку web-сервера и базы данных с целью снизить эффект от атаки, а также для отсеивания DoS-ботов с помощью различных приемов.

    Во-первых, следует увеличить максимальное число коннектов к базе данных одновременно.
    Во-вторых, установить перед web-сервером Apache легкий и производительный nginx – он будет кэшировать запросы и отдавать статику. Это решение из списка "must have", которое не только снизит эффект DoS-атак, но и позволит серверу выдержать огромные нагрузки.
    Например:

    nano /etc/nginx/nginx.conf
    # Увеличиваем максимальное количество используемых файлов
    worker_rlimit_nofile 8192;
    ## Число рабочих процессов, рекомендуется ставить по количеству ядер
    worker_processes 1;
    # Уменьшает число системных вызовов gettimeofday(), что приводит к увеличению производительности
    timer_resolution 100ms;
    # Директива задаёт приоритет рабочих процессов от -20 до 20 (отрицательное число означает более высокий приоритет).
    worker_priority -5;

    events {
    # Увеличиваем максимальное количество соединений
    worker_connections 2048;
    # Использовать эффективный метод epoll для обработки соединений
    use epoll;
    }
    http {
    # Включить sendfile(). Использование sendfile() экономит системные вызовы, уменьшает число копирований данных
    sendfile on;
    output_buffers 2 64k;

    gzip on;
    gzip_min_length 1100;
    gzip_buffers 64 8k;
    gzip_comp_level 3;
    gzip_http_version 1.1;
    gzip_proxied any;
    gzip_types text/plain application/xml application/x-javascript text/css;
    # Отключаем таймаут на закрытие keep-alive соединений
    keepalive_timeout 0;
    # Не отдавать версию nginx в заголовке ответа
    server_tokens off;
    # Сбрасывать соединение по таймауту
    reset_timedout_connection on;
    #Директива описывает зону, в которой хранятся состояния сессий. Значения сессий определяется заданной переменной.
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

    server {
    listen 80 default;
    server_name localhost;

    access_log /var/log/nginx/localhost.access.log;

    location / {
    root /var/www/;
    index index.html index.htm index.php;
    open_file_cache max=1024 inactive=600s;
    open_file_cache_valid 2000s;
    open_file_cache_min_uses 1;
    open_file_cache_errors on;
    }
    location ~ \.php$ {
    limit_req zone=one burst=5;
    fastcgi_pass unix://tmp/php5-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /var/www$fastcgi_script_name;
    include fastcgi_params;
    fastcgi_hide_header "Cache-Control";
    }
    location ~ /\.ht {
    deny all;
    }
    expires max; # Внимание!!! Эта строка expires необходима!
    add_header Last-Modified $sent_http_Expires;
    }


    В случае необходимости можно задействовать nginx-модуль ngx_http_limit_req_module, ограничивающий количество одновременных подключений с одного адреса. Ресурсоемкие скрипты можно защитить от ботов с помощью задержек, кнопок "Нажми меня", выставления кукисов и других приемов, направленных на проверку "человечности".

    Чтобы не попасть в безвыходное положение во время обрушения DDoS-шторма на системы, необходимо тщательным образом подготовить их к такой ситуации:

    1. Сервера, имеющие прямой доступ во внешнюю сеть, должны быть подготовлены к простому и быстрому удаленному ребуту (sshd спасет отца русской демократии). Большим плюсом будет наличие второго, административного, сетевого интерфейса, через который можно получить доступ к серверу в случае забитости основного канала.
    2. Программное обеспечение(ПО), используемое на сервере, всегда должно находиться в актуальном состоянии. Все дырки - пропатчены, обновления установлены (между прочим, простой совет, которому многие не следуют). Это оградит от DoS-атак, эксплуатирующих баги в сервисах.
    3. Все слушающие сетевые сервисы, предназначенные для административного использования, должны быть спрятаны брандмауэром ото всех, кто не должен иметь к ним доступ. Тогда атакующий не сможет использовать их для проведения DoS-атаки или брутфорса.
    4. На подходах к серверу (ближайшем маршрутизаторе) должна быть установлена система анализа трафика (NetFlow в помощь), которая позволит своевременно узнать о начинающейся атаке и вовремя принять меры по ее предотвращению.

    Повторить пробу через десять секунд

    Сохраним, и применим:

    sudo sysctl -p

    Все приемы, приведенные в этом топике, направлены на снижение эффективности DDoS-атак, ставящих своей целью израсходовать ресурсы машины.
    От флуда, забивающего канал мусором, защититься практически невозможно, и единственно правильный, но не всегда осуществимый способ борьбы заключается в том, чтобы "лишить атаку смысла".
    Если вы заимеешь в свое распоряжение действительно широкий канал, который легко пропустит трафик небольшого ботнета, то считай, что от 90% атак твой сервер защищен. Есть и более изощренный способ защиты.
    Он основан на организации распределенной вычислительной сети, включающей в себя множество дублирующих серверов, которые подключены к разным магистральным каналам.
    Когда вычислительные мощности или пропускная способность канала заканчиваются, все новые клиенты перенаправляются на другой сервер (или же постепенно "размазываются" по серверам по принципу round-robin).
    Это очень дорогая, но очень стойкая структура, завалить которую практически нереально.
    Ещё одно более-менее эффективное решение заключается в покупке дорогостоящих хардварных систем Cisco Traffic Anomaly Detector и Cisco Guard.
    Работая в связке, они могут подавить начинающуюся атаку, но, как и большинство других решений, основанных на обучении и анализе состояний, дают сбои.
    Поэтому следует подумать перед тем, как выбивать из начальства десятки тысячи баксов на такую защиту.

    "CENSORED, началось. Что делать?"

    Главное не паникуйте. Перед непосредственным началом атаки боты "разогреваются", постепенно наращивая поток пакетов на атакуемую машину. Важно поймать момент и начать активные действия. Поможет в этом постоянное наблюдение за маршрутизатором, подключенным к внешней сети (анализ графиков NetFlow). На сервере-жертве определить начало атаки можно подручными средствами.

    Наличие SYN-флуда устанавливается легко - через подсчет числа "полуоткрытых" TCP-соединений:

    Значения, в несколько раз превышающие среднестатистические, дают основания задуматься. Далее следует просмотреть список IP-адресов, с которых идут запросы на подключение:

    Убедитесь в существовании интерфейса eth1. Проверить это просто - ifconfig. В случае чего замените на свой.

    Показателем служит большой поток однообразных (и не содержащих полезной информации) пакетов от разных IP, направленных на один порт/сервис (например, корень web-сервера или определенный cgi-скрипт).
    Окончательно определившись, начинаем дропать неугодных по IP-адресам (будет гораздо больше эффекта, если ты сделаешь это на маршрутизаторе):

    Это даст вам некоторую фору (совсем маленькую; зачастую IP-адрес источника спуфится), которую ты должен использовать для того, чтобы обратиться к провайдеру/хостеру (с приложенными к сообщению логами web-сервера, ядра, брандмауэра и списком выявленных тобой IP-адресов).
    Большинство из них, конечно, проигнорируют это сообщение (а хостинги с оплатой трафика еще и порадуются - DoS-атака принесет им прибыль) или просто отключат ваш сервер. Но в любом случае это следует сделать обязательно, – эффективная защита от DDoS возможна только на магистральных каналах. В одиночку ты справишься с мелкими нападками, направленными на истощение ресурсов сервера, но окажешься беззащитным перед более-менее серьезным DDoS"ом.

    Не нужно копировать всё отсюда и вставлять в конфиг. Проверьте сначала, может параметр уже определён, и его стоит просто переопределить. Например

    cat /etc/sysctl.conf |grep net.ipv6.conf.lo.disable_ipv6

    Борьба с 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%% *}"; done

    Если формат лог-файлов нестандартный (не 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 [email protected]$(($(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; # Прочая конфигурация location } location /search/ { limit_req zone=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 Мбит/с значения по умолчанию еще как-то годятся; но если у вас в наличии хотя бы гигабит в cекунду, то лучше использовать что-то вроде:

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

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

    Идеально изучить все параметры /proc/sys/net/**. Надо посмотреть, насколько они отличаются от дефолтных, и понять, насколько они адекватно выставлены. Linux-разработчик (или системный администратор), разбирающийся в работе подвластного ему интернет-сервиса и желающий его оптимизировать, должен с интересом прочитать документацию всех параметров сетевого стека ядра. Возможно, он найдет там специфические для своего сайта переменные, которые помогут не только защитить сайт от злоумышленников, но и ускорить его работу.

    Не бояться!

    Успешные DDoS-атаки изо дня в день гасят e-commerce, сотрясают СМИ, c одного удара отправляют в нокаут крупнейшие платежные системы. Миллионы интернет-пользователей теряют доступ к критичной информации. Угроза насущна, поэтому нужно встречать ее во всеоружии. Выполните домашнюю работу, не бойтесь и держите голову холодной. Вы не первый и не последний, кто столкнется с DDoS-атакой на свой сайт, и в ваших силах, руководствуясь своими знаниями и здравым смыслом, свести последствия атаки к минимуму.

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

    Вы можете помочь и перевести немного средств на развитие сайта

    

    Развернем два сервера: 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.shmmax = $shmmax echo 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-атак веб-сайта с минимальными затратами.

    P.S.: Убедитесь, что другие сервисы на Frontend-сервере хорошо защищены и не позволят злоумышленнику получить удаленный доступ (например, по SSH или FTP).

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