Распределенная атака типа "отказ в обслуживании" (DDoS) - это попытка сделать недоступным какой-либо сервис, обычно веб-сайт, путем бомбардировки его таким количеством трафика с нескольких машин, что сервер, предоставляющий услугу, больше не может функционировать правильно из-за истощения ресурсов.
Как правило, злоумышленник пытается насытить систему таким количеством соединений и запросов, что она больше не может принимать новый трафик или становится настолько медленной, что становится фактически непригодной для использования.
Характеристики DDoS-атак на прикладном уровне
DDoS-атаки на прикладном уровне (Layer 7/HTTP) осуществляются с помощью программ (ботов), которые могут быть настроены таким образом, чтобы наилучшим образом использовать уязвимости конкретных систем. Например, для систем, которые плохо обрабатывают большое количество одновременных соединений, простое открытие большого количества соединений и поддержание их активности путем периодической отправки небольшого объема трафика может исчерпать возможности системы для новых соединений. Другие атаки могут выражаться в отправке большого количества запросов или очень больших запросов. Поскольку эти атаки осуществляются ботами, а не реальными пользователями, злоумышленник может легко открыть большое количество соединений и очень быстро отправить большое количество запросов.
Характеристики DDoS-атак, которые можно использовать для защиты от них, включают следующие (этот список не является исчерпывающим):
- Трафик обычно исходит из фиксированного набора IP-адресов, принадлежащих машинам, используемым для осуществления атаки. В результате каждый IP-адрес отвечает за гораздо большее количество соединений и запросов, чем можно было бы ожидать от реального пользователя.
- Важно не считать, что такая схема трафика всегда представляет собой DDoS-атаку. Использование прямых прокси-серверов также может создавать подобную картину, поскольку IP-адрес прямого прокси-сервера используется в качестве клиентского адреса для запросов от всех реальных клиентов, которых он обслуживает. Однако количество соединений и запросов от прямого прокси-сервера обычно намного меньше, чем при DDoS-атаке.
- Поскольку трафик генерируется ботами и призван перегрузить сервер, скорость трафика намного выше, чем может генерировать пользователь.
- Заголовок User-Agent иногда устанавливается на нестандартное значение.
- Заголовок Referer иногда устанавливается в значение, которое можно связать с атакой.
Использование NGINX для борьбы с DDoS-атаками
NGINX и NGINX Plus обладают рядом особенностей, которые в сочетании с вышеупомянутыми характеристиками DDoS-атаки делают их ценной частью решения по борьбе с DDoS-атаками. Эти функции решают проблему DDoS-атаки как путем регулирования входящего трафика, так и путем контроля трафика при его проксировании на внутренние серверы.
Неотъемлемая защита архитектуры NGINX, управляемой событиями
NGINX разработан, чтобы быть "амортизатором" для вашего сайта или приложения. Он имеет неблокирующую, управляемую событиями архитектуру, которая справляется с огромным количеством запросов без заметного увеличения загрузки ресурсов.
Новые запросы из сети не отвлекают NGINX от обработки текущих запросов, а это значит, что NGINX имеет свободные ресурсы для применения описанных ниже методов, которые защищают ваш сайт или приложение от атак.
Ограничение скорости запросов
Вы можете ограничить скорость, с которой NGINX и NGINX Plus принимают входящие запросы, до значения, типичного для реальных пользователей. Например, вы можете решить, что реальный пользователь, заходящий на страницу входа в систему, может делать запрос только каждые 2 секунды. Вы можете настроить NGINX и NGINX Plus так, чтобы разрешить одному IP-адресу клиента пытаться войти в систему только каждые 2 секунды (эквивалентно 30 запросам в минуту):
1 2 3 4 5 6 7 8 9 | 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 в блоке location для /login.html ссылается на зону общей памяти.
Ограничение количества подключений
Вы можете ограничить количество соединений, которые могут быть открыты одним IP-адресом клиента, опять же до значения, соответствующего реальным пользователям. Например, вы можете разрешить каждому клиентскому IP-адресу открывать не более 10 соединений с областью /store вашего сайта:
1 2 3 4 5 6 7 8 9 | limit_conn_zone $binary_remote_addr zone=addr:10m; server { # ... location /store/ { limit_conn addr 10; # ... } } |
Директива limit_conn_zone настраивает зону общей памяти addr для хранения запросов на указанный ключ, в данном случае (как и в предыдущем примере) IP-адрес клиента, $binary_remote_addr. Директива limit_conn в блоке location для /store ссылается на зону общей памяти и устанавливает максимум 10 соединений с каждого IP-адреса клиента.
Закрытие медленных соединений
Вы можете закрыть соединения, которые записывают данные слишком редко, что может представлять собой попытку держать соединения открытыми как можно дольше (тем самым снижая способность сервера принимать новые соединения). Slowloris является примером такого типа атаки. Директива client_body_timeout управляет временем ожидания NGINX между записями тела клиента, а директива client_header_timeout управляет временем ожидания NGINX между записями заголовков клиента. По умолчанию для обеих директив установлено значение 60 секунд. Этот пример настраивает NGINX на ожидание не более 5 секунд между записями от клиента как заголовков, так и тела:
1 2 3 4 5 | server { client_body_timeout 5s; client_header_timeout 5s; # ... } |
Запрет IP-адресов
Если вы можете определить IP-адреса клиентов, используемые для атаки, вы можете внести их в список с помощью директивы deny, чтобы NGINX и NGINX Plus не принимали их соединения или запросы. Например, если вы определили, что атаки исходят из диапазона адресов 123.123.123.1 - 123.123.123.16:
1 2 3 4 | location / { deny 123.123.123.0/28; # ... } |
Или если вы определили, что атака идет с IP-адресов клиентов 123.123.123.3, 123.123.123.5 и 123.123.123.7:
1 2 3 4 5 6 | location / { deny 123.123.123.3; deny 123.123.123.5; deny 123.123.123.7; # ... } |
Разрешающий список IP-адресов
Если доступ к вашему сайту или приложению разрешен только с одного или нескольких определенных наборов или диапазонов IP-адресов клиентов, вы можете использовать директивы allow и deny вместе, чтобы разрешить доступ к сайту или приложению только с этих адресов. Например, вы можете ограничить доступ только адресами в определенной локальной сети:
1 2 3 4 5 | location / { allow 192.168.1.0/24; deny all; # ... } |
Здесь директива deny all блокирует все IP-адреса клиентов, которые не входят в диапазон, указанный директивой allow.
Использование кэширования для сглаживания скачков трафика
Вы можете настроить NGINX и NGINX Plus на поглощение значительной части всплеска трафика, возникающего в результате атаки, включив кэширование и установив определенные параметры кэширования для разгрузки запросов с бэкенда. Вот некоторые из полезных параметров:
- Параметр обновления в директиве proxy_cache_use_stale указывает NGINX, что когда ему нужно получить обновление устаревшего кэшированного объекта, он должен отправить только один запрос на обновление и продолжать обслуживать устаревший объект клиентам, которые запрашивают его в течение времени, необходимого для получения обновления от внутреннего сервера. Когда повторные запросы на определенный файл являются частью атаки, это значительно сокращает количество запросов к внутренним серверам.
- Ключ, определяемый директивой proxy_cache_key, обычно состоит из встроенных переменных (ключ по умолчанию, $scheme$proxy_host$request_uri, имеет три переменные). Если значение включает переменную $query_string, то атака, посылающая случайные строки запросов, может вызвать чрезмерное кэширование. Мы рекомендуем не включать переменную $query_string в ключ, если у вас нет особых причин для этого.
Блокирование запросов
Вы можете настроить NGINX на блокировку нескольких видов запросов:
- Запросы к определенному URL, который кажется целевым.
- Запросы, в которых заголовок User-Agent установлен в значение, не соответствующее нормальному клиентскому трафику
- Запросы, в которых заголовок Referer имеет значение, которое может быть связано с атакой
- Запросы, в которых другие заголовки имеют значения, которые могут быть связаны с атакой.
Например, если вы определили, что DDoS-атака направлена на URL /foo.php, вы можете заблокировать все запросы к этой странице:
1 2 3 | location /foo.php { deny all; } |
Или если вы обнаружите, что запросы DDoS-атаки имеют в заголовке User-Agent значение foo или bar, вы можете заблокировать эти запросы.
1 2 3 4 5 6 | location / { if ($http_user_agent ~* foo|bar) { return 403; } # ... } |
Переменная http_name ссылается на заголовок запроса, в приведенном выше примере - на заголовок User-Agent. Аналогичный подход можно использовать и с другими заголовками, значения которых могут быть использованы для идентификации атаки.
Ограничение количества подключений к внутренним серверам
Экземпляр NGINX или NGINX Plus обычно может обрабатывать гораздо больше одновременных соединений, чем внутренние серверы, на которые он балансирует нагрузку. С помощью NGINX Plus вы можете ограничить количество соединений с каждым внутренним сервером. Например, если вы хотите ограничить NGINX Plus установлением не более 200 подключений к каждому из двух внутренних серверов в группе upstream веб-сайта:
1 2 3 4 5 | 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, применяемый к каждому серверу, определяет максимальное количество соединений. Директива queue ограничивает количество запросов в очереди, когда все серверы в группе upstream достигнут своего лимита соединений, а параметр timeout определяет время нахождения запроса в очереди.
Борьба с атаками на основе диапазона
Один из методов атаки заключается в отправке заголовка Range с очень большим значением, что может привести к переполнению буфера. Обсуждение того, как использовать NGINX для защиты от этого типа атак на примере.
Обработка высоких нагрузок
DDoS-атаки обычно приводят к высокой нагрузке на трафик. Советы по настройке NGINX и операционной системы, чтобы система могла выдерживать более высокие нагрузки, см. в разделе Настройка NGINX для повышения производительности.
Резюме
NGINX могут использоваться как ценная часть решения по снижению DDoS-атак.