Введение: что такое модуль stream и когда он нужен
Модуль stream в Nginx предназначен для работы с TCP и UDP трафиком на 4-м уровне модели OSI. В отличие от HTTP-модуля, он не анализирует заголовки запросов, cookies или URI. Его задача - принимать входящие соединения, устанавливать соединения с бэкендами и передавать байты в обе стороны с минимальными накладными расходами. Модуль доступен в стандартной поставке Nginx с версии 1.9.0 и не требует отдельной компиляции.
Типовые сценарии использования модуля stream: прокси для баз данных (MySQL, PostgreSQL), балансировка кэширующих систем (Redis, Memcached), организация отказоустойчивого доступа к почтовым серверам (SMTP, IMAP), проксирование DNS-запросов и любого другого трафика, который не является HTTP.
Минимальная рабочая конфигурация выглядит так:
stream {
server {
listen 3306;
proxy_pass 192.168.1.10:3306;
}
}
Эти четыре строки забирают TCP-соединения с порта 3306 и перенаправляют их на сервер 192.168.1.10:3306. Никакой дополнительной логики не требуется. Если вам нужна более сложная маршрутизация TCP/UDP трафика, сравнение подходов с HAProxy и готовые конфигурации с SSL-терминацией разобраны в руководстве по балансировке на уровне L4.
Базовая конфигурация TCP/UDP прокси
Конфигурация модуля stream размещается в блоке stream {}, который находится на одном уровне с блоками http {} и events {} в файле nginx.conf. Внутри блока stream определяются серверы (server {}), которые слушают порты и проксируют трафик.
Директива listen: порты и протоколы
Директива listen определяет, на каком IP-адресе и порту Nginx принимает соединения. Для TCP синтаксис стандартный, для UDP необходимо явно указать протокол.
Синтаксис:
listen адрес:порт [udp];
Примеры:
listen 3306;- принимать TCP-соединения на порту 3306 на всех интерфейсах;listen 53 udp;- принимать UDP-датаграммы на порту 53;listen 127.0.0.1:11211;- принимать TCP-соединения только на loopback-интерфейсе, порт 11211;listen 10.0.0.1:5432;- привязка к конкретному IP-адресу.
Ошибка с UDP - одна из самых частых. Если не указать ключевое слово udp, Nginx будет ожидать TCP-соединения, и DNS-запросы или syslog-сообщения не дойдут до бэкенда.
Директива proxy_pass: куда отправлять трафик
Директива proxy_pass указывает адрес, на который Nginx будет проксировать входящие соединения. Можно передать IP-адрес с портом, имя upstream-группы или переменную.
Синтаксис:
proxy_pass адрес;
Примеры:
proxy_pass backend_mysql;- отправка трафика в upstream-группу backend_mysql;proxy_pass 192.168.1.10:3306;- проксирование на конкретный сервер;proxy_pass $backend;- динамический выбор бэкенда через переменную (например, на основе IP-адреса клиента через map).
Использование переменных в proxy_pass даёт гибкость: можно направить разных клиентов на разные бэкенды без изменения upstream-групп. Переменная вычисляется при каждом новом соединении.
Балансировка нагрузки с upstream
Upstream-группа в stream определяет пул серверов, между которыми Nginx распределяет входящие соединения. Директива upstream размещается внутри блока stream. Методы балансировки идентичны тем, что используются в HTTP-модуле, и выбираются под характер трафика конкретного сервиса.
Round-robin: равномерное распределение
Метод по умолчанию. Соединения распределяются между серверами последовательно, по кругу. Подходит для сервисов с короткоживущими соединениями и примерно одинаковой нагрузкой на каждый запрос.
stream {
upstream dns_servers {
server 10.0.0.1:53;
server 10.0.0.2:53;
server 10.0.0.3:53;
}
server {
listen 53 udp;
proxy_pass dns_servers;
}
}
Этот пример распределяет DNS-запросы между тремя серверами. Каждый новый UDP-датаграммный сеанс уходит на следующий сервер в списке.
Least_conn: для долгоживущих соединений
Метод least_conn отправляет новое соединение на сервер с наименьшим количеством активных соединений. Приоритетен для баз данных и других сервисов, где клиенты держат постоянные соединения.
stream {
upstream postgres_cluster {
least_conn;
server db1:5432;
server db2:5432;
server db3:5432;
}
server {
listen 5432;
proxy_pass postgres_cluster;
}
}
PostgreSQL использует модель с отдельными соединениями на клиента. Если один сервер обрабатывает 50 соединений, а другой 5, least_conn направит нового клиента на второй сервер. Это предотвращает перегрузку отдельных узлов кластера.
Ip_hash: привязка клиента к серверу
Метод ip_hash вычисляет хэш от IP-адреса клиента и направляет все соединения с одного адреса на один и тот же бэкенд. Полезен для stateful-сервисов, где важна сессионная привязка.
stream {
upstream redis_stateful {
ip_hash;
server redis1:6379;
server redis2:6379;
}
server {
listen 6379;
proxy_pass redis_stateful;
}
}
Предупреждение: ip_hash теряет эффективность, если клиенты находятся за NAT или общим прокси. Все пользователи офиса с одним внешним IP попадут на один сервер, создавая неравномерную нагрузку. В таких случаях лучше использовать least_conn или рассмотреть альтернативные прокси-решения.
Мониторинг и отказоустойчивость
Модуль stream не имеет встроенных активных health check в open-source версии Nginx. Активные проверки доступны в Nginx Plus или через сторонние патчи. Базовая версия полагается на пассивные проверки и резервные серверы.
Пассивные проверки: max_fails и fail_timeout
Пассивные проверки работают на основе неудачных попыток соединения. Параметры max_fails и fail_timeout задают порог отказов и время изоляции проблемного сервера.
stream {
upstream mysql_production {
server db1:3306 max_fails=3 fail_timeout=30s;
server db2:3306 max_fails=3 fail_timeout=30s;
server db3:3306 max_fails=3 fail_timeout=30s;
}
server {
listen 3306;
proxy_pass mysql_production;
}
}
Логика работы: если Nginx трижды не может подключиться к db1, он помечает сервер как недоступный на 30 секунд. Трафик уходит на db2 и db3. Через 30 секунд Nginx пробует снова. Если соединение успешно, сервер возвращается в пул. Этот механизм защищает клиентов от guaranteed fail при отказе бэкенда.
Резервные серверы: backup
Сервер, помеченный как backup, получает трафик только тогда, когда все основные серверы недоступны. Это классический сценарий для катастрофоустойчивости.
stream {
upstream smtp_ha {
server mail1:25 max_fails=2 fail_timeout=10s;
server mail2:25 max_fails=2 fail_timeout=10s;
server mail_dr:25 backup;
}
server {
listen 25;
proxy_pass smtp_ha;
}
}
В нормальном режиме работают mail1 и mail2. Если оба отказали, трафик уходит на mail_dr - сервер в другом дата-центре или с меньшей производительностью, который обеспечивает непрерывность сервиса.
Зона состояния: zone
Директива zone создаёт разделяемую область памяти для хранения состояния серверов upstream-группы. Это необходимо для сбора статистики и корректной работы параметров max_fails и fail_timeout в конфигурациях с несколькими рабочими процессами.
stream {
upstream redis_monitored {
zone redis_zone 64k;
least_conn;
server redis1:6379;
server redis2:6379;
server redis3:6379;
}
server {
listen 6379;
proxy_pass redis_monitored;
}
}
Размер зоны 64 КБ достаточен для отслеживания десятков серверов. Статистику из зоны можно получить через API Nginx Plus или через stub_status при мониторинге производительности. Для глубокого контроля состояния бэкендов с визуализацией в Grafana используйте руководство по мониторингу upstream с health checks.
Логирование и отладка
Модуль stream поддерживает собственные директивы access_log и error_log, независимые от HTTP-логов. Это позволяет отделить записи о TCP/UDP соединениях от веб-трафика и настроить формат под конкретные нужды.
Настройка access_log
Лог соединений включается директивой access_log в контексте stream или server. Можно использовать предопределённые форматы или создать свой.
stream {
log_format stream_log '$remote_addr [$time_local] $protocol $status '
'$bytes_sent $bytes_received $session_time';
access_log /var/log/nginx/stream.log stream_log;
server {
listen 3306;
proxy_pass mysql_backend;
}
}
Переменные, доступные в формате stream:
$remote_addr- IP-адрес клиента;$time_local- локальное время соединения;$protocol- протокол (TCP или UDP);$status- статус соединения (200 - успех, 502 - ошибка бэкенда);$bytes_sent- количество отправленных клиенту байт;$bytes_received- количество полученных от клиента байт;$session_time- длительность сессии в секундах с миллисекундной точностью.
Использование error_log для диагностики
Уровень логирования ошибок настраивается от warn до debug. Debug-уровень включает максимально детальную информацию о каждом соединении, но генерирует огромный объём данных.
stream {
error_log /var/log/nginx/stream_error.log debug;
server {
listen 5432;
proxy_pass pg_backend;
}
}
Используйте debug только для поиска проблем на тестовом окружении. В production достаточно уровня warn или error. После завершения отладки верните уровень логирования обратно - переполнение диска логами способно остановить сервер.
Production-кейсы: готовые конфигурации
Следующие конфигурации проверены на Nginx версий 1.26–1.28 в 2026 году и готовы к использованию после замены IP-адресов на ваши.
Прокси для MySQL
Единая точка входа для кластера MySQL с балансировкой по наименьшему числу соединений и пассивными проверками.
stream {
upstream mysql {
least_conn;
server db1:3306 max_fails=3 fail_timeout=30s;
server db2:3306 max_fails=3 fail_timeout=30s;
server db3:3306 max_fails=3 fail_timeout=30s;
}
server {
listen 3306;
proxy_pass mysql;
proxy_connect_timeout 5s;
proxy_timeout 300s;
}
}
Параметр proxy_connect_timeout ограничивает время ожидания подключения к бэкенду пятью секундами. Если сервер не отвечает, соединение быстро перебрасывается на другой узел. proxy_timeout задаёт максимальную длительность неактивного соединения - 300 секунд достаточно для большинства приложений.
Прокси для PostgreSQL
Аналогичная конфигурация для PostgreSQL на порту 5432.
stream {
upstream postgresql {
least_conn;
server pg1:5432 max_fails=2 fail_timeout=15s;
server pg2:5432 max_fails=2 fail_timeout=15s;
server pg3:5432 max_fails=2 fail_timeout=15s;
}
server {
listen 5432;
proxy_pass postgresql;
proxy_connect_timeout 3s;
}
}
PostgreSQL использует отдельные долгоживущие соединения, поэтому least_conn здесь работает эффективно. Быстрый fail_timeout в 15 секунд ускоряет восстановление после кратковременных сбоев.
Балансировка Redis
Распределение нагрузки между экземплярами Redis с least_conn.
stream {
upstream redis_cluster {
least_conn;
server redis1:6379 max_fails=3 fail_timeout=20s;
server redis2:6379 max_fails=3 fail_timeout=20s;
server redis3:6379 max_fails=3 fail_timeout=20s;
}
server {
listen 6379;
proxy_pass redis_cluster;
proxy_timeout 600s;
}
}
Важное ограничение: модуль stream не анализирует протокол Redis. Он не может маршрутизировать запросы по ключу или слоту. Для шардирования на уровне приложения используйте клиентские библиотеки Redis Cluster. Stream обеспечивает только балансировку TCP-соединений между экземплярами.
Балансировка Memcached
Настройка для Memcached аналогична Redis.
stream {
upstream memcached_pool {
least_conn;
server mem1:11211 max_fails=2 fail_timeout=10s;
server mem2:11211 max_fails=2 fail_timeout=10s;
server mem3:11211 max_fails=2 fail_timeout=10s;
}
server {
listen 11211;
proxy_pass memcached_pool;
proxy_connect_timeout 1s;
}
}
Memcached-соединения обычно короткие, поэтому агрессивный fail_timeout в 10 секунд и быстрое переключение уместны.
Отказоустойчивый доступ к SMTP и IMAP
Обеспечение высокой доступности почтовых серверов с резервным узлом.
stream {
upstream smtp {
server mail1:25 max_fails=2 fail_timeout=30s;
server mail2:25 max_fails=2 fail_timeout=30s;
server mail_backup:25 backup;
}
upstream imap {
server mail1:143 max_fails=2 fail_timeout=30s;
server mail2:143 max_fails=2 fail_timeout=30s;
server mail_backup:143 backup;
}
server {
listen 25;
proxy_pass smtp;
proxy_connect_timeout 10s;
}
server {
listen 143;
proxy_pass imap;
proxy_connect_timeout 10s;
}
}
Резервный сервер mail_backup вступает в работу только при полном отказе основных. Это может быть менее мощный сервер в другом дата-центре, который поддерживает работу почты в аварийном режиме.
Ограничения и подводные камни
Модуль stream работает на 4-м уровне OSI и не анализирует протоколы прикладного уровня. Нельзя маршрутизировать соединения по HTTP-заголовкам, Redis-ключам или SQL-запросам. Для сложной маршрутизации на 7-м уровне потребуется HTTP-модуль Nginx или специализированные прокси вроде Envoy.
Метод ip_hash даёт сбой при массовом использовании NAT. Все клиенты за одним публичным IP попадают на один бэкенд. Решение: переключиться на least_conn или использовать Nginx Plus с sticky-сессиями.
UDP требует явного указания протокола в директиве listen. Пропуск ключевого слова udp - частая ошибка при настройке DNS или syslog прокси. Nginx будет молча ожидать TCP-соединения, и трафик не дойдёт до бэкенда.
Активные health check отсутствуют в open-source версии. Пассивные проверки через max_fails и fail_timeout реагируют только на факт отказа соединения, но не на деградацию сервиса (например, медленные ответы). Для проактивного мониторинга рассмотрите Nginx Plus или внешние инструменты.
Готовые конфигурации для типовых задач с комментариями собраны в подборке рабочих конфигураций Nginx для 2026 года. Если вы настраиваете веб-часть сервера параллельно с stream, используйте разбор структуры nginx.conf с практическими примерами.
Заключение: когда стоит использовать модуль stream
Модуль stream - оптимальный выбор, когда нужно проксировать или балансировать не-HTTP трафик в инфраструктуре, где уже используется Nginx. Единая конфигурация для HTTP и TCP/UDP упрощает управление, а производительность stream сопоставима с HAProxy на сопоставимом железе.
Используйте stream для:
- проксирования баз данных (MySQL, PostgreSQL, MongoDB);
- балансировки кэшей (Redis, Memcached);
- отказоустойчивого доступа к почтовым серверам (SMTP, IMAP, POP3);
- проксирования DNS (UDP) и syslog;
- любого TCP/UDP трафика, где не нужен анализ содержимого пакетов.
Рассмотрите альтернативы, если требуется сложная маршрутизация на 7-м уровне, content-based switching или активные health check в open-source. В этих случаях подойдут HAProxy (богаче health check) или Envoy (для service mesh).
Для развёртывания отказоустойчивой инфраструктуры с Nginx stream на облачных серверах подойдёт Timeweb Cloud с гибким масштабированием VDS и управляемыми базами данных. Если вы автоматизируете генерацию конфигураций или документации, обратите внимание на AiTunnel - агрегатор API для доступа к GPT и Claude без VPN с оплатой в рублях.