Потоковый модуль#
Базовый потоковый модуль реализует основную функциональность для обработки TCP- и UDP-соединений: это определение серверных блоков, маршрутизация трафика, настройка проксирования, поддержка SSL/TLS и управление подключениями для потоковых сервисов, таких как базы данных, DNS и другие протоколы, работающие на основе TCP и UDP.
Остальные модули этого раздела расширяют эту функциональность, позволяя гибко настраивать и оптимизировать работу потокового сервера под различные сценарии и требования.
При сборке из исходного кода модуль не собирается по умолчанию; его необходимо
включить с помощью параметра сборки
‑‑with‑stream.
В пакетах и образах из
наших репозиториев
модуль включен в сборку.
Пример конфигурации#
worker_processes auto;
error_log /var/log/angie/error.log info;
events {
worker_connections 1024;
}
stream {
upstream backend {
hash $remote_addr consistent;
server backend1.example.com:12345 weight=5;
server 127.0.0.1:12345 max_fails=3 fail_timeout=30s;
server unix:/tmp/backend3;
}
upstream dns {
server 192.168.0.1:53535;
server dns.example.com:53;
}
server {
listen 12345;
proxy_connect_timeout 1s;
proxy_timeout 3s;
proxy_pass backend;
}
server {
listen 127.0.0.1:53 udp reuseport;
proxy_timeout 20s;
proxy_pass dns;
}
server {
listen [::1]:12345;
proxy_pass unix:/tmp/stream.socket;
}
}
Директивы#
error_log_user_tag#
Добавлено в версии 1.12.0.
Добавляет тег, зависящий от сессии, в записи error_log. Значение может
содержать переменные. Директива может задаваться
несколько раз для добавления нескольких тегов. Теги используются в фильтрах
filter=tag: директивы error_log.
listen#
Изменено в версии 1.10.0.
| |
По умолчанию | — |
server |
Задает адрес и порт для сокета, на котором сервер будет принимать соединения. Можно указать только порт, и тогда Angie будет слушать на всех доступных IPv4-интерфейсах (и IPv6, если он включен). Кроме того, адрес может быть именем хоста, например:
listen 127.0.0.1:12345;
listen *:12345;
listen 12345; # то же, что и *:12345
listen localhost:12345;
IPv6-адреса задаются в квадратных скобках:
listen [::1]:12345;
listen [::]:12345;
Диапазоны портов задаются при помощи указания первого и последнего порта через дефис:
listen 127.0.0.1:12345-12399;
listen 12345-12399;
UNIX-сокеты задаются префиксом unix:
listen unix:/var/run/angie.sock;
Примечание
Разные серверы должны слушать на разных парах адрес:порт.
| указывает на то, что все соединения, принимаемые на данном слушающем сокете, должны работать в режиме SSL. |
| конфигурирует слушающий сокет для работы с датаграммами. Для обработки пакетов с одного адреса и порта в рамках одной сессии необходимо также указывать параметр reuseport. |
| указывает на то, что все соединения, принимаемые на данном порту, должны использовать протокол PROXY. |
В директиве listen можно также указать несколько дополнительных параметров, специфичных для связанных с сокетами системных вызовов.
| устанавливает связанную таблицу маршрутизации, FIB (параметр
|
| включает "TCP Fast Open" для слушающего сокета и ограничивает максимальную длину очереди соединений, которые еще не завершили процесс трехстороннего рукопожатия. Предупреждение Не включайте "TCP Fast Open", не убедившись, что сервер может адекватно обрабатывать многократное получение одного и того же SYN-пакета с данными. |
| задает параметр backlog в вызове listen(), который ограничивает максимальный размер очереди ожидающих приема соединений. По умолчанию backlog устанавливается равным -1 для FreeBSD, DragonFly BSD и macOS, и 511 для других платформ. |
| задает размер буфера приема (параметр SO_RCVBUF) для слушающего сокета. |
| задает размер буфера передачи (параметр SO_SNDBUF) для слушающего сокета. |
| задает имя принимающего фильтра (параметр |
| указывает использовать отложенный |
| указывает, что для данного слушающего сокета нужно делать bind()
отдельно. Это нужно потому, что если описаны несколько директив
|
| определяет (через параметр сокета |
| указывает, что нужно создавать отдельный слушающий сокет для каждого рабочего процесса (через параметр сокета SO_REUSEPORT для Linux 3.9+ и DragonFly BSD или SO_REUSEPORT_LB для FreeBSD 12+), позволяя ядру распределять входящие соединения между рабочими процессами. В настоящий момент это работает только на Linux 3.9+, DragonFly BSD и FreeBSD 12+. Предупреждение Ненадлежащее использование параметра reuseport может быть небезопасно. |
| включает прием соединений по протоколу Multipath TCP (MPTCP),
поддерживаемому в ядре Linux с версии 5.6.
Параметр несовместим с |
so_keepalive=on | off | [keepidle]:[keepintvl]:[keepcnt]
Конфигурирует для слушающего сокета поведение "TCP keepalive".
| если параметр опущен, для сокета будут действовать настройки операционной системы |
| для сокета включается параметр SO_KEEPALIVE |
| для сокета параметр SO_KEEPALIVE выключается |
Некоторые операционные системы поддерживают настройку параметров "TCP keepalive"
на уровне сокета посредством параметров TCP_KEEPIDLE, TCP_KEEPINTVL и
TCP_KEEPCNT. На таких системах их можно сконфигурировать с помощью параметров
keepidle, keepintvl и keepcnt. Один или два параметра могут быть опущены,
в таком случае для соответствующего параметра сокета будут действовать
стандартные системные настройки.
Например,
so_keepalive=30m::10
установит таймаут бездействия (TCP_KEEPIDLE) в 30 минут, для интервала проб (TCP_KEEPINTVL) будет действовать стандартная системная настройка, а счетчик проб (TCP_KEEPCNT) будет равен 10.
preread_buffer_size#
Задает размер буфера предварительного чтения.
preread_timeout#
Задает время фазы предварительного чтения.
proxy_protocol_timeout#
Задает время для завершения операции чтения заголовка протокола PROXY. Если по истечении этого времени заголовок полностью не получен, соединение закрывается.
resolver#
| |
По умолчанию |
|
stream, server, upstream |
Задает серверы DNS, используемые для преобразования имен вышестоящих серверов в адреса, например:
resolver 127.0.0.53 [::1]:5353;
Адрес может быть указан в виде доменного имени или IP-адреса, и необязательного порта. Если порт не указан, используется порт 53. Серверы DNS опрашиваются циклически.
Необходимо указать хотя бы один адрес DNS-сервера или параметр conf,
кроме формы resolver off;.
Примечание
Рекомендуется использовать локальный доверенный резолвер, например
127.0.0.53 (systemd-resolved), а не публичный (например, 8.8.8.8).
Публичные резолверы раскрывают DNS-запросы третьим сторонам и повышают
риск атак с подменой кэша.
Примечание
Значение директивы наследуется вложенными блоками и может быть переопределено в них при необходимости. В пределах одного блока директиву допустимо указывать только один раз; повторное указание является ошибкой конфигурации.
Директива включает разрешение DNS-имен для вышестоящих серверов, задаваемых через переменные или настроенных с параметром resolve, а также для прикрепления OCSP-ответов.
Помимо явно заданных адресов серверов директива распознает:
| явно отключает разрешение DNS-имен |
| считывает адреса DNS-серверов из указанного файла или из
|
Файл может содержать строки nameserver в том же формате, что
использует системный резолвер:
nameserver 127.0.1.4
nameserver 127.0.1.5
Адреса, считанные из файла, добавляются к адресам, заданным явно в
директиве, и все они затем опрашиваются совместно циклическим образом. Если
файл отсутствует, недоступен для чтения или не содержит адресов, а явно ни
один сервер не задан, используется сервер по умолчанию 127.0.0.1:53.
Angie перечитывает файл автоматически при его изменении, обновляя набор активных серверов.
По умолчанию Angie кэширует каждый ответ на время, заданное значением TTL в
DNS-ответе. Необязательный параметр valid позволяет это
переопределить:
| необязательный параметр, позволяет переопределить срок кэширования ответа |
resolver 127.0.0.53 [::1]:5353 valid=30s;
По умолчанию Angie будет искать как IPv4-, так и IPv6-адреса при преобразовании имен в адреса.
| запрещает поиск IPv4-адресов |
| запрещает поиск IPv6-адресов |
| необязательный параметр; включает сбор метрик запросов и ответов DNS-сервера (/status/resolvers/<зона>) в указанной зоне |
Совет
Для предотвращения DNS-спуфинга рекомендуется использовать DNS-серверы в защищенной доверенной локальной сети.
Совет
При запуске в Docker используйте соответствующий внутренний адрес DNS-сервера, например 127.0.0.11.
resolver_timeout#
Задает таймаут для преобразования имени в адрес, например:
resolver_timeout 5s;
server#
Задает конфигурацию для сервера.
server_name#
Задает имена виртуального сервера.
Предупреждение
В модуле stream директива server_name основана на Server Name
Indication (SNI) и работает только с TLS-соединениями. Для
использования необходимо настроить TLS-терминацию или
включить TLS preread в соответствующем блоке
server.
Пример конфигурации:
server {
listen 443 ssl;
server_name example.com www.example.com;
ssl_certificate /etc/angie/cert.pem;
ssl_certificate_key /etc/angie/key.pem;
}
Первое указанное имя становится основным именем сервера.
Имена серверов могут включать звездочку (*),
заменяющую первую или последнюю часть имени:
server {
server_name example.com *.example.com www.example.*;
}
Такие имена называются подстановочными (wildcard).
Также можно использовать регулярные выражения в именах серверов,
предваряя имя тильдой (~):
server {
server_name www.example.com ~^www\d+\.example\.com$;
}
Регулярные выражения могут включать захватываемые группы, которые можно использовать в других директивах:
server {
server_name ~^(www\.)?(.+)$;
proxy_pass www.$2:12345;
}
Именованные захваты в регулярных выражениях создают переменные, которые можно использовать в других директивах:
server {
server_name ~^(www\.)?(?<domain>.+)$;
proxy_pass www.$domain:12345;
}
Если параметр директивы установлен на $hostname, будет вставлено имя
хоста машины.
При поиске виртуального сервера по имени, если имя совпадает с более чем одним из указанных вариантов (например, совпадают и шаблонное имя, и регулярное выражение), будет выбрано первое совпавшее имя в следующем порядке приоритета:
Точное имя
Самое длинное шаблонное имя, начинающееся с звездочки, например,
*.example.comСамое длинное шаблонное имя, заканчивающееся звездочкой, например,
mail.*Первое совпавшее регулярное выражение (в порядке появления в конфигурационном файле)
server_names_hash_bucket_size#
| |
По умолчанию |
|
stream |
Задает размер корзины для хэш-таблиц имен серверов. Значение по умолчанию зависит от размера кэш-линии процессора.
server_names_hash_max_size#
| |
По умолчанию |
|
stream |
Задает максимальный размер хэш-таблиц имен серверов.
status_zone#
Выделяет зону разделяемой памяти для сбора метрик /status/stream/server_zones/<зона>.
Несколько контекстов server
могут совместно использовать одну и ту же зону для сбора данных.
Синтаксис с одним значением зоны объединяет все метрики для текущего контекста в одну зону разделяемой памяти:
server {
listen 80;
server_name *.example.com;
status_zone single;
# ...
}
Альтернативный синтаксис позволяет задавать следующие параметры:
значение | Строка с переменными, значение которой определяет группировку подключений в зоне. Все подключения, дающие одинаковые значения после подстановки, объединяются в одну группу. Если подстановка возвращает пустое значение, метрики не обновляются. |
зона | Имя зоны разделяемой памяти. |
число (необязательный) | Максимальное количество отдельных групп для сбора метрик. Если новые значения ключа превышают этот лимит, они объединяются в группу zone. Значение по умолчанию — 1. |
В следующем примере все соединения с одинаковым значением $server_addr
группируются в host_zone. Метрики собираются отдельно для каждого
уникального значения $server_addr до тех пор, пока количество групп
метрик не достигнет 10. После этого любые новые значения $server_addr
будут добавляться в группу server_zone:
stream {
upstream backend {
server 192.168.0.1:3306;
server 192.168.0.2:3306;
# ...
}
server {
listen 3306;
proxy_pass backend;
status_zone $server_addr zone=server_zone:10;
}
}
Результирующие метрики разделяются по отдельным серверам в выводе API.
Примечание
Эти метрики собираются, только если задан status_zone. Без него
сервер не отображается в /status/stream/server_zones/<зона>,
в виджете «TCP/UDP Zones»
и в выводе Prometheus,
и предупреждение при этом не выводится.
stream#
Предоставляет контекст конфигурационного файла, в котором указываются директивы stream-сервера.
tcp_nodelay#
Разрешает или запрещает использование параметра TCP_NODELAY. Параметр включается как для клиентских соединений, так и для соединений с проксируемыми серверами.
time_format#
Определяет $переменную, содержащую текущее локальное время, отформатированное
в соответствии со строкой формата, которая поддерживает спецификаторы в стиле
strftime, а также %L для миллисекунд. Директива полезна, когда
возможностей $time_local и $time_iso8601 недостаточно — например, если требуется точность до
миллисекунд:
time_format $time_ms "%Y-%m-%dT%H:%M:%S.%L%Z";
log_format tf '$time_ms $remote_addr $status';
При таком формате переменная $time_ms принимает значение вида 2024-01-15T14:34:56.789+03:00.
Попытка переопределить встроенную переменную, например $time_local, или повторно объявить time_format с тем же именем
приводит к ошибке загрузки конфигурации вида: "the duplicate "..." variable".
Строка формата поддерживает следующие спецификаторы; все они вычисляются в том же часовом поясе, что и $time_local:
| год, 4 цифры |
| год, 2 цифры |
| месяц, |
| день месяца, |
| день месяца, дополненный пробелом, |
| час, |
| час, |
| минута, |
| секунда, |
| миллисекунды, |
| обозначение AM/PM в верхнем регистре, |
| то же самое в нижнем регистре, |
| сокращенное название дня недели, |
| полное название дня недели, |
| сокращенное название месяца, |
| полное название месяца, |
| смещение часового пояса, |
| смещение часового пояса в формате ISO 8601, |
| перевод строки |
| табуляция |
| символ |
Примечание
Нераспознанный спецификатор копируется в вывод без изменений, включая ведущий
символ %; одиночный символ % в самом конце строки
формата отбрасывается.
variables_hash_bucket_size#
Задает размер корзины в хэш-таблице переменных. Подробнее настройка хэш-таблиц обсуждается отдельно.
variables_hash_max_size#
Задает максимальный размер хэш-таблиц переменных. Подробнее настройка хэш-таблиц обсуждается отдельно.
Встроенные переменные#
Базовый потоковый модуль поддерживает встроенные переменные:
$angie_version#
версия Angie
$binary_remote_addr#
адрес клиента в бинарном виде, длина значения всегда 4 байта для IPv4-адресов или 16 байт для IPv6-адресов
$bytes_received#
число байт, полученных от клиента
$bytes_sent#
число байт, переданных клиенту
$connection#
порядковый номер соединения
$hostname#
имя хоста
$msec#
текущее время в секундах с точностью до миллисекунд
$nginx_version#
версия nginx
$pid#
номер (PID) рабочего процесса
$protocol#
протокол, используемый для работы с клиентом: TCP или UDP
$proxy_protocol_addr#
адрес клиента, полученный из заголовка протокола PROXY. Протокол PROXY должен быть предварительно включен при помощи установки параметра proxy_protocol в директиве listen.
$proxy_protocol_port#
порт клиента, полученный из заголовка протокола PROXY. Протокол PROXY должен быть предварительно включен при помощи установки параметра proxy_protocol в директиве listen.
$proxy_protocol_server_addr#
адрес сервера, полученный из заголовка протокола PROXY. Протокол PROXY должен быть предварительно включен при помощи установки параметра proxy_protocol в директиве listen.
$proxy_protocol_server_port#
порт сервера, полученный из заголовка протокола PROXY. Протокол PROXY должен быть предварительно включен при помощи установки параметра proxy_protocol в директиве listen.
$proxy_protocol_tlv_<имя>#
TLV, полученный из заголовка протокола PROXY. Имя может быть именем типа TLV или его числовым значением. В последнем случае значение задается в шестнадцатеричном виде и должно начинаться с 0x:
$proxy_protocol_tlv_alpn
$proxy_protocol_tlv_0x01
SSL TLV могут также быть доступны как по имени типа TLV, так и по его числовому значению, оба должны начинаться с ssl_:
$proxy_protocol_tlv_ssl_version
$proxy_protocol_tlv_ssl_0x21
Поддерживаются следующие имена типов TLV:
alpn (0x01)- протокол более высокого уровня, используемый поверх соединенияauthority (0x02)- значение имени хоста, передаваемое клиентомunique_id (0x05)- уникальный идентификатор соединенияnetns (0x30)- имя пространства именssl (0x20)- структура SSL TLV в бинарном виде
Поддерживаются следующие имена типов SSL TLV:
ssl_version (0x21)- версия SSL, используемая в клиентском соединенииssl_cn (0x22)- Common Name сертификатаssl_cipher (0x23)- имя используемого шифраssl_sig_alg (0x24)- алгоритм, используемый для подписи сертификатаssl_key_alg (0x25)- алгоритм публичного ключа
Также поддерживается следующее специальное имя типа SSL TLV:
ssl_verify- результат проверки клиентского сертификата: 0, если клиент предоставил сертификат и он был успешно верифицирован, либо ненулевое значение
Протокол PROXY должен быть предварительно включен при помощи установки параметра proxy_protocol в директиве listen.
$remote_addr#
адрес клиента
$remote_port#
порт клиента
$server_addr#
адрес сервера, принявшего соединение.
Получение значения этой переменной обычно требует одного системного вызова. Чтобы избежать системного вызова, в директивах listen следует указывать адреса и использовать параметр bind.
$server_port#
порт сервера, принявшего соединение
$session_time#
длительность сессии в секундах с точностью до миллисекунд
$status#
статус сессии, может принимать одно из следующих значений:
| сессия завершена успешно |
| невозможно разобрать данные, полученные от клиента, например заголовок протокола PROXY |
| доступ запрещен, например при ограничении доступа для определенных адресов клиентов |
| внутренняя ошибка сервера |
| плохой шлюз, например если невозможно выбрать сервер группы или сервер недоступен |
| сервис недоступен, например при ограничении по числу соединений |
$time_iso8601#
локальное время в формате по стандарту ISO 8601
$time_local#
локальное время в Common Log Format