Nginx — пока еще один из самых популярных веб-серверов, и ключевой компонент современной корпоративной архитектуры. В этой статье мы рассмотрим базовые параметры конфигурации (доступные "из коробки"), которые упрощают мониторинг, улучшают производительность и усиливают безопасность — в конечном итоге повышая устойчивость вашей инфраструктуры.
Логирование в формате JSON
JSON — лучший выбор формата для логов Nginx по двум основным причинам. Во-первых, он гораздо более читаем для человека. Во-вторых, передача логов в такие системы, как OpenSearch, для последующего мониторинга или в рамках SIEM-решений становится сильно проще.
Вот простой пример из nginx.conf:
log_format json-logger escape=json '{
"type": "access-log",
"time": "$time_iso8601",
"remote-ip": "$remote_addr",
"x-forward-for": "$proxy_add_x_forwarded_for",
"request-id": "$request_id",
"request-length": "$request_length",
"response-bytes": "$bytes_sent",
"response-body-size": "$body_bytes_sent",
"status": "$status",
"vhost": "$host",
"protocol": "$server_protocol",
"path": "$uri",
"query": "$args",
"duration": "$request_time",
"backend-duration": "$upstream_response_time",
"backend-status": "$upstream_status",
"method": "$request_method",
"referer": "$http_referer",
"user-agent": "$http_user_agent",
"active-connections": "$connections_active"
}';
access_log /var/log/nginx/access.log json-logger;
Это приведёт к следующему выводу в файле access.log:
{
"type": "access-log",
"time": "2025-02-25T16:02:54+00:00",
"remote-ip": "130.61.78.239",
"x-forward-for": "130.61.78.239",
"request-id": "38750f2a1a51b196fa0a76025b0d1be9",
"request-length": "258",
"response-bytes": "353",
"response-body-size": "167",
"status": "404",
"vhost": "3.69.78.187",
"protocol": "HTTP/1.1",
"path": "/lib/phpunit/Util/PHP/eval-stdin.php",
"query": "",
"duration": "0.016",
"backend-duration": "0.016",
"backend-status": "404",
"method": "GET",
"referer": "",
"user-agent": "Custom-AsyncHttpClient",
"active-connections": "1"
}
Параметризация запросов
Большие размеры тела запроса, длительные тайм-ауты и чрезмерно увеличенные настройки KeepAlive могут негативно повлиять на производительность. Чтобы повысить эффективность, лучше устанавливать эти параметры на минимально возможные значения — при этом, само собой, соблюдая требования вашего приложения.
client_max_body_size 10M;
client_body_timeout 10s;
client_header_timeout 10s;
keepalive_timeout 5s 5s;
Определяет максимальный размер тела HTTP-запроса, который клиент может отправить. Если лимит превышен, Nginx возвращает ошибку 413 Request Entity Too Large.
Задает максимальное время ожидания полного тела запроса. Если за это время тело не получено, соединение будет закрыто.
Устанавливает максимальное время ожидания полного заголовка HTTP-запроса от клиента. Если лимит превышен — соединение также закрывается.
Определяет, как долго будет оставаться открытым соединение Keep-Alive после последнего запроса.
Первый параметр (например, 5s) задаёт тайм-аут на стороне сервера. Второй (опциональный) параметр передаётся клиенту как предложение о том, как долго он может держать соединение открытым.
Ограничение количества запросов
На случай если клиент пытается перегрузить веб-сервер частыми запросами, Nginx предоставляет возможность настроить "зоны ограничения запросов" (limit request zones) — для контроля трафика по различным параметрам.
Пример настройки (реверс-прокси с зоной ограничения запросов):
limit_req_zone $binary_remote_addr zone=limitreqsbyaddr:20m rate=15r/s;
limit_req_status 429;
upstream app.localhost {
server localhost:8080;
}
server {
listen 443 ssl;
server_name app.devlab.intern;
location / {
limit_req zone=limitreqsbyaddr burst=10;
proxy_pass http://app.localhost;
}
}
Используется для настройки зоны ограничения по IP-адресу клиента. Адрес сохраняется в бинарной форме (это снижает потребление памяти).
Создаёт общую (shared) область памяти объёмом 20 МБ с именем limitreqsbyaddr. В этой зоне хранятся данные о лимитах для разных IP-адресов.
Ограничивает количество запросов до 15 запросов в секунду на IP. Превышение лимита приводит к отклонению избыточных запросов.
При превышении лимита Nginx возвращает статус 429 Too Many Requests, что означает: "Слишком много запросов за короткое время".
Эта конфигурация помогает защитить сервисы от перегрузки и злоупотреблений.
Ограничение только на необходимые HTTP-методы
На мой взгляд, ограничение допустимых HTTP-методов только теми, которые действительно необходимы или поддерживаются приложением (например, REST API), — это чистый и логичный способ синхронизации настроек веб-сервера с логикой приложения. Это помогает не только предотвратить неправильное использование API или вызов нежелательных методов, но и блокирует потенциально опасные запросы вроде TRACE. Кроме того, это снижает ненужную нагрузку на сервер, устраняя неподдерживаемые или неуместные запросы.
Пример: разрешён только метод GET (HEAD разрешается по умолчанию):
# HEAD is implicit
limit_except GET {
deny all;
}
Пример: разрешить все методы, кроме TRACE и PATCH:
if ($request_method ~ ^(PATCH|TRACE)$) {
return 405;
}
Простая защита от ботов
Если на сервер поступают запросы от ботов или плохо сконфигурированных сканеров (часто с «говорящими» user-agent'ами), можно внести путаницу и затруднить их работу, возвращая нестандартный статус HTTP от самого Nginx.
Для этого создаём файл bot.protection.conf в директории /etc/nginx/snippets со следующим содержимым:
map $http_user_agent $blacklist_user_agents {
~*wpscan 1;
~*dirbuster 1;
~*gobuster 1;
}
Вы можете дополнять список по мере необходимости.
Внутри конфигурации виртуального хоста (VHost) подключите файл следующим образом:
include /etc/nginx/snippets/bot.protection.conf;
if ($blacklist_user_agents) {
return 444;
}
HTTP 444 также можно «весело» использовать для предотвращения угадывания служебных файлов, таких как .env:
# <your-domain>/.bash_history for example ends with HTTP 444.
location ~ /\. {
return 444;
}
HTTP 444 — это нестандартизированный статус-код, используемый в NGINX, который заставляет сервер мгновенно закрыть соединение без отправки заголовков ответа клиенту. Чаще всего используется для отклонения вредоносных или некорректно оформленных запросов. Интересный побочный эффект: некоторые сканеры не умеют корректно обрабатывать такие ответы, что добавляет дополнительный уровень защиты.
Включение TCP Fast Open
TCP Fast Open — это важное улучшение в Nginx, которое позволяет более эффективно устанавливать TCP-соединения. Эта функция даёт возможность начать передачу данных уже во время начального рукопожатия, что заметно ускоряет процесс установления соединения. Особенно полезна она в условиях высокой сетевой задержки, так как помогает сократить латентность и повысить производительность.
Проверка поддержки TCP Fast Open в ядре Linux
Выполните следующую команду:
cat /proc/sys/net/ipv4/tcp_fastopen
Если в ответе вернётся 1, функция уже включена. Если нет — включите её командой:
echo 1 > /proc/sys/net/ipv4/tcp_fastopen
Использование в конфигурации Nginx
Добавьте параметр fastopen в директивы listen:
listen [::]:443 ssl http2 fastopen=500;
listen 443 ssl http2 fastopen=500;
Число 500 — это количество подключений, которые могут использовать TCP Fast Open одновременно (значение можно адаптировать под вашу нагрузку).
Сжатие с помощью GZip
GZip — это метод сжатия данных, позволяющий уменьшить размер файлов. При этом исходные данные можно полностью восстановить путём распаковки («разархивирования») сжатого файла.
Для веб-приложений и сайтов GZip особенно важен, поскольку HTTP-протокол поддерживает передачу данных в сжатом виде до того, как они попадут в сеть.
Снижение трафика: при включённом GZip размер передаваемых файлов уменьшается, что приводит к меньшему потреблению пропускной способности.
Экономия на хостинге: меньше трафика — ниже затраты на обслуживание.
Ускорение загрузки для пользователей: посетители получают более лёгкие файлы, что сокращает время загрузки страниц.
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
Эта настройка включает GZip и указывает типы содержимого, которые следует сжимать (текст, CSS, JavaScript, XML, JSON и др.).