Что такое Nginx
Nginx — это веб- и прокси-сервер с открытым исходным кодом для обслуживания статических и динамических веб-сайтов. Он способен балансировать нагрузку, ускорять обработку запросов и повышать общую надежность веб-приложений.
Сервер Nginx популярен во всем мире и используется крупными компаниями, включая Netflix, ВКонтакте, 2ГИС, WordPress и другими. Также Nginx является ключевым компонентом многих технологических стеков, используемых в веб-разработке и веб-хостинге. Один из распространенных способов применения — в качестве веб-сервера для размещения сайта.
Помимо этого, Nginx обладает рядом функций, которые пользователи могут использовать для защиты своего веб-ресурса от DDoS-атак:
- Ограничение скорости запросов. Поможет снизить нагрузку на сервер и предотвратить DDoS-атаки, основанные на отправке большого количества запросов от одного и того же источника.
- Балансировка нагрузки. Распределит нагрузку между несколькими серверами и поможет снизить риск отказа всей системы при атаке на один сервер.
- Отказ от подключения. Способствует предотвращению DDoS-атак, которые основаны на установлении большого количества подключений к серверу.
- Сокращение времени соединения. Закроет неактивные соединения и снизит риск DDoS-атак, основанных на удержании открытых соединений.
- Управление буферизацией. Минимизирует риск DDoS-атак, основанных на отправке больших объемов данных.
Далее в статье каждый из пунктов разберем подробнее с примерами конфигураций и директив. Чтобы использовать все описанные решения, загрузите последнюю версию Nginx для вашей операционной системы на официальном сайте компании.
Все перечисленные функции помогают использовать Nginx в качестве средства для борьбы со многими видами DDoS-атак, однако для полноценной защиты от них стоит использовать профессиональные anti-DDoS решения.
Как защититься от DDoS-атак с помощью Nginx
1. Ограничение скорости обработки запросов
Для ограничения обработки запросов Nginx использует алгоритм под названием «дырявое ведро» (англ.«leaky bucket»). В данном случае ведро — это буфер, который имеет ограниченную емкость. Когда запросы поступают на сервер, они добавляются в ведро. Затем, запросы обрабатываются с определенной скоростью, не превышающей предел обработки сервера. Это один из методов управления трафиком, который можно использовать для защиты от DDoS-атак и обеспечения стабильной обработки запросов на сервере.
Чтобы настроить ограничение скорости, следует использовать две основные директивы: limit_req_zone и limit_req.
Директива limit_req_zone используется для создания зоны ddos_limit, в которой будет храниться информация о запросах от каждого уникального IP-адреса. Размер зоны определяется параметром 10m, что означает использование 10 мегабайт памяти для хранения информации о запросах. Пример:
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s; server { location /login/ { limit_req zone=mylimit; proxy_pass http://my_upstream; } } |
В данном примере $binary_remote_addr используется для идентификации клиентского IP-адреса, который является ключом в зоне ограничения. Зона будет использоваться для ограничения скорости запросов до 10 запросов в секунду (10r/s). Далее с помощью директивы server { ... } определяется блок настроек для конкретного сервера. Ограничение запросов будет регулировать location /login/ { ... }.
Внутри указанной локации mylimit директива limit_req zone=mylimit активирует ограничение запросов для зоны. Она регулирует запросы к URL-адресам. Все, которые начинаются с «/login/» — будут ограничены в соответствии с настройками.
Директива proxy_pass http://my_upstream — задает прокси-сервер, на который будут идти запросы после прохождения ограничения. В примере запросы будут передаваться на «my_upstream», — здесь следует указать реальный адрес сервера-приемника.
2. Балансировка нагрузки
Nginx в качестве прокси-сервера может использовать базовую конфигурацию для балансировки нагрузки между несколькими серверами. Пример конфигурации:
http { server { location / { |
В этом примере на служебных записях DNS srv1, srv2 и srv3 запущены 3 экземпляра одного и того же приложения. Без настройки данный метод балансировки будет по умолчанию использовать циклический перебор. Nginx использует балансировку нагрузки HTTP для распределения запросов, которые проксируются к группе серверов myapp1. Чтобы реализовать обратное прокси в nginx, следует настроить балансировку для HTTPS вместо HTTP. Для этого в качестве протокола используйте «https».
3. Отказ от подключения
Для ограничения количества одновременных подключений в Nginx можно использовать директиву limit_conn. Она позволяет задать лимиты не только к определенному серверу, но и контексту. Пример полной конфигурации для ограничения количества одновременных подключений:
upstream api_service { server { limit_conn limitconnbyaddr 50; #include snippets/error_pages.conf; proxy_set_header X-Real-IP $remote_addr; |
В этом примере была использована директива limit_conn_zone для создания зоны ограничения подключений с именем conn_limit_per_ip. Для этого используется переменная $binary_remote_addr, чтобы идентифицировать каждый уникальный IP-адрес, который подключается к серверу.
Затем следует задать ограничение с помощью директивы limit_conn, где будет указано имя зоны conn_limit_per_ip и максимальное количество одновременных подключений, равное 10.
С помощью директив задаем ограничение на количество одновременных подключений к серверу. Если количество подключений превышает заданный лимит, то Nginx будет возвращать ошибку 503 «Service Unavailable» клиентам, которые пытаются подключиться к серверу.
4. Сокращение времени соединения
Для сокращения времени соединения в Nginx есть несколько директив и конфигураций. Рассмотрим три из них — включение keep-alive соединений, сжатие и кэширование.
Включение keep-alive соединений
Keep-alive соединения позволяют клиенту и серверу устанавливать одно TCP-соединение и использовать его для множества последовательных HTTP-запросов и ответов вместо установки нового соединения для каждого запроса. Это значительно улучшает производительность и уменьшает нагрузку на сервер.
Рассмотрим одну из директив, которая определяет время ожидания соединения keep-alive между Nginx и клиентом — keepalive_timeout. Директива устанавливает время в секундах, в течение которого соединение keep-alive может оставаться открытым, ожидая новых запросов от клиента. Если в течение этого времени не было нового запроса, соединение будет закрыто.
Пример использования:
http { ... keepalive_timeout 60s; } |
В данном примере, keepalive_timeout установлен в 60 секунд. Это означает, что соединение keep-alive может оставаться открытым в течение 60 секунд после последнего запроса от клиента.
Значение keepalive_timeout следует выбирать с учетом потребностей вашего приложения и среды. Слишком короткое время тайм-аута приводит к частым закрытиям и повторным установкам соединений, что может увеличить нагрузку на сервер.
Важно отметить, что конфигурация keep-alive может различаться в зависимости от требований вашего приложения, версии Nginx и других факторов. Рекомендуется ознакомиться с документацией Nginx и учесть специфику вашей среды перед применением конфигурации.
Включение сжатия
Nginx по умолчанию сжимает запросы типа text/html. Сжатие позволяет уменьшить размер передаваемых данных, что существенно ускоряет их передачу и сокращает время соединения. Пример конфигурации:
server { gzip on; gzip_types text/plain application/xml; gzip_proxied no-cache no-store private expired auth; gzip_min_length 1000; ... } |
Эта директива имеет ряд параметров, которые определяют, какие типы прокси-запросов Nginx следует сжимать. Например, ее можно настроить таким образом, чтобы сжимались только те ответы на запросы, которые не будут кэшироваться на прокси-сервере. Для этого используйте параметры директивы gzip_proxied, которые будут проверять Cache-Control поле заголовка в ответе и сжимать ответ, если значение равно no-cache, no-store или private.
Помимо этого важно включить параметр expired для проверки значения поля заголовка Expires. Чтобы настроить возможность сжатия других типов прокси-запросов, включите директиву gzip_types и перечислите их. Чтобы указать минимальную длину ответа для сжатия, используйте директиву gzip_min_length. Значение по умолчанию равно 20 байтам (в примере конфигурации скорректировано на 1000). Используйте gzip_proxied для настройки сжатия прокси-запросов.
Использование кэширования
Кэширование позволяет сохранять копии ранее запрошенных ресурсов и возвращать их без повторного выполнения запроса. Эти действия помогают ускорить время соединения и ответа. Пример конфигурации:
proxy_cache_path /data/nginx/cache keys_zone=cache_zone:10m; map $request_method $purge_method { server { |
Для этого примера была использована директива proxy_cache_path для создания кэша статических ресурсов. Чтобы задать размер кэша вводим keys_zone=static_cache:10m, он должен быть равен 10 мегабайтам. Переменная $purge_method сбрасывает кэш и по умолчанию равна нулю. Таким образом Nginx работает в обычном режиме и сохраняет ответы от бэкенда. Если метод запроса — «PURGE», переменной будет присвоено значение «1», в противном случае — «0». Proxy_cache_purge $purge_method; указывает на то, что кэш должен быть очищен при выполнении запроса с методом «PURGE». Значение переменной $purge_method определяет, является ли текущий запрос запросом на очистку кэша или нет.
5. Управление буферизацией
Буферизация в Nginx включена по умолчанию. Если вы хотите отключить эту функцию или настроить под индивидуальные параметры, потребуется выполнить ряд действий.
- Чтобы отключить буферизацию в Nginx используйте директиву proxy_buffering с параметром off.
- Чтобы настроить размер буфера для проксируемых ответов от сервера используйте директиву proxy_buffer_size. По умолчанию значение proxy_buffer_size равно 4K или 8K, в зависимости от версии Nginx и используемого модуля проксирования. Однако, вы можете изменить это значение в соответствии с вашими требованиями. Чтобы избежать частой ошибки «502 Bad Gateway» — значение для proxy_buffer_size должно быть не меньше максимально возможного размера HTTP-заголовков ответа, которые поступают из вашего веб-ресурса.
Веб-серверы сами по себе не являются средствами защиты от вредоносного трафика. Однако их инструменты и программные решения могут помочь в предотвращении или смягчении последствий DDoS-атак. В следующих статьях рассмотрим защитные решения по настройке Apache, Lighttpd и других серверов.
Важно отметить, что защита от DDoS-атак требует комплексного подхода, который включает не только самостоятельное использование вспомогательных инструментов или правильную настройку веб-серверов, а в целом основывается на использовании специализированных защитных решений.