Возможности NGINX и NGINX Plus для защиты от ддос-атак

Тема в разделе "Защита от Ddos-атак", создана пользователем admin, 25 сен 2016.

  1. Мы уже писали про ограничение частоты запросов на Nginx, здесь опишем остальные возможности Nginx для защиты от ддос-атак.


    Защита от медленных ддос-атак.

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

    Наша цель - соединения, которые отправляют данные слишком долго (подвисают) и препятствуют созданию новых соединений, что приводит к отказам в открытии сайта. Специальная директива client_body_timeout контролирует время ожидания NGINX между записями в теле клиента, а директива client_header_timeout ограничивает время ожидания для заголовков. По умолчанию эти настройки выставлены в 60 секунд, но можно изменить на 10 секунд.
    Код:
    server
    {
       client_header_timeout 10s;
       client_body_timeout 10s;
        ...
    }
    
    Теперь "подвисшие" соединения будут разрываться через 10 секунд.


    Блокировка отдельных запросов и IP в Nginx.

    Лучше всего блокировать ддос-ботов на уровне фаервола, но если его нет, IP можно добавить в сам конфиг Nginx. Едва ли это имеет смысл делать при массированном ддосе.
    Код:
    location /
    {
       deny 168.33.153.0/28;   /* Блокируем диапазон 168.33.153.1 через адрес 168.33.153.16 */
       deny 168.33.153.3;
       deny 168.33.153.5;
       ...
    }
    
    Можно задать разрешенный IP, например свой. Если сайт по-прежнему не будет открываться, значит настройками Nginx тут уже не помочь - ддос сильный.
    Код:
    location /
    {
       allow 168.33.153.0/24;
       deny all;
       ...
    }
    
    Можно проанализировать заголовки ддос-ботов и, если встречаются частые совпадения, выставить на них фильтр.
    Код:
    location / {
        if ($http_user_agent ~* babes|forsale|girl|love|nudit) {
            return 403;
        }
        ...
    }
    

    Настраиваем кэширование на Nginx.

    Ддос атака может быть нацелена на загрузку больших файлов и тяжелых страниц, в этом случае надо смотреть логи и ограничивать отдельно нагрузку к таким файлам/страницам либо задать общие настройки для поглощения трафика во время атаки.

    В Nginx есть директива proxy_cache_use_stale, которая отвечает за обновление кэша, через нее можно указать, в каких случаях отдавать клиенту старый кэш.
    Например.
    Код:
    server {
      proxy_cache_use_stale error timeout invalid_header http_500 http_502 http_503 http_504;
    ...
    }
    
    Если нужно отключить настройки кэширования для отдельного location, прописываем в локейшене "proxy_cache off".

    Можно разграничить кеширование для зарегистрированных пользователей и гостей, что станет эффективным способом снижения нагрузки на форумы и блоги.
    Код:
    server {
        listen          *:80;
        server_name     site.name;
    
        # ключ по которому сохраняются и берутся данные из кеша
        proxy_cache_key "$request_method|$http_if_modified_since|$http_if_none_match|$host|$request_uri";
        # Указывает в каких случаях клиенту можно отдать несвежий ответ из кеша
        proxy_cache_use_stale error timeout invalid_header http_500 http_502 http_503 http_504;
    
        location / {
            # оригинальный url (нужен для кеширования)
            set $o_uri $request_uri;
    
            # Определение пользователя по куке LOGIN (замените на свою)
            if ( $cookie_LOGIN = "" ) {
                # если кука LOGIN не установлена обрабатывать запрос через кеш
                rewrite ^ /ng_cache last;
            }
    
            # Для авторизованных отдать данные напрямую
            proxy_cache        pagecache;
            proxy_cache_valid    any 0;
    
            proxy_pass              http://10.0.1.26;
            proxy_set_header        Host             $host;
            proxy_set_header        X-Real-IP        $remote_addr;
        }
    
        # !Важно! url по которому осуществляется авторизвация
        # и устанавливается определяющая кука (LOGIN)
        location /login {
            proxy_pass              http://10.0.1.26;
            proxy_set_header        Host             $host;
            proxy_set_header        X-Real-IP        $remote_addr;
        }
    
            # Учтите что кешируется весь ответ от беэнда, если хотите исключить некоторые файла, то
            # добавте эту настройку. Исключаем картинки, видео, музыку, архивы:
        location ~* \.(jpe?g|gif|png|tif|svg|mp3|ogg|avi|mpe?g|zip|gz|bz2?|rar|ico|bmp|swf|txt|xml)$ {
                    proxy_pass              http://10.0.1.26;
                    proxy_set_header        Host             $host;
                    proxy_set_header        X-Real-IP        $remote_addr;
        }
    
        # Обработка через кеш
        location /ng_cache {
            internal;
    
            # активировать зону кеширования pagecache
            proxy_cache        pagecache;
            # Кешировать указанные коды ответов 10 минут
            proxy_cache_valid    200 301 302 304 10m;
            # Защита от раздачи одинаковой куки в кешированном ответе
            proxy_hide_header    "Set-Cookie";
            # Игнорировать параметры кеша заданные бекэндом
            proxy_ignore_headers    "Cache-Control" "Expires";
    
            # Получение данных от бекэнда по оригинальному url
            proxy_pass              http://10.0.1.26:80$o_uri;
            proxy_set_header        Host             $host;
            proxy_set_header        X-Real-IP        $remote_addr;
        }
    }
    
    По-умолчанию proxy_cache_key состоит из встроенных вариаций (default key, $scheme$proxy_host$request_uri). Если значение включает $query_string, то атака, посылающая редкие строки запросов, может привести к избыточному кэшированию, поэтому без необходимости ее не следует включать.

    Защита от Range-Based-атак

    Есть вариант атаки, при котором заголовок функции Range отправляется с очень большим значением, способным привести к переполнению буфера.

    Вот пример заголовка, способного вызвать сбой:
    Код:
    GET / HTTP/1.1\r\n
    Host: stuff\r\n
    Range: bytes=0-18446744073709551615\r\n
    \r\n
    
    Самым простым способом защиты от подобных атак является обнуление заголовка до отправки его на сервер.
    Код:
    server {
      listen 80;
    
      location / {
      proxy_set_header Range "";
      proxy_pass http://windowsserver:80;
      }
    }
    
    Как вариант, можно возвращать 444 ошибку, если заголовок range имеет подозрительно большое значение.
    Код:
    server {
      listen 80;
    
      if ($http_range ~ "\d{9,}") {
      return 444;
      }
    }
    
     
    Последнее редактирование: 26 сен 2016
    25 сен 2016

Поделиться этой страницей