Перейти к содержанию

Это многостраничная версия текущего раздела для печати. .

Вернуться к обычному виду страницы.

Документация HAProxy 3.4.6-66

Полное русское издание руководств HAProxy 3.4 для начинающих, по конфигурации и управлению в формате Markdown

HAProxy — свободный, быстрый и надёжный обратный прокси для обеспечения высокой доступности, балансировки нагрузки TCP и HTTP и управления трафиком приложений. Этот раздел содержит полный перевод трёх основных руководств HAProxy 3.4, организованных в единую плоскую последовательность страниц Markdown для чтения в OINK.

Это издание соответствует официальным английским руководствам ветки сопровождения на снимке 3.4.6-66. Последний стабильный выпуск — 3.4.6 (v3.4.6); снимок включает изменения документации, внесённые после этого выпуска. Точный источник — коммит 16acce1dac1d .

Выберите руководство

  • Руководство для начинающих — 9 тем о принципах балансировки нагрузки, архитектуре HAProxy, возможностях, выборе ресурсов, выпусках и экосистеме.
  • Руководство по конфигурации — 12 глав о прокси, ACL, образцах, ведении журнала, фильтрах и всех семействах параметров.
  • Руководство по управлению — 13 глав о запуске, перезагрузке конфигурации, ресурсах, ведении журнала, статистике, CLI времени выполнения, отладке и безопасности.

Охват издания

Руководство Исходный материал проекта Локальная организация
Руководство для начинающих 1,695 строк 9 страниц тем без вложенности
Руководство по конфигурации 33,216 строк 12 страниц глав без вложенности
Руководство по управлению 5,305 строк 13 страниц глав без вложенности

Все 34 страницы для чтения находятся непосредственно в корне компонента HAProxy. Три разделителя без ссылок отделяют руководства в боковой панели, не добавляя уровней каталогов или остановок в последовательной навигации.

Полные исходные материалы зафиксированной версии и контрольные суммы SHA-256 сохранены в sources/haproxy/. Лицензионное уведомление проекта и текст GPLv2 опубликованы вместе с руководствами. Для каждой страницы также доступно проверенное издание на упрощённом китайском языке.

1 - Основы балансировки нагрузки

Основы балансировки нагрузки на уровне пакетов, сети, серверов, L4 и L7

Этот документ знакомит с HAProxy тех, кто ещё не знает продукт, а также тех, кто знаком с его старыми версиями и хочет открыть его заново. Главная цель — предоставить все сведения, необходимые для решения, подходит ли HAProxy пользователю. Опытные пользователи могут найти здесь отдельные элементы решений ранее возникших задач, о которых они не знали из-за незнакомства с новой функцией. Также приведены сведения для расчёта ресурсов, описан жизненный цикл продукта и даны сравнения с продуктами, чьи возможности частично пересекаются с HAProxy.

Этот документ не содержит помощи или советов по настройке, но объясняет, где искать соответствующую документацию. Руководство представлено плоской последовательностью тематических страниц в боковой панели HAProxy.

Балансировка нагрузки объединяет несколько компонентов, чтобы получить общую производительность выше производительности каждого из них, без вмешательства конечного пользователя и с возможностью масштабирования. В результате за время, необходимое одному компоненту для выполнения одной операции, одновременно выполняется больше операций. Однако отдельная операция по-прежнему выполняется только на одном компоненте и не ускоряется по сравнению с работой без балансировки. Чтобы задействовать все компоненты и полностью использовать преимущества балансировки, всегда нужно как минимум столько же операций, сколько компонентов, а также эффективный механизм распределения нагрузки. Наглядный пример — число полос на автомагистрали: оно позволяет пропустить больше автомобилей за одно и то же время без увеличения скорости каждого автомобиля.

Примеры балансировки нагрузки:

  • Планирование процессов в многопроцессорных системах.
  • Балансировка нагрузки каналов связи (например, EtherChannel, Bonding).
  • Балансировка по IP-адресам (например, ECMP, циклический выбор DNS).
  • Балансировка нагрузки серверов (с помощью балансировщиков нагрузки).

Механизм или компонент, выполняющий распределение нагрузки, называется балансировщиком нагрузки. В веб-средах такие компоненты называют «сетевыми балансировщиками нагрузки», а чаще просто «балансировщиками нагрузки», поскольку это наиболее известная область их применения.

Балансировщик нагрузки может действовать:

  • На уровне канала: балансировка нагрузки каналов связи выбирает сетевой канал, по которому отправить пакет.

  • На уровне сети: сетевая балансировка нагрузки выбирает маршрут для последовательности пакетов.

  • На уровне сервера: балансировка нагрузки серверов определяет сервер, который обработает соединение или запрос.

Существуют две разные технологии, решающие разные, хотя частично пересекающиеся задачи. В обоих случаях важно помнить: балансировка отклоняет трафик от его естественного пути, поэтому всегда требуется некоторая осторожность, чтобы сохранять необходимую согласованность всех решений о маршрутизации.

Первая технология работает на уровне пакетов и обрабатывает их более или менее независимо. Между входными и выходными пакетами существует соответствие 1-к-1, поэтому трафик по обе стороны балансировщика можно отслеживать обычным анализатором сетевого трафика. Эта технология может быть очень дешёвой и чрезвычайно быстрой. Обычно она реализуется аппаратно, на ASIC, и позволяет достичь скорости линии — например, в коммутаторах с ECMP. Чаще всего она не хранит состояние, но может учитывать сеанс, к которому относится пакет; такой вариант называют layer4-LB или L4. Если пакеты не изменяются, возможна поддержка DSR — прямого ответа сервера без повторного прохождения через балансировщик. Однако содержимое практически не анализируется. Эта технология отлично подходит для балансировки на уровне сети, хотя иногда применяется и для простейшей высокоскоростной балансировки нагрузки серверов.

Вторая технология работает с содержимым сеансов. Для этого входной поток необходимо собрать и обработать целиком. Содержимое можно изменить, а выходной поток разбивается на новые пакеты. Поэтому такую обработку обычно выполняют прокси, часто называемые балансировщиками нагрузки уровня 7 или L7. Это подразумевает два отдельных соединения по обе стороны балансировщика и отсутствие связи между размерами и числом входных и выходных пакетов. Клиенты и серверы не обязаны использовать один и тот же протокол: например, возможны IPv4 и IPv6 или незашифрованный трафик и SSL. Операции всегда сохраняют состояние, а обратный трафик обязательно проходит через балансировщик. Дополнительная обработка требует ресурсов, поэтому достичь скорости линии удаётся не всегда, особенно на маленьких пакетах. Зато технология даёт широкие возможности и обычно реализуется целиком программно, даже во встроенных аппаратных устройствах. Она отлично подходит для балансировки нагрузки серверов.

Балансировщики, работающие с пакетами, обычно развёртываются в режиме сквозной пересылки: их устанавливают на обычном пути трафика, который они перенаправляют согласно конфигурации. Обратный трафик не обязательно проходит через балансировщик. Для направления трафика нужному адресату может изменяться сетевой адрес назначения. В таком случае обратный трафик обязательно должен проходить через балансировщик. Если маршруты этого не позволяют, балансировщик может также заменить исходный адрес пакетов своим, принудительно направляя обратный трафик через себя.

Балансировщики на основе прокси развёртываются как серверы с собственными IP-адресами и портами, без изменения архитектуры. Иногда приходится адаптировать приложения, чтобы клиенты направлялись на IP-адрес балансировщика, а не прямо к серверу. Некоторым балансировщикам для этого нужно изменять ответы серверов — например, поле заголовка HTTP Location, используемое при перенаправлениях. Некоторые балансировщики на основе прокси умеют перехватывать трафик для чужого адреса и подставлять адрес клиента при соединении с сервером. Это позволяет развёртывать их как обычный маршрутизатор или межсетевой экран, в режиме сквозной пересылки, очень похожем на режим пакетных балансировщиков. Это особенно ценится в продуктах, сочетающих режим обработки пакетов и режим прокси. Очевидно, что DSR в таком случае по-прежнему невозможен, а обратный трафик необходимо направлять через балансировщик.

Хорошо масштабируемая многоуровневая схема может начинаться с пограничного маршрутизатора, принимающего трафик из нескольких сбалансированных каналов и распределяющего его с помощью ECMP на первый уровень из нескольких пакетных балансировщиков с состоянием (L4). Эти балансировщики L4 передают трафик ещё большему числу балансировщиков на основе прокси (L7), которые разбирают содержимое и выбирают конечный сервер-получатель.

Увеличение числа компонентов и возможных путей трафика повышает риск отказа. В очень больших средах нормально, когда несколько неисправных компонентов постоянно находятся на ремонте или замене. Балансировка без учёта работоспособности всего стека значительно снижает доступность. Поэтому любой разумно устроенный балансировщик проверяет, что компоненты, которым он собирается отправлять трафик, работают и доступны, и прекращает направлять трафик неисправным. Для этого применяют разные методы.

Самый распространённый метод — периодические пробы, подтверждающие работоспособность компонента. Их называют «проверками работоспособности». Они должны соответствовать типам отказов, которые требуется выявить. Например, проверка ping не обнаружит, что веб-сервер аварийно завершился и больше не прослушивает порт. Соединение с портом выявит такую проблему, а более сложный запрос может также подтвердить работоспособность сервера и доступность используемой им базы данных. Проверки часто повторяют несколько раз, чтобы исключить случайные ошибки измерения. Интервал между ними должен быть достаточно мал, чтобы неисправный компонент не использовался слишком долго после возникновения ошибки.

Другие методы анализируют выборку рабочего трафика, отправляемого адресату, проверяют правильность его обработки и исключают компоненты с некорректными ответами. Однако при этом приходится жертвовать частью рабочего трафика, что не всегда допустимо. Сочетание обоих механизмов объединяет их преимущества: для выявления отказа применяются оба, а для определения восстановления — только проверки работоспособности. Ещё один метод основан на централизованных сообщениях: центральный агент мониторинга периодически сообщает всем балансировщикам состояние всех компонентов. Это даёт каждому компоненту общее представление об инфраструктуре, хотя иногда с меньшей точностью или оперативностью. Такой подход лучше всего подходит для сред с большим числом балансировщиков и серверов.

Балансировщики уровня 7 сталкиваются и с другой задачей — привязкой сеансов, также называемой сохранением привязки. Обычно несколько последовательных запросов или соединений от одного источника, например конечного пользователя, нужно направлять одному адресату. Самый известный пример — корзина интернет-магазина. Если каждый щелчок создаёт новое соединение, пользователя всегда необходимо отправлять на сервер, где хранится его корзина. Анализ содержимого позволяет легче выделить в запросе элементы для определения нужного сервера, но этого не всегда достаточно. Например, если ключом выбора сервера служит исходный адрес, можно применить алгоритм хеширования: один IP-адрес всегда направляется на один сервер на основе деления адреса на число доступных серверов. Но при отказе сервера результат изменится, и все пользователи внезапно попадут на другие серверы, потеряв свои корзины. Решение — запоминать выбранного адресата и при каждом появлении того же посетителя направлять его на тот же сервер независимо от числа доступных серверов. Сведения можно хранить в памяти балансировщика; если он не единственный, их может потребоваться реплицировать другим балансировщикам. Либо их можно разными способами хранить у клиента, если он способен передавать их с каждым запросом: посредством вставки cookie, перенаправления на поддомен и т. п. Дополнительное преимущество такого механизма — отсутствие зависимости от нестабильных или неравномерно распределённых сведений, например исходного IP-адреса. Именно это является главным доводом в пользу балансировщика уровня 7 вместо уровня 4.

Чтобы извлечь cookie, поле заголовка host, URL или другие сведения, балансировщику может потребоваться расшифровать трафик SSL/TLS и, возможно, снова зашифровать его перед передачей серверу. Высокая стоимость этой операции объясняет, почему в некоторых инфраструктурах с большим объёмом трафика бывает много балансировщиков.

Поскольку балансировщик уровня 7 выполняет множество сложных операций с трафиком — расшифровывает, разбирает, изменяет, сопоставляет cookie, выбирает сервер и т. п., — он действительно может вызывать проблемы. Но очень часто его обвиняют и в тех проблемах, которые он лишь выявил. Нередко обнаруживается нестабильность серверов, которые периодически отключаются и возвращаются в работу; жёстко заданные ссылки на веб-страницах, заставляющие клиентов обращаться прямо к определённому серверу в обход балансировщика; либо очень медленные ответы под высокой нагрузкой, вызывающие тайм-ауты. Поэтому ведение журнала — исключительно важная часть балансировки уровня 7. После сообщения о проблеме необходимо выяснить, принял ли балансировщик неверное решение и, если да, почему, чтобы исключить повторение.

2 - Что такое HAProxy и как он работает

Назначение, границы применения, событийная архитектура и модель обработки запросов HAProxy

Название «HAProxy» обозначает продукт, а «haproxy» — исполняемую программу, программный пакет или процесс. Однако оба варианта часто используются в обоих значениях и произносятся как H-A-Proxy. На раннем этапе «haproxy» расшифровывалось как «прокси высокой доступности», а название писалось в два отдельных слова, хотя сейчас оно означает только «HAProxy».

3.1. Чем является и чем не является HAProxy

HAProxy — это:

  • TCP-прокси: он может принять TCP-соединение на прослушивающем сокете, подключиться к серверу и связать эти сокеты, обеспечивая передачу трафика в обоих направлениях; с обеих сторон поддерживаются IPv4, IPv6 и даже сокеты UNIX, что даёт простой способ преобразовывать адреса между разными семействами.

  • обратный HTTP-прокси (в терминологии HTTP — «шлюз»): он выступает в качестве сервера, получает HTTP-запросы по соединениям, принятым на прослушивающем TCP-сокете, и передаёт запросы из этих соединений серверам по другим соединениям. Он может использовать любую комбинацию HTTP/1.x и HTTP/2 с любой стороны и даже автоматически определяет протокол каждой стороны при использовании ALPN поверх TLS.

  • средство завершения, инициирования и разгрузки SSL: SSL/TLS можно использовать на соединении от клиента, на соединении к серверу или даже на обоих соединениях. Многие параметры можно задавать для отдельных имён (SNI) и обновлять во время выполнения без перезапуска. Такие конфигурации прекрасно масштабируются: сообщалось о развёртываниях, использующих от десятков до сотен тысяч сертификатов.

  • нормализатор TCP: поскольку соединения локально завершаются операционной системой, их стороны не связаны между собой, поэтому аномальный трафик, например некорректные пакеты, сочетания флагов, объявления окон, номера последовательности, незавершённые соединения (SYN-флуд) и тому подобное, не передаётся на другую сторону. Это защищает уязвимые стеки TCP от атак на протокол, а также позволяет оптимизировать параметры соединения с клиентом без изменения настроек стеков TCP на серверах.

  • нормализатор HTTP: при настройке обработки HTTP-трафика передаются только корректные полные запросы. Это защищает от множества атак на протокол. Кроме того, отклонения от протокола, допустимые по спецификации, исправляются, чтобы не вызывать проблем на серверах (например, многострочные заголовки).

  • инструмент исправления HTTP: он может изменять, исправлять, добавлять, удалять и переписывать URL или любой заголовок запроса либо ответа. Это помогает устранять проблемы совместимости в сложных средах.

  • коммутатор на основе содержимого: он может учитывать любой элемент запроса, решая, какому серверу передать запрос или соединение. Поэтому через один порт можно обслуживать несколько протоколов (например, HTTP, HTTPS, SSH).

  • балансировщик серверной нагрузки: он может распределять TCP-соединения и HTTP-запросы. В режиме TCP решение о балансировке принимается для всего соединения. В режиме HTTP решение принимается для каждого запроса.

  • регулятор трафика: он может ограничивать интенсивность в различных точках, защищать серверы от перегрузки, менять приоритеты трафика в зависимости от содержимого и даже передавать эту информацию нижним уровням и внешним сетевым компонентам с помощью маркировки пакетов.

  • средство защиты от DDoS и злоупотребления сервисом: он может вести обширную статистику по IP-адресам, URL, файлам cookie и другим признакам, выявлять злоупотребления и принимать меры (замедлять нарушителей, блокировать их, перенаправлять к устаревшему содержимому и т. д.).

  • точка наблюдения для устранения сетевых неполадок: благодаря точности информации, записываемой в журналы, он часто используется для сужения круга причин сетевых проблем.

  • средство разгрузки HTTP-сжатия: он может сжимать ответы, которые сервер не сжал, сокращая время загрузки страниц для клиентов с плохим подключением или использующих мобильные сети с высокой задержкой.

  • кэширующий прокси: он может кэшировать ответы в оперативной памяти, чтобы последующие запросы того же объекта не требовали повторной передачи по сети с сервера, пока объект остаётся в кэше и сохраняет актуальность. При этом объекты не сохраняются в постоянном хранилище. Учтите, что эта функция кэширования не требует обслуживания и направлена исключительно на экономию ценных ресурсов haproxy, а не ресурсов сервера. Кэши, предназначенные для оптимизации серверов, требуют гораздо более тонкой настройки и гибкости. Если нужен такой расширенный кэш, используйте Varnish Cache, который прекрасно интегрируется с haproxy, особенно когда SSL/TLS требуется с любой из сторон.

  • шлюз FastCGI: FastCGI можно рассматривать как другое представление HTTP, и поэтому HAProxy может непосредственно распределять нагрузку по группе серверов приложений FastCGI в любых сочетаниях, без дополнительного уровня шлюза между ними. Это экономит ресурсы и снижает затраты на обслуживание.

HAProxy не является:

  • явным HTTP-прокси, то есть прокси, через который браузеры выходят в Интернет. Для этой задачи есть отличное специализированное ПО с открытым исходным кодом, например Squid. Однако HAProxy можно установить перед таким прокси для балансировки нагрузки и обеспечения высокой доступности.

  • средством очистки данных: он не изменяет тела запросов или ответов.

  • статическим веб-сервером: при запуске он изолирует себя в окружении chroot и сбрасывает привилегии, поэтому после запуска вообще не обращается к файловой системе. По этой причине его невозможно превратить в статический веб-сервер (однако динамические серверы поддерживаются через FastCGI). Для этого есть отличное ПО с открытым исходным кодом, например Apache и Nginx, а HAProxy можно легко установить перед ними для балансировки нагрузки, обеспечения высокой доступности и ускорения.

  • балансировщиком нагрузки на уровне пакетов: он не видит IP-пакеты или UDP-дейтаграммы, не выполняет NAT и тем более DSR. Эти задачи относятся к нижним уровням. Некоторые компоненты на уровне ядра, например IPVS (Linux Virtual Server), уже прекрасно с ними справляются и отлично дополняют HAProxy.

3.2. Как работает HAProxy

HAProxy — это неблокирующий движок с событийной архитектурой, сочетающий очень быстрый уровень ввода-вывода с многопоточным планировщиком на основе приоритетов. Поскольку он изначально предназначен для пересылки данных, его архитектура оптимизирована для максимально быстрой передачи данных с минимальным числом операций. Особое внимание уделяется эффективному использованию кэша CPU: соединения закрепляются за одним CPU как можно дольше. Для этого реализована многоуровневая модель с механизмами обхода на каждом уровне, которые гарантируют, что данные не попадут на более высокие уровни без необходимости. Основная обработка происходит в ядре, а HAProxy старается помочь ядру выполнить работу как можно быстрее, передавая подсказки или избегая определённых операций, если предполагает, что их можно будет сгруппировать позже. В результате типичное распределение времени обработки составляет 15% в HAProxy и 85% в ядре в режиме TCP или HTTP close и около 30% в HAProxy и 70% в ядре в режиме HTTP keep-alive.

Один процесс может запускать множество экземпляров прокси; сообщалось об успешной работе конфигураций с 300000 отдельными прокси в одном процессе. Системы с одним процессором и одним ядром более чем достаточно для более чем 99% пользователей, поэтому пользователям контейнеров и виртуальных машин рекомендуется выбирать самые маленькие доступные образы, чтобы снизить эксплуатационные затраты и упростить устранение неполадок. Однако машина, на которой работает HAProxy, ни при каких обстоятельствах не должна использовать подкачку, а её CPU нельзя искусственно ограничивать (выделяя долю CPU в гипервизоре) или делить с ресурсоёмкими вычислительными процессами, которые создавали бы очень большую задержку переключения контекста.

Многопоточность позволяет задействовать всю доступную вычислительную мощность, используя один поток на ядро CPU. Это особенно полезно для SSL или когда требуется скорость пересылки данных выше 40 Гбит/с. В таких случаях критически важно избегать взаимодействия между несколькими физическими CPU: оно может создавать серьёзные узкие места в сетевом стеке и в самом HAProxy. Хотя некоторым это кажется нелогичным, при возникновении проблем с производительностью первым действием часто должно быть уменьшение числа CPU, на которых работает HAProxy.

Для работы HAProxy нужны только исполняемый файл haproxy и файл конфигурации. Для ведения журнала настоятельно рекомендуется настроить демон syslog и ротацию журналов. Журналы также можно отправлять в stdout/stderr, что бывает полезно внутри контейнеров. Файлы конфигурации разбираются до запуска, затем HAProxy пытается привязать все прослушивающие сокеты и отказывается запускаться, если что-либо не удалось. После этого сбои уже невозможны. Это означает, что ошибок во время выполнения не возникает и, если запуск прошёл успешно, программа будет работать до остановки.

После запуска HAProxy выполняет ровно 3 действия:

  • обрабатывает входящие соединения;

  • периодически проверяет состояние серверов (проверки работоспособности);

  • обменивается информацией с другими узлами haproxy.

Обработка входящих соединений — безусловно, самая сложная задача, поскольку зависит от множества вариантов конфигурации, однако её можно свести к следующим 9 шагам:

  • принять входящие соединения с прослушивающих сокетов, принадлежащих сущности конфигурации «frontend», которая ссылается на один или несколько прослушиваемых адресов;

  • применить к этим соединениям правила обработки фронтенда, которые могут привести к их блокировке, изменению некоторых заголовков или перехвату для выполнения внутренних апплетов, таких как страница статистики или CLI;

  • передать эти входящие соединения другой сущности конфигурации, представляющей группу серверов «backend», которая содержит список серверов и стратегию балансировки нагрузки для этой группы серверов;

  • применить к этим соединениям правила обработки бэкенда;

  • выбрать сервер для передачи соединения в соответствии со стратегией балансировки нагрузки;

  • применить к данным ответа правила обработки бэкенда;

  • применить к данным ответа правила обработки фронтенда;

  • создать запись в журнале с подробным описанием произошедшего;

  • в случае HTTP вернуться ко второму шагу и ждать нового запроса, иначе закрыть соединение.

Фронтенды и бэкенды иногда считают половинами прокси, поскольку каждый из них работает только с одной стороной сквозного соединения: фронтенд — только с клиентами, а бэкенд — только с серверами. HAProxy также поддерживает полные прокси, которые представляют собой точное объединение фронтенда и бэкенда. Когда нужна обработка HTTP, конфигурацию обычно разделяют на фронтенды и бэкенды: это открывает много возможностей, поскольку любой фронтенд может передать соединение любому бэкенду. Для прокси, работающих только с TCP, разделение на фронтенды и бэкенды редко даёт преимущество, а конфигурация с полными прокси может быть удобнее для чтения.

3 - Базовые возможности

Проксирование, TLS, мониторинг, высокая доступность, балансировка, привязка сеансов, журналы и статистика

В этом разделе перечислены возможности HAProxy: одни обычно ожидаются от любого современного балансировщика нагрузки, другие непосредственно вытекают из архитектуры HAProxy. Более сложные возможности подробно рассматриваются в следующем разделе.

3.3.1. Базовые возможности: проксирование

Проксирование — передача данных между клиентом и сервером по двум независимым соединениям. HAProxy поддерживает следующие базовые возможности проксирования и управления соединениями:

  • Предоставление серверу корректного соединения для защиты от любых ошибок или атак со стороны клиента.

  • Прослушивание нескольких IP-адресов и/или портов, в том числе диапазонов портов.

  • Прозрачный приём: перехват трафика к произвольному IP-адресу, даже не принадлежащему локальной системе.

  • Порт сервера не обязан быть связан с прослушиваемым портом и может даже преобразовываться с фиксированным смещением, что удобно для диапазонов.

  • Прозрачное подключение: при необходимости подстановка IP-адреса клиента или любого другого адреса при соединении с сервером.

  • Предоставление серверам надёжного IP-адреса для обратного трафика при балансировке между несколькими площадками.

  • Снижение нагрузки на сервер за счёт буферов и, при необходимости, короткоживущих соединений, уменьшающих число одновременных соединений и потребление памяти.

  • Оптимизация стеков TCP, например SACK, управления перегрузкой и уменьшение влияния RTT.

  • Поддержка разных семейств протоколов по обе стороны, например IPv4/IPv6/Unix.

  • Соблюдение тайм-аутов: HAProxy поддерживает несколько уровней тайм-аутов в зависимости от этапа соединения, чтобы неработающий клиент, сервер или злоумышленник не удерживал ресурсы слишком долго.

  • Проверка протокола: анализ HTTP, SSL или полезной нагрузки с отклонением некорректных элементов протокола, если явно не предписано их принимать.

  • Применение политик: пересылается только разрешённый трафик.

  • Ограничение входящих и исходящих соединений определёнными сетевыми пространствами имён (только Linux), упрощающее создание балансировщика между контейнерами для нескольких арендаторов.

  • Протокол PROXY передаёт серверу IP-адрес клиента даже для трафика, отличного от HTTP. Это расширение HAProxy уже принято рядом сторонних продуктов; на момент написания как минимум следующими:

    • клиент: haproxy, stud, stunnel, exaproxy, ELB, squid;
    • сервер: haproxy, stud, postfix, exim, nginx, squid, node.js, varnish.

3.3.2. Базовые возможности: SSL

Инженеры Google считают стек SSL HAProxy одним из самых функциональных (http://istlsfastyet.com/ ). Наиболее часто используемые возможности, обеспечивающие его полноту:

  • Обслуживание нескольких сайтов на основе SNI без ограничения их числа и с упором на производительность. Известно как минимум одно развёртывание с 50000 доменов и отдельными сертификатами для них.

  • Поддержка сертификатов с подстановочными знаками, уменьшающая необходимое число сертификатов.

  • Аутентификация клиентов по сертификатам с настраиваемыми действиями при отсутствии действительного сертификата. Например, можно направить клиента на другую серверную ферму для повторного выпуска его сертификата.

  • Аутентификация сервера бэкенда, подтверждающая, что это настоящий сервер, а не посредник.

  • Аутентификация перед сервером бэкенда, позволяющая ему убедиться, что подключается именно ожидаемый узел haproxy.

  • Расширения TLS NPN и ALPN, позволяющие надёжно завершать зашифрованные соединения SPDY/HTTP2 и передавать их серверам бэкенда в открытом виде.

  • OCSP stapling, дополнительно сокращающий время загрузки первой страницы за счёт передачи ответа OCSP вместе с остальными данными, когда клиент запрашивает Certificate Status Request.

  • Динамический размер записей, обеспечивающий одновременно высокую производительность и низкую задержку и заметно сокращающий время загрузки страницы: браузер может начинать получать новые объекты, пока предыдущие пакеты ещё находятся в пути.

  • Постоянный доступ ко всем существенным сведениям уровня SSL/TLS для журналирования, контроля доступа, отчётности и т. п. Эти сведения можно включать в заголовки HTTP или даже в расширение протокола PROXY, чтобы сервер получил всю информацию, доступную ему при самостоятельном завершении SSL.

  • Обнаружение, запись в журнал и блокировка известных атак даже при уязвимых библиотеках SSL, например атаки Heartbleed на некоторые версии OpenSSL.

  • Поддержка возобновления сеансов без хранения состояния (расширение TLS Ticket из RFC 5077). Билеты TLS можно обновлять через CLI, что позволяет реализовать совершенную прямую секретность, часто меняя билеты.

3.3.3. Базовые возможности: мониторинг

HAProxy уделяет большое внимание доступности, поэтому следит за состоянием серверов и сообщает собственное состояние другим сетевым компонентам:

  • Состояние серверов постоянно контролируется с параметрами, заданными для каждого сервера. Это подтверждает работоспособность пути к серверу для обычного трафика.

  • Проверки работоспособности поддерживают два порога гистерезиса для переходов в рабочее и нерабочее состояния, защищая от частого переключения состояний.

  • Проверки можно отправлять на другой адрес, порт или по другому протоколу. Это позволяет проверять одну службу как показатель работоспособности нескольких, например порт HTTPS у сервера HTTP+HTTPS.

  • Серверы могут отслеживать другие серверы и одновременно переходить в нерабочее состояние. Так сервер, предоставляющий несколько служб, исключается целиком, и никто не направляется на частично отказавший сервер.

  • На сервере можно разместить агент для контроля нагрузки и работоспособности. Серверу может потребоваться сообщать о нагрузке, рабочем и административном состоянии независимо от того, что видят проверки работоспособности. Простой агент позволяет учитывать собственную оценку сервера в дополнение к проверкам всего пути.

  • Доступны разные методы проверки: соединение TCP, запрос HTTP, приветствие SMTP, приветствие SSL, LDAP, SQL, Redis, сценарии send/expect — все с SSL или без него.

  • Изменение состояния отражается в журналах и на странице статистики с указанием причины отказа, например полученного при обнаружении ошибки ответа HTTP. При изменении также можно отправлять письмо на настраиваемый адрес.

  • Состояние сервера отображается в интерфейсе статистики и может использоваться при маршрутизации: трафик можно направлять на разные фермы в зависимости от их размера и/или работоспособности, например при потере связи между ЦОД.

  • Через запросы проверки работоспособности HAProxy может передавать серверам сведения: их имена, вес, число других серверов в ферме и т. п. Серверы могут учитывать их при ответах и принятии решений, например отложить резервное копирование, чтобы сохранить больше ресурсов CPU.

  • Через проверки работоспособности серверы могут сообщать более подробное состояние, чем просто включён/выключен: например, запросить остановку направления новых посетителей перед своим выключением.

  • Сам HAProxy может сообщать состояние внешним компонентам — маршрутизаторам или другим балансировщикам, что позволяет строить полноценные инфраструктуры с несколькими путями и уровнями.

3.3.4. Базовые возможности: высокая доступность

Как любой серьёзный балансировщик нагрузки, HAProxy уделяет большое внимание доступности и максимальной непрерывности обслуживания:

  • Используются только работоспособные серверы, остальные автоматически исключаются из ферм балансировки. Однако при определённых условиях их всё же можно принудительно использовать.

  • Поддерживается плавный вывод серверов из фермы без воздействия на существующие соединения.

  • При отказе активных серверов автоматически используются резервные, заменяя их так, чтобы по возможности сохранить сеансы. Это также позволяет создать несколько путей к одному серверу, например через разные интерфейсы.

  • Можно сообщать об общем отказе фермы, если не работает слишком много серверов. Вместе с мониторингом это позволяет вышестоящему компоненту выбрать другой узел балансировки для данной службы.

  • Архитектура без сохранения состояния упрощает создание кластеров: HAProxy стремится обеспечить максимальную непрерывность обслуживания без хранения сведений, которые можно потерять при отказе. Благодаря этому передача обслуживания происходит максимально плавно.

  • Хорошая интеграция со стандартным демоном VRRP keepalived: HAProxy легко сообщает ему своё состояние и хорошо работает с плавающими виртуальными IP-адресами. Примечание: используйте только протоколы резервирования IP (VRRP/CARP), а не кластерные решения (Heartbeat и т. п.), поскольку они обеспечивают наиболее быстрое, плавное и надёжное переключение.

3.3.5. Базовые возможности: балансировка нагрузки

HAProxy предлагает довольно полный набор средств балансировки нагрузки, большинство из которых, к сожалению, отсутствует в ряде других продуктов:

  • Поддерживается не менее 10 алгоритмов балансировки, некоторые из которых используют входные данные и дают неограниченное число вариантов применения. Наиболее распространены round-robin — поочерёдный выбор серверов для коротких соединений; leastconn — выбор сервера, который дольше всего не использовался, среди серверов с минимальным числом соединений, подходящий для длительных соединений; source — прямой выбор по исходному адресу клиента для ферм SSL или терминальных серверов; URI — прямой выбор по URI HTTP для кешей HTTP; hdr — прямой выбор по содержимому определённого поля заголовка HTTP; first — сосредоточение всех соединений на минимальном числе серверов, чтобы неиспользуемые короткоживущие виртуальные машины можно было выключить.

  • Все перечисленные алгоритмы поддерживают вес каждого сервера, позволяя сочетать в ферме разные поколения серверов или направлять небольшую долю трафика на отдельные серверы для отладки, работы следующей версии программы и т. п.

  • Для round-robin, leastconn и согласованного хеширования поддерживаются динамические веса. Их можно менять на лету через CLI или даже с помощью агента на сервере.

  • Везде, где поддерживается динамический вес, доступен slow-start — постепенное принятие сервером трафика. Это важно для чувствительных серверов приложений, которым нужно компилировать классы во время работы, и холодных кешей, которые необходимо заполнить перед полной нагрузкой.

  • Хеширование может применяться к разным элементам: исходному адресу клиента, компонентам URL, элементу строки запроса, значениям полей заголовков, параметру POST, cookie RDP.

  • Согласованное хеширование защищает фермы от массового перераспределения нагрузки при добавлении или удалении серверов. Это особенно важно для больших кеширующих ферм и позволяет использовать slow-start для заполнения холодных кешей.

  • Внутренние метрики, например число соединений на сервер и бэкенд или число свободных мест для соединений в бэкенде, позволяют строить очень сложные стратегии балансировки.

3.3.6. Базовые возможности: привязка сеансов

Без привязки сеансов балансировка нагрузки приложений была бы бесполезна. HAProxy предоставляет широкий набор средств для закрепления посетителя за одним сервером даже при добавлении и удалении серверов, отказах и восстановлении. Некоторые методы устойчивы к расстояниям между узлами балансировки, поскольку не требуют репликации:

  • При необходимости сведения для привязки можно независимо сопоставлять и запоминать из разных источников. Например, JSESSIONID можно искать и в cookie, и в URL. Одновременно можно запоминать до 8 источников, каждый из которых может указывать на отдельную таблицу stick-table.

  • Источником привязки может быть всё, что видно в запросе или ответе: исходный адрес, смещение и длина полезной нагрузки TCP, элементы строки запроса HTTP, значения полей заголовков, cookie и т. п.

  • Таблицы stick-tables реплицируются между всеми узлами в режиме с несколькими ведущими узлами.

  • Часто используемые элементы, например SSL-ID или cookie RDP для ферм TSE, доступны непосредственно, что упрощает работу с ними.

  • Все правила привязки могут динамически зависеть от условий ACL.

  • Можно отказаться от привязки к определённым серверам, например резервным, чтобы после возвращения основного сервера нагрузка автоматически перешла к нему. Это часто используется в средах с несколькими путями.

  • В HTTP часто предпочитают ничего не запоминать, а управлять специальным cookie привязки. Такой cookie можно обнаруживать, переписывать, вставлять или дополнять префиксом, чтобы клиент запомнил назначенный сервер.

  • Сервер может изменить или очистить cookie привязки при выходе пользователя, автоматически снимая привязку уходящих посетителей.

  • Правила ACL позволяют выборочно игнорировать или принудительно применять привязку независимо от состояния сервера. Вместе с расширенными проверками работоспособности это помогает администратору убедиться, что устанавливаемый сервер работает, прежде чем открыть его всем.

  • Специальный механизм ограничения времени бездействия и срока действия cookie позволяет плавно прекращать привязку на постоянно работающих устройствах — смартфонах, телевизорах, бытовой технике — без хранения этих сведений в постоянном хранилище.

  • Несколько записей серверов могут иметь одинаковые ключи привязки, чтобы при отказе одного пути в многопутевой среде привязка сохранялась.

  • soft-stop гарантирует, что к назначенному серверу продолжат обращаться только пользователи, уже имеющие сведения о привязке, а новые туда не попадут.

3.3.7. Базовые возможности: ведение журнала

Ведение журнала исключительно важно для балансировщика нагрузки. Во-первых, его часто ошибочно обвиняют в проблемах, которые он лишь выявляет. Во-вторых, он находится в критической точке инфраструктуры, где нужно анализировать всю обычную и аномальную активность и сопоставлять её с другими компонентами.

HAProxy предоставляет очень подробные журналы с миллисекундной точностью и точным временем приёма соединения, которое можно найти в журналах межсетевого экрана, например для сопоставления NAT. По умолчанию журналы TCP и HTTP содержат все необходимые для устранения неполадок сведения: исходный IP-адрес и порт, фронтенд, бэкенд, сервер, таймеры получения запроса, ожидания в очереди, установки соединения, получения заголовков ответа и передачи данных; общее состояние процесса; число соединений; состояние очередей; число повторных попыток; подробные действия привязки и причины отключения; захваченные заголовки с безопасным кодированием вывода. Формат можно расширить или заменить, включив любые извлечённые образцы, переменные и захваченные значения, чтобы получить очень подробные сведения. Например, можно записывать суммарное число запросов клиента или число посещённых им разных URL.

Уровень журналирования можно настраивать для каждого запроса обычными ACL: автоматически подавлять шумные записи и повышать уровень до предупреждения при аномальном поведении небольшой части трафика, например при слишком большом числе URL или ошибок HTTP с одного исходного адреса. Административные сообщения также имеют свои уровни и сообщают, например, об отказе или восстановлении сервера.

Каждый фронтенд и бэкенд может использовать несколько независимых направлений вывода журналов, что упрощает обслуживание нескольких арендаторов. Журналы предпочтительно отправлять по UDP, возможно в JSON, обрезая строки до настраиваемой длины для гарантированной доставки. Их также можно отправлять в stdout/stderr, любой файловый дескриптор или кольцевой буфер, на который клиент может подписаться для получения записей.

3.3.8. Базовые возможности: статистика

HAProxy предоставляет веб-интерфейс статистики с аутентификацией, уровнями безопасности и областями видимости. Поэтому каждому заказчику хостинга можно дать отдельную страницу только с его экземплярами. Её можно разместить по скрытому URL обычного сайта, не открывая новый порт. Страница также может показывать доступность других узлов HAProxy, позволяя с первого взгляда оценить работоспособность всей системы. Представление компактно, но доступны многочисленные подробности: причины ошибок, время с последнего обращения и изменения и т. п. Те же данные доступны в виде таблицы CSV, которую другие инструменты могут импортировать для построения графиков. Страница может автоматически обновляться для использования как панели мониторинга на большом экране. В административном режиме она также позволяет менять состояние серверов, упрощая обслуживание.

Также предоставляется экспортёр Prometheus, позволяющий получать статистику в другом формате в зависимости от развёртывания.

4 - Стандартные возможности

Извлечение образцов, карты отображения, ACL, переключение содержимого, таблицы привязок, переписывание и защита серверов

В этом разделе перечислены возможности, широко используемые в HAProxy, но не обязательно присутствующие в других балансировщиках нагрузки.

3.4.1. Стандартные возможности: извлечение и преобразование сведений

HAProxy поддерживает получение сведений с помощью широкого набора функций извлечения образцов. Они извлекают отдельные сведения, называемые образцами, для немедленного использования. Это применяется для привязки сеансов, построения условий, вывода сведений в журналы или дополнения заголовков HTTP.

Образцы можно извлекать из разных источников:

  • Константы: целые числа, строки, IP-адреса, двоичные блоки.

  • Процесс: дата, переменные окружения, состояние сервера/фронтенда/бэкенда/процесса, число и интенсивность передачи байтов/соединений, длина очереди, генератор случайных чисел и т. п.

  • Переменные: на уровне сеанса, запроса или ответа.

  • Клиентское соединение: исходные и целевые адреса и порты и все связанные статистические счётчики.

  • Клиентский сеанс SSL: протокол, версия, алгоритм, шифр, размер ключа, идентификатор сеанса, все поля сертификатов клиента и сервера, серийный номер сертификата, SNI, ALPN, NPN, поддержка клиентом определённых расширений.

  • Содержимое буферов запроса и ответа: произвольная полезная нагрузка по смещению и длине, длина данных, cookie RDP, декодирование типа приветствия SSL, декодирование TLS SNI.

  • HTTP, запрос и ответ: метод, URI, путь, аргументы строки запроса, код состояния, значения заголовков, значение заголовка по позиции, cookie, захваченные значения, аутентификация, элементы тела.

Затем образец может пройти через операторы, называемые преобразователями. Преобразователь принимает образец и создаёт новый, возможно совершенно другого типа. Например, он может вернуть целочисленную длину входной строки или перевести строку в верхний регистр. До окончательного использования к образцу можно последовательно применить любое число преобразователей. Среди доступных чаще всего используются:

  • Арифметические и логические операторы для сложных вычислений над входными данными: отношений, процентов или просто перевода между единицами измерения.

  • Маски IP-адресов, полезные для объединения адресов в более крупные сети.

  • Представление данных: декодирование URL, base64, шестнадцатеричный формат, строки JSON, хеширование.

  • Преобразование строк: извлечение подстрок по фиксированным позиции и длине, отдельных полей по разделителям и определённых слов, смена регистра, замена по регулярным выражениям.

  • Преобразование дат: в формат даты HTTP, из местного времени в UTC и обратно, добавление и вычитание смещения.

  • Поиск записи в таблице привязок для получения статистики или назначенного сервера.

  • Преобразование ключа в значение по карте отображения из файла, преимущественно для геолокации.

3.4.2. Стандартные возможности: карты отображения

Карты отображения — мощный тип преобразователя. При запуске в память загружается файл с двумя столбцами, затем каждый входной образец ищется в первом столбце. Если запись найдена, возвращается соответствующее значение из второго столбца, иначе — значение по умолчанию. Результат тоже является образцом, поэтому к нему можно применять последующие преобразования, включая поиск в других картах. Чаще всего карты используют для преобразования IP-адреса клиента в номер AS или код страны, поскольку они поддерживают наиболее длинное совпадение сетевых адресов, но возможны и многие другие применения.

Одно из их преимуществ — обновление на лету через CLI или определённые действия с использованием других образцов. Это позволяет хранить и извлекать сведения между последовательными обращениями. Другое преимущество — индексирование на основе двоичных деревьев: даже при сотнях тысяч записей поиск чрезвычайно быстр, поэтому геолокация требует мало ресурсов и легко настраивается.

3.4.3. Стандартные возможности: ACL и условия

Большинство операций HAProxy может выполняться условно. Условия строятся объединением нескольких ACL логическими операторами AND, OR и NOT. Каждая ACL представляет собой последовательность проверок на основе следующих элементов:

  • Метод извлечения образца для получения проверяемого элемента.

  • Необязательная последовательность преобразователей элемента.

  • Список шаблонов для сопоставления.

  • Метод сопоставления, определяющий способ сравнения шаблонов с образцом.

Например, образец можно получить из заголовка HTTP «Host», перевести в нижний регистр, а затем сопоставить с несколькими регулярными выражениями соответствующим методом.

Технически ACL построены на той же основе, что карты отображения: у них одинаковые внутренние структуры, методы сопоставления шаблонов и производительность. Единственное существенное отличие: вместо образца они возвращают только «found» или «not found». Шаблоны ACL можно объявлять прямо в конфигурации, отдельный файл не требуется. Для удобства и понятности конфигурации ACL можно именовать. Именованную ACL можно объявить несколько раз: все определения будут проверяться по очереди до первого совпадения.

Предоставляется около 13 методов сопоставления шаблонов, включая маску IP-адреса, диапазоны целых чисел, подстроки и регулярные выражения. Они работают как функции, и, как в любом языке программирования, вычисляется только необходимое. Если условие с OR уже истинно, следующие части не вычисляются; если условие с AND уже ложно, оставшаяся часть также не вычисляется.

Практического ограничения на число объявленных ACL нет, и несколько часто используемых ACL предоставляются готовыми. Однако опыт показывает, что конфигурации с множеством именованных ACL трудно отлаживать. Иногда проще использовать анонимные ACL прямо в правилах, поскольку приходится реже обращаться к определениям вне анализируемой области.

3.4.4. Стандартные возможности: переключение содержимого

HAProxy реализует механизм переключения на основе содержимого. Соединение или запрос поступает во фронтенд, затем обрабатываются переданные с ним сведения. На их основе можно задать условия ACL для выбора бэкенда, который обработает запрос. Так трафик направляется в разные бэкенды в зависимости от содержимого запроса. Типичный пример — использование заголовка Host и/или частей пути (подкаталогов либо расширений файлов), чтобы определить, относится ли запрос HTTP к статическому объекту или приложению. Статические объекты направляются в бэкенд из быстрых лёгких серверов, а остальной трафик — на более сложный сервер приложений. Получается гибкая схема виртуального хостинга, удобная для объединения нескольких технологий в общее решение.

Другой вариант применения — выбор алгоритма балансировки по разным критериям. Например, кеш может использовать хеш URI, а приложение — round-robin.

Наконец, механизм позволяет нескольким заказчикам использовать небольшие доли общего ресурса, ограничивая число соединений для каждого бэкенда, а значит, и заказчика.

Правила переключения содержимого хорошо масштабируются, хотя производительность может зависеть от числа и сложности ACL. Можно также использовать динамические правила, в которых значение образца напрямую преобразуется в имя бэкенда, вообще без ACL. Сообщалось об успешной работе таких конфигураций в рабочей среде как минимум с 300000 бэкендов.

3.4.5. Стандартные возможности: таблицы привязок

Таблицы привязок обычно хранят сведения о привязке сеансов — ссылку на сервер, куда был направлен посетитель. Ключом служит связанный с посетителем идентификатор: исходный адрес, идентификатор SSL соединения, cookie HTTP или RDP, номер заказчика из URL или полезной нагрузки и т. п. Сохраняемое значение — идентификатор сервера.

Таблицы привязок поддерживают 3 типа образцов в ключах: целые числа, строки и адреса. В прокси можно ссылаться только на одну таблицу привязок, везде обозначаемую именем прокси. Параллельно можно отслеживать до 8 ключей. Идентификатор сервера фиксируется при обработке запроса или ответа, когда известны и ключ, и сервер.

Содержимое таблиц может реплицироваться в режиме active-active с другими узлами HAProxy, называемыми «peers», а при перезагрузке конфигурации — также с новым процессом. Тогда все узлы балансировки имеют одинаковые сведения и принимают одинаковые решения о маршрутизации, даже если запросы клиента распределяются между несколькими узлами.

Поскольку таблицы индексируются по признаку, позволяющему распознать клиента, в них часто хранят и дополнительные сведения, например статистику по клиентам. Дополнительная статистика занимает место и должна объявляться явно. Можно хранить входящую и исходящую пропускную способность, число одновременных соединений, интенсивность и число соединений за период, количество и частоту ошибок, специальные метки и счётчики и т. п. Чтобы сохранять такие сведения без обязательной привязки к серверу, реализована специальная функция отслеживания. Она позволяет одновременно отслеживать до 3 ключей из разных таблиц независимо от правил привязки. Любую сохраняемую статистику можно искать, выгружать и очищать через CLI, расширяя возможности устранения неполадок в реальном времени.

Хотя этот механизм позволяет повышать приоритет возвращающегося посетителя или менять качество обслуживания в зависимости от хорошего или плохого поведения, чаще всего его используют для борьбы со злоупотреблениями и DDoS. Он позволяет строить сложные модели выявления нежелательного поведения при высокой скорости обработки.

3.4.6. Стандартные возможности: форматированные строки

HAProxy работает со строками во многих местах: в журналах, перенаправлениях, добавляемых заголовках и т. п. Для максимальной гибкости введены форматированные строки, первоначально для журналирования, поэтому механизм до сих пор называется «log-format». Такие строки содержат управляющие последовательности для вставки динамических данных, включая переменные и выражения извлечения образцов, и даже изменения кодирования при преобразовании результата в строку, например добавления кавычек. Это мощное средство формирования заголовков, данных ответа и даже шаблонов ответов, а также настройки строк журнала. Чтобы обычные строки оставались простыми в составлении, предусмотрено около 50 специальных меток — сокращений для часто используемых в журналах сведений.

3.4.7. Стандартные возможности: переписывание HTTP и перенаправления

Установка балансировщика перед приложением, которое на это не рассчитано, без подходящих инструментов может оказаться сложной. Одна из самых частых задач — изменить заголовки запросов и ответов, чтобы балансировщик выглядел исходным сервером, и исправить жёстко заданные сведения. Сюда относятся изменение пути запроса (что настоятельно не рекомендуется), поля Host, поля Location в ответах перенаправления, атрибутов пути и домена cookie и т. п. Также многие серверы слишком многословны и раскрывают в ответах лишние сведения, повышая уязвимость к целевым атакам. Хотя теоретически очищать ответы не задача балансировщика, на практике он расположен в наиболее удобной точке инфраструктуры для гарантированной очистки.

Иногда балансировщику также нужно перехватить запрос и ответить перенаправлением на новый URL. Перенаправление и переписывание иногда путают, но это совершенно разные понятия: при переписывании клиент и сервер видят разные данные и по-разному представляют расположение страницы, а перенаправление просит клиента обратиться к новому URL, чтобы он видел то же расположение, что и сервер.

Для этого HAProxy поддерживает разные возможности переписывания и перенаправления, в том числе:

  • Переписывание URL и заголовков запросов и ответов по регулярным выражениям. Это самый распространённый способ изменения значений заголовков благодаря понятности и удобству регулярных выражений.

  • Добавление, удаление или замена заголовков на основе форматированных строк для передачи сведений, например алгоритма и шифра TLS на стороне клиента.

  • Перенаправления HTTP с любым кодом 3xx на относительный, абсолютный или полностью динамический URI из форматированной строки.

  • Дополнительные параметры перенаправлений: установка или удаление cookie, отбрасывание строки запроса, добавление отсутствующей завершающей косой черты и т. п.

  • Мощная директива «return», позволяющая настроить любую часть ответа — состояние, заголовки, тело — с динамическим содержимым или даже файлами шаблонов.

  • Условия на основе ACL для всех операций.

3.4.8. Стандартные возможности: защита серверов

HAProxy стремится максимально повысить доступность службы и для этого защищает серверы от перегрузки и атак. Первый и самый важный принцип: серверам пересылаются только полные корректные запросы. Прежде всего HAProxy должен найти элементы протокола, необходимые для синхронизации с потоком байтов. Кроме того, пока запрос не получен полностью, нельзя знать, не изменят ли некоторые элементы его смысл. Прямое преимущество — серверы не получают некорректные или неполные запросы. Это очень эффективная защита от атак slowloris, практически не влияющих на HAProxy.

Другой важный момент — буферы HAProxy для запросов и ответов. Отправляя запрос серверу только после полного получения и быстро считывая весь ответ из локальной сети, HAProxy занимает соединение с сервером на очень короткое время, максимально сохраняя его ресурсы.

Из этого непосредственно следует возможность искусственно ограничивать число одновременных соединений или незавершённых запросов к серверу. Это гарантирует отсутствие перегрузки, даже если во время всплесков трафика сервер непрерывно работает на 100% мощности. Все лишние запросы просто ждут в очереди освобождения места. Такая огромная экономия ресурсов обычно настолько улучшает время ответа, что работа оказывается быстрее, чем при перегрузке сервера. Запросы из очереди можно перераспределять на другие серверы или даже отменять в очереди при отказе клиента от запроса. Это защищает и от «эффекта обновления страницы»: каждый щелчок «обновить» на медленно загружаемой странице обычно создаёт новый запрос и поддерживает перегрузку.

Механизм slow-start также защищает перезапускаемые серверы от интенсивного трафика, пока они ещё завершают запуск или компилируют классы.

На уровне протокола парсер HTTP можно ослабить, чтобы принимать не соответствующие стандарту, но безвредные запросы и ответы и даже исправлять их. Это сохраняет доступность ошибочных приложений на время разработки исправления. Одновременно проблемные сообщения полностью захватываются с подробным отчётом, помогающим разработчикам найти ошибку. Наиболее опасные нарушения протокола корректно выявляются, обрабатываются и исправляются. Например, некорректный запрос или ответ с двумя заголовками Content-length исправляется, если их значения в точности совпадают, и отклоняется при различии, поскольку это уже угроза безопасности. Анализ протокола не ограничен HTTP: он доступен и для других протоколов, например TLS или RDP.

При обнаружении нарушения протокола или атаки возможны разные реакции: обычный ответ «HTTP 400 bad request», закрытие соединения сбросом TCP или имитация ошибки после длительной задержки — ловушка соединений («tarpit»), сбивающая атакующего с толку. Всё это защищает серверы, делая продолжение атаки слишком затратным для нарушителя.

HAProxy также предлагает более сложные средства защиты от случайных утечек данных и смешения сеансов. Он может не только записывать подозрительные ответы сервера, но и журналировать и при необходимости блокировать ответ, угрожающий конфиденциальности посетителя. Например, кешируемый cookie в кешируемом ответе может быть выдан промежуточным кешем другому посетителю, случайно предоставив общий доступ к сеансу.

5 - Расширенные возможности

Управление во время работы, возможности операционной системы, скрипты Lua и трассировка в реальном времени

3.5.1. Расширенные возможности: управление

HAProxy спроектирован для исключительно стабильной работы и безопасного управления в обычной рабочей среде. Он поставляется одним исполняемым файлом и не требует процедуры установки. Несколько версий легко могут сосуществовать: экземпляры можно и рекомендуется обновлять постепенно, в порядке важности, вместо одновременного переноса всех экземпляров. Файлы конфигурации удобно хранить под контролем версий. Проверка конфигурации выполняется отдельно от работающей службы, поэтому не нужно перезапускать службу, рискуя получить сбой. При проверке могут обнаруживаться сложные ошибки (например, правило, скрывающее другое правило, или неработоспособная привязка сеансов); для их устранения выдаются подробные предупреждения и рекомендации. Обратная совместимость конфигурации охватывает очень давние версии: версия 1.5 полностью поддерживала конфигурации версии 1.1, написанные 13 лет назад, а в 1.6 прекращена поддержка лишь почти неиспользуемых устаревших директив, которые можно заменить другими средствами. Обновление конфигурации и программы происходит плавно и без прерывания обслуживания: старые и новые процессы могут сосуществовать в системе, каждый обрабатывая свои соединения. При запуске выводятся состояние системы, параметры сборки и сведения о совместимости библиотек.

Некоторые расширенные возможности позволяют администратору приложения плавно вывести сервер из обслуживания, определить момент прекращения активности, отключить его, остановить, обновить, обеспечить отсутствие трафика во время обновления, а затем снова проверить его через обычный путь доступа, не открывая доступ публике. Всё это не требует вмешательства в HAProxy. Благодаря этому даже сложные операции в рабочей среде можно выполнять в рабочее время, когда доступны все технические специалисты.

Процесс старается максимально экономить ресурсы: использует пулы памяти для сокращения времени выделения и ограничения фрагментации, освобождает буферы полезной нагрузки сразу после отправки их содержимого и поддерживает жёсткие пределы памяти. При достижении такого предела соединения ждут освобождения буфера вместо выделения дополнительной памяти. Этот механизм позволяет гарантировать потребление памяти в средах со строгими ограничениями.

Интерфейс командной строки (CLI) доступен через сокет UNIX или TCP и позволяет выполнять различные операции и получать сведения для устранения неполадок. Действия через этот сокет не требуют изменения конфигурации, поэтому его в основном используют для временных изменений. Через интерфейс можно менять адрес, вес и состояние сервера; просматривать статистику и сбрасывать счётчики; выгружать и очищать таблицы привязок, в том числе выборочно по критериям ключей; выводить и принудительно закрывать соединения со стороны клиентов и серверов; выгружать сохранённые ошибки с подробным анализом точной причины и места; выводить, добавлять и удалять записи ACL и карт отображения; обновлять общие секреты TLS; на лету ограничивать число соединений и их интенсивность для произвольных фронтендов (полезно в средах совместного хостинга); отключать отдельный фронтенд, освобождая прослушиваемый порт (полезно, если операции в дневное время запрещены, но исправление всё же необходимо). Также разрешены обновление сертификатов и их конфигурации на лету, включение и просмотр трассировки каждого этапа обработки трафика.

Для сред, где обязателен SNMP, существуют как минимум два агента. Один поставляется с исходным кодом HAProxy и использует модуль Perl Net-SNMP. Другой входит в коммерческие пакеты и не требует Perl. По охвату возможностей они примерно эквивалентны.

На машине с HAProxy часто рекомендуется установить 4 утилиты:

  • socat — для подключения к CLI, хотя некоторые варианты netcat тоже в определённой мере это умеют;

  • halog из последней версии HAProxy — инструмент анализа журналов, который чрезвычайно быстро (от 1 до 2 GB в секунду) разбирает собственные журналы TCP и HTTP и извлекает полезные сведения и статистику: запросы по URL и исходным адресам, URL, отсортированные по времени ответа или частоте ошибок, коды завершения и т. п. Он предназначен для установки на рабочих серверах и устранения неполадок в реальном времени, поэтому должен быть установлен и готов к использованию;

  • tcpdump — настоятельно рекомендуется для получения сетевых трассировок при исследовании проблем, замеченных в журналах. В какой-то момент анализ приложения и haproxy может разойтись, и только сетевые трассировки позволяют определить, кто прав. С помощью tcpdump также довольно часто обнаруживают ошибки сетевых стеков и гипервизоров;

  • strace — дополнение к tcpdump. Он показывает, что в действительности видит HAProxy, и помогает отделить проблемы операционной системы от проблем самого HAProxy. Strace часто запрашивают при подозрении на ошибку в HAProxy.

3.5.2. Расширенные возможности: системные функции

В зависимости от операционной системы, на которой развёрнут HAProxy, могут быть доступны или необходимы дополнительные возможности. Хотя HAProxy поддерживает ряд платформ, в основном его разрабатывают на Linux, поэтому некоторые функции доступны только на этой платформе.

Прозрачная привязка и установка соединений, привязка соединений к определённому сетевому интерфейсу, а также привязка нескольких процессов к одним IP-адресам и портам доступны только в Linux и BSD. При этом лишь Linux распределяет входящие запросы между доступными процессами средствами ядра.

Linux также предоставляет дополнительные возможности и оптимизации: поддержку сетевых пространств имён (также известных как «контейнеры»), позволяющую HAProxy служить шлюзом между всеми контейнерами; установку MSS, меток Netfilter и поля IP TOS для клиентского соединения; поддержку TCP FastOpen на стороне прослушивания; пользовательские тайм-ауты TCP, позволяющие ядру быстро закрыть соединение, если оно обнаружило исчезновение клиента до истечения заданных тайм-аутов; TCP splicing, при котором ядро пересылает данные между сторонами соединения без многократного копирования памяти; параметр привязки «defer-accept», чтобы получать уведомление о входящем соединении только после появления данных в буферах ядра; отправку запроса вместе с ACK, подтверждающим установку соединения (иногда называемую «piggy-back»), включаемую параметром «tcp-smart-connect». Кроме того, в Linux HAProxy тщательно управляет отложенными ACK TCP, чтобы максимально сократить число пакетов в сети.

В некоторых системах часы ненадёжны и скачут то назад, то вперёд. Раньше это встречалось на отдельных системах NUMA, где процессоры видели немного разное время. В последнее время проблема чаще возникает в виртуализированных средах, где виртуальные часы не связаны с реальными, из-за чего возможны огромные скачки времени — наблюдались даже скачки до 30 секунд. Это создаёт серьёзные проблемы с соблюдением тайм-аутов. Чтобы обойти этот недостаток, HAProxy поддерживает собственные монотонные часы, основанные на системных, но с измерением и компенсацией отклонения. Благодаря этому даже при очень плохих системных часах таймеры остаются достаточно точными, а тайм-ауты продолжают работать. Учтите, что проблема затрагивает все программы в такой системе и не специфична для HAProxy. Типичные проявления — ложные тайм-ауты или зависания приложений. Поэтому при обнаружении такого поведения систему необходимо исправить, даже несмотря на защиту HAProxy.

В Linux новый запускаемый процесс может связаться с предыдущим и повторно использовать его прослушивающие файловые дескрипторы, чтобы при замене процесса работа прослушивающих сокетов никогда не прерывалась.

3.5.3. Расширенные возможности: скрипты

HAProxy можно собрать с поддержкой встроенного языка Lua. Это открывает широкие возможности сложной обработки запросов и ответов, принятия решений о маршрутизации, обработки статистики и многого другого. Через Lua можно даже устанавливать параллельные соединения с другими серверами для обмена сведениями. Так можно, например, разработать систему аутентификации, хотя это и непросто. Подробнее об использовании Lua см. документацию в файле «doc/lua-api/index.rst».

3.5.4. Расширенные возможности: трассировка

Администратор в любой момент может подключиться к CLI и включить трассировку различных внутренних подсистем. По умолчанию доступны разные уровни детализации: на практике можно получать от одной строки до 500 строк на запрос. Доступны фильтры и механизм автоматического включения, выключения и приостановки захвата, позволяющие дождаться определённого события и подробно изучить его. Это исключительно удобно для диагностики нарушений протокола неисправными серверами и клиентами или атак отказа в обслуживании.

6 - Расчёт ресурсов и производительность

Принципы планирования ресурсов, порядок величин производительности и практические ориентиры

Типичные показатели использования CPU: в режиме TCP или HTTP с закрытием соединений на HAProxy приходится 15% времени обработки, а на ядро — 85%; в режиме постоянных соединений HTTP на HAProxy приходится около 30%, а на ядро — 70%. Это означает, что операционная система и её настройка сильно влияют на общую производительность.

Сценарии использования сильно различаются: одни пользователи ориентируются на пропускную способность, другие — на интенсивность запросов, число одновременных соединений или производительность SSL. В этом разделе приведены некоторые сведения, помогающие оценить необходимые ресурсы.

Важно помнить, что любая операция требует затрат: накладные расходы каждой операции прибавляются к остальным. В одних обстоятельствах они могут быть пренебрежимо малы, а в других — преобладать.

При обработке запросов в рамках соединения можно утверждать следующее:

  • Пересылка данных требует меньше ресурсов, чем разбор заголовков запроса или ответа.

  • Разбор заголовков запроса или ответа требует меньше ресурсов, чем установка и последующее закрытие соединения с сервером.

  • Установка и закрытие соединения требуют меньше ресурсов, чем возобновление TLS.

  • Возобновление TLS требует меньше ресурсов, чем полное рукопожатие TLS с вычислением ключа.

  • Бездействующее соединение потребляет меньше CPU, чем соединение, в буферах которого есть данные.

  • Контекст TLS требует ещё больше памяти, чем соединение с данными.

На практике обработка байтов полезной нагрузки обходится дешевле обработки байтов заголовков, поэтому высокой пропускной способности сети проще добиться с большими объектами (мало запросов на единицу объёма), чем с маленькими (много запросов на единицу объёма). Этим объясняется, почему максимальную пропускную способность всегда измеряют на больших объектах, а интенсивность запросов или соединений — на маленьких.

Некоторые операции хорошо масштабируются при использовании нескольких процессов на разных CPU, другие — хуже. Пропускная способность сети масштабируется лишь до определённого предела, поскольку для больших объектов узким местом редко бывает CPU: обычно ограничение задают сеть и шины данных, по которым передаются данные к сетевым интерфейсам. Интенсивность соединений плохо масштабируется на несколько процессоров из-за ряда системных блокировок при работе с таблицей локальных портов. Интенсивность запросов по постоянным соединениям масштабируется очень хорошо: такие запросы не требуют большого объёма памяти или пропускной способности сети и не обращаются к структурам с блокировками. Вычисление ключей TLS также отлично масштабируется, поскольку полностью ограничено ресурсами CPU. Возобновление TLS масштабируется умеренно хорошо, но примерно на 4 процессах достигает предела: накладные расходы доступа к общей таблице нивелируют небольшой выигрыш от дополнительных вычислительных ресурсов.

От хорошо настроенной системы можно ожидать показателей производительности в приведённых ниже пределах. Их важно воспринимать как порядок величин и учитывать возможные значительные отклонения в обе стороны в зависимости от процессора, настройки IRQ, типа памяти и сетевого интерфейса, настройки операционной системы и прочих факторов.

Следующие результаты получены на Core i7 с частотой 3.7 GHz и двухпортовыми сетевыми адаптерами 10 Gbps под управлением ядра Linux 3.10, HAProxy 1.6 и OpenSSL 1.0.2. HAProxy работал одним процессом на одном выделенном ядре CPU, а ещё два ядра были выделены для сетевых прерываний:

  • Максимальная пропускная способность сети без шифрования — 20 Gbps для объектов размером 256 kB и больше, 10 Gbps для объектов размером 41kB и больше.

  • 4.6 Gbps трафика TLS с шифром AES256-GCM на больших объектах.

  • 83000 соединений TCP в секунду от клиента до сервера.

  • 82000 соединений HTTP в секунду от клиента до сервера.

  • 97000 запросов HTTP в секунду в режиме server-close (постоянное соединение с клиентом, закрытие соединения с сервером).

  • 243000 запросов HTTP в секунду в режиме постоянных соединений на всём пути.

  • 300000 отфильтрованных соединений TCP в секунду (защита от DDoS).

  • 160000 запросов HTTPS в секунду в режиме постоянных соединений поверх постоянных соединений TLS.

  • 13100 запросов HTTPS в секунду с возобновляемыми соединениями TLS.

  • 1300 соединений HTTPS в секунду с повторным согласованием соединений TLS с использованием RSA2048.

  • 20000 одновременных полностью загруженных соединений на GB оперативной памяти, включая память системных буферов. Тщательная настройка позволяет улучшить этот показатель, но такого результата легко достичь.

  • Около 8000 одновременных соединений TLS (только со стороны клиента) на GB оперативной памяти, включая память системных буферов.

  • Около 5000 одновременных сквозных соединений TLS (с обеих сторон) на GB оперативной памяти, включая память системных буферов.

В более новом тесте многопоточный HAProxy 2.4 на 64-ядерном процессоре ARM Graviton2 в AWS достиг 2 миллионов запросов HTTPS в секунду при времени ответа менее миллисекунды и объёме трафика 100 Gbps:

https://www.haproxy.com/blog/haproxy-forwards-over-2-million-http-requests-per-second-on-a-single-aws-arm-instance/

Полезный практический ориентир: интенсивность запросов уменьшается в 10 раз при переходе от постоянных соединений TLS к возобновлению TLS и от возобновления TLS к повторному согласованию TLS, тогда как при переходе от постоянных соединений HTTP к закрытию соединений HTTP она уменьшается лишь в 3 раза. Ещё один ориентир: высокочастотное ядро с инструкциями AES может обрабатывать около 20 Gbps AES-GCM на ядро.

Также полезно учитывать, что на том же сервере HAProxy способен полностью загрузить:

  • около 5-10 серверов статических файлов или кеширующих прокси;

  • около 100 антивирусных прокси;

  • около 100-1000 серверов приложений в зависимости от используемой технологии.

7 - Выпуски, пакеты и обновления

Стабильные ветки, источники выпусков, определение версии, сопровождение и обновления

HAProxy — проект с открытым исходным кодом под лицензией GPLv2. Это означает, что его разрешено распространять при условии предоставления доступа к исходному коду по запросу, особенно если в него внесены изменения.

HAProxy развивается в основной ветке разработки «master» или «mainline», от которой создают новые ветки, когда код считается стабильным. Многие сайты добровольно используют ветки разработки в рабочей среде — чтобы участвовать в проекте или потому, что им нужна самая новая функция. Их обратная связь очень ценна для исправления ошибок и оценки общего качества и стабильности разрабатываемой версии.

Новые ветки, создаваемые после достижения достаточной стабильности кода, образуют стабильную версию и обычно сопровождаются несколько лет. Поэтому даже при использовании не самой новой ветки срочно переходить на следующую не требуется. После выпуска стабильная ветка получает только исправления ошибок и очень редко небольшие обновления функций, облегчающие жизнь пользователям. Все исправления в стабильной ветке обязательно происходят из ветки master. Это гарантирует, что после обновления ни одно исправление не потеряется. Поэтому, исправляя ошибку, готовьте патч для master, а не для стабильной ветки. Возможно, вы обнаружите, что ошибка уже исправлена. Этот процесс также делает регрессии в стабильной ветке исключительно редкими, поэтому нет причин отказываться от обновления до последней версии текущей ветки.

Номер ветки состоит из двух чисел, разделённых точкой, например «1.6». Начиная с 1.9 ветки с нечётным вторым числом в основном предназначены для существенных технических изменений и опытных пользователей, поскольку в них вероятнее появление ошибок. Они сопровождаются лишь около года, и их нельзя развёртывать там, где невозможно экстренно откатить обновление. Полный номер версии включает один или два номера подверсии, обозначающих уровень исправлений. Например, 1.5.14 — это 14-й корректирующий выпуск ветки 1.5 после выхода 1.5.0. Он содержит 126 исправлений отдельных ошибок, 24 обновления документации и 75 других перенесённых патчей, большинство из которых требовалось для исправления указанных 126 ошибок. Существующую функцию в стабильной ветке нельзя изменять или удалять: это гарантирует безопасность обновлений в пределах одной ветки.

HAProxy доступен из нескольких источников с разной частотой выпусков:

  • Официальный сайт сообщества http://www.haproxy.org/ предоставляет исходный код последнего выпуска разработки, всех стабильных выпусков и ночные снимки каждой ветки. Цикл выпусков небыстрый: между стабильными выпусками или снимками разработки проходит несколько месяцев. Там по-прежнему поддерживаются очень старые версии. Всё предоставляется только в виде исходного кода, поэтому полученное оттуда нужно собирать и/или упаковывать заново.

  • GitHub https://github.com/haproxy/haproxy/ — зеркало только ветки разработки, обеспечивающее интеграцию с системой отслеживания задач, непрерывной интеграцией и инструментами покрытия кода. Оно предназначено исключительно для участников разработки.

  • Ряд операционных систем, например дистрибутивы Linux и порты BSD, обычно предоставляют версии с длительным сопровождением. В них не всегда есть все исправления официальных выпусков, но как минимум критические исправления присутствуют. Часто это хороший вариант для большинства пользователей, которым не нужны сложные конфигурации и важно простое обновление.

  • Коммерческие версии с http://www.haproxy.com/ — профессиональные пакеты с поддержкой, собранные для разных операционных систем или поставляемые как готовые устройства. Они основаны на последних стабильных версиях и включают востребованные функции, перенесённые из следующего выпуска. Это лучший вариант для пользователей, которым нужны новейшие функции с надёжностью стабильной ветки, максимально быстрое исправление ошибок либо просто договор поддержки продукта с открытым исходным кодом.

Чтобы убедиться, что используется последняя версия своей ветки, действуйте следующим образом:

  • Проверьте, какой исполняемый файл HAProxy запускается. В некоторых системах он поставляется по умолчанию, а администраторы устанавливают свои версии в другом месте. Поэтому важно проверить используемый файл в сценариях запуска.

  • Определите источник своей версии HAProxy. Обычно достаточно команды «haproxy -v». Версия разработки выглядит следующим образом: после номера ветки стоит слово «dev».

HAProxy version 2.4-dev18-a5357c-137 2021/05/09 - https://haproxy.org/
Стабильная версия выглядит следующим образом, как и неизменённые стабильные

версии, поставляемые производителями операционных систем:

HAProxy version 1.5.14 2015/07/02
Ночной снимок стабильной версии выглядит следующим образом: после номера
версии идёт шестнадцатеричная последовательность, а дата снимка указывается

вместо даты выпуска:

HAProxy version 1.5.14-e4766ba 2015/07/29
Любой другой формат может указывать на пакет для конкретной системы
с собственным набором патчей. Например, версии HAProxy Enterprise отображаются

в следующем формате (<branch>-<latest commit>-<revision>):

HAProxy version 1.5.0-994126-357 2015/07/02
Обратите внимание: версии до 2.4 выводили имя процесса с дефисом между
"HA" и "Proxy". Это относится и к версиям выше, примеры которых исправлены
лишь для демонстрации правильного формата. Поэтому в сценариях лучше
игнорировать это слово или использовать менее строгое сопоставление.
Кроме того, современные версии добавляют URL домашней страницы проекта.

Наконец, версии 2.1 и выше включают строку "Status", указывающую,
безопасно ли использовать версию в рабочей среде и, если да, до какого
срока, а также ссылку на список известных ошибок этой версии.
  • Для системных пакетов проверьте репозиторий пакетов или систему обновлений поставщика, чтобы убедиться, что система всё ещё поддерживается и для вашей ветки выпускаются исправления. Для версий сообщества с haproxy.org посетите сайт, проверьте состояние ветки и сравните последнюю версию со своей. Если ваша версия не последняя, её можно обновить. Если ветка больше не сопровождается, вы сильно отстали и должны рассмотреть переход на более новую ветку, внимательно прочитав README.

HAProxy следует обновлять способом, соответствующим его источнику. Обычно это стандартная процедура обновления пакета у поставщика системы. Если HAProxy собран из исходного кода, после распаковки прочитайте README в каталоге исходников и следуйте инструкциям для своей операционной системы.

8 - Сопутствующие продукты и альтернативы

Взаимодействие HAProxy с Apache, NGINX, Varnish, LVS, Envoy и другими балансировщиками нагрузки

HAProxy хорошо сочетается с некоторыми перечисленными ниже продуктами. Поэтому они упомянуты здесь, хотя и не связаны непосредственно с HAProxy.

4.1. HTTP-сервер Apache

Apache — фактический стандарт среди серверов HTTP. Это очень функциональный модульный проект, поддерживающий как выдачу файлов, так и динамическое содержимое. Он может служить фронтендом для серверов приложений, а также проксировать запросы и кешировать ответы. Во всех этих сценариях перед ним обычно требуется балансировщик нагрузки. Apache может работать в разных режимах, одни из которых требуют больше ресурсов, чем другие. Некоторые модули до сих пор требуют более тяжёлой модели с заранее созданными процессами, что мешает Apache эффективно работать с большим числом соединений. В таком случае HAProxy может значительно помочь: он ограничивает число соединений с каждым сервером безопасным значением, заметно ускоряя сервер и сохраняя его ресурсы для приложения.

Apache может извлекать адрес клиента из заголовка X-Forwarded-For с помощью расширения «mod_rpaf». HAProxy автоматически заполняет этот заголовок, если в конфигурации задано «option forwardfor». HAProxy также может хорошо защищать Apache, доступный из интернета, поскольку лучше противостоит многим видам атак DoS.

4.2. NGINX

NGINX — второй фактический стандарт среди серверов HTTP. Как и Apache, он предоставляет широкий набор функций. NGINX построен по модели, сходной с HAProxy, поэтому без труда обрабатывает десятки тысяч одновременных соединений. При использовании в качестве шлюза к приложениям (например, через включённый PHP FPM) часто полезно ограничить число соединений на входе, чтобы снизить нагрузку на приложение PHP. Здесь HAProxy пригодится и как обычный балансировщик нагрузки, и как регулятор трафика, ускоряющий PHP за счёт устранения перегрузки. Кроме того, благодаря событийной архитектуре оба продукта потребляют мало CPU, и их часто легко разместить в одной системе. NGINX поддерживает протокол PROXY от HAProxy, поэтому HAProxy легко передаёт ему сведения о клиентском соединении, необходимые приложению. Некоторые тесты также показали, что при выдаче больших статических файлов согласованное хеширование в HAProxy перед NGINX может повысить долю попаданий в кеш операционной системы, фактически умножая её на число серверных узлов.

4.3. Varnish

Varnish — интеллектуальный кеширующий обратный прокси, который, пожалуй, точнее всего назвать ускорителем веб-приложений. Varnish не реализует SSL/TLS, предпочитая отдавать все ресурсы CPU тому, что умеет лучше всего. Он также поддерживает протокол PROXY от HAProxy, поэтому HAProxy легко развернуть перед Varnish для обработки SSL и балансировки нагрузки с передачей всех необходимых сведений о клиенте. Кроме того, Varnish умеет распаковывать объекты из кеша, если сервер передал их сжатыми, но сам сжатие не выполняет. Если серверы бэкенда не поддерживают сжатие, исходящие данные можно сжимать в HAProxy, хотя делать это на балансировщике редко бывает хорошей идеей, кроме случаев небольшого трафика.

При построении больших кеширующих ферм из нескольких узлов HAProxy может применять согласованное хеширование URL для разумного распределения нагрузки между кеширующими узлами и предотвращения дублирования кеша. Тогда общий размер кеша равен сумме кешей всех узлов. Кроме того, кратковременное кеширование очень маленьких простых объектов в HAProxy иногда позволяет избежать сетевых обменов и снизить нагрузку на CPU как узлов HAProxy, так и Varnish. Это возможно только тогда, когда Varnish никак не обрабатывает эти объекты. Такой подход часто называют «кешем favicon»: иногда он позволяет исключить заметную долю бесполезных запросов к следующему уровню. Однако не включайте длительное кеширование в HAProxy (более нескольких секунд) перед другим кешем: это значительно усложнит устранение неполадок без существенной экономии ресурсов.

4.4. Альтернативы

Linux Virtual Server (LVS или IPVS) — балансировщик нагрузки уровня 4, встроенный в ядро Linux. Он работает на уровне пакетов и обрабатывает TCP и UDP. В большинстве случаев он скорее дополняет HAProxy, чем заменяет его, поскольку совершенно не понимает уровень 7.

Pound — ещё один известный балансировщик нагрузки. Он значительно проще HAProxy и обладает гораздо меньшим числом функций, но для многих простейших конфигураций подходят оба продукта. Автор Pound всегда ставил на первое место возможность аудита кода и стремится сохранять небольшой набор функций. Его архитектура на основе потоков хуже масштабируется при большом числе соединений, но это хороший продукт.

Pen — довольно лёгкий балансировщик нагрузки. Он поддерживает SSL и сохраняет привязку с помощью таблицы фиксированного размера с IP-адресами клиентов. У него есть режим работы с пакетами, позволяющий в определённых пределах поддерживать прямой ответ сервера и UDP. Он рассчитан на небольшие нагрузки: таблица привязок содержит всего 2048 записей.

NGINX в определённой мере умеет балансировать нагрузку, хотя это явно не его основное назначение. Сбои серверов выявляются по рабочему трафику, набор алгоритмов балансировки более ограничен, а поддержка привязки сеансов очень невелика. Но он может быть уместен в простых схемах развёртывания, где уже используется. Поскольку NGINX отлично сочетается с HAProxy, ничто не мешает добавить HAProxy позже, когда возможности NGINX будут исчерпаны.

Varnish также балансирует нагрузку между своими серверами бэкенда и поддерживает полноценные проверки работоспособности. Однако привязку сеансов он не реализует, поэтому, как и в случае NGINX, его может быть достаточно для начала, если привязка не нужна. И аналогично, благодаря хорошей совместимости HAProxy и Varnish, HAProxy легко добавить позже, чтобы расширить набор возможностей.

9 - Документация и сообщество

Комплект руководств проекта, расположение исходников, каналы поддержки, контакты и лицензирование

1. Доступная документация

Полная документация HAProxy содержится в перечисленных ниже документах. Обращайтесь к соответствующей документации, чтобы сэкономить время и получить наиболее точный ответ на свой вопрос. Также воздержитесь от отправки в список рассылки вопросов, ответы на которые уже есть в этих документах.

  • intro.txt (этот документ): здесь представлены основы балансировки нагрузки, HAProxy как продукт, его возможности и ограничения, известные подводные камни, которых следует избегать, некоторые ограничения конкретных ОС, способы получения, развитие проекта, способы убедиться, что используются все известные исправления, обновление, дополнения и альтернативы.

  • management.txt : объясняет, как запускать haproxy, управлять им во время выполнения, управлять им на нескольких узлах и выполнять обновления без перерыва в обслуживании.

  • configuration.txt : справочное руководство подробно описывает все ключевые слова конфигурации и их параметры. Оно используется, когда требуется изменить конфигурацию.

  • coding-style.txt: предназначен для разработчиков, которые хотят предложить проекту свой код. В нём объясняется стиль, которого следует придерживаться при написании кода. Правила не очень строгие, и не вся кодовая база полностью им соответствует, но изменения, слишком сильно от них отклоняющиеся, будут отклонены.

  • proxy-protocol.txt: фактическая спецификация протокола PROXY, реализованного в HAProxy и ряде сторонних продуктов.

  • security.txt: как сообщить о проблеме безопасности и что считается или не считается уязвимостью.

  • README: как собрать HAProxy из исходного кода

5. Контакты

Если требуется связаться с разработчиками или любым участником сообщества по какому-либо вопросу, обычно лучше всего воспользоваться списком рассылки, отправив сообщение на haproxy@formilux.org . Учтите, что список рассылки и его архивы общедоступны, поэтому следует избегать раскрытия конфиденциальной информации. В нём участвует тысяча пользователей с разным уровнем опыта, и даже на самые сложные вопросы обычно удаётся сравнительно быстро найти оптимальный ответ. Предложения тоже приветствуются. Для пользователей, которым сложно пользоваться электронной почтой, доступна платформа Discourse по адресу http://discourse.haproxy.org/ . Однако учитывайте, что вопросы там читает меньше людей и на большинство из них отвечает очень небольшая команда. В любом случае проявляйте терпение и уважение к тем, кто посвящает своё свободное время помощи другим.

Если кажется, что обнаружена ошибка, но уверенности нет, лучше сообщить об этом в список рассылки. Если есть твёрдая уверенность, что обнаружена ошибка, используется актуальная версия своей ветки и уже есть учётная запись GitHub, можно сразу перейти на https://github.com/haproxy/haproxy/ и создать сообщение об ошибке со всеми доступными подробностями. Этот ресурс тоже общедоступен, поэтому не публикуйте информацию, о раскрытии которой впоследствии можно пожалеть. Поскольку система отслеживания ошибок представляет обсуждение в виде очень длинной ветки, не вставляйте очень длинные дампы (несколько сотен строк и более) в текст, а прикладывайте их как вложения.

Если есть основания полагать, что обнаружена проблема безопасности, обратитесь к файлу doc/security.txt. Он объясняет, что считается или не считается уязвимостью HAProxy и как конфиденциально сообщить о настоящей уязвимости. Большинство предполагаемых проблем безопасности оказываются обычными ошибками, о которых лучше сообщать описанным выше способом.

Полный комплект локальных руководств

Происхождение издания

10 - 1. Краткое напоминание об HTTP

Транзакции HTTP, запросы, ответы, заголовки и терминология протокола

Этот документ описывает язык конфигурации в реализации указанной выше версии. Он не содержит подсказок, примеров или рекомендаций. За такими сведениями обращайтесь к справочному руководству или руководству по архитектуре. Пронумерованные главы расположены в плоской боковой панели HAProxy для прямого перехода.

Когда HAProxy работает в режиме HTTP, и запрос, и ответ полностью анализируются и индексируются. Это позволяет строить критерии сопоставления практически по любым элементам содержимого.

Однако важно понимать устройство запросов и ответов HTTP и то, как HAProxy разбирает их на части. Тогда будет проще писать корректные правила и отлаживать существующие конфигурации.

Прежде всего, HTTP стандартизован серией RFC, которым HAProxy следует максимально точно:

  • RFC 9110: семантика HTTP (объясняет смысл элементов протокола).
  • RFC 9111: кеширование HTTP (описывает правила, которым должен следовать кеш HTTP).
  • RFC 9112: HTTP/1.1 (представление, правила взаимодействия, безопасность).
  • RFC 9113: HTTP/2 (представление, правила взаимодействия, безопасность).
  • RFC 9114: HTTP/3 (представление, правила взаимодействия, безопасность).

Кроме того, RFC с 8999 по 9002 определяют транспортный уровень QUIC, используемый протоколом HTTP/3.

1.1. Модель транзакций HTTP

Протокол HTTP основан на транзакциях. Это означает, что каждый запрос приводит ровно к одному ответу. Изначально, в версии 1.0, на соединение приходился один запрос: клиент устанавливал соединение TCP с сервером, отправлял по нему запрос, сервер отвечал, после чего соединение закрывалось. Для нового запроса требовалось новое соединение:

[CON1] [REQ1] ... [RESP1] [CLO1] [CON2] [REQ2] ... [RESP2] [CLO2] ...

В этом режиме, часто называемом «HTTP close», число установок соединений равно числу транзакций HTTP. Поскольку сервер закрывает соединение после ответа, клиенту не нужно знать длину содержимого: он считает ответ завершённым при закрытии соединения. Это также означает, что при обрыве ответа из-за сетевой ошибки клиент мог ошибочно счесть его полным; раньше это иногда приводило к отображению обрезанных изображений.

Транзакционная природа протокола позволила усовершенствовать его, исключив закрытие соединения между двумя последовательными транзакциями. Однако в таком режиме сервер обязан указывать длину содержимого каждого ответа, чтобы клиент не ждал бесконечно. Для этого используется специальный заголовок «Content-length». Этот режим называется «keep-alive» и появился в HTTP/1.1 (его поддерживают некоторые агенты HTTP/1.0), а соединения, повторно используемые между запросами, называются постоянными:

[CON] [REQ1] ... [RESP1] [REQ2] ... [RESP2] [CLO] ...

Преимущества — меньшая задержка между транзакциями, меньшие затраты вычислительных ресурсов сервера и возможность обнаруживать обрезанные ответы. Обычно этот режим быстрее режима закрытия соединений, но не всегда: некоторые клиенты ограничивают число одновременных соединений меньшим значением и потому хуже компенсируют низкое качество сети. Кроме того, некоторым серверам приходится долго держать соединения открытыми в ожидании нового запроса, что при большом числе соединений может потреблять много памяти. Слишком быстрое закрытие может нарушить обработку запросов, пришедших в момент закрытия соединения.

В этом режиме размер ответа нужно знать заранее, что не всегда возможно для динамически формируемого или сжатого содержимого. Поэтому был реализован другой режим — «chunked mode». Вместо объявления полного размера отправитель сообщает только размер следующего фрагмента ответа, уже находящегося в буфере, и может завершить передачу в любой момент фрагментом нулевого размера. В этом режиме заголовок Content-Length не используется.

Ещё одно улучшение обмена — конвейерный режим. Он по-прежнему использует постоянные соединения, но клиент не ждёт первого ответа, чтобы отправить второй запрос. Это удобно при загрузке большого числа изображений страницы:

[CON] [REQ1] [REQ2] ... [RESP1] [RESP2] [CLO] ...

Очевидно, что устранение сетевой задержки между последовательными запросами может значительно повысить производительность. Многие агенты HTTP некорректно поддерживают конвейерную обработку, поскольку HTTP не позволяет явно связать ответ с соответствующим запросом. Поэтому сервер обязан отвечать строго в порядке получения запросов. На практике после нескольких попыток внедрения в разных клиентах от этого режима полностью отказались из-за ненадёжной работы с некоторыми серверами. Однако серверы обязаны его поддерживать.

Следующее усовершенствование — мультиплексирование, реализованное в HTTP/2 и HTTP/3. В этом режиме несколько транзакций, то есть пар «запрос — ответ», передаются параллельно по одному соединению и продвигаются независимо, каждая со своей скоростью. Для описания таких параллельных обменов в одном соединении протоколы с мультиплексированием ввели понятие потока. Каждому потоку обычно назначается уникальный в рамках соединения идентификатор, по которому обе стороны определяют, куда направлять данные. Клиенты довольно часто запускают множество потоков (до 100, иногда больше) параллельно по одному соединению, позволяя серверу обрабатывать их и отвечать в любом порядке по мере готовности ответов. Главное преимущество мультиплексирования — значительное сокращение числа сетевых обменов и ускорение загрузки страниц в сетях с высокой задержкой. Иногда это заметно на сайтах с большим числом изображений, где все изображения будто загружаются одновременно.

Эти протоколы также повысили эффективность за счёт механизмов сжатия полей заголовков, уменьшающих число передаваемых байтов. Поэтому без соответствующих инструментов их практически невозможно обрабатывать вручную или читать невооружённым глазом, как HTTP/1. По этой причине в литературе, включая этот документ, примеры сообщений HTTP продолжают представлять в синтаксисе HTTP/1 даже для новых версий протокола.

У HTTP/2 есть ограничения архитектуры: например, потеря пакетов затрагивает сразу все потоки. Если клиент слишком долго получает объект, например записывает его на диск, он может замедлить получение и тем самым временно сделать недоступными данные, ожидающие за этим объектом. Это называется блокировкой начала очереди — «head of line blocking», «HoL blocking» или просто «HoL».

HTTP/3 реализован поверх QUIC, который, в свою очередь, работает поверх UDP. QUIC устраняет блокировку начала очереди на транспортном уровне за счёт независимой обработки потоков. При потере данных затронутый поток не влияет на остальные, и все потоки доступны параллельно. QUIC также поддерживает миграцию соединений, но в настоящее время haproxy её не поддерживает.

По умолчанию HAProxy использует режим постоянных соединений: для каждого соединения он обрабатывает запросы и ответы и оставляет соединение открытым, но бездействующим с обеих сторон между окончанием ответа и началом следующего запроса. При получении клиентского соединения HTTP/2 он параллельно обрабатывает все запросы и оставляет соединение в ожидании новых, как обычное постоянное соединение HTTP.

В основном HAProxy поддерживает 3 режима соединений:

  • keep alive: обрабатываются все запросы и ответы, а соединения со стороны клиента и сервера сохраняются для новых запросов. Это режим по умолчанию, подходящий для современного веба и современных протоколов HTTP/2 и HTTP/3.

  • server close: соединение с сервером закрывается после ответа.

  • close: после завершения ответа соединение активно закрывается с обеих сторон.

Кроме того, по умолчанию соединение с сервером может повторно использоваться любым запросом любого клиента, как требует спецификация HTTP. Поэтому необходимые сведения о конкретном клиенте, например исходный адрес, нужно передавать с каждым запросом. При использовании HTTP/2 с сервером HAProxy по умолчанию выделяет это соединение одному клиенту, чтобы избежать риска блокировки начала очереди между клиентами.

1.2. Терминология

Терминология HAProxy со временем немного менялась вслед за развитием протокола HTTP и способов его использования. Изначально существенных различий между соединением, сеансом, потоком и транзакцией не было. Со временем понятия уточнили в соответствии с современными версиями HTTP, хотя ради исторической совместимости некоторые термины сохранились в конфигурации и интерфейсе командной строки.

Следующие определения относятся к текущей версии HAProxy:

  • Соединение: отдельный двунаправленный канал связи между удалённым агентом (клиентом или сервером) и haproxy на самом низком возможном уровне. Обычно это сокет TCP между парой IP-адресов и портов. На клиентской стороне соединения создаются самыми первыми при подключении клиента к haproxy, и правила уровня соединения применяются раньше всех остальных.

  • Сеанс: добавляет к соединению контекстные сведения, в том числе информацию транспортного уровня (например, ключи TLS) или переменные. Долгое время этот термин в HAProxy обозначал сквозной обмен HTTP/1.0 между двумя сторонами. Поэтому он сохранился в именах некоторых команд CLI и статистических показателей, хотя теперь они представляют потоки; справка и описания стараются устранить неоднозначность. Термин по-прежнему уместен на сетевом уровне (например, сеансы TCP в операционной системе или через межсетевой экран) и в пользовательских приложениях, не использующих HTTP (например, сеанс telnet или SSH). Его нельзя путать с сеансами приложения, которые хранят полный контекст пользователя в cookie и требуют направления запросов на один сервер.

  • Поток: в точности соответствует сквозному двунаправленному обмену на уровне приложения, где могут применяться анализ и преобразования. В HTTP он содержит один запрос и связанный с ним ответ, создаётся при поступлении запроса и завершается по окончании доставки ответа. В этом контексте между таким потоком и потоком мультиплексируемого протокола существует соответствие 1:1. При обмене по TCP на соединение приходится один поток.

  • Транзакция: только пара из запроса и связанного с ним ответа. До появления потоков термин использовали вместе с сеансами, но теперь транзакция и поток находятся в отношении 1:1. Главным образом он встречается в области видимости переменных «txn», действующей на протяжении всей транзакции, а значит, и потока.

  • Запрос: трафик от клиента к серверу. Термин преимущественно используется в HTTP для указания направления выполнения операций. Он также применяется к операциям TCP, обозначая направление обработки данных. Запросы часто используются в счётчиках как единица трафика или активности. Не каждый запрос получает ответ, например из-за ошибок, но поскольку самопроизвольных ответов без запросов не бывает, запросы остаются подходящей мерой общей активности. В TCP число запросов равно числу соединений.

  • Ответ: трафик от сервера к клиенту, а иногда от HAProxy к клиенту, если HAProxy сам формирует ответ, например перенаправление HTTP.

  • Служба: обычно внутренняя обработка в HAProxy, не требующая сервера, например страница статистики, кеш или код Lua, реализующий небольшое приложение. Как правило, служба читает запрос, выполняет операции и формирует ответ.

1.3. Запрос HTTP

Сначала рассмотрим следующий запрос HTTP:

Номер    Содержимое
строки
   1     GET /serv/login.php?lang=en&profile=2 HTTP/1.1
   2     Host: www.mydomain.com
   3     User-agent: my small browser
   4     Accept: image/jpeg, image/gif
   5     Accept: image/png

1.3.1. Строка запроса

Строка 1 — это строка запроса. Она всегда состоит из 3 полей:

  • Метод: GET.
  • URI: /serv/login.php?lang=en&profile=2.
  • Метка версии: HTTP/1.1.

Все поля разделяются тем, что стандарт называет LWS — линейными пробельными символами. Обычно это пробелы, но возможны также табуляции либо переводы строки/возвраты каретки с последующими пробелами или табуляциями. Сам метод не может содержать двоеточие (’:’) и состоит только из букв алфавита. Из-за множества комбинаций лучше, чтобы HAProxy сам разбивал строку на части, а не заставлял пользователя писать сложное или неточное регулярное выражение.

URI может иметь несколько форм:

  • Относительный URI:
  /serv/login.php?lang=en&profile=2

Это полный URL без части, обозначающей узел. Обычно именно в таком виде
его получают серверы, обратные прокси и прозрачные прокси.
  • Абсолютный URI, также называемый URL:
  http://192.168.0.12:8080/serv/login.php?lang=en&profile=2

Он состоит из схемы (имени протокола с последующим '://'), имени или
адреса узла, необязательного двоеточия (':') с номером порта, а затем
относительного URI, начинающегося с первой косой черты ('/') после
адресной части. Обычно такую форму получают прокси, но сервер,
поддерживающий HTTP/1.1, также обязан её принимать.
  • Звёздочка (’*’): эта форма разрешена только с методом OPTIONS и не подлежит ретрансляции. Она используется для запроса возможностей следующего узла.

  • Сочетание адреса и порта: 192.168.0.12:80. Используется с методом CONNECT для установки туннелей TCP через прокси HTTP, обычно для HTTPS, но иногда и для других протоколов.

В относительном URI выделяют две части. Часть до вопросительного знака называется путём. Обычно это относительный путь к статическим объектам на сервере. Часть после вопросительного знака называется строкой запроса. Она в основном используется в запросах GET к динамическим скриптам и сильно зависит от языка, фреймворка или приложения.

HTTP/2 и HTTP/3 не передают сведения о версии вместе с запросом: предполагается версия используемого протокола, например «HTTP/2». Кроме того, эти протоколы не передают строку запроса целиком, а разбивают её на отдельные поля — псевдозаголовки, имена которых начинаются с двоеточия. HAProxy для удобства собирает их в эквивалентную строку запроса. Поэтому строки запросов в журналах могут немного различаться для HTTP/1.x и HTTP/2 или HTTP/3.

1.3.2. Заголовки запроса

Заголовки начинаются со второй строки. В начале строки находится имя, сразу за ним — двоеточие (’:’). Традиционно после двоеточия добавляют LWS, но это не обязательно. Далее идут значения. Несколько одноимённых заголовков можно объединить в одну строку, разделяя значения запятыми и сохраняя их порядок. Это часто встречается в поле «Cookie:». Заголовок может занимать несколько строк, если последующие строки начинаются с LWS. В примере из 1.3 строки 4 и 5 задают суммарно 3 значения заголовка «Accept:». Наконец, согласно спецификации все LWS в начале и конце заголовка игнорируются и не входят в значение.

Вопреки распространённому заблуждению, имена заголовков нечувствительны к регистру. Их значения также нечувствительны к регистру, если ссылаются на имена других заголовков, как в «Connection:». В HTTP/2 и HTTP/3 имена заголовков всегда передаются в нижнем регистре, что видно в режиме отладки. Внутри HAProxy все имена заголовков приводятся к нижнему регистру, чтобы HTTP/1.x и HTTP/2 или HTTP/3 использовали одно и то же представление, и в таком виде передаются другой стороне. Поэтому запрос HTTP/1.x, введённый с именами в смешанном регистре, доставляется с именами в нижнем регистре.

Первая пустая строка обозначает конец заголовков. Часто говорят о двойном переводе строки, что неточно, хотя двойной перевод строки — одна из допустимых форм пустой строки.

К счастью, HAProxy сам обрабатывает все эти сложные сочетания при индексации заголовков, проверке значений и подсчёте. Поэтому об их конкретном оформлении можно не беспокоиться, но важно не обвинять приложение в ошибке, если оно использует необычные, но допустимые конструкции.

Важное примечание:

Как рекомендует RFC7231, HAProxy нормализует заголовки, заменяя переводы
строк внутри них на LWS, чтобы объединить многострочные заголовки.
Это необходимо для корректного анализа и помогает менее совершенным
средствам разбора HTTP работать правильно, не позволяя таким сложным
конструкциям вводить их в заблуждение.

1.4. Ответ HTTP

Ответ HTTP очень похож на запрос HTTP. И тот и другой называют сообщениями HTTP. Рассмотрим следующий ответ:

Номер    Содержимое
строки
   1     HTTP/1.1 200 OK
   2     Content-length: 350
   3     Content-Type: text/html

Особый случай в HTTP — так называемые информационные ответы с кодами состояния 1xx. Они не содержат никакой части ответа, а служат сигнальными сообщениями, например чтобы попросить клиента продолжить отправку запроса. При коде 100 запрошенные сведения содержатся в следующем после информационного сообщении ответа с кодом, отличным от 100. Это означает, что на один запрос может быть отправлено несколько ответов и что такое возможно только при включённых постоянных соединениях (сообщения 1xx появились в HTTP/1.1). HAProxy умеет корректно пересылать и пропускать эти сообщения, обрабатывая лишь следующий ответ с кодом, отличным от 100. Поэтому такие сообщения не записываются в журнал и не преобразуются, если явно не указано иное. Сообщения с кодом 101 означают смену протокола в том же соединении, и HAProxy должен перейти в туннельный режим, как после CONNECT. Заголовок Upgrade в таком случае содержит дополнительные сведения о протоколе, на который переключается соединение.

1.4.1. Строка ответа

Строка 1 — это строка ответа. Она всегда состоит из 3 полей:

  • Метка версии: HTTP/1.1.
  • Код состояния: 200.
  • Причина: OK.

Код состояния всегда состоит из 3 цифр. Первая обозначает общую категорию:

  • 1xx = информационное сообщение, которое следует пропустить (например, 100, 101).
  • 2xx = OK, далее следует содержимое (например, 200, 206).
  • 3xx = OK, далее содержимого нет (например, 302, 304).
  • 4xx = ошибка по вине клиента (например, 401, 403, 404).
  • 5xx = ошибка по вине сервера (например, 500, 502, 503).

Коды состояния выше 599 запрещено передавать при обмене, хотя некоторые агенты могут записывать их в журналы для обозначения внутренних состояний. Подробное значение всех кодов описано в RFC9110. В HTTP/2 и новее нет метки версии, а код состояния передаётся в псевдозаголовке «:status».

Поле причины служит лишь подсказкой и не разбирается клиентами. В нём может быть что угодно, но принято использовать общеизвестные сообщения. Оно может состоять из одного или нескольких слов, например «OK», «Found» или «Authentication Required». В HTTP/2 и новее этого поля нет и оно не передаётся. При передаче ответа из HTTP/2 или новее клиенту HTTP/1 HAProxy формирует стандартное поле причины, соответствующее коду состояния.

HAProxy может самостоятельно выдавать следующие коды состояния:

Код   Условие / причина
 200  при обращении к странице статистики и при ответе на запросы мониторинга
 301  при перенаправлении, в зависимости от настроенного кода
 302  при перенаправлении, в зависимости от настроенного кода
 303  при перенаправлении, в зависимости от настроенного кода
 307  при перенаправлении, в зависимости от настроенного кода
 308  при перенаправлении, в зависимости от настроенного кода
 400  при некорректном или слишком большом запросе
 401  если для выполнения действия требуется аутентификация
      (при обращении к странице статистики)
 403  если запрос запрещён правилом "http-request deny"
 404  если запрошенный ресурс не найден
 408  если время ожидания запроса истекло до его полного получения
 410  если запрошенный ресурс больше недоступен и впредь доступен не будет
 413  если запрос HTTP/1.0 GET/HEAD/DELETE содержит полезную нагрузку;
      см. также параметр "h1-accept-payload-with-any-method"
 500  если HAProxy сталкивается с невосстановимой внутренней ошибкой,
      например с ошибкой выделения памяти, чего никогда не должно происходить
 501  если HAProxy не может выполнить запрос клиента из-за отсутствия
      поддержки необходимой функции
 502  если сервер возвращает пустой, некорректный или неполный ответ либо
      если правило "http-response deny" блокирует ответ
 503  если нет доступного сервера для обработки запроса либо в ответ на
      запросы мониторинга, соответствующие условию "monitor fail"
 504  если время ожидания ответа истекло до того, как сервер ответил

Приведённые выше ответы с кодами ошибок 4xx и 5xx можно настраивать (см. «errorloc» в разделе 4.2 ). Другие коды состояния можно выдавать намеренно с помощью специальных действий (например, «deny», «return» и «redirect» в разделе 4.3 ).

1.4.2. Заголовки ответа

Заголовки ответа устроены точно так же, как заголовки запроса, поэтому HAProxy использует для обоих одну функцию разбора. Подробнее см. пункт 1.3.2.

11 - 2. Настройка HAProxy

Синтаксис файлов, кавычки, переменные, условия, форматы времени и размера, адреса и примеры

2.1. Формат файла конфигурации

При настройке HAProxy используются 3 основных источника параметров:

  • аргументы из командной строки, которые всегда имеют приоритет
  • файл или файлы конфигурации, формат которых описан здесь
  • окружение запущенного процесса, если на переменные окружения явно ссылаются в конфигурации

Файл конфигурации имеет довольно простой иерархический формат, подчиняющийся нескольким основным правилам:

1. Файл конфигурации — упорядоченная последовательность инструкций.

2. Инструкция — одна непустая строка до первого незащищённого символа "#"
   (решётки).

3. Строка — последовательность токенов, или «слов», разделённых
   незащищёнными пробелами или табуляциями.

4. Первое слово или последовательность слов в строке — одно из ключевых
   слов или сочетаний ключевых слов, перечисленных в этом документе.

5. Все остальные слова — аргументы первого: одни являются известными
   ключевыми словами из этого документа, другие — значениями, ссылками
   на другие части конфигурации или выражениями.

6. Некоторые ключевые слова открывают секцию, внутри которой поддерживается
   только определённое подмножество ключевых слов.

7. Секция заканчивается в конце файла либо перед специальным ключевым
   словом, открывающим новую секцию.

Этого достаточно для создания простого, но надёжного генератора конфигурации, однако недостаточно для надёжного разбора произвольной конфигурации и обработки некоторых особых случаев.

Из этих правил следует несколько выводов. Правила 6 и 7 означают, что ключевые слова, определяющие новую секцию, допустимы везде и не могут иметь другого смысла в какой-либо отдельной секции. Такие ключевые слова всегда состоят из одного слова, а не из последовательности слов. Традиционно следующую за ними секцию называют так же. Например, «секция global» — это часть конфигурации после ключевого слова “global”. Такое обозначение часто используется в сообщениях об ошибках, чтобы указать место, требующее исправления.

Некоторые секции создают внутренний объект или область конфигурации, которую необходимо отличать от других. В этом случае дополнительное слово задаёт имя секции. Для некоторых типов секций имя обязательно. Например, “frontend foo” создаёт секцию типа “frontend” с именем “foo”. Обычно имя относится только к своему типу секций, и две секции разных типов могут иметь одинаковое имя, но это не рекомендуется, поскольку усложняет управление конфигурацией.

Прямое следствие правила 7 заключается в том, что при одновременном чтении нескольких файлов каждый из них должен начинаться с новой секции, а завершение каждого файла должно завершать соответствующую секцию. Файл не может содержать вложенные секции и не может завершать существующую секцию, чтобы начать новую.

Правило 1 указывает, что порядок имеет значение. Некоторые ключевые слова создают директивы, которые можно повторять, формируя последовательность правил для применения в заданном порядке. Например, “tcp-request” позволяет чередовать правила “accept” и “reject” с разными критериями. Поэтому средство обработки конфигурации при редактировании файла обязано сохранять порядок элементов внутри секции. Порядок самих секций обычно неважен, кроме секции global, которая должна находиться перед остальными, но при необходимости может повторяться. Кроме того, некоторым создаваемым объектам, например прокси, автоматически назначаются идентификаторы, которые меняются при перестановке секций. Эти идентификаторы встречаются, например, в статистике. В приведённой ниже конфигурации “foo” получит меньший идентификатор, чем “bar”. Если поменять секции местами, соотношение изменится:

listen foo
    bind :80

listen bar
    bind :81

Согласно правилам 2 и 3, пустые строки, пробелы, табуляции и комментарии после незащищённого символа “#” не входят в конфигурацию: они служат только разделителями. Поэтому следующие конфигурации полностью эквивалентны:

    global#this is the global section
daemon#daemonize
    frontend         foo
mode             http   # or tcp

и:

global
    daemon

# this is the public web frontend
frontend foo
    mode http

Обычно по левому краю выравнивают только ключевое слово, открывающее новую секцию, а перед остальными добавляют отступ — табуляцию или несколько пробелов, — чтобы их принадлежность к одной секции была сразу видна, как во втором примере выше. Комментарии перед секцией помогают читателю определить, та ли это секция, которую он ищет. Пустая строка в конце секции также помогает заметить её границу при редактировании.

Табуляция удобна для отступов, но плохо переносится при копировании и вставке. Если вместо неё используются пробелы, рекомендуется ограничиться небольшим числом (от 2 до 4), чтобы редактирование на месте не становилось обременительным в простых редакторах без автоматических отступов.

Раньше аргументы часто выравнивали по фиксированным позициям табуляции, поскольку большинство ключевых слов принимало не более двух аргументов. В современных версиях со сложными выражениями этот приём уже не подходит и не рекомендуется.

2.2. Кавычки и экранирование

В современных конфигурациях некоторые аргументы требуют символов, которые раньше использовались только как разделители. Для этого HAProxy поддерживает экранирование обратной косой чертой (’\’) перед нужным символом, слабое цитирование двойными кавычками ("") вокруг текста и сильное цитирование одинарными кавычками (’’).

Это похоже на правила многих языков программирования и особенно близко к поведению оболочки Bourne. Разбивая строки конфигурации на слова, анализатор учитывает кавычки и обратные косые черты, чтобы отличить разделитель от буквального символа внутри текущего слова. Затем символ экранирования и кавычки удаляются, а оставшееся слово используется без изменений, например как ключевое слово или аргумент.

Если в слове нужна обратная косая черта, её необходимо либо экранировать такой же чертой, то есть удвоить, либо заключить в одинарные кавычки.

Вне кавычек специальный символ экранируют обратной косой чертой (’\’), стоящей перед ним:

\    пробел, который следует отличать от разделителя
\#   решётка, которую следует отличать от начала комментария
\\   обратная косая черта
\'   одинарная кавычка, которую следует отличать от границы сильного цитирования
\"   двойная кавычка, которую следует отличать от границы слабого цитирования

Кроме того, несколько непечатаемых символов могут быть выведены с помощью их обычного представления на языке C:

\n   перевод строки (LF, символ \x0a или десятичный код ASCII 10)
\r   возврат каретки (CR, символ \x0d или десятичный код ASCII 13)
\t   табуляция (символ \x09 или десятичный код ASCII 9)
\xNN символ с шестнадцатеричным кодом ASCII NN (например, \x0a для LF).

Для слабого цитирования защищаемый символ или последовательность символов заключают в двойные кавычки (""). Это предотвращает интерпретацию следующих символов:

     пробел или табуляция как разделитель слов
'    одинарная кавычка как граница сильного цитирования
#    решётка как начало комментария

Слабое цитирование допускает подстановку переменных окружения, перед которыми стоит знак доллара (’$’); вне кавычек эти переменные не вычисляются. Если внутри двойных кавычек нужен сам знак доллара, его необходимо экранировать обратной косой чертой.

Для сильного цитирования защищаемый символ или последовательность символов заключают в одинарные кавычки (’’). Внутри них ничего не интерпретируется, поэтому они удобны для регулярных выражений.

Следующая таблица показывает, как вводить специальные символы в разных контекстах. Непечатаемые символы обозначены именами в угловых скобках. Некоторые символы можно представить только с экранированием, а внутри одинарных кавычек их представить невозможно, поэтому соответствующие ячейки пусты:

  Символ     |  Без кавычек  |  В двойных кавычках         |  В одинарных
  -----------+---------------+-----------------------------+-----------------
    <TAB>    |  \<TAB>, \x09 |  "<TAB>", "\<TAB>", "\x09"  |  '<TAB>'
  -----------+---------------+-----------------------------+-----------------
    <LF>     |  \n, \x0a     |  "\n", "\x0a"               |
  -----------+---------------+-----------------------------+-----------------
    <CR>     |  \r, \x0d     |  "\r", "\x0d"               |
  -----------+---------------+-----------------------------+-----------------
    <SPC>    |  \<SPC>, \x20 |  "<SPC>", "\<SPC>", "\x20"  |  '<SPC>'
  -----------+---------------+-----------------------------+-----------------
    "        |  \", \x22     |  "\"", "\x22"               |  '"'
  -----------+---------------+-----------------------------+-----------------
    #        |  \#, \x23     |  "#", "\#", "\x23"          |  '#'
  -----------+---------------+-----------------------------+-----------------
    $        |  $, \$, \x24  |  "\$", "\x24"               |  '$'
  -----------+---------------+-----------------------------+-----------------
    '        |  \', \x27     |  "'", "\'", "\x27"          |
  -----------+---------------+-----------------------------+-----------------
    \        |  \\, \x5c     |  "\\", "\x5c"               |  '\'
  -----------+---------------+-----------------------------+-----------------

Пример:

# those are all strictly equivalent:
log-format %{+Q}o\ %t\ %s\ %{-Q}r
log-format "%{+Q}o %t %s %{-Q}r"
log-format '%{+Q}o %t %s %{-Q}r'
log-format "%{+Q}o %t"' %s %{-Q}r'
log-format "%{+Q}o %t"' %s'\ %{-Q}r

В одном особом случае может потребоваться второй уровень цитирования или экранирования. Некоторые ключевые слова принимают аргументы в круглых скобках, иногда разделённые запятыми. Обычно это целые числа или предопределённые слова. Однако для произвольных строк может потребоваться дополнительный уровень экранирования, чтобы отличить символы самого аргумента от разделителей аргументов. Типичный пример — преобразователь “regsub”, принимающий регулярное выражение. Если в нём нужна закрывающая круглая скобка, её необходимо отдельно заключить в кавычки.

Анализатор аргументов ключевых слов обрабатывает кавычки точно так же, как анализатор верхнего уровня, за исключением того, что последовательности \#, \$ и \xNN не обрабатываются. Менее очевидно то, что используемые внутри разделители сначала нужно экранировать или заключить в кавычки, чтобы они не были обработаны на верхнем уровне.

Рассмотрим пример с преобразователем “regsub”, принимающим 3 аргумента: регулярное выражение, строку замены и набор флагов:

# replace all occurrences of "foo" with "blah" in the path:
http-request set-path %[path,regsub(foo,blah,g)]

Здесь специальные кавычки не требовались. Но для замены “foo” или “bar” на “blah” нужно регулярное выражение “(foo|bar)”. Нельзя написать так:

http-request set-path %[path,regsub((foo|bar),blah,g)]

поскольку строку требуется разделить так:

    http-request set-path %[path,regsub((foo|bar),blah,g)]
                                       |---------|----|-|
                                 arg1 _/         /    /
                                 arg2 __________/    /
                                 arg3 ______________/

но на самом деле передаётся строка между открывающей и закрывающей скобками, затем мусор:

    http-request set-path %[path,regsub((foo|bar),blah,g)]
                                       |--------|--------|
                        arg1=(foo|bar _/        /
                    лишние символы    _________/

Кажется, достаточно заключить закрывающую скобку в кавычки. Однако это не сработает: как сказано выше, анализатор верхнего уровня обработает кавычки ещё до разбора этого слова:

http-request set-path %[path,regsub("(foo|bar)",blah,g)]
------------ -------- ----------------------------------
   word1       word2    word3=%[path,regsub((foo|bar),blah,g)]

Таким образом, для анализатора аргументов второго уровня ничего не изменилось: он по-прежнему видит усечённое регулярное выражение как единственный аргумент и лишние символы в конце строки. Если экранировать кавычки, они дойдут до второго уровня без изменений:

    http-request set-path %[path,regsub(\"(foo|bar)\",blah,g)]
    ------------ -------- ------------------------------------
       word1       word2    word3=%[path,regsub("(foo|bar)",blah,g)]
                                                |---------||----|-|
                                arg1=(foo|bar) _/          /    /
                                    arg2=blah  ___________/    /
                                        arg3=g _______________/

Другой подход заключается в использовании одинарных кавычек снаружи всей строки и двойных кавычек внутри (таким образом, двойные кавычки не удаляются повторно):

    http-request set-path '%[path,regsub("(foo|bar)",blah,g)]'
    ------------ --------  ----------------------------------
       word1       word2    word3=%[path,regsub("(foo|bar)",blah,g)]
                                                |---------||----|-|
                                arg1=(foo|bar) _/          /    /
                                          arg2 ___________/    /
                                          arg3 _______________/

В этом случае разделители внутри строки верхнего уровня остаются обычными символами и больше не выполняют роль разделителей. В частности, пробелы и табуляции вокруг запятых становятся частью строки. В следующем примере сразу несколько ошибок:

    http-request set-path '%[path, regsub("(foo|bar)", blah, g)]'
    ------------ --------  --------------------------------------
       word1       word2    word3=%[path, regsub("(foo|bar)", blah, g)]
                                        |--------|---------||-----|--|
                  преобразователь=" regsub" _/        /         /   /
                                    arg1=(foo|bar) _/         /   /
                                     arg2=" blah" ___________/   /
                                        arg3=" g" ______________/

Из-за пробелов вокруг запятых эти пробелы стали частью полей. Поэтому преобразователь " regsub", начинающийся с пробела, не будет найден, что вызовет ошибку. Менее заметная проблема — строка замены " blah" добавит пробел в результат. Практическое правило: никогда не вставлять в выражения ненужные пробелы.

При использовании регулярных выражений может возникнуть ситуация, когда символ доллара (’$’) присутствует в выражении или используется обратный слеш (’\’) в строке замены. В таком случае эти символы будут обработаны внутри двойных кавычек, поэтому предпочтительны одинарные кавычки (или двойное экранирование). Пример:

    http-request set-path '%[path,regsub("^/(here)(/|$)","my/\1",g)]'
    ------------ --------  -----------------------------------------
       word1       word2    word3=%[path,regsub("^/(here)(/|$)","my/\1",g)]
                                                |-------------| |-----||-|
                              arg1=(here)(/|$) _/               /      /
                                    arg2=my/\1 ________________/      /
                                          arg3 ______________________/

Внутри одинарных кавычек обратные косые черты не служат символами экранирования, а всё слово в примере выше уже защищено одинарными кавычками. Если же заключить всё выражение в двойные кавычки, знак доллара и обратные косые черты будут обработаны на верхнем уровне, что нарушит содержимое аргумента на втором уровне.

Поскольку внутри одинарных кавычек нельзя экранировать одинарную кавычку, для включения такого символа в аргумент потребуется два уровня экранирования или цитирования. Это можно сделать несколькими способами:

http-request set-var(txn.foo) str("\\'foo\\'")
http-request set-var(txn.foo) str(\"\'foo\'\")
http-request set-var(txn.foo) str(\\\'foo\\\')

При сомнениях начните с варианта без кавычек. Затем заключите в одинарные или двойные кавычки аргументы, которым нужна запятая или закрывающая скобка, и при наличии в строке знака доллара или обратной косой черты предусмотрите экранирование этих кавычек обратной косой чертой. Это похоже на двойное экранирование команды, передаваемой “eval” в оболочке Bourne. Разработчикам API, вероятно, удобнее заключать каждый аргумент в экранированные кавычки независимо от его содержимого. Для пользователей, вероятно, более читаема конфигурация с одинарными кавычками вокруг всего выражения и двойными вокруг каждого аргумента.

2.3. Переменные окружения

В конфигурации HAProxy поддерживаются переменные окружения. Они интерпретируются только внутри двойных кавычек, а их значения подставляются при разборе конфигурации. Перед именем переменной должен стоять знак доллара ("$"); само имя можно заключить в фигурные скобки ("{}"), как в оболочке Bourne. Имена могут содержать буквы, цифры и знак подчёркивания ("_"), но их не следует начинать с цифры. Если переменная содержит несколько значений, разделённых пробелами, их можно подставить как отдельные аргументы: для этого переменную заключают в фигурные скобки и добавляют суффикс ‘[*]’ перед закрывающей скобкой. Также можно задать значение по умолчанию для случая, когда переменная не определена: его добавляют после имени переменной через дефис ‘-’. Значение по умолчанию заменяет только отсутствующую переменную, а не переменную с пустым значением.

Пример:

bind "fd@${FD_APP1}"

log "${LOCAL_SYSLOG-127.0.0.1}:514" local0 notice  # send to local server

user "$HAPROXY_USER"

Некоторые переменные определяются HAProxy, они могут использоваться в конфигурации. Эти переменные приведены в матрице ниже и классифицируются по четырём категориям:

  • доступна: переменную можно использовать в конфигурации — подставить её значение либо использовать её в условных блоках или предикатах, чтобы включать или отключать фрагменты конфигурации, как описано в разделе 2.4 «Условные блоки».

  • изменяема: переменную можно переопределить или удалить в конфигурации с помощью ключевых слов “setenv”/“unsetenv”.

  • выводится: переменная присутствует в выводе команды CLI “show env”, описанной в разделе 9.3 «Команды сокетов Unix» руководства по управлению.

Также есть две подкатегории — главный и рабочий процессы, обозначенные в таблице ниже соответственно ‘M’ и ‘W’. Они показывают различия между процессами при запуске HAProxy в режиме master-worker.

  • главный процесс: переменная задана и доступна в главном процессе. Она отображается в выводе “show env” интерфейса CLI главного процесса и может использоваться в условных блоках или директивах для включения специальных настроек этого процесса (см. примеры в разделе 2.4 «Условные блоки»).

  • рабочий процесс: переменная задана и доступна в рабочем процессе. Она отображается в выводе “show env” интерфейса CLI рабочего процесса или “@1 show env” интерфейса CLI главного процесса. От неё также могут зависеть параметры рабочего процесса (см. примеры в разделе 2.4 «Условные блоки»).

В автономном режиме, без параметра “-W” и ключевого слова “master-worker”, процесс ведёт себя как рабочий, но переменные “HAPROXY_MASTER_CLI” и “HAPROXY_MWORKER” не определены.

Некоторые переменные помечены как недоступные и неизменяемые:

  • HAPROXY_CFGFILES
  • HAPROXY_MWORKER
  • HAPROXY_CLI
  • HAPROXY_MASTER_CLI
  • HAPROXY_LOCALPEER

При разборе конфигурации их значения не определены: они устанавливаются позднее, на этапе инициализации. Поэтому рекомендуется не использовать эти переменные в условных блоках и не ссылаться на них в директивах “setenv”/“resetenv”/“unsetenv” секции global.

Таблица ниже содержит краткое описание состояния каждой переменной для различных режимов работы:

  +---------------------------+---------+------------+-----------+
  |        Переменная         |Доступна | Изменяема  | Выводится |
  |                           +---------+------------+-----------+
  |                           |  M | W  |   M  |  W  |  M  |  W  |
  +---------------------------+----+----+------+-----+-----+-----+
  | HAPROXY_STARTUP_VERSION   |  X | X  |      |     |  X  |  X  |
  | HAPROXY_BRANCH            |  X | X  |      |     |  X  |  X  |
  | HAPROXY_CFGFILES          |    |    |      |     |  X  |  X  |
  | HAPROXY_MWORKER           |    |    |      |     |  X  |  X  |
  | HAPROXY_CLI               |    |    |      |     |     |  X  |
  | HAPROXY_MASTER_CLI        |    |    |      |     |  X  |     |
  | HAPROXY_LOCALPEER         |    | X  |      |     |     |  X  |
  | HAPROXY_HTTP_LOG_FMT      |    | X  |      |  X  |     |     |
  | HAPROXY_HTTP_CLF_LOG_FMT  |    | X  |      |  X  |     |     |
  | HAPROXY_HTTPS_LOG_FMT     |    | X  |      |  X  |     |     |
  | HAPROXY_TCP_LOG_FMT       |    | X  |      |  X  |     |     |
  | HAPROXY_TCP_CLF_LOG_FMT   |    | X  |      |  X  |     |     |
  | HAPROXY_KEYLOG_FC_LOG_FMT |    | X  |      |  X  |     |     |
  | HAPROXY_KEYLOG_BC_LOG_FMT |    | X  |      |  X  |     |     |
  +---------------------------+----+----+------+-----+-----+-----+

Речь идёт о следующих переменных:

  • HAPROXY_LOCALPEER: определяется при запуске процесса и содержит имя локального однорангового узла. См. “-L” в руководстве по управлению.

  • HAPROXY_CFGFILES: список файлов конфигурации, загруженных HAProxy, разделённых точками с запятой. Полезен, если при запуске был указан каталог.

  • HAPROXY_HTTP_LOG_FMT: содержит значение формата журнала HTTP по умолчанию, описанного в разделе 8.2.3 “Формат журнала HTTP”. Позволяет переопределить формат журнала по умолчанию без копирования всего исходного определения.

  • HAPROXY_HTTP_CLF_LOG_FMT: содержит значение формата журнала HTTP CLF по умолчанию, описанного в разделе 8.2.3 “Формат журнала HTTP”. Позволяет переопределить формат журнала по умолчанию без копирования всего исходного определения.

Пример:

# Add the rule that gave the final verdict to the log
log-format "${HAPROXY_TCP_LOG_FMT} lr=%[last_rule_file]:%[last_rule_line]"
  • HAPROXY_HTTPS_LOG_FMT: аналогична HAPROXY_HTTP_LOG_FMT, но содержит формат журнала HTTPS, описанный в разделе 8.2.4 «Формат журнала HTTPS».

  • HAPROXY_TCP_LOG_FMT: аналогична HAPROXY_HTTP_LOG_FMT, но содержит формат журнала TCP, описанный в разделе 8.2.2 «Формат журнала TCP».

  • HAPROXY_TCP_CLF_LOG_FMT: аналогична HAPROXY_HTTP_CLF_LOG_FMT, но содержит формат журнала TCP CLF, описанный в разделе 8.2.2 «Формат журнала TCP».

  • HAPROXY_KEYLOG_FC_LOG_FMT: содержит формат журнала ключей для соединения TLS со стороны фронтенда, то есть клиента. Записи ключей разделяются переводами строк, поэтому формат может оказаться несовместимым с используемым сервером syslog. Требуется “tune.ssl.keylog on”.

  • HAPROXY_KEYLOG_BC_LOG_FMT: аналогична HAPROXY_KEYLOG_FC_LOG_FMT, но относится к соединению TLS со стороны бэкенда, то есть сервера. Записи ключей разделяются переводами строк, поэтому формат может оказаться несовместимым с используемым сервером syslog. Требуется “tune.ssl.keylog on”.

  • HAPROXY_MWORKER: В режиме master-worker, эта переменная устанавливается в 1.

  • HAPROXY_CLI: настроенные адреса слушателей сокета статистики каждого процесса, эти адреса разделяются точками с запятой.

  • HAPROXY_MASTER_CLI: В режиме master-worker, адреса слушателей главного CLI, разделённые точками с запятой.

  • HAPROXY_STARTUP_VERSION: содержит версию, использованную при запуске. В режиме master-worker это версия, с которой запущен главный процесс, даже после обновления исполняемого файла и перезагрузки конфигурации.

  • HAPROXY_BRANCH: содержит версию ветки HAProxy (например, “2.8”). В ней не содержится полная версия. Может быть полезна при миграции, если ресурсы (например, карты или сертификаты) находятся в пути, содержащем номер ветки.

Кроме того, некоторые псевдопеременные вычисляются внутри HAProxy и могут использоваться как обычные переменные. Их имена всегда начинаются с точки (’.’); только в именах псевдопеременных разрешена точка. Текущий список псевдопеременных:

  • .FILE: имя разбираемого в данный момент файла конфигурации.

  • .LINE: номер разбираемой в данный момент строки файла конфигурации, начиная с единицы.

  • .SECTION: имя разбираемой в данный момент секции, её тип, если имя отсутствует (например, “global”), либо пустая строка до первой секции.

Значения этих переменных вычисляются в месте их разбора. Например, если переменная “.LINE” используется в директиве “log-format” секции defaults, номер строки вычисляется до разбора и компиляции этой директивы “log-format”. Поэтому последующие прокси будут использовать тот же номер строки.

Таким образом, возможно передавать информацию для определения местоположения правила в переменных, логах, статусах ошибок, проверках работоспособности, значениях заголовков или даже использовать номера строк для названия некоторых объектов конфигурации, например, серверов.

2.4. Условные блоки

Иногда удобно включать или отключать произвольные части конфигурации по условию: например, SSL, шифры или слушатели для предэксплуатационной среды без изменения конфигурации, либо адаптировать синтаксис для двух версий HAProxy во время миграции. HAProxy предоставляет набор директив с поддержкой вложенности, похожих на директивы препроцессора. Они позволяют включать или игнорировать блоки текста. Каждая директива должна находиться на отдельной строке и действует на следующие за ней строки. Две директивы принимают выражение, остальные переключаются на альтернативный блок или завершают текущий уровень. Для условных блоков определены следующие 4 директивы:

  • .if <condition>
  • .elif <condition>
  • .else
  • .endif

Директива “.if” открывает новый уровень вложенности, “.elif” и “.else” остаются на том же уровне, а “.endif” закрывает уровень. Каждой “.if” должна соответствовать завершающая “.endif”. Директива “.elif” допустима только после “.if” или “.elif”; длина цепочки “.elif” не ограничена. На каждую “.if” допускается только одна “.else”, которая должна находиться после “.if” или последней “.elif” этого блока.

Комментарии могут быть размещены на той же строке, если необходимо, после ‘#’, они будут проигнорированы. Директивы токенизируются так же, как и другие директивы конфигурации, и, следовательно, возможно использование переменных среды в условиях.

Условия также можно вычислить при запуске с параметром -cc. См. «3. Запуск HAProxy» в руководстве по управлению.

Условия могут быть либо пустой строкой (в этом случае возвращается ложь), либо выражением, состоящим из любой комбинации:

  • целое число ноль (‘0’), которое всегда возвращает “false”
  • ненулевое целое число, например ‘1’, которое всегда возвращает “true”.
  • предикат, за которым могут следовать аргументы в круглых скобках.
  • условие в круглых скобках ‘(’ и ‘)’
  • восклицательный знак (’!’) перед любым из перечисленных непустых элементов, отрицающий его значение.
  • выражения, объединённые логическим И (’&&’); они вычисляются слева направо, пока одно из них не вернёт ложь
  • выражения, объединённые логическим ИЛИ (’||’); они вычисляются справа налево, пока одно из них не вернёт истину

Используются те же средства разбиения строк на слова и разбора аргументов, что и в остальном языке конфигурации. Слова разделяются последовательностями из одного или нескольких пробелов или табуляций вне кавычек, а перед вычислением снова соединяются одиночными пробелами. Благодаря этому не нужно заключать всю строку в кавычки. Однако пробелы вокруг запятых или круглых скобок становятся частью значения, что не всегда очевидно. Например, выражение:

.if defined( HAPROXY_MWORKER )

проверит наличие переменной " HAPROXY_MWORKER " (с пробелами), и это:

.if streq("$ENABLE_SSL",     1)

сравнивает переменную окружения “ENABLE_SSL” со значением " 1" (с одним ведущим пробелом). Причина заключается в том, что строка сначала разбивается на слова так:

   .if streq("$ENABLE_SSL",     1)
  |---|--------------------|   |--|
    1           2               3

затем обрабатываются двойные кавычки и подставляется значение переменной окружения “$ENABLE_SSL”, например ENABLE_SSL=0. Наконец, слова вновь объединяются в строку с одним пробелом между ними:

   .if streq(0, 1)
  |---|-------|--|
    1     2     3

и только после этого строка разбирается как единое выражение. Пробел между запятой и “1” остаётся частью значения аргумента, поэтому аргумент равен " 1":

   .if streq(0, 1)
  |---|-----|-|--|
    \    \    \  \_ аргумент2: " 1"
     \    \    \___ аргумент1: "0"
      \    \_______ функция: "streq"
       \___________ директива: ".if"

Здесь видно, что даже если ENABLE_SSL был равен “1”, это не совпадало с " 1", поскольку строка отличалась одним пробелом.

Примечание: как объяснено в секции “2.2. Цитирование и экранирование”, хорошим правилом является никогда не вставлять ненужные пробелы внутри выражений.

Как и в других языках, оператор И имеет приоритет над ИЛИ, поэтому “A && B || C && D” вычисляется как “(A && B) || (C && D)”.

Список поддерживаемых на данный момент предикатов следующий:

  • awslc_api_atleast(<ver>): возвращает true, если текущее значение awslc API не старше <ver>, иначе false. Пример: awslc_api_atleast(35)

  • awslc_api_before(<ver>): возвращает true, если текущий номер awslc API строго старше <ver> иначе false. Пример: awslc_api_before(26)

  • defined(<name>) : возвращает true, если переменная среды <name> существует, независимо от её содержимого

  • feature(<name>) : возвращает true, если возможность <name> отмечена как доступная в списке, выводимом командой “haproxy -vv”, то есть <name> стоит после знака ‘+’.

  • openssl_version_atleast(<ver>): возвращает true, если текущая версия OpenSSL не старше <ver>, в противном случае — false. Библиотеки, такие как LibreSSL, AWS-LC и WolfSSL, также предоставляют псевдо-версию OpenSSL. Пример:

ssllib_name_startswith(OpenSSL) && openssl_version_atleast(1.1.1)
  • openssl_version_before(<ver>): возвращает true, если текущая версия OpenSSL строго старше <ver>, иначе false. Библиотеки, такие как LibreSSL, AWS-LC и WolfSSL, также предоставляют псевдоверсию OpenSSL. Пример: openssl_version_before(3.5.0)

  • ssllib_name_startswith(<name>) : возвращает true, если имя библиотеки SSL, с которой скомпонован HAProxy, начинается с <name>. Пример: ssllib_name_startswith(wolfSSL)

  • streq(<str1>,<str2>) : возвращает true только в случае равенства двух строк

  • strneq(<str1>,<str2>): возвращает true только если две строки различаются

  • strstr(<str1>,<str2>): возвращает true только если вторая строка содержится в первой.

  • version_atleast(<ver>): возвращает true, если текущая версия HAProxy не старше <ver>, в противном случае — false. Синтаксис версии совпадает с тем, что показано командой “haproxy -v”, отсутствующие компоненты считаются равными нулю.

  • version_before(<ver>): возвращает true, если текущая версия HAProxy строго старше <ver> в противном случае — false. Синтаксис версии соответствует тому, что показывает “haproxy -v” и отсутствующие компоненты считаются нулевыми.

  • enabled(<opt>) : возвращает true, если параметр <opt> включён во время работы. Поддерживается только часть параметров:

POLL, EPOLL, KQUEUE, EVPORTS, SPLICE,
GETADDRINFO, REUSEPORT, FAST-FORWARD,
SERVER-SSL-VERIFY-NONE

Пример:

# 1. HAPROXY_MWORKER variable is set automatically by HAProxy in master and
# in worker process environments (see HAProxy variables matrix from
# 2.3. Environment variables). Its presence enables an additional listener.

global
  master-worker

.if defined(HAPROXY_MWORKER)
    listen mwcli_px
       bind :1111
       ...
.endif
# 2. HAPROXY_BRANCH is set automatically by HAProxy in master and in worker
# process environments (see HAProxy variables matrix from 2.3. Environment
# variables). We check HAPROXY_BRANCH value and conditionally enable
# mworker-max-reloads parameter.

global
  master-worker

.if streq("$HAPROXY_BRANCH",3.1)
     mworker-max-reloads 5
.endif
# 3. Some arbitrary environment variables are set by user in the global
# section. If HAProxy is started in master-worker mode, they are presented in
# master and in worker process environments. We check values of these
# variables and conditionally enable ports 80 and 443. Environment variables
# checks can be mixed with features and version checks.

global
  setenv WITH_SSL yes
  unsetenv SSL_ONLY

.if strneq("$SSL_ONLY",yes)
       bind :80
.endif

.if streq("$WITH_SSL",yes)
  .if feature(OPENSSL)
       bind :443 ssl crt ...
  .endif
.endif

.if feature(OPENSSL) && (streq("$WITH_SSL",yes) || streq("$SSL_ONLY",yes))
       bind :443 ssl crt ...
.endif

.if version_atleast(2.4-dev19)
    profiling.memory on
.endif

.if !feature(OPENSSL)
    .alert "SSL support is mandatory"
.endif

Четыре другие директивы предоставляются для отображения некоторых состояний:

  • .diag “message” : выводит сообщение только в режиме диагностики (-dD)
  • .notice “message” : выводит сообщение с уровнем NOTICE
  • .warning “message”: выводит сообщение с уровнем WARNING
  • .alert “message” : выводит сообщение с уровнем ALERT

Сообщения уровня WARNING могут помешать запуску процесса, если включён “zero-warning”. Сообщения уровня ALERT всегда приводят к неустранимой ошибке. Эти директивы позволяют выявлять неподходящие условия и давать пользователю рекомендации.

Пример:

.if "${A}"
  .if "${B}"
     .notice "A=1, B=1"
  .elif "${C}"
     .notice "A=1, B=0, C=1"
  .elif "${D}"
     .warning "A=1, B=0, C=0, D=1"
  .else
     .alert "A=1, B=0, C=0, D=0"
  .endif
.else
     .notice "A=0"
.endif

.diag "WTA/2021-05-07: replace 'redirect' with 'return' after switch to 2.4"
      http-request redirect location /goaway if ABUSE

2.5. Формат времени

Некоторые параметры включают значения, представляющие время, такие как тайм-ауты. Эти значения обычно выражаются в миллисекундах (если не указано иное), но могут быть выражены в любой другой единице путём добавления этой единицы к числовому значению. Важно учитывать это, поскольку оно не будет повторяться для каждого ключевого слова. Поддерживаемые единицы:

  • us: микросекунды. 1 микросекунда = 1/1000000 секунды
  • ms: миллисекунды. 1 миллисекунда = 1/1000 секунды. Это значение по умолчанию.
  • s : секунды. 1s = 1000ms
  • m : минуты. 1m = 60s = 60000ms
  • h : часы. 1h = 60m = 3600s = 3600000ms
  • d : дни. 1d = 24h = 1440m = 86400s = 86400000ms

2.6. Формат размера

Некоторые параметры включают значения, представляющие объём, такие как ограничения пропускной способности. Эти значения обычно выражаются в байтах (кроме случаев, когда это явно указано иначе), но могут быть выражены в любой другой единице путём добавления суффикса единицы к числовому значению. Важно учитывать это, поскольку оно не будет повторяться для каждого ключевого слова. Поддерживаемые единицы являются нечувствительными к регистру:

  • k: килобайты. 1 килобайт = 1024 байт
  • m: мегабайты. 1 мегабайт = 1048576 байт
  • g: гигабайты. 1 гигабайт = 1073741824 байт

Оба формата времени и объёма требуют целых чисел; дробная запись не допускается.

2.7. Формат имён карт отображения и ACL

Возможно использовать список шаблонов для карт или ACL. Список шаблонов определяется его именем и может использоваться в разных местах конфигурации. Списки шаблонов делятся на три категории в зависимости от формата имени:

  • Списки шаблонов из обычных файлов: вариант по умолчанию. В качестве имени используется абсолютный или относительный путь к файлу. Файл должен существовать, иначе возникает ошибка, но может быть пустым. Также можно указать префикс “file@”, который не входит в имя списка. Имя файла с префиксом и без него обозначает один и тот же список шаблонов.

  • Списки шаблонов из необязательных файлов: перед именем файла должен стоять префикс “opt@”. Наличие файла необязательно. Если он существует, его содержимое загружается; отсутствие файла не вызывает ошибки. Префикс не входит в имя списка, поэтому при одинаковом имени обычный и необязательный файлы обозначают один и тот же список шаблонов.

  • Списки шаблонов, основанные на виртуальных файлах: имя служит лишь идентификатором. Оно не ссылается на какой-либо файл. Обязательно использовать префикс “virt@”. Он входит в идентификатор. Следовательно, такие списки не могут смешиваться с другими типами списков.

Виртуальные файлы полезны, когда шаблоны полностью управляются динамически и отсутствуют при запуске и перезагрузке конфигурации. В тех же условиях можно использовать необязательные файлы, но в них можно сохранять шаблоны, например внешним скриптом на основе команды CLI “show map”. Это позволяет сохранить шаблоны при перезагрузке конфигурации.

Примечание: хотя это маловероятный случай, обычный файл с именем, начинающимся с “file@”, “opt@” или “virt@”, нельзя загрузить без явного добавления “./” перед именем, например “file@./virt@map”.

2.8. Переменные

В конфигурации HAProxy переменные можно использовать в функциях извлечения образца, преобразователях, строках log-format и действиях TCP/HTTP. Можно определять переменные уровня процесса, доступные глобально на протяжении всей его работы. Другие переменные имеют меньший срок жизни. Как и в сценариях оболочки, переменная — это символическое имя области памяти. Размер переменных не ограничен, память для них выделяется динамически. Поэтому переменные необходимо использовать осторожно, особенно при интенсивном обращении к ним. Максимальный объём занимаемой ими памяти можно ограничить глобальными параметрами “tune.vars”.

Переменные должны обозначаться в формате “<scope>.<name>”. <scope> — одно слово, указывающее срок жизни переменной. Часть <name> может содержать только символы ‘a-z’, ‘A-Z’, ‘0-9’ и ‘_’. Имя уникально в пределах области видимости, но одинаковые имена в разных областях допустимы и обозначают разные переменные. Поддерживаются следующие области видимости:

  • proc : переменные, существующие на протяжении всей работы процесса и доступные глобально. С переменными “proc” можно работать через CLI с помощью команд “get var” и “set var”. Их также можно задавать в секциях “global” директивами “set-var” и “set-var-fmt”.

  • sess : для переменных, известных на протяжении всего жизненного цикла сессии. Переменные “sess” являются приватными для сессии, недоступными снаружи и не используются совместно с другими сессиями.

  • txn : для переменных, известных на протяжении всего жизненного цикла транзакции. Переменные “txn” являются приватными для потока, недоступными снаружи и не используются совместно с другими потоками.

  • req : для переменных, известных в процессе обработки запроса для конкретного потока. Переменные “req” доступны с момента создания потока и до первой попытки соединения с сервером. Они являются приватными для потока, недоступными снаружи и не используются совместно с другими потоками. Между переменными “req” и “res” нет пересечений вовсе.

  • res : для переменных, известных во время обработки ответа для конкретного потока. Переменные “res” видны с первой попытки соединения с сервером и до уничтожения потока. Они являются приватными для потока, недоступными снаружи и не используются совместно с другими потоками. Между переменными “req” и “res” нет никакого пересечения.

  • check: для переменных, известных во время выполнения проверки работоспособности. Переменные “check” являются приватными для проверки работоспособности, недоступными снаружи и не используются совместно с другими проверками работоспособности. Их можно задавать с помощью специализированных директив “tcp-check” или “http-check”.

В зависимости от контекста, могут использоваться дополнительные области, отражающие родительский поток текущего потока:

  • psess: то же, что и “sess”, но с использованием сессии родительского потока, если такой имеется.

  • ptxn : то же, что и “txn”, но с использованием транзакции родительского потока, если такой имеется.

  • preq : то же, что и “req”, но с использованием родительского потока, если такой имеется. Переменные “preq” доступны только во время обработки запроса родительского потока.

  • pres : то же, что и “res”, но с использованием родительского потока, если такой имеется. Переменные “pres” доступны только во время обработки ответа родительского потока.

Области, отражающие родительский поток, доступны с момента определения потока. В большинстве случаев отсутствует родительский поток. Однако, если это применимо, такой факт будет явно указан. В настоящее время возможно только извлечение значений переменных, определённых в области родительского потока. Установка или удаление таких переменных невозможны. Обычно дочерний поток выполняет обработку для родительского потока в определённый момент и останавливает его выполнение до завершения операции. Это означает, что родительский поток может быть остановлен на этапе обработки запроса или ответа. В связи с этим, определённые области недоступны из дочернего потока. Например, если запрос подвергается анализу в дочернем потоке, дочерний поток не найдёт переменные в области “pres”, поскольку родительский поток не обрабатывает ответ, и, следовательно, не имеет переменных в его области “res”.

Содержимое переменной — результат вычисления выражения извлечения образца; переменная наследует тип результата этого выражения. При использовании переменной её тип должен соответствовать выполняемой операции. Например, для успешного применения преобразователя “add()” строковое значение должно преобразовываться в корректное целое число. Это особенно важно при сравнении переменных со статическими значениями: необходимо выбрать правильный метод сопоставления.

2.9. Форматы адресов

Некоторым директивам, в том числе “bind”, “server”, “nameserver” и “log”, требуется адрес.

Адресом может быть имя узла, адрес IPv4, адрес IPv6 или ‘’. Значение ‘’ эквивалентно специальному адресу “0.0.0.0” и в директивах “bind” или “dgram-bind” позволяет слушать все адреса IPv4 системы. Эквивалент для IPv6 — ‘::’.

В зависимости от директивы за IP-адресом следует порт или диапазон портов. Для ‘bind’ он обязателен, для ‘server’ — нет.

Адрес также может начинаться с косой черты ‘/’. В этом случае он относится к семейству “unix”, а ‘/’ и следующие символы должны задавать путь.

Тип сокета или способ передачи по умолчанию, “datagram” либо “stream”, зависит от директивы, в которой указан адрес. Для ‘bind’ и ‘server’ по умолчанию используется тип “stream”, а для ’log’, ’nameserver’ и ‘dgram-bind’ — “datagram”.

С помощью необязательного префикса можно явно задать семейство адресов, тип сокета и/или способ передачи.

2.9.1. Префиксы семейств адресов

‘abns@<name>’ — следующее за префиксом <name> относится к абстрактному пространству имён (только Linux).

‘abnsz@<name>’ — следующее за префиксом <name> относится к абстрактному пространству имён и завершается нулевым символом (только Linux).

‘fd@<n>’ — далее указан файловый дескриптор <n>, унаследованный от родительского процесса. Он должен быть привязан к адресу и может уже слушать соединения, но это необязательно.

‘ip@<address>[:port1[-port2]]’ — следующее за префиксом <address> считается адресом IPv4 или IPv6 в зависимости от синтаксиса. В зависимости от директивы, использующей этот адрес, порт или диапазон портов может быть необязательным либо обязательным.

‘ipv4@<address>[:port1[-port2]]’ — следующее за префиксом <address> всегда считается адресом IPv4. В зависимости от директивы, использующей этот адрес, порт или диапазон портов может быть необязательным либо обязательным.

‘ipv6@<address>[:port1[-port2]]’ — следующее за префиксом <address> всегда считается адресом IPv6. В зависимости от директивы, использующей этот адрес, порт или диапазон портов может быть необязательным либо обязательным.

‘sockpair@<n>’ — далее указан файловый дескриптор соединённого сокета Unix или пары сокетов. При установке соединения инициатор создаёт пару соединённых сокетов и передаёт один из них другой стороне через этот дескриптор. Слушатель ждёт получения дескриптора через сокет Unix и использует его как дескриптор, возвращённый accept(). Следует использовать с осторожностью.

           Ошибки: известно, что этот протокол ненадёжен на macOS из-за
           ошибки в реализации sendmsg(2) в macOS. Соединение может быть
           принято некорректно.

‘unix@<path>’ — следующая строка рассматривается как путь <path> к сокету UNIX. Этот префикс удобен для пути к сокету UNIX, который не начинается с косой черты ‘/’.

2.9.2. Префиксы типов сокетов

Перед описанными выше префиксами семейства адресов можно добавить ещё один префикс, чтобы явно задать тип сокета и способ передачи. Значение по умолчанию зависит от директивы, использующей адрес, но в некоторых случаях его можно изменить. Например, директива “log” по умолчанию использует syslog поверх UDP, но её можно настроить на syslog поверх TCP.

Эти префиксы предназначены для внутреннего использования. Пользователям следует применять вместо них псевдонимы из следующего раздела «2.9.3. Префиксы протоколов». Однако иногда такие префиксы удобны, например с унаследованными сокетами, известными по номерам файловых дескрипторов: в этом случае семейство адресов — “fd”, а тип сокета необходимо указать явно.

Если нужную настройку удаётся задать только этими префиксами, а префиксы протоколов её не позволяют, следует сообщить об этом сопровождающим проекта.

‘stream+<family>@<address>’ — явно задаёт тип сокета и способ передачи “stream”.

‘dgram+<family>@<address>’ — явно задаёт тип сокета и способ передачи “datagram”.

‘quic+<family>@<address>’ — явно задаёт тип сокета “datagram” и способ передачи “stream”.

2.9.3. Префиксы протоколов

‘quic4@<address>[:port1[-port2]]’ — следующее за префиксом <address> всегда считается адресом IPv4, но тип сокета явно задаётся как “datagram”, а способ передачи — как “stream”. В зависимости от директивы, использующей этот адрес, UDP-порт или диапазон портов может быть необязательным либо обязательным. Эквивалентно “quic+ipv4@”.

‘quic6@<address>[:port1[-port2]]’ — следующее за префиксом <address> всегда считается адресом IPv6, но тип сокета явно задаётся как “datagram”, а способ передачи — как “stream”. В зависимости от директивы, использующей этот адрес, UDP-порт или диапазон портов может быть необязательным либо обязательным. Эквивалентно “quic+ipv6@”.

’tcp@<address>[:port1[-port2]]’ — следующее за префиксом <address> считается адресом IPv4 или IPv6 в зависимости от синтаксиса, но тип сокета и способ передачи явно задаются как “stream”. В зависимости от директивы, использующей этот адрес, порт или диапазон портов может быть необязательным либо обязательным. Это псевдоним ‘stream+ip@’.

’tcp4@<address>[:port1[-port2]]’ — следующее за префиксом <address> всегда считается адресом IPv4, но тип сокета и способ передачи явно задаются как “stream”. В зависимости от директивы, использующей этот адрес, порт или диапазон портов может быть необязательным либо обязательным. Это псевдоним ‘stream+ipv4@’.

’tcp6@<address>[:port1[-port2]]’ — следующее за префиксом <address> всегда считается адресом IPv6, но тип сокета и способ передачи явно задаются как “stream”. В зависимости от директивы, использующей этот адрес, порт или диапазон портов может быть необязательным либо обязательным. Это псевдоним ‘stream+ipv6@’.

‘mptcp@<address>[:port1[-port2]]’ — следующее за префиксом <address> считается адресом IPv4 или IPv6 в зависимости от синтаксиса, но тип сокета и способ передачи явно задаются как “stream”, с протоколом MPTCP. В зависимости от директивы, использующей этот адрес, порт или диапазон портов может быть необязательным либо обязательным.

‘mptcp4@<address>[:port1[-port2]]’ — следующее за префиксом <address> всегда считается адресом IPv4, но тип сокета и способ передачи явно задаются как “stream”, с протоколом MPTCP. В зависимости от директивы, использующей этот адрес, порт или диапазон портов может быть необязательным либо обязательным.

‘mptcp6@<address>[:port1[-port2]]’ — следующее за префиксом <address> всегда считается адресом IPv6, но тип сокета и способ передачи явно задаются как “stream”, с протоколом MPTCP. В зависимости от директивы, использующей этот адрес, порт или диапазон портов может быть необязательным либо обязательным.

‘udp@<address>[:port1[-port2]]’ — следующее за префиксом <address> считается адресом IPv4 или IPv6 в зависимости от синтаксиса, но тип сокета и способ передачи явно задаются как “datagram”. В зависимости от директивы, использующей этот адрес, порт или диапазон портов может быть необязательным либо обязательным. Это псевдоним ‘dgram+ip@’.

‘udp4@<address>[:port1[-port2]]’ — следующее за префиксом <address> всегда считается адресом IPv4, но тип сокета и способ передачи явно задаются как “datagram”. В зависимости от директивы, использующей этот адрес, порт или диапазон портов может быть необязательным либо обязательным. Это псевдоним ‘dgram+ipv4@’.

‘udp6@<address>[:port1[-port2]]’ — следующее за префиксом <address> всегда считается адресом IPv6, но тип сокета и способ передачи явно задаются как “datagram”. В зависимости от директивы, использующей этот адрес, порт или диапазон портов может быть необязательным либо обязательным. Это псевдоним ‘dgram+ipv6@’.

‘uxdg@<path>’ — следующая строка рассматривается как путь <path> к сокету unix, но способ передачи явно задаётся как “datagram”. Это псевдоним ‘dgram+unix@’.

‘uxst@<path>’ — следующая строка рассматривается как путь <path> к сокету unix, но способ передачи явно задаётся как “stream”. Это псевдоним ‘stream+unix@’.

В будущих версиях могут появиться другие префиксы для протоколов, таких как QUIC, обеспечивающих потоковую передачу поверх сокетов типа “datagram”.

2.10. Примеры

# Simple configuration for an HTTP proxy listening on port 80 on all
    # interfaces and forwarding requests to a single backend "servers" with a
    # single server "server1" listening on 127.0.0.1:8000
    global
        daemon
        maxconn 256

    defaults
        mode http
        timeout connect 5000ms
        timeout client 50000ms
        timeout server 50000ms

    frontend http-in
        bind *:80
        default_backend servers

    backend servers
        server server1 127.0.0.1:8000 maxconn 32


    # The same configuration defined with a single listen block. Shorter but
    # less expressive, especially in HTTP mode.
    global
        daemon
        maxconn 256

    defaults
        mode http
        timeout connect 5000ms
        timeout client 50000ms
        timeout server 50000ms

    listen http-in
        bind *:80
        server server1 127.0.0.1:8000 maxconn 32

Если haproxy находится в $PATH, проверить эти конфигурации можно следующей командой оболочки:

$ sudo haproxy -f configuration.conf -c

12 - 3. Секция global

Безопасность процессов, настройка производительности, отладка и параметры HTTP-клиента

Параметры секции “global” действуют на весь процесс и часто зависят от ОС. Обычно их задают один раз, и после правильной настройки менять их не требуется. У некоторых есть эквиваленты в командной строке.

В секции “global” поддерживаются следующие ключевые слова:

  • Управление процессами и безопасность

    • 51degrees-allow-unmatched
    • 51degrees-cache-size
    • 51degrees-data-file
    • 51degrees-difference
    • 51degrees-drift
    • 51degrees-property-name-list
    • 51degrees-property-separator
    • 51degrees-use-performance-graph
    • 51degrees-use-predictive-graph
    • ca-base
    • chroot
    • cluster-secret
    • cpu-affinity
    • cpu-map
    • cpu-policy
    • cpu-set
    • crt-base
    • daemon
    • default-path
    • description
    • deviceatlas-json-file
    • deviceatlas-log-level
    • deviceatlas-properties-cookie
    • deviceatlas-separator
    • dns-accept-family
    • expose-deprecated-directives
    • expose-experimental-directives
    • external-check
    • fd-hard-limit
    • gid
    • grace
    • group
    • h1-accept-payload-with-any-method
    • h1-case-adjust
    • h1-case-adjust-file
    • h1-do-not-close-on-insecure-transfer-encoding
    • h2-workaround-bogus-websocket-clients
    • hard-stop-after
    • harden.reject-privileged-ports.tcp
    • harden.reject-privileged-ports.quic
    • insecure-fork-wanted
    • insecure-setuid-wanted
    • issuers-chain-path
    • jwt.allow_none_alg
    • jwt.decrypt_alg_list
    • jwt.decrypt_enc_list
    • key-base
    • limited-quic
    • localpeer
    • log
    • log-send-hostname
    • log-tag
    • lua-load
    • lua-load-per-thread
    • lua-prepend-path
    • max-threads-per-group
    • mworker-max-reloads
    • nbthread
    • node
    • numa-cpu-mapping
    • ocsp-update.disable
    • ocsp-update.maxdelay
    • ocsp-update.mindelay
    • ocsp-update.httpproxy
    • ocsp-update.mode
    • pidfile
    • pp2-never-send-local
    • presetenv
    • prealloc-fd
    • resetenv
    • set-dumpable
    • set-var
    • setenv
    • ssl-default-bind-ciphers
    • ssl-default-bind-ciphersuites
    • ssl-default-bind-client-sigalgs
    • ssl-default-bind-curves
    • ssl-default-bind-options
    • ssl-default-bind-sigalgs
    • ssl-default-server-ciphers
    • ssl-default-server-ciphersuites
    • ssl-default-server-client-sigalgs
    • ssl-default-server-curves
    • ssl-default-server-options
    • ssl-default-server-sigalgs
    • ssl-dh-param-file
    • ssl-propquery
    • ssl-provider
    • ssl-provider-path
    • ssl-security-level
    • ssl-server-verify
    • ssl-skip-self-issued-ca
    • stats
    • stats-file
    • strict-limits
    • uid
    • ulimit-n
    • unix-bind
    • unsetenv
    • user
    • wurfl-cache-size
    • wurfl-data-file
    • wurfl-information-list
    • wurfl-information-list-separator
  • Настройка производительности

    • busy-polling
    • max-spread-checks
    • maxcompcpuusage
    • maxcomprate
    • maxconn
    • maxconnrate
    • maxpipes
    • maxsessrate
    • maxsslconn
    • maxsslrate
    • maxzlibmem
    • no-memory-trimming
    • noepoll
    • noevports
    • nogetaddrinfo
    • nokqueue
    • noktls
    • nopoll
    • noreuseport
    • nosplice
    • profiling.memory
    • profiling.tasks
    • server-state-base
    • server-state-file
    • spread-checks
    • ssl-engine
    • ssl-mode-async
    • tune.applet.zero-copy-forwarding
    • tune.buffers.limit
    • tune.buffers.reserve
    • tune.bufsize
    • tune.bufsize.large
    • tune.bufsize.small
    • tune.cli.max-payload-size
    • tune.comp.maxlevel
    • tune.defaults.purge
    • tune.disable-fast-forward
    • tune.disable-zero-copy-forwarding
    • tune.epoll.mask-events
    • tune.events.max-events-at-once
    • tune.fail-alloc
    • tune.fd.edge-triggered
    • tune.h1.be.glitches-threshold
    • tune.h1.fe.glitches-threshold
    • tune.h1.zero-copy-fwd-recv
    • tune.h1.zero-copy-fwd-send
    • tune.h2.be.glitches-threshold
    • tune.h2.be.initial-window-size
    • tune.h2.be.max-concurrent-streams
    • tune.h2.be.max-frames-at-once
    • tune.h2.be.rxbuf
    • tune.h2.fe.glitches-threshold
    • tune.h2.fe.initial-window-size
    • tune.h2.fe.max-concurrent-streams
    • tune.h2.fe.max-frames-at-once
    • tune.h2.fe.max-rst-at-once
    • tune.h2.fe.max-total-streams
    • tune.h2.fe.rxbuf
    • tune.h2.header-table-size
    • tune.h2.initial-window-size
    • tune.h2.max-concurrent-streams
    • tune.h2.max-frame-size
    • tune.h2.zero-copy-fwd-send
    • tune.http.cookielen
    • tune.http.logurilen
    • tune.http.maxhdr
    • tune.idle-pool.shared
    • tune.idletimer
    • tune.lua.bool-sample-conversion
    • tune.lua.burst-timeout
    • tune.lua.forced-yield
    • tune.lua.log.loggers
    • tune.lua.log.stderr
    • tune.lua.maxmem
    • tune.lua.openlibs
    • tune.lua.service-timeout
    • tune.lua.session-timeout
    • tune.lua.task-timeout
    • tune.max-checks-per-thread
    • tune.maxaccept
    • tune.maxpollevents
    • tune.maxrewrite
    • tune.max-rules-at-once
    • tune.memory.hot-size
    • tune.pattern.cache-size
    • tune.peers.max-updates-at-once
    • tune.pipesize
    • tune.pool-high-fd-ratio
    • tune.pool-low-fd-ratio
    • tune.pt.zero-copy-forwarding
    • tune.quic.be.cc.cubic-min-losses
    • tune.quic.be.cc.hystart
    • tune.quic.be.cc.max-frame-loss
    • tune.quic.be.cc.max-win-size
    • tune.quic.be.cc.reorder-ratio
    • tune.quic.be.max-idle-timeout
    • tune.quic.be.sec.glitches-threshold
    • tune.quic.be.stream.data-ratio
    • tune.quic.be.stream.max-concurrent
    • tune.quic.be.stream.rxbuf
    • tune.quic.be.tx.pacing
    • tune.quic.be.tx.udp-gso
    • tune.quic.cc.cubic.min-losses (устарело)
    • tune.quic.cc-hystart (устарело)
    • tune.quic.disable-tx-pacing (устарело)
    • tune.quic.disable-udp-gso (устарело)
    • tune.quic.fe.cc.cubic-min-losses
    • tune.quic.fe.cc.hystart
    • tune.quic.fe.cc.max-frame-loss
    • tune.quic.fe.cc.max-win-size
    • tune.quic.fe.cc.reorder-ratio
    • tune.quic.fe.max-idle-timeout
    • tune.quic.fe.sec.glitches-threshold
    • tune.quic.fe.sec.retry-threshold
    • tune.quic.fe.sock-per-conn
    • tune.quic.fe.stream.data-ratio
    • tune.quic.fe.stream.max-concurrent
    • tune.quic.fe.stream.max-total
    • tune.quic.fe.stream.rxbuf
    • tune.quic.fe.tx.pacing
    • tune.quic.fe.tx.udp-gso
    • tune.quic.frontend.max-data-size (устарело)
    • tune.quic.frontend.max-idle-timeout (устарело)
    • tune.quic.frontend.max-streams-bidi (устарело)
    • tune.quic.frontend.max-tx-mem (устарело)
    • tune.quic.frontend.stream-data-ratio (устарело)
    • tune.quic.frontend.default-max-window-size (устарело)
    • tune.quic.listen
    • tune.quic.max-frame-loss (устарело)
    • tune.quic.mem.tx-max
    • tune.quic.reorder-ratio (устарело)
    • tune.quic.retry-threshold (устарело)
    • tune.quic.socket-owner (устарело)
    • tune.quic.zero-copy-fwd-send
    • tune.renice.runtime
    • tune.renice.startup
    • tune.rcvbuf.backend
    • tune.rcvbuf.client
    • tune.rcvbuf.frontend
    • tune.rcvbuf.server
    • tune.recv_enough
    • tune.ring.queues
    • tune.runqueue-depth
    • tune.sched.low-latency
    • tune.sndbuf.backend
    • tune.sndbuf.client
    • tune.sndbuf.frontend
    • tune.sndbuf.server
    • tune.streams-elasticity
    • tune.stick-counters
    • tune.ssl.cachesize
    • tune.ssl.capture-buffer-size
    • tune.ssl.capture-cipherlist-size (устарело)
    • tune.ssl.certificate-compression
    • tune.ssl.default-dh-param
    • tune.ssl.force-private-cache
    • tune.ssl.hard-maxrecord
    • tune.ssl.keylog
    • tune.ssl.keyupdate-rate-limit
    • tune.ssl.lifetime
    • tune.ssl.maxrecord
    • tune.ssl.ssl-ctx-cache-size
    • tune.ssl.ocsp-update.maxdelay (устарело)
    • tune.ssl.ocsp-update.mindelay (устарело)
    • tune.takeover-other-tg-connections
    • tune.vars.global-max-size
    • tune.vars.proc-max-size
    • tune.vars.reqres-max-size
    • tune.vars.sess-max-size
    • tune.vars.txn-max-size
    • tune.zlib.memlevel
    • tune.zlib.windowsize
  • Debugging

    • anonkey
    • debug.counters
    • force-cfg-parser-pause
    • quiet
    • warn-blocked-traffic-after
    • zero-warning
  • HTTPClient

    • httpclient.resolvers.disabled
    • httpclient.resolvers.id
    • httpclient.resolvers.prefer
    • httpclient.retries
    • httpclient.ssl.ca-file
    • httpclient.ssl.verify
    • httpclient.timeout.connect

3.1. Управление процессами и безопасность

51degrees-data-file <file path>

51degrees-data-file <file path>

Путь к файлу данных 51Degrees для определения устройств. Файл следует распаковать и предоставить HAProxy необходимые права доступа к нему.

Обратите внимание: этот параметр доступен только в том случае, если HAProxy собран с USE_51DEGREES.

51degrees-property-name-list [<string> ...]

51degrees-property-name-list [<string> ...]

Список имён свойств 51Degrees, которые нужно загрузить из набора данных. Полный список имён доступен на сайте 51Degrees: https://51degrees.com/resources/property-dictionary

Обратите внимание: этот параметр доступен только в том случае, если HAProxy собран с USE_51DEGREES.

51degrees-property-separator <char>

51degrees-property-separator <char>

Символ, добавляемый после каждого значения свойства в заголовке ответа с результатами 51Degrees. Если не задан, используется ‘,’.

Обратите внимание: этот параметр доступен только в том случае, если HAProxy собран с USE_51DEGREES.

51degrees-cache-size <number>

51degrees-cache-size <number>

Задаёт размер кэша преобразователя 51Degrees: <number> записей. Этот кэш LRU хранит результаты предыдущих определений устройств. По умолчанию кэш отключён.

Обратите внимание: этот параметр доступен только в том случае, если HAProxy собран с USE_51DEGREES.

51degrees-use-performance-graph { on | off }

51degrees-use-performance-graph { on | off }

Включает (‘on’) или отключает (‘off’) использование графа производительности при определении устройства. Значение по умолчанию зависит от библиотеки 51Degrees.

Обратите внимание: этот параметр доступен только в том случае, если HAProxy собран с USE_51DEGREES и 51DEGREES_VER=4.

51degrees-use-predictive-graph { on | off }

51degrees-use-predictive-graph { on | off }

Включает (‘on’) или отключает (‘off’) использование прогнозного графа при определении устройства. Значение по умолчанию зависит от библиотеки 51Degrees.

Обратите внимание: этот параметр доступен только в том случае, если HAProxy собран с USE_51DEGREES и 51DEGREES_VER=4.

51degrees-drift <number>

51degrees-drift <number>

Задаёт допустимую величину смещения при определении устройства.

Обратите внимание: этот параметр доступен только в том случае, если HAProxy собран с USE_51DEGREES и 51DEGREES_VER=4.

51degrees-difference <number>

51degrees-difference <number>

Задаёт допустимую величину различия при определении устройства.

Обратите внимание: этот параметр доступен только в том случае, если HAProxy собран с USE_51DEGREES и 51DEGREES_VER=4.

51degrees-allow-unmatched { on | off }

51degrees-allow-unmatched { on | off }

Включает (‘on’) или отключает (‘off’) использование несовпавших узлов при определении устройства. Значение по умолчанию зависит от библиотеки 51Degrees.

Обратите внимание: этот параметр доступен только в том случае, если HAProxy собран с USE_51DEGREES и 51DEGREES_VER=4.

acme.scheduler { auto | off }

acme.scheduler { auto | off }

Включает или отключает планировщик ACME.

Планировщик ACME запускается при старте HAProxy. Он перебирает сертификаты и запускает задачу обновления ACME, когда значение notAfter оказывается раньше curtime + (notAfter - notBefore) / 12; если notBefore не определено, используется интервал 7 дней. Затем планировщик переходит в режим ожидания и просыпается через 12 часов.

Значение по умолчанию — “auto”.

См. также: acme

ca-base <dir>

ca-base <dir>

Задаёт каталог по умолчанию для загрузки сертификатов центров сертификации SSL и списков отзыва CRL, когда в директивах “ca-file”, “ca-verify-file” или “crl-file” указан относительный путь. Абсолютные пути в “ca-file”, “ca-verify-file” и “crl-file” имеют приоритет; “ca-base” в этом случае игнорируется.

chroot { <jail dir> | auto }

chroot { <jail dir> | auto }

Меняет текущий каталог на <jail dir> и выполняет в нём chroot() перед сбросом привилегий. Это повышает безопасность при эксплуатации неизвестной уязвимости, поскольку существенно затрудняет атакующему дальнейшее воздействие на систему. Важно убедиться, что каталог <jail dir> пуст и никому не доступен для записи. Если процесс запущен с правами суперпользователя, chroot() выполняется напрямую. В Linux при запуске без привилегий haproxy пытается выполнить его в новом пользовательском пространстве имён, созданном с помощью unshare(CLONE_NEWUSER); если этот механизм недоступен, chroot() завершается обычной ошибкой.

В качестве особого случая для <jail dir> можно указать “auto”. Тогда haproxy создаёт анонимный временный каталог, удаляет ссылку на него и выполняет chroot в этот каталог. Полученная изолированная среда не имеет имени в файловой системе, пуста и доступна только для чтения; отдельный каталог для неё подготавливать не требуется.

Если при запуске с правами суперпользователя chroot не используется, выводится предупреждение, призывающее всегда применять этот механизм. Если есть веская причина отказаться от chroot, например доступ к серверу через сокет UNIX с неудобным путём, предупреждение можно отключить, явно добавив “chroot /”. Преимущество такой записи в том, что она видна в конфигурации.

close-spread-time <time>

close-spread-time <time>

Задаёт временной интервал, по которому распределяется закрытие простаивающих и активных соединений при плавной остановке. После получения SIGUSR1 и окончания льготного периода, если он задан, при отсутствии этого параметра все простаивающие соединения закрываются сразу. Активные соединения HTTP или HTTP2 завершаются после получения следующего запроса: в ответ HTTP добавляется строка “Connection: close”, а в случае HTTP2 отправляется кадр GOAWAY. Если параметр задан, закрытие соединений распределяется по указанному интервалу <time>. Если close-spread-time имеет значение “infinite”, закрытие активных соединений при плавной остановке отключается. Заголовок “Connection: close” больше не добавляется в ответы HTTP, а GOAWAY не отправляется для HTTP2; простаивающие соединения закрываются только по истечении их тайм-аутов, определяемых соответствующими параметрами конфигурации.

Аргументы:

<time>  — временной интервал (по умолчанию в миллисекундах), на протяжении
        которого распределяется закрытие соединений при мягкой остановке;
        значение "infinite" отключает активное закрытие соединений.

Если используется параметр “hard-stop-after”, для этого параметра рекомендуется задать меньшее значение, чтобы все соединения успели корректно закрыться до остановки процесса.

См. также: grace, hard-stop-after, idle-close-on-response

cluster-secret <secret>

cluster-secret <secret>

Задаёт общий секрет в виде строки ASCII для нескольких узлов одного кластера. Он может применяться для разных целей. В частности, из него выводятся токены сброса без сохранения состояния для всех соединений QUIC, созданных этим процессом, а также секреты для шифрования токенов Retry.

Если этот параметр не задан, при запуске процесса выбирается случайное значение. Это позволяет использовать зависящие от него возможности, хотя и с некоторыми ограничениями.

cpu-map [auto:]<thread-group>[/<thread-set>] <cpu-set>[,...] [...]

cpu-map [auto:]<thread-group>[/<thread-set>] <cpu-set>[,...] [...]

В некоторых операционных системах группу потоков или отдельный поток можно привязать к определённому набору CPU. Это означает, что указанные потоки никогда не будут выполняться на других CPU. Директива “cpu-map” задаёт наборы CPU для отдельных потоков или групп потоков. Первый аргумент — диапазон групп потоков, за которым можно указать набор потоков. Эти диапазоны имеют следующий формат:

all | odd | even | number[-[number]]

<number> должен быть числом от 1 до 32 или 64 в зависимости от разрядности машинного слова. Идентификаторы групп, превышающие ’thread-groups’, и идентификаторы потоков, превышающие разрядность машинного слова, игнорируются. Все номера потоков отсчитываются относительно группы, к которой они принадлежат. Диапазон можно задать двумя такими числами, разделёнными дефисом (’-’). Можно также указать все потоки сразу с помощью “all”, только потоки с нечётными номерами с помощью “odd” или с чётными номерами с помощью “even”, как и в директиве привязки “thread”. Второй и последующие аргументы — наборы CPU. Каждый набор CPU задаётся либо одним номером, начиная с 0 для первого CPU, либо диапазоном из двух таких номеров, разделённых дефисом (’-’). Номера и диапазоны CPU можно перечислять через запятую или передавать дополнительные диапазоны как новые аргументы в той же строке. В операционных системах, отличных от Linux и BSD, максимальный индекс CPU может быть ограничен значением 31 или 63. Можно задать несколько директив “cpu-map”, но каждая из них заменяет предыдущие в той части, где они пересекаются.

Диапазоны можно задавать частично: верхнюю границу можно опустить. Тогда вместо неё используется соответствующее максимальное значение — 32 или 64 в зависимости от разрядности машинного слова.

Перед набором потоков можно добавить префикс “auto:”, чтобы HAProxy автоматически привязывал потоки к CPU, последовательно увеличивая номера потоков и CPU в наборах. Оба набора должны иметь одинаковый размер. Независимо от порядка объявления наборов CPU привязка выполняется от меньшего номера к большему. С префиксом “auto:” нельзя одновременно задавать диапазон групп и диапазон потоков. Поддерживается только один диапазон; второй элемент должен быть фиксированным числом.

Обратите внимание: диапазоны групп поддерживаются по историческим причинам. Сейчас отдельное число обозначает группу потоков; если группы потоков не используются, оно должно быть равно 1. При указании номера или диапазона потоков без использования групп потоков перед ним необходимо добавить “1/”. Запись “1” полностью эквивалентна “1/all” и обозначает все потоки группы.

Примеры:

cpu-map 1/all 0-3 # bind all threads of the first group on the
                  # first 4 CPUs

cpu-map 1/1- 0-   # will be replaced by "cpu-map 1/1-64 0-63"
                  # or "cpu-map 1/1-32 0-31" depending on the machine's
                  # word size.

# all these lines bind thread 1 to the cpu 0, the thread 2 to cpu 1
# and so on.
cpu-map auto:1/1-4   0-3
cpu-map auto:1/1-4   0-1 2-3
cpu-map auto:1/1-4   3 2 1 0
cpu-map auto:1/1-4   3,2,1,0

# bind each thread to exactly one CPU using all/odd/even keyword
cpu-map auto:1/all   0-63
cpu-map auto:1/even  0-31
cpu-map auto:1/odd   32-63

# invalid cpu-map because thread and CPU sets have different sizes.
cpu-map auto:1/1-4   0    # invalid
cpu-map auto:1/1     0-3  # invalid

# map 40 threads of those 4 groups to individual CPUs
cpu-map auto:1/1-10   0-9
cpu-map auto:2/1-10   10-19
cpu-map auto:3/1-10   20-29
cpu-map auto:4/1-10   30-39

# Map 80 threads to one physical socket and 80 others to another socket
# without forcing assignment. These are split into 4 groups since no
# group may have more than 64 threads.
cpu-map 1/1-40   0-39,80-119    # node0, siblings 0 & 1
cpu-map 2/1-40   0-39,80-119
cpu-map 3/1-40   40-79,120-159  # node1, siblings 0 & 1
cpu-map 4/1-40   40-79,120-159

cpu-affinity <affinity>

cpu-affinity <affinity>

Определяет способ привязки потоков к CPU. Сейчас поддерживаются следующие значения:

  • per-core: каждый поток привязывается ко всем аппаратным потокам одного ядра.
  • per-group: каждый поток привязывается ко всем аппаратным потокам группы. Это значение по умолчанию, если в “cpu-policy” не задано “threads-per-core 1”. “per-group” принимает необязательный аргумент, определяющий распределение CPU. Когда список CPU превышает максимально допустимое число CPU в группе и его нужно разделить между несколькими группами, дополнительный параметр позволяет выбрать способ привязки групп к этим CPU:
    • auto: каждой группе потоков выделяется соразмерная доля последовательных ядер CPU, которые используются только ею и не разделяются с другими группами. Это значение по умолчанию, поскольку обычно оно обеспечивает более оптимальную работу.
    • loose: каждой группе по-прежнему разрешается использовать любой CPU из списка. Обычно это усиливает конкуренцию за ресурсы, но иногда помогает лучше справляться с посторонней нагрузкой на тех же CPU.
  • auto: обычно используется “per-group”. Если в “cpu-policy” задано “threads-per-core 1”, используется “per-core”. Это значение по умолчанию.
  • per-thread: каждый поток привязывается только к одному аппаратному потоку. Если в “cpu-policy” задано “threads-per-core 1”, каждый поток привязывается к одному аппаратному потоку отдельного ядра.
  • per-ccx: каждый поток привязывается ко всем аппаратным потокам одного CCX.

cpu-policy <policy> [threads-per-core 1 | auto]

cpu-policy <policy> [threads-per-core 1 | auto]

Выбирает политику распределения CPU.

В системах с несколькими CPU может быть много причин не использовать все доступные ядра или распределять их по разным группам потоков: производительность, задержки, стоимость или управление ресурсами всей системы. Директива “cpu-set” уже позволяет исключить часть CPU, но после этого нужно решить, как распределить оставшиеся между потоками и группами потоков.

Обычно это распределение задаётся директивой “cpu-map”, однако в неоднородных системах поддерживать такую настройку может быть особенно трудно.

Если “cpu-map” не используется, директива “cpu-policy” позволяет выбрать вместо него одну из нескольких политик распределения. Сейчас поддерживаются следующие политики; по умолчанию используется “performance”:

  • none: дополнительный отбор не выполняется. Можно использовать все включённые CPU. Если число потоков не задано, оно принимается равным числу доступных CPU, но не более 32 в 32-битных системах или 64 в 64-битных системах на одну группу потоков. Если число групп потоков не задано, используется 1.

  • efficiency: работает так же, как описанная ниже “group-by-ccx”, но исключает кластеры CPU из ядер, производительность которых более чем на 25% превышает производительность следующего, менее производительного типа. Обычно это ядра “big” или “performance”. Таким образом, при обнаружении нескольких типов ядер CPU используется только энергоэффективный. Это может быть полезно при умеренной нагрузке, когда самые мощные ядра нужно оставить приложению или компоненту безопасности. Некоторые современные CPU имеют много таких энергоэффективных ядер, которые вместе обеспечивают приемлемую производительность при меньшем энергопотреблении.

  • first-usable-node: если набор CPU ранее не был ограничен при запуске, например утилитой “taskset”, и директива “nbthread” не задана, используется первый узел NUMA с включёнными CPU. Число этих CPU принимается за число потоков. Для всех них включается одна группа потоков с ограничением в 32 или 64 в зависимости от системы.

  • group-by-2-ccx: работает так же, как описанная ниже “group-by-ccx”, но создаёт одну группу на каждые два CCX. Это может быть полезно для CPU с большим числом CCX, в каждом из которых мало ядер, чтобы не создавать слишком много групп или немного выровнять распределение, когда используются не все ядра. Обратите внимание: при медленном обмене между CCX производительность может существенно ухудшиться. Обычно эту политику использовать не рекомендуется.

  • group-by-2-clusters: работает так же, как описанная “group-by-cluster”, но создаёт одну группу на каждые два кластера. Это может быть полезно для CPU с большим числом кластеров, в каждом из которых мало ядер, чтобы не создавать слишком много групп или немного выровнять распределение, когда используются не все ядра. Обратите внимание: при медленном обмене между кластерами производительность может существенно ухудшиться. Обычно эту политику использовать не рекомендуется.

  • group-by-3-ccx: работает так же, как описанная ниже “group-by-ccx”, но создаёт одну группу на каждые три CCX. Это может быть полезно для CPU с большим числом CCX, в каждом из которых мало ядер, чтобы не создавать слишком много групп или немного выровнять распределение, когда используются не все ядра. Обратите внимание: при медленном обмене между CCX производительность может существенно ухудшиться. Обычно эту политику использовать не рекомендуется.

  • group-by-3-clusters: работает так же, как описанная “group-by-cluster”, но создаёт одну группу на каждые три кластера. Это может быть полезно для CPU с большим числом кластеров, в каждом из которых мало ядер, чтобы не создавать слишком много групп или немного выровнять распределение, когда используются не все ядра. Обратите внимание: при медленном обмене между кластерами производительность может существенно ухудшиться. Обычно эту политику использовать не рекомендуется.

  • group-by-4-ccx: работает так же, как описанная ниже “group-by-ccx”, но создаёт одну группу на каждые четыре CCX. Это может быть полезно для CPU с большим числом CCX, в каждом из которых мало ядер, чтобы не создавать слишком много групп или немного выровнять распределение, когда используются не все ядра. Обратите внимание: при медленном обмене между CCX производительность может существенно ухудшиться. Обычно эту политику использовать не рекомендуется.

  • group-by-4-clusters: работает так же, как описанная “group-by-cluster”, но создаёт одну группу на каждые четыре кластера. Это может быть полезно для CPU с большим числом кластеров, в каждом из которых мало ядер, чтобы не создавать слишком много групп или немного выровнять распределение, когда используются не все ядра. Обратите внимание: при медленном обмене между кластерами производительность может существенно ухудшиться. Обычно эту политику использовать не рекомендуется.

  • group-by-ccx: если не заданы ни “nbthread”, ни “nbtgroups”, для каждого комплекса ядер CPU (“CCX”) с доступными CPU создаётся одна группа потоков с числом потоков, равным числу CPU. CCX объединяет CPU с одинаково быстрым доступом к кэшу последнего уровня (“LLC”), обычно к L3. В большинстве современных систем для производительности критически важно не объединять CPU из удалённых CCX в одну группу потоков. Все потоки группы привязываются ко всем CPU этого CCX, чтобы обмен внутри группы оставался локальным для CCX без чрезмерно жёсткой привязки. Соблюдаются ограничения на число потоков в группе и на число групп потоков. Эта политика рекомендуется для многосокетных систем и систем NUMA, а также для CPU с большими задержками обмена между CCX.

  • group-by-cluster: если не заданы ни “nbthread”, ни “nbtgroups”, для каждого кластера CPU с доступными CPU создаётся одна группа потоков с числом потоков, равным числу CPU. Все потоки группы привязываются ко всем CPU кластера, чтобы обмен внутри группы оставался локальным для кластера без чрезмерно жёсткой привязки. Соблюдаются ограничения на число потоков в группе и на число групп потоков. Эта политика рекомендуется для многосокетных систем и систем NUMA, а также для CPU с большими задержками обмена между CCX. В большинстве серверных систем кластеры и CCX совпадают, но в неоднородных системах (“performance” и “efficiency” либо “big” и “little”) кластер обычно включает лишь часть CCX с очень похожими CPU: одного типа и с разницей частот не более +/-5%. Это различие заметно на современных ноутбуках и настольных компьютерах, на которых разработчики и администраторы проверяют конфигурации.

  • performance: работает так же, как описанная выше “group-by-ccx”, но исключает кластеры CPU из ядер, производительность которых составляет менее 80% от производительности следующего, более производительного типа. Обычно это ядра “little” или “efficient”: их добавление, как правило, не даёт существенного выигрыша и легко может ухудшить результат, например при рукопожатиях TLS. Часто гораздо эффективнее оставить такие ядра для других задач, например обработки сети. В системах разработки на них также можно запускать вспомогательные средства, например генераторы нагрузки и средства мониторинга. Это политика по умолчанию.

  • resource: работает так же, как описанная выше “group-by-cluster”, но использует только самый маленький и энергоэффективный кластер CPU, игнорируя все остальные. Это позволяет ограничить использование ресурсов необходимым минимумом, при котором ещё сохраняется приемлемая производительность. Например, можно дополнительно снизить энергопотребление или сократить число ядер для вспомогательного процесса sidecar в арендованной системе, чтобы было проще уменьшить выделенные ей ресурсы. Обратите внимание: если кластер всего один, он всё равно используется целиком.

Можно добавить необязательное ключевое слово “threads-per-core”. Оно принимает значения “1” и “auto”. При значении 1 создаётся только один поток на ядро независимо от числа аппаратных потоков этого ядра. При значении auto создаётся по одному потоку на каждый аппаратный поток. Если привязка явно не задана и используется threads-per-core 1, по умолчанию применяется привязка per-core.

См. также: “cpu-map”, “cpu-set”, “nbthread”

cpu-set <directive>...

cpu-set <directive>...

Позволяет символически описать наборы CPU для выполнения. Директива поддерживает следующие ключевые слова: - reset отменяет все прежние ограничения, которые могли быть унаследованы, например, от диспетчера служб или команды “taskset”. - drop-cpu <set> не привязывает к CPU из этого набора - only-cpu <set> не привязывает к CPU вне этого набора - drop-node <set> не привязывает к CPU этого узла NUMA - only-node <set> не привязывает к CPU других узлов NUMA - drop-cluster <set> не привязывает к CPU аппаратного кластера с этим номером - only-cluster <set> не привязывает к CPU аппаратных кластеров с другими номерами - drop-core <set> не привязывает к CPU аппаратного ядра с этим номером - only-core <set> не привязывает к CPU аппаратных ядер с другими номерами - drop-thread <set> не привязывает к CPU аппаратного потока с этим номером - only-thread <set> не привязывает к CPU аппаратных потоков с другими номерами См. также: “cpu-policy”

crt-base <dir>

crt-base <dir>

Задаёт каталог по умолчанию для загрузки сертификатов SSL, когда в директивах “crtfile” или “crt” используется относительный путь. Заданные абсолютные пути имеют приоритет; “crt-base” в этом случае игнорируется.

daemon

daemon

Переводит процесс в фоновый режим через fork. Это рекомендуемый режим работы. Он эквивалентен аргументу командной строки “-D” и может быть отключён аргументом “-db”. В режиме systemd этот параметр игнорируется.

default-path { current | config | parent | origin <path> }

default-path { current | config | parent | origin <path> }

По умолчанию HAProxy загружает все файлы с относительными путями из каталога, в котором был запущен процесс. В некоторых случаях желательно принудительно отсчитывать относительные пути от другого каталога, как если бы процесс был запущен из него. Для этого и предназначена эта директива. Технически она временно выполняет chdir() в указанный каталог при обработке каждого конфигурационного файла и возвращается в исходный каталог после обработки каждого файла. Аргумент задаёт политику загрузки файлов, путь к которым не начинается с косой черты (’/’): - “current” означает, что все файлы с относительными путями загружаются из каталога запуска процесса; это значение по умолчанию.

- "config" означает, что все файлы с относительными путями следует загружать из каталога конфигурационного файла. Точнее, если путь к конфигурационному файлу содержит косую черту ('/'), для перехода используется вся часть пути до последней косой черты; иначе используется текущий каталог. Этот режим удобен для объединения таблиц соответствий, файлов ошибок, сертификатов и сценариев Lua в перемещаемые пакеты. При загрузке нескольких конфигурационных файлов каталог обновляется для каждого из них.

- "parent" означает, что все файлы с относительными путями следует загружать из родительского каталога по отношению к каталогу конфигурационного файла. Точнее, если путь к конфигурационному файлу содержит косую черту ('/'), к части пути до последней косой черты добавляется ".."; полученный путь используется для перехода. В противном случае используется каталог "..". Этот режим удобен для объединения таблиц соответствий, файлов ошибок, сертификатов и сценариев Lua в перемещаемые пакеты, где каждая часть находится в своём подкаталоге, например "config/", "certs/", "maps/" и т. д.

- "origin" означает, что все файлы с относительными путями следует загружать из каталога, путь к которому обязательно должен быть указан. Это упрощает управление несколькими экземплярами HAProxy, работающими параллельно в одной системе: у каждого экземпляра может быть собственный префикс, а остальные секции остаются легко перемещаемыми.

Каждая директива “default-path” немедленно заменяет предыдущую и может привести к переходу в другой каталог. Хотя это должно давать ожидаемый результат, использовать несколько директив default-path не рекомендуется. Если они всё же используются, следует придерживаться согласованной политики во всех конфигурационных файлах.

Предупреждение: некоторые элементы конфигурации, например таблицы соответствий или сертификаты, однозначно определяются заданным для них путём. При использовании перемещаемой структуры несколько элементов могут получить одно и то же уникальное имя, что затруднит их обновление во время работы, особенно если несколько конфигурационных файлов загружаются из разных каталогов. Перед переходом на относительные пути необходимо строго придерживаться схемы именования файлов без коллизий. Надёжным решением может быть добавление к именам всех файлов префикса с именем соответствующего сайта либо применение такого префикса на уровне каталогов.

description <text>

description <text>

Добавляет текст с описанием экземпляра.

Обратите внимание: некоторые символы, например #, необходимо экранировать. Поскольку этот текст вставляется в страницу HTML, следует избегать символов “<” и “>”.

deviceatlas-json-file <path>

deviceatlas-json-file <path>

Задаёт путь к файлу данных DeviceAtlas в формате JSON, который загружает API. Путь должен указывать на корректный файл данных JSON, доступный процессу HAProxy.

deviceatlas-log-level <value>

deviceatlas-log-level <value>

Задаёт уровень информации, возвращаемой API. Директива необязательна; если она не задана, по умолчанию используется 0.

deviceatlas-properties-cookie <name>

deviceatlas-properties-cookie <name>

Задаёт имя клиентского cookie, используемого для определения устройства, если при запросе применялся клиентский компонент DeviceAtlas. Директива необязательна; если она не задана, по умолчанию используется DAPROPS.

deviceatlas-separator <char>

deviceatlas-separator <char>

Задаёт символ-разделитель для результатов свойств API. Директива необязательна; если она не задана, по умолчанию используется |.

dns-accept-family <family>[,...]

dns-accept-family <family>[,...]

По умолчанию резолверы DNS принимают адреса IPv4 и IPv6. На выбор можно влиять ключевым словом “resolve-prefer” в строках server и аргументом семейства в действии “do-resolve”, однако это только предпочтение: оно не запрещает использовать другое семейство, если доступно только оно. В средах, где невозможно использовать оба стека, недоступная запись DNS только с адресом IPv6 может вызвать серьёзные проблемы: она заменит прежнюю запись IPv4, которая, возможно, продолжала бы работать до следующего запроса. Глобальный параметр “dns-accept-family” позволяет принудительно использовать только одно семейство адресов или оба. Аргумент — список следующих слов через запятую: - “ipv4”: запрашивать и принимать адреса IPv4 (записи “A”) - “ipv6”: запрашивать и принимать адреса IPv6 (записи “AAAA”) - “auto”: использовать IPv4, а также IPv6, если в системе для него есть шлюз по умолчанию. Результат последней проверки кэшируется на 30 секунд.

Если используется одно семейство, запросы к резолверам для другого семейства не отправляются, а любые ответы для него игнорируются. Начиная с 3.3 значение по умолчанию — “auto”: оба семейства включаются только после подтверждения возможности маршрутизации IPv6; иначе используется только IPv4. См. также: “resolve-prefer”, “do-resolve”

expose-deprecated-directives

expose-deprecated-directives

Эта директива должна находиться перед использованием некоторых директив, помеченных как устаревшие, чтобы отключить предупреждения и предотвратить отклонение конфигурационного файла. Это касается не всех устаревших директив, а только тех, для которых нет альтернативного решения.

expose-experimental-directives

expose-experimental-directives

Эта директива должна находиться перед использованием директив, помеченных как экспериментальные; иначе конфигурационный файл будет отклонён. Обратите внимание: для возможностей, на которые распространяется этот параметр, корректная работа не гарантируется; они могут перестать работать в течение цикла сопровождения. Пока разрабатывается следующая версия, разработчики будут поддерживать их по мере возможностей и прилагать разумные усилия, чтобы не нарушить их работу, но без гарантий. Поэтому поддержка этих возможностей после выхода следующего выпуска LTS не предполагается. Пользователям экспериментальных возможностей следует оперативно обновляться, чтобы получать внесённые улучшения. Определить, нужна ли ещё эта директива, просто: если она включена, но ни одна такая возможность её не использует, выводится предупреждение с предложением отключить её. Если предупреждения нет, директива всё ещё нужна.

external-check [preserve-env]

external-check [preserve-env]

Разрешает использовать внешний агент для проверок работоспособности. По соображениям безопасности по умолчанию это отключено. Даже после включения проверки могут завершаться неудачей, если также не включён “insecure-fork-wanted”. Если запускаемая программа использует исполняемый файл с setuid, чего ей действительно не следует делать, в секции global может также потребоваться “insecure-setuid-wanted”. По умолчанию проверки запускаются с чистым окружением, содержащим только переменные, определённые командой “external-check” в секции backend. Иногда желательно сохранить окружение, например если сложные сценарии получают из него дополнительные пути или сведения. Для этого можно добавить ключевое слово “preserve-env”. Однако в таком случае настоятельно рекомендуется не запускать программу с setuid или от привилегированного пользователя, поскольку это открывает возможности для атак на программу проверки. Подробности см. в “option external-check”, “insecure-fork-wanted” и “insecure-setuid-wanted”.

fd-hard-limit <number>

fd-hard-limit <number>

Задаёт верхнюю границу числа файловых дескрипторов, используемых процессом, независимо от системных лимитов. Значение можно принудительно задать через “ulimit-n” и “maxconn”; если они не заданы, процесс ограничивается жёстким лимитом RLIMIT_NOFILE, который показывает “ulimit -n -H”. Однако некоторые современные ОС допускают здесь чрезвычайно большие значения, порядка 1 миллиарда, что при обычной работе потребовало бы слишком много RAM. Параметр fd-hard-limit позволяет установить для этого лимита, возможно, более низкую верхнюю границу. Если системные лимиты ниже <number>, они всегда соблюдаются; если выше, используется заданное значение. По умолчанию fd-hard-limit равен 1048576. Это значение можно изменить переменной времени компиляции DEFAULT_MAXFD, которая может служить максимальным системным лимитом ядра при чрезмерно большом жёстком лимите RLIMIT_NOFILE. Параметр fd-hard-limit в секции global позволяет временно переопределить значение DEFAULT_MAXFD, заданное при сборке. В следующем примере другие параметры не заданы, и maxconn автоматически подстраивается под меньшее из значений “fd-hard-limit” и лимита RLIMIT_NOFILE:

global
    # use as many FDs as possible but no more than 50000
    fd-hard-limit 50000

См. также: ulimit-n, maxconn

gid <number>

gid <number>

Меняет идентификатор группы процесса на <number>. Рекомендуется выделить эту группу для HAProxy или небольшого набора схожих демонов. HAProxy должен запускаться от пользователя, входящего в эту группу, либо с правами суперпользователя. Обратите внимание: если пользователь запуска имеет дополнительные группы, HAProxy сможет отказаться от них только при запуске с правами суперпользователя. См. также “group” и “uid”.

grace <time>

grace <time>

Задаёт задержку между SIGUSR1 и фактической плавной остановкой.

Аргументы:

<time>  — дополнительная задержка (по умолчанию в миллисекундах) после
        получения сигнала SIGUSR1, которую нужно выждать перед переходом
        к мягкой остановке.

Используется для совместимости с устаревшими средами, где процесс haproxy нужно остановить, но внешние компоненты должны обнаружить его состояние до освобождения слушающих сокетов. Внутренняя переменная “stopping”, которую возвращает одноимённая функция извлечения образца “stopping”, переключается в true. При этом слушающие сокеты продолжают принимать соединения без изменений до истечения задержки, после чего начинается обычная плавная остановка. Это нельзя использовать для процессов, конфигурация которых перезагружается: старый процесс не сможет освободить сокеты, что может помешать запуску нового или вызвать другие проблемы.

Пример:

global
  grace 10s

# Returns 200 OK until stopping is set via SIGUSR1
frontend ext-check
  bind :9999
  monitor-uri /ext-check
  monitor fail if { stopping }

Обратите внимание: более гибкий и устойчивый подход — чтобы система оркестрации задавала глобальную переменную через CLI, использовала её при ответах на внешние проверки, а затем после задержки отправляла сигнал SIGUSR1.

Пример:

# Returns 200 OK until proc.stopping is set to non-zero. May be done
# from HTTP using set-var(proc.stopping) or from the CLI using:
# > set var proc.stopping int(1)
frontend ext-check
  bind :9999
  monitor-uri /ext-check
  monitor fail if { var(proc.stopping) -m int gt 0 }

См. также: hard-stop-after, monitor

group <group name>

group <group name>

Аналогичен “gid”, но использует GID группы с именем <group name> из /etc/group. См. также “gid” и “user”.

h1-accept-payload-with-any-method

h1-accept-payload-with-any-method

Не отклоняет запросы HTTP/1.0 GET/HEAD/DELETE с полезной нагрузкой ответом HTTP 413 Payload Too Large.

Хотя HTTP/1.1 явно разрешает такую полезную нагрузку, HTTP/1.0 не даёт однозначного ответа, и некоторые старые серверы не ожидают её и вообще не проверяют длину тела по заголовкам Content-Length или Transfer-Encoding. Поэтому одни промежуточные узлы могут правильно обработать полезную нагрузку запросов HTTP/1.0 GET/HEAD/DELETE, а другие — полностью её проигнорировать. Это создаёт риск для безопасности, поскольку возможна атака с подменой границ запросов. Поэтому по умолчанию HAProxy отклоняет запросы HTTP/1.0 GET/HEAD/DELETE с полезной нагрузкой.

Однако это может создавать проблемы для некоторых старых клиентов. В таком случае можно задать этот глобальный параметр.

h1-do-not-close-on-insecure-transfer-encoding

h1-do-not-close-on-insecure-transfer-encoding

Если где-либо в цепочке до или после узла есть агент HTTP/1.0, одновременное наличие полей Transfer-Encoding и Content-Length в одном сообщении создаёт серьёзный риск атаки с подменой границ содержимого. Согласно спецификации HTTP/1.1 (RFC9112#6.1), в такой ситуации агент обязан закрыть соединение после ответа, чтобы исключить эксплуатацию этой уязвимости. Однако это может снизить производительность некоторых очень старых клиентов, особенно если им приходится заново согласовывать соединение TLS для каждого запроса. Этот параметр позволяет попросить HAProxy не применять такое правило: сообщение очищается, но соединение остаётся открытым после ответа. Это допустимо только при полной уверенности, что в цепочке нет агентов HTTP/1.0 и все реализации перед HAProxy полностью соблюдают правила HTTP/1.1 для этих полей заголовков. В любом случае HAProxy продолжает игнорировать и удалять лишний заголовок Content-Length, чтобы не вводить следующий узел в заблуждение.

При включении этого параметра для обхода ошибки старого клиента или сервера важно понимать: независимо от того, нужен ли этот параметр, сообщения такого агента, нарушающего правило, могут быть усечены старыми агентами, которые учитывают Content-Length и игнорируют Transfer-Encoding. Причина в том, что не учитывается общий объём данных, которыми закодированы размеры блоков. Поэтому приведённое выше правило касается не только безопасности, но и отказа от агентов, у которых могут возникать проблемы обмена из-за несовместимости со старыми реализациями.

h1-case-adjust <from> <to>

h1-case-adjust <from> <to>

Задаёт преобразование регистра имени заголовка <from> в <to> перед отправкой клиентам или серверам HTTP/1, если такое преобразование включено. <from> должен быть в нижнем регистре, а <from> и <to> должны различаться только регистром. Если нужно изменить несколько имён заголовков, директиву можно повторять. Дубликаты запрещены. Если имён много, удобнее может быть “h1-case-adjust-file”. Обратите внимание: преобразование не применяется, пока для прокси не задано “option h1-case-adjust-bogus-client” или “option h1-case-adjust-bogus-server”.

Стандартного регистра имён заголовков нет: как указано в RFC7230, они нечувствительны к регистру. Поэтому приложения должны обрабатывать их без учёта регистра. Однако некоторые некорректные приложения нарушают стандарты и ошибочно полагаются на регистр, который чаще всего используют браузеры. Для HTTP/2 эта проблема критична, поскольку все имена заголовков должны передаваться в нижнем регистре; HAProxy следует тому же правилу. Все имена заголовков отправляются клиентам и серверам в нижнем регистре независимо от версии HTTP.

Для приложений, которые неправильно обрабатывают запросы или ответы, могут временно потребоваться такие обходные меры, меняющие регистр отправляемых им имён заголовков, пока приложение не будет исправлено. Обратите внимание: приложение, которому нужны такие обходные меры, может быть уязвимо к атакам с подменой границ содержимого и обязательно должно быть исправлено.

Пример:

global
  h1-case-adjust content-length Content-Length

См. “h1-case-adjust-file”, “option h1-case-adjust-bogus-client” и “option h1-case-adjust-bogus-server”.

h1-case-adjust-file <hdrs-file>

h1-case-adjust-file <hdrs-file>

Задаёт файл со списком пар ключ/значение для изменения регистра некоторых имён заголовков перед отправкой клиентам или серверам HTTP/1. В файле <hdrs-file> каждая строка должна содержать 2 имени заголовка. Первое должно быть в нижнем регистре, а оба имени должны различаться только регистром. Строки, начинающиеся с ‘#’, игнорируются, как и пустые строки. Начальные и конечные табуляции и пробелы удаляются. Дубликаты запрещены. Обратите внимание: преобразование не применяется, пока для прокси не задано “option h1-case-adjust-bogus-client” или “option h1-case-adjust-bogus-server”.

Если директива повторяется, обрабатывается только последняя. Она служит альтернативой “h1-case-adjust”, когда нужно изменить регистр многих имён заголовков. Прочитайте описание рисков, связанных с её использованием.

См. “h1-case-adjust”, “option h1-case-adjust-bogus-client” и “option h1-case-adjust-bogus-server”.

h2-workaround-bogus-websocket-clients

h2-workaround-bogus-websocket-clients

Отключает объявление клиентам о поддержке WebSocket по h2. Это позволяет обойти проблемы клиентов с реализацией относительно нового RFC8441, например Firefox 88. Чтобы клиенты могли автоматически перейти на http/1.1 для туннеля WebSocket, задайте поддержку h2 в строке bind с помощью “alpn” без явного ключевого слова “proto”. Если эта директива была включена ранее, её можно отключить, добавив перед ключевым словом “no”.

hard-stop-after <time>

hard-stop-after <time>

Задаёт максимальное время, отведённое на корректную плавную остановку.

Аргументы:

<time>  — максимальное время (по умолчанию в миллисекундах), в течение
        которого экземпляр продолжит работу после получения запроса
        мягкой остановки через сигнал SIGUSR1.

Позволяет гарантировать завершение экземпляра, даже если во время плавной остановки остаются открытые соединения, например при больших тайм-аутах прокси в режиме tcp. Применяется в режимах TCP и HTTP.

Пример:

global
  hard-stop-after 30s

См. также: grace

harden.reject-privileged-ports.tcp { on | off }

harden.reject-privileged-ports.tcp { on | off }
harden.reject-privileged-ports.quic { on | off }

Включает или отключает для каждого протокола защиту, запрещающую обмен с клиентами, которые используют привилегированные порты в качестве порта источника. Диапазон этих портов определён в RFC 6335. По умолчанию защита включена для QUIC, поскольку такое поведение подозрительно и может применяться для подмены источника или атак с усилением DNS/NTP.

http-err-codes [+-]<range>[,...] [...]

http-err-codes [+-]<range>[,...] [...]

Заменяет, сокращает или расширяет список кодов состояния, считающихся ошибкой для кодов завершения и счётчика “http_err_cnt” в таблицах привязок. По умолчанию ошибками считаются коды от 400 до 499. Однако некоторые пользователи предпочитают исключать отдельные коды в определённых условиях, особенно при учёте ошибок клиентов, например 404 в системах с динамически создаваемым содержимым. См. также “http-fail-codes” и “http_err_cnt”.

Диапазон без ‘+’ или ‘-’ заменяет существующий диапазон новым. Диапазон с начальным ‘+’ добавляется к существующему независимо от того, пересекаются они или нет. Диапазон с начальным ‘-’ удаляется из существующего. Диапазон задаётся числом от 100 до 599, после которого можно указать “-” и ещё одно число, не меньше первого, как верхнюю границу. Для одной операции добавления, удаления или замены можно указать несколько диапазонов через запятую.

Пример:

http-err-codes 400,402-444,446-480,490   # sets exactly these codes
http-err-codes 400-499 -450 +500         # sets 400 to 500 except 450
http-err-codes -450-459                  # removes 450 to 459 from range
http-err-codes +501,505                  # adds 501 and 505 to range

http-fail-codes [+-]<range>[,...] [...]

http-fail-codes [+-]<range>[,...] [...]

Заменяет, сокращает или расширяет список кодов состояния, считающихся сбоем для кодов завершения и счётчика “http_fail_cnt” в таблицах привязок. По умолчанию это коды от 500 до 599, кроме 501 и 505, которые могут быть вызваны клиентами. Обычно коды сбоев указывают на неспособность сервера обработать запрос. Некоторые пользователи предпочитают исключать коды в тех условиях, где известно, что они не относятся к сбоям, например 500 в некоторых средах SOAP, где этот код не означает ошибку сервера. Синтаксис точно такой же, как у описанного выше http-err-codes. См. также “http-err-codes” и “http_fail_cnt”.

insecure-fork-wanted

insecure-fork-wanted

По умолчанию HAProxy старается предотвратить любое создание потоков и процессов после запуска. Это особенно важно при использовании файлов Lua неизвестного происхождения и при работе с разрабатываемыми версиями, в которых ещё могут быть ошибки с неясными возможностями эксплуатации. В целом полезно гарантировать, что трафик не сможет вызвать непредвиденную фоновую активность. Однако эта защита мешает работе внешних проверок и может нарушать работу некоторых специфических сценариев Lua, которым необходим fork. Этот параметр отключает защиту. Обратите внимание: отключать её нежелательно, поскольку тогда уязвимость в библиотеке или самом HAProxy будет легче эксплуатировать. Кроме того, fork из Lua или любого другого места ненадёжен: дочерний процесс может случайно унаследовать блокировку, установленную другим потоком, и никогда не завершить операцию. Поэтому настоятельно рекомендуется никогда не использовать этот параметр, а задачи, требующие fork, пересмотреть и перенести на более безопасное решение, например использовать агентов вместо внешних проверок. Параметр поддерживает префикс “no” для отключения. Его также можно включить аргументом “-dI” в командной строке haproxy.

insecure-setuid-wanted

insecure-setuid-wanted

HAProxy не требуется запускать исполняемые файлы во время работы, кроме внешних проверок, от которых настоятельно рекомендуется отказаться. Более того, предполагается его изоляция в пустом chroot. Поэтому практически нет обоснованной причины разрешать запуск исполняемого файла с setuid без полного понимания пользователем рисков. Если HAProxy требуется вызывать внешние проверки или отключить chroot, эксплуатация уязвимости в библиотеке или самом HAProxy может привести к запуску внешней программы. В Linux процесс можно ограничить так, чтобы бит setuid любого такого исполняемого файла игнорировался. Это существенно снижает риск повышения привилегий; именно так HAProxy действует по умолчанию. Если это мешает внешней проверке, например использующей команду “ping”, защиту можно отключить, явно добавив эту директиву в секцию global. Если директива включена, её можно снова отключить, добавив перед ней ключевое слово “no”.

issuers-chain-path <dir>

issuers-chain-path <dir>

Задаёт каталог для загрузки цепочек сертификатов, используемых при достраивании цепочки издателя. Все файлы должны быть в формате PEM. Если для сертификата, загруженного через “crt” или “crt-list”, цепочка сертификатов не включена в PEM, HAProxy достроит её, когда издатель сертификата соответствует первому сертификату цепочки, загруженной через “issuers-chain-path”. Такие сертификаты цепочки также обычно называют промежуточными. Файл “crt” с PrivateKey+Certificate+IntermediateCA2+IntermediateCA1 можно заменить файлом с PrivateKey+Certificate. HAProxy достроит цепочку, если в каталоге “issuers-chain-path” есть файл с IntermediateCA2+IntermediateCA1. Все остальные сертификаты с тем же издателем будут совместно использовать эту цепочку в памяти.

Возможности OCSP могут использовать достроенную цепочку, если .issuer не использовался или цепочка не была предоставлена в PEM.

jwt.allow_none_alg

jwt.allow_none_alg

Разрешает JWT-токены с алгоритмом “none” в преобразователе ‘jwt_verify’. При включении этой опции такие токены всегда считаются действительными. По умолчанию неподписанные токены отклоняются как небезопасные (см. RFC8725 раздел 3.1 ).

jwt.decrypt_alg_list <list>

jwt.decrypt_alg_list <list>

Задаёт список алгоритмов, разрешённых в преобразователях jwt_decrypt_XXX. Токены JWT с неподдерживаемыми или отключёнными алгоритмами никогда не расшифровываются. Алгоритмы должны быть указаны в формате из раздела 4.1 RFC7518 и разделены двоеточиями. Специальное имя “ALL” включает все поддерживаемые алгоритмы; полный список см. в описании преобразователя “jwt_decrypt_jwk”. К имени алгоритма можно добавить ‘!’, чтобы явно отключить его. Обратите внимание: если “ALL” не указан, этот параметр отключает все алгоритмы, которые не перечислены явно.

Примеры:

# Enable all algorithms but the "ECDH-ES" one
jwt.decrypt_alg_list ALL:!ECDH-ES

# Only enable ECDH-ES algorithms
jwt.decrypt_alg_list ECDH-ES:ECDH-ES+A128KW:ECDH-ES+A192KW:ECDH-ES+A256KW

jwt.decrypt_enc_list <list>

jwt.decrypt_enc_list <list>

Задаёт список алгоритмов шифрования, разрешённых в преобразователях jwt_decrypt_XXX. Токены JWT с неподдерживаемыми или отключёнными алгоритмами шифрования никогда не расшифровываются. Алгоритмы должны быть указаны в формате из раздела 5.1 RFC7518 и разделены двоеточиями. Специальное имя “ALL” включает все поддерживаемые алгоритмы; полный список см. в описании преобразователя “jwt_decrypt_jwk”. К имени алгоритма можно добавить ‘!’, чтобы явно отключить его. Обратите внимание: если “ALL” не указан, этот параметр отключает все алгоритмы, которые не перечислены явно.

Примеры:

# Enable only AES GCM encrypting algorithms
jwt.decrypt_enc_list A128GCM:A192GCM:A256GCM

key-base <dir>

key-base <dir>

Задаёт каталог по умолчанию для загрузки закрытых ключей SSL, когда в директивах “key” используется относительный путь. Заданные абсолютные пути имеют приоритет; “key-base” в этом случае игнорируется. Этот параметр работает только со строкой load в crt-store.

limited-quic

limited-quic

Этот параметр необходимо использовать для явного включения слушающих сокетов QUIC, если haproxy собран с версией OpenSSL без поддержки QUIC. Он активирует внутренний слой совместимости haproxy, который должен быть выбран при сборке с помощью USE_QUIC_OPENSSL_COMPAT=1. Этот слой поддерживает большинство необходимых операций TLS, но не поддерживает QUIC 0-RTT.

Эта возможность предназначена прежде всего для OpenSSL до версии 3.5.2, где API QUIC отсутствовал или был реализован лишь частично. Слой совместимости можно включить и для версии 3.5.2 или новее, но, вероятно, это не требуется.

Если limited-quic задан, но слой совместимости не был выбран при сборке, параметр игнорируется без сообщения, а операции QUIC TLS выполняются средствами библиотеки TLS.

localpeer <name>

localpeer <name>

Задаёт имя локального экземпляра среди узлов peers. Оно игнорируется, если указан аргумент командной строки “-L” или директива использована после определений секций “peers”. В таких случаях при разборе конфигурации выводится предупреждение.

Этот параметр также задаёт переменную окружения HAPROXY_LOCALPEER. См. также “-L” в руководстве по управлению и секцию “peers” ниже.

log <target> [len <length>] [format <format>] [sample <ranges>:<sample_size>]

log <target> [len <length>] [format <format>] [sample <ranges>:<sample_size>]
    [profile <prof>] <facility> [max level [min level]]

Добавляет глобальный сервер syslog. Можно задать несколько таких серверов. Они получают записи о запуске и завершении, а также все журналы прокси, настроенных с “log global”. Подробности см. в описании параметра “log” для прокси.

log-send-hostname [<string>]

log-send-hostname [<string>]

Задаёт поле имени хоста в заголовке syslog. Если указан необязательный параметр “string”, полю присваивается содержимое этой строки; иначе используется имя хоста системы. Обычно это нужно, если журналы не пересылаются через промежуточный сервер syslog, либо для изменения имени хоста, выводимого в журнале.

log-tag <string>

log-tag <string>

Задаёт этой строкой поле тега в заголовке syslog. По умолчанию используется имя программы при запуске из командной строки, обычно “haproxy”. Иногда это полезно для различения нескольких процессов на одном хосте. См. также директиву “log-tag” для отдельных прокси.

lua-load <file> [ <arg1> [ <arg2> [ ... ] ] ]

lua-load <file> [ <arg1> [ <arg2> [ ... ] ] ]

Эта глобальная директива загружает и выполняет файл Lua в общем контексте, видимом всем потокам. Любая переменная, заданная в таком контексте, видна из любого потока. Это самый простой и рекомендуемый способ загрузки программ Lua, но при большом числе вызовов Lua он плохо масштабируется: с глобальным состоянием одновременно может работать только один поток. Программа, загруженная таким способом, всегда видит 0 в переменной “core.thread”. Директиву можно использовать несколько раз.

Аргументы args доступны в файле Lua через приведённый ниже код в теле файла. Не забывайте, что индексы массивов Lua начинаются с 1. Переменная “local”, объявленная в файле, доступна во всём этом файле и недоступна в других файлах.

 local args = table.pack(...)

lua-load-per-thread <file> [ <arg1> [ <arg2> [ ... ] ] ]

lua-load-per-thread <file> [ <arg1> [ <arg2> [ ... ] ] ]

Эта глобальная директива загружает и выполняет файл Lua в каждом запущенном потоке. Глобальные переменные видимы только внутри потока, поэтому каждый поток может видеть своё значение. В программах, загруженных таким способом, настоятельно рекомендуется не использовать глобальные переменные. Для каждого потока загружается и инициализируется отдельная копия; всё выполняется последовательно, по возрастанию номеров потоков от 1 до nbthread. Если какие-то операции нужно выполнить только один раз, программе следует проверить переменную “core.thread”, чтобы определить, какой поток инициализируется. Загруженные таким способом программы выполняются параллельно во всех потоках и хорошо масштабируются. Это рекомендуемый способ загрузки простых функций, регистрирующих методы извлечения образцов, преобразователи, действия или службы, когда точно известно, что программа не зависит от глобальных переменных. Для простоты директива доступна и при использовании одного потока, и даже при отключённой поддержке потоков; в последнем случае она эквивалентна lua-load. Директиву можно использовать несколько раз.

Об использовании args см. lua-load.

lua-prepend-path <string> [<type>]

lua-prepend-path <string> [<type>]

Добавляет указанную строку с последующей точкой с запятой в начало переменной Lua package.<type>. <type> должен быть “path” или “cpath”. Если <type> не задан, по умолчанию используется “path”.

Пути Lua — списки шаблонов, разделённых точкой с запятой. Они определяют, как функция require пытается найти исходный файл библиотеки. Знаки вопроса (?) в шаблоне заменяются именем модуля. Путь проверяется слева направо, поэтому пути, добавленные в начало позже, проверяются раньше.

Например, если указать следующий путь:

lua-prepend-path /usr/share/haproxy-lua/?/init.lua
lua-prepend-path /usr/share/haproxy-lua/?.lua

При вызове require "example" Lua сначала пытается загрузить /usr/share/haproxy-lua/example.lua как сценарий. Если его нет, проверяется /usr/share/haproxy-lua/example/init.lua, а если нет и этого файла — пути по умолчанию.

Подробности см. в документации Lua: https://www.lua.org/pil/8.1.html .

master-worker (deprecated)

master-worker (deprecated)

Режим master-worker. Эквивалентен аргументу командной строки “-W”.

Это ключевое слово устарело; для запуска в режиме master-worker используйте “-W” или “-Ws”.

В этом режиме запускается главный процесс “master”, который после чтения конфигурации создаёт через fork рабочий процесс “worker” для обработки трафика. Главный процесс выполняет роль диспетчера процессов, следящего за рабочими процессами “workers”.

В этом режиме HAProxy можно перезагрузить напрямую, отправив главному процессу сигнал SIGUSR2. При перезагрузке главный процесс повторно читает конфигурацию и создаёт через fork новый рабочий процесс. Прежний рабочий процесс остаётся до завершения своих задач.

Режим master-worker совместим как с работой на переднем плане, так и с режимом демона.

По умолчанию, если рабочий процесс завершается с кодом ошибки, например из-за ошибки сегментации, все рабочие процессы принудительно завершаются, а главный процесс выходит. Это удобно сочетать с Restart=on-failure в файле модуля systemd для повторного запуска всех процессов. Чтобы отключить такое поведение, необходимо использовать ключевое слово “no-exit-on-failure”.

См. также “-W” в руководстве по управлению.

master-worker no-exit-on-failure

master-worker no-exit-on-failure

В режиме master-worker по умолчанию, если рабочий процесс завершается с кодом ошибки, например из-за ошибки сегментации, все рабочие процессы принудительно завершаются, а главный процесс выходит. Это удобно сочетать с Restart=on-failure в файле модуля systemd для повторного запуска всех процессов.

Это ключевое слово позволяет оставить остальные процессы работающими после аварийного завершения рабочего процесса, вместо того чтобы завершать их все. Использовать его нужно осторожно: оно предназначено только для отладки и может привести главный процесс в нештатное состояние.

max-threads-per-group <number>

max-threads-per-group <number>

Задаёт максимальное число потоков в группе. Если число групп потоков не зафиксировано директивой “thread-groups”, haproxy создаёт столько групп, сколько нужно для запрошенного числа потоков. Минимальное значение — 1, максимальное — 64 в 64-битных системах или 32 в 32-битных. Меньшие значения снижают конкуренцию за общее состояние при атомарных операциях, но могут увеличить число сокетов, необходимых для всех слушателей и для хранения простаивающих соединений с бэкендами. Большие значения уменьшают эти затраты, но увеличивают использование CPU при конкуренции за ресурсы и снижают скорость установления соединений. Значение по умолчанию — 16: это лучший компромисс, выявленный экспериментально на разных системах, включая процессоры x86_64 нескольких производителей и большие системы Arm64, как на физическом оборудовании, так и под гипервизорами.

mworker-max-reloads <number>

mworker-max-reloads <number>

В режиме master-worker этот параметр ограничивает число перезагрузок, которые может пережить рабочий процесс. Если после перезагрузки он не завершился и число пережитых перезагрузок превысило указанное значение, процесс получает SIGTERM. Это помогает контролировать число рабочих процессов. См. также “show proc” в руководстве по управлению.

По умолчанию это значение равно 50.

nbthread <number>

nbthread <number>

Этот параметр доступен только при сборке с поддержкой потоков. Он запускает HAProxy с <number> потоками. “nbthread” работает и при запуске HAProxy на переднем плане. На некоторых платформах с поддержкой привязки к CPU значение “nbthread” по умолчанию автоматически принимается равным числу CPU, к которым процесс привязан при запуске. Поэтому число потоков можно легко регулировать из вызывающего процесса командами вроде “taskset” или “cpuset”. В остальных случаях по умолчанию используется 1. Значение по умолчанию показывается в выводе “haproxy -vv”. Обратите внимание: заданные здесь или автоматически определённые значения ограничиваются параметром “thread-hard-limit”, если он задан.

numa-cpu-mapping

numa-cpu-mapping

При работе на платформе с поддержкой NUMA позволяет директиве “cpu-policy” изучить топологию, выбрать оптимальный набор CPU и соответствующее число потоков. Если на конкретной архитектуре полученная привязка неоптимальна, её можно отключить записью ’no numa-cpu-mapping’. Автоматическая привязка также не применяется, если в конфигурации есть директива ’nbthread’, если привязка процесса уже задана, например директивой ‘cpu-map’ или утилитой taskset, либо если cpu-policy задано любое другое значение. См. также “cpu-map”, “cpu-policy”, “cpu-set”.

ocsp-update.disable [ on | off ]

ocsp-update.disable [ on | off ]

Полностью отключает ocsp-update в HAProxy. Любая конфигурация ocsp-update игнорируется. Значение по умолчанию — “off”. Подробности о механизме автоматического обновления см. в описании параметра “ocsp-update”.

ocsp-update.httpproxy <address>[:port]

ocsp-update.httpproxy <address>[:port]

Разрешает использовать прокси HTTP для обновлений OCSP. Работает только с HTTP; HTTPS не поддерживается. Этот параметр позволяет средству обновления OCSP отправлять абсолютный URI в запросе к прокси.

ocsp-update.maxdelay <number>

ocsp-update.maxdelay <number>
tune.ssl.ocsp-update.maxdelay <number> (deprecated)

Задаёт максимальный интервал между двумя автоматическими обновлениями одного ответа OCSP. Время задаётся в секундах; по умолчанию — 3600 (1 час). Значение должно быть больше “ocsp-update.mindelay”. Подробности о механизме автоматического обновления см. в описании параметра “ocsp-update”.

ocsp-update.mindelay <number>

ocsp-update.mindelay <number>
tune.ssl.ocsp-update.mindelay <number> (deprecated)

Задаёт минимальный интервал между двумя автоматическими обновлениями одного ответа OCSP. Время задаётся в секундах; по умолчанию — 300 (5 минут). Особенно полезно для ответов OCSP без явно заданного срока действия. Значение должно быть меньше “ocsp-update.maxdelay”. Подробности о механизме автоматического обновления см. в описании параметра “ocsp-update”.

ocsp-update.mode [ on | off ]

ocsp-update.mode [ on | off ]

Задаёт режим ocsp-update по умолчанию для всех сертификатов, используемых в конфигурации. Этот глобальный параметр может быть переопределён параметром “ocsp-update” в crt-list. По умолчанию он имеет значение “off”. Подробности о механизме автоматического обновления см. в описании параметра “ocsp-update”.

pidfile <pidfile>

pidfile <pidfile>

Записывает идентификаторы всех демонов в файл <pidfile> в режиме демона либо PID главного процесса в файл <pidfile> в режиме master-worker. Эквивалентен аргументу командной строки “-p”. Файл должен быть доступен пользователю, запускающему процесс. См. также “daemon” и “master-worker”.

pp2-never-send-local

pp2-never-send-local

В реализации протокола PROXY v2 в HAProxy вплоть до версии 2.1 была ошибка: для проверок работоспособности отправлялась команда PROXY вместо LOCAL. Это малозначительное отклонение, но оно вносит путаницу в журналы некоторых серверов. К сожалению, ошибку обнаружили очень поздно. Выяснилось, что некоторые серверы, возможно проверявшие свою реализацию протокола PROXY только с HAProxy, неправильно обрабатывают команду LOCAL и при проверках HAProxy постоянно остаются в состоянии “down”. В этом случае можно включить глобальный параметр, возвращающий прежнее ошибочное поведение, на время обращения к поставщикам затронутых компонентов и получения исправлений. По умолчанию параметр отключён и действует на все серверы с директивой “send-proxy-v2”.

presetenv <name> <value>

presetenv <name> <value>

Задаёт переменной окружения <name> значение <value>. Если переменная уже существует, она не перезаписывается. Изменения вступают в силу немедленно: следующая строка конфигурационного файла уже видит новое значение. См. также “setenv”, “resetenv” и “unsetenv”.

prealloc-fd

prealloc-fd

Однократно открывает максимальный файловый дескриптор, вызывая предварительное выделение структур данных ядра. Это предотвращает краткие паузы, возникающие при nbthread>1, когда HAProxy открывает файловый дескриптор и ядру требуется расширить свои структуры данных.

resetenv [<name> ...]

resetenv [<name> ...]

Удаляет все переменные окружения, кроме указанных в аргументе. Позволяет получить чистое управляемое окружение перед установкой новых значений через setenv или unsetenv. Обратите внимание: некоторые внутренние функции могут использовать переменные окружения, например функции работы со временем, а также OpenSSL и внешние проверки. Применять этот параметр необходимо крайне осторожно и только после полной проверки. Изменения вступают в силу немедленно: следующая строка конфигурационного файла уже видит новое окружение. См. также “setenv”, “presetenv” и “unsetenv”.

server-state-base <directory>

server-state-base <directory>

Задаёт префикс каталога, добавляемый перед именами всех файлов состояния серверов, которые не начинаются с ‘/’. См. также “server-state-file”, “load-server-state-from-file” и “server-state-file-name”.

server-state-file <file>

server-state-file <file>

Задаёт путь к файлу состояния серверов. Если путь начинается с косой черты (’/’), он считается абсолютным; иначе — относительным к каталогу “server-state-base”, если он задан, либо к текущему каталогу. Перед перезагрузкой HAProxy текущее состояние серверов можно сохранить командой статистики “show servers state”. Вывод этой команды должен быть записан в файл <file>. При запуске, до начала обработки трафика, HAProxy прочитает, загрузит и применит состояние каждого сервера, который найден в файле и присутствует в текущей рабочей конфигурации. См. также “server-state-base”, “show servers state”, “load-server-state-from-file” и “server-state-file-name”

set-dumpable [ on | off | libs ]

set-dumpable [ on | off | libs ]

Позволяет выбрать поведение при создании дампа памяти после аварийного завершения процесса. Доступны следующие варианты:

  • on: включает создание дампов памяти на уровне процесса, если оно ранее было отключено.

  • off: отключает ранее включённое создание дампов памяти.

  • libs: включает создание дампов памяти со встроенной копией исполняемых файлов и библиотек, необходимых для отладки. Это может потребоваться разработчикам. В этом случае haproxy пытается загрузить в память библиотеки, от которых он зависит, и сохранить их там. Если процесс аварийно завершится, они попадут в дамп памяти, поэтому их больше не потребуется извлекать из файловой системы и не будет риска их несоответствия дампу. Для этого требуется от нескольких мегабайт до нескольких десятков мегабайт дополнительной RAM, поэтому на небольших системах этот режим лучше не использовать.

Этот параметр лучше оставить отключённым по умолчанию и включать только по запросу разработчика. По умолчанию он отключён. Без аргумента используется значение “on”. Если параметр включён, его всё равно можно принудительно отключить, добавив перед ним ключевое слово “no” или задав значение “off”. Он не влияет ни на производительность, ни на стабильность, но настойчиво пытается снова включить создание дампов памяти, которое могло быть отключено ограничением размера файла (ulimit -f), ограничением размера дампа (ulimit -c) или запретом создания дампа процесса после изменения его UID/GID (например, /proc/sys/fs/suid_dumpable в Linux). Создание дампов всё ещё могут ограничивать права доступа к текущему каталогу (следует проверить, из какого каталога запускается файл), права доступа к каталогу chroot (может потребоваться временно отключить директиву chroot или перенести его в отдельный каталог, доступный для записи) либо другие ограничения конкретной системы. Например, некоторые варианты Linux известны тем, что заменяют путь к файлу дампа по умолчанию путём к исполняемому файлу, которого даже нет в системе (следует проверить /proc/sys/kernel/core_pattern). Часто проблему решает простая запись “core”, “core.%p” или “/var/log/core/core.%p”. При включении этого параметра в ожидании повторного проявления редкой проблемы часто полезно сначала попытаться получить такой дамп, например отправив “kill -11” процессу “haproxy”, и проверить, что при завершении он оставляет дамп в ожидаемом месте.

set-var <var-name> <expr>

set-var <var-name> <expr>

Задаёт переменной уровня процесса ‘<var-name>’ результат вычисления выражения образца <expr>. Переменная ‘<var-name>’ может быть только переменной уровня процесса (с префиксом ‘proc.’). Работает точно так же, как действие ‘set-var’ в правилах TCP или HTTP, но выражение вычисляется при разборе конфигурации и переменная задаётся немедленно. В выражении разрешены только функции извлечения образцов и преобразователи, использующие внутренние данные, обычно ‘int(value)’ или ‘str(value)’. Можно также ссылаться на ранее выделенные переменные. Затем эти переменные будут доступны для чтения и изменения из обычных наборов правил.

Пример:

global
    set-var proc.current_state str(primary)
    set-var proc.prio int(100)
    set-var proc.threshold int(200),sub(proc.prio)

set-var-fmt <var-name> <fmt>

set-var-fmt <var-name> <fmt>

Задаёт переменной уровня процесса ‘<var-name>’ строку, полученную при вычислении формата журнала <fmt>. Переменная ‘<var-name>’ может быть только переменной уровня процесса (с префиксом ‘proc.’). Работает точно так же, как действие ‘set-var-fmt’ в правилах TCP или HTTP, но выражение вычисляется при разборе конфигурации и переменная задаётся немедленно. В выражении разрешены только функции извлечения образцов и преобразователи, использующие внутренние данные, обычно ‘int(value)’ или ‘str(value)’. Можно также ссылаться на ранее выделенные переменные. Затем эти переменные будут доступны для чтения и изменения из обычных наборов правил. Подробности о синтаксисе пользовательского формата журнала см. в разделе 8.2.6 .

Пример:

global
    set-var-fmt proc.current_state "primary"
    set-var-fmt proc.bootid        "%pid|%t"

setcap <name>[,<name>...]

setcap <name>[,<name>...]

Задаёт список полномочий, которые должны сохраняться при запуске и работе от имени пользователя без прав root (uid > 0) либо при запуске с uid 0 (root) и последующем переходе к пользователю без прав root. По умолчанию при смене uid теряются все права, но некоторые из них часто нужны при соединении с сервером с чужого адреса во время прозрачного проксирования либо при привязке к порту ниже 1024, например при использовании “tune.quic.fe.sock-per-conn default-on”. В результате такие конфигурации целиком работают с uid 0. Назначение полномочий обычно безопаснее, поскольку сохраняются только необходимые полномочия. Эта возможность зависит от ОС и включена только в Linux, если при сборке задано USE_LINUX_CAP=1. Список поддерживаемых полномочий также зависит от ОС и перечисляется в сообщении об ошибке, выводимом при передаче неверного или пустого имени полномочия. Можно передать несколько полномочий, разделённых запятыми. Из часто используемых полномочий “cap_net_raw” разрешает прозрачную привязку к чужому адресу, а “cap_net_bind_service” разрешает привязку к привилегированному порту и может использоваться QUIC. Если процесс запускается и работает от имени одного и того же пользователя без прав root, необходимые полномочия следует задать исполняемому файлу haproxy с помощью setcap вместе с этим ключевым словом. Подробнее о назначении полномочий исполняемому файлу haproxy см. в главе 13.1 о поддержке полномочий Linux в руководстве по управлению.

Пример:

global
    setcap cap_net_bind_service,cap_net_admin

setenv <name> <value>

setenv <name> <value>

Задаёт переменной окружения <name> значение <value>. Если переменная существует, она перезаписывается. Изменения вступают в силу немедленно: следующая строка конфигурационного файла уже видит новое значение. См. также “presetenv”, “resetenv” и “unsetenv”.

shm-stats-file <name>

shm-stats-file <name>

Эта директива включает использование разделяемой памяти для хранения статистических счётчиков. <name> передаётся как аргумент shm_open() для открытия разделяемой памяти в уникальном месте. Это также означает, что директива доступна только в системах с поддержкой shm_open(). При использовании SHM для статистики все счётчики фронтендов, бэкендов, слушателей и серверов, которые могут совместно использоваться, хранятся в SHM при условии, что для них задан GUID. При перезагрузке haproxy новый процесс пытается найти в SHM объекты, которые можно сопоставить с объектами конфигурации по GUID и типу, чтобы сохранить значения некоторых счётчиков при перезагрузке. При корректной остановке haproxy объекты SHM, напротив, освобождаются, то есть счётчики фактически сбрасываются. Для принудительного сброса можно также вручную удалить файл перед запуском нового процесса.

См. также “guid”, “guid-prefix” и “shm-stats-file-max-objects”

shm-stats-file-max-objects <number>

shm-stats-file-max-objects <number>

Задаёт максимальное число объектов, которые разделяемая память для общих счётчиков может хранить для каждой группы потоков. Значение напрямую связано с максимальным размером разделяемой памяти и используется для предварительного отображения shm заданного размера, чтобы избежать повторного отображения во время работы. По умолчанию используется 2k, что должно подходить для большинства конфигураций без риска чрезмерного использования памяти; при необходимости значение легко изменить. При запуске haproxy выдаст ошибку, если значение слишком мало для регистрации объектов, которые должны храниться в разделяемой памяти. Параметр имеет значение только при заданном “shm-stats-file”.

См. также “thread-groups”

ssl-default-bind-ciphers <ciphers>

ssl-default-bind-ciphers <ciphers>

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он задаёт строку по умолчанию со списком алгоритмов шифрования (наборов шифров), согласуемых при рукопожатии SSL/TLS вплоть до TLSv1.2, для всех строк “bind”, где такой список не задан явно. Формат строки определён в “man 1 ciphers” из справочных страниц OpenSSL. Справочную информацию и рекомендации см., например, в (https://wiki.mozilla.org/Security/Server_Side_TLS ) и (https://mozilla.github.io/server-side-tls/ssl-config-generator/ ). Для настройки шифров TLSv1.3 см. ключевое слово “ssl-default-bind-ciphersuites”. Подробнее см. описание ключевого слова “bind”.

ssl-default-bind-ciphersuites <ciphersuites>

ssl-default-bind-ciphersuites <ciphersuites>

Этот параметр доступен только при сборке с поддержкой OpenSSL и использовании OpenSSL 1.1.1 или новее для сборки HAProxy. Он задаёт строку по умолчанию со списком алгоритмов шифрования (наборов шифров), согласуемых при рукопожатии TLSv1.3, для всех строк “bind”, где такой список не задан явно. Формат строки определён в разделе “ciphersuites” страницы “man 1 ciphers” из справочных страниц OpenSSL. Для настройки шифров TLSv1.2 и более ранних версий см. ключевое слово “ssl-default-bind-ciphers”. Этот параметр может принимать наборы шифров TLSv1.2, однако такое поведение не документировано и не рекомендуется, поскольку оно может быть непоследовательным или ошибочным. Наборы шифров TLSv1.3 по умолчанию в OpenSSL: “TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256”

TLSv1.3 поддерживает только 5 наборов шифров:

  • TLS_AES_128_GCM_SHA256
  • TLS_AES_256_GCM_SHA384
  • TLS_CHACHA20_POLY1305_SHA256
  • TLS_AES_128_CCM_SHA256
  • TLS_AES_128_CCM_8_SHA256

Подробнее см. описание ключевого слова “bind”.

Пример:

global
    ssl-default-bind-ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256
    ssl-default-bind-ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256

ssl-default-bind-client-sigalgs <sigalgs>

ssl-default-bind-client-sigalgs <sigalgs>

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он задаёт строку по умолчанию со списком алгоритмов подписи для аутентификации клиента для всех строк “bind”, где такой список не задан явно. Формат строки — список алгоритмов подписи, разделённых двоеточиями. Каждый алгоритм подписи можно записать в одной из двух форм: имя схемы подписи TLS1.3 (“rsa_pss_rsae_sha256”) либо алгоритм открытого ключа + алгоритм хеширования (“ECDSA+SHA256”). Список может содержать обе формы. Подробнее о формате см. SSL_CTX_set1_client_sigalgs(3). Список алгоритмов подписи также приведён в разделе 4.2.3 RFC8446 и в файле ssl/t1_lib.c в OpenSSL. Этот параметр неприменим к TLSv1.1 и более ранним версиям протокола, поскольку в них алгоритмы подписи отдельно не согласуются. Изменять этот параметр не рекомендуется, если не требуется совместимость с промежуточным сетевым устройством.

ssl-default-bind-curves <curves>

ssl-default-bind-curves <curves>

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он задаёт строку по умолчанию со списком алгоритмов эллиптических кривых (набором кривых), согласуемых при рукопожатии SSL/TLS с ECDHE. Формат строки — список имён кривых, разделённых двоеточиями. Подробнее см. описание ключевого слова “bind”.

ssl-default-bind-options [<option>]...

ssl-default-bind-options [<option>]...

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он задаёт параметры ssl-options по умолчанию, принудительно применяемые ко всем строкам “bind”. Доступные параметры см. в описании ключевого слова “bind”.

Пример:

global
   ssl-default-bind-options ssl-min-ver TLSv1.0 no-tls-tickets

ssl-default-bind-sigalgs <sigalgs>

ssl-default-bind-sigalgs <sigalgs>

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он задаёт строку по умолчанию со списком алгоритмов подписи, согласуемых при рукопожатии TLSv1.2 и TLSv1.3, для всех строк “bind”, где такой список не задан явно. Формат строки — список алгоритмов подписи, разделённых двоеточиями. Каждый алгоритм подписи можно записать в одной из двух форм: имя схемы подписи TLS1.3 (“rsa_pss_rsae_sha256”) либо алгоритм открытого ключа + алгоритм хеширования (“ECDSA+SHA256”). Список может содержать обе формы. Подробнее о формате см. SSL_CTX_set1_sigalgs(3). Список алгоритмов подписи также приведён в разделе 4.2.3 RFC8446 и в файле ssl/t1_lib.c в OpenSSL. Этот параметр неприменим к TLSv1.1 и более ранним версиям протокола, поскольку в них алгоритмы подписи отдельно не согласуются. Изменять этот параметр не рекомендуется, если не требуется совместимость с промежуточным сетевым устройством.

ssl-default-server-ciphers <ciphers>

ssl-default-server-ciphers <ciphers>

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он задаёт строку по умолчанию со списком алгоритмов шифрования, согласуемых при рукопожатии SSL/TLS с сервером вплоть до TLSv1.2, для всех строк “server”, где такой список не задан явно. Формат строки определён в “man 1 ciphers” из справочных страниц OpenSSL. Справочную информацию и рекомендации см., например, в (https://wiki.mozilla.org/Security/Server_Side_TLS ) и (https://mozilla.github.io/server-side-tls/ssl-config-generator/ ). Для настройки шифров TLSv1.3 см. ключевое слово “ssl-default-server-ciphersuites”. Подробнее см. описание ключевого слова “server”.

ssl-default-server-ciphersuites <ciphersuites>

ssl-default-server-ciphersuites <ciphersuites>

Этот параметр доступен только при сборке с поддержкой OpenSSL и использовании OpenSSL 1.1.1 или новее для сборки HAProxy. Он задаёт строку по умолчанию со списком алгоритмов шифрования, согласуемых при рукопожатии TLSv1.3 с сервером, для всех строк “server”, где такой список не задан явно. Формат строки определён в разделе “ciphersuites” страницы “man 1 ciphers” из справочных страниц OpenSSL. Для настройки шифров TLSv1.2 и более ранних версий см. ключевое слово “ssl-default-server-ciphers”. Подробнее см. описание ключевого слова “server”.

ssl-default-server-client-sigalgs <sigalgs>

ssl-default-server-client-sigalgs <sigalgs>

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он задаёт строку по умолчанию со списком алгоритмов подписи для аутентификации клиента для всех строк “server”, где такой список не задан явно. Формат строки — список алгоритмов подписи, разделённых двоеточиями. Каждый алгоритм подписи можно записать в одной из двух форм: имя схемы подписи TLS1.3 (“rsa_pss_rsae_sha256”) либо алгоритм открытого ключа + алгоритм хеширования (“ECDSA+SHA256”). Список может содержать обе формы. Подробнее о формате см. SSL_CTX_set1_client_sigalgs(3). Список алгоритмов подписи также приведён в разделе 4.2.3 RFC8446 и в файле ssl/t1_lib.c в OpenSSL. Этот параметр неприменим к TLSv1.1 и более ранним версиям протокола, поскольку в них алгоритмы подписи отдельно не согласуются. Изменять этот параметр не рекомендуется, если не требуется совместимость с промежуточным сетевым устройством.

ssl-default-server-curves <curves>

ssl-default-server-curves <curves>

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он задаёт строку по умолчанию со списком алгоритмов эллиптических кривых (набором кривых), согласуемых при рукопожатии SSL/TLS с ECDHE. Формат строки — список имён кривых, разделённых двоеточиями. Подробнее см. описание ключевого слова “server”.

ssl-default-server-options [<option>]...

ssl-default-server-options [<option>]...

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он задаёт параметры ssl-options по умолчанию, принудительно применяемые ко всем строкам “server”. Доступные параметры см. в описании ключевого слова “server”.

ssl-default-server-sigalgs <sigalgs>

ssl-default-server-sigalgs <sigalgs>

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он задаёт строку по умолчанию со списком алгоритмов подписи, согласуемых при рукопожатии TLSv1.2 и TLSv1.3, для всех строк “server”, где такой список не задан явно. Формат строки — список алгоритмов подписи, разделённых двоеточиями. Каждый алгоритм подписи можно записать в одной из двух форм: имя схемы подписи TLS1.3 (“rsa_pss_rsae_sha256”) либо алгоритм открытого ключа + алгоритм хеширования (“ECDSA+SHA256”). Список может содержать обе формы. Подробнее о формате см. SSL_CTX_set1_sigalgs(3). Список алгоритмов подписи также приведён в разделе 4.2.3 RFC8446 и в файле ssl/t1_lib.c в OpenSSL. Этот параметр неприменим к TLSv1.1 и более ранним версиям протокола, поскольку в них алгоритмы подписи отдельно не согласуются. Изменять этот параметр не рекомендуется, если не требуется совместимость с промежуточным сетевым устройством.

ssl-dh-param-file <file>

ssl-dh-param-file <file>

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он задаёт параметры DH по умолчанию, используемые при рукопожатии SSL/TLS с обменом ключами на основе эфемерного алгоритма Диффи — Хеллмана (DHE), для всех строк “bind”, где они не заданы явно. Их переопределяют пользовательские параметры DH из файла сертификата bind, если они там есть. Если пользовательские параметры DH не заданы ни с помощью ssl-dh-param-file, ни непосредственно в файле сертификата, шифры DHE не используются, если не задан tune.ssl.default-dh-param. В последнем случае используются предопределённые параметры DH указанного размера. Пользовательские параметры считаются более безопасными, поэтому рекомендуется использовать их. Пользовательские параметры DH можно создать командой OpenSSL “openssl dhparam <size>”, где размер следует выбирать не менее 2048, поскольку 1024-битные параметры DH больше не следует считать безопасными.

ssl-passphrase-cmd <cmd> <args> ...

ssl-passphrase-cmd <cmd> <args> ...

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он позволяет задать полную командную строку, вызываемую при загрузке зашифрованного сертификата во время инициализации. Команда может быть сценарием или любой другой программой. Первым параметром ей передаётся путь к зашифрованному закрытому ключу, затем заданные пользователем параметры “args”; ей следует вывести в стандартный вывод парольную фразу, позволяющую расшифровать закрытый ключ. Для каждого нового зашифрованного закрытого ключа, загружаемого при инициализации, HAProxy сначала пробует расшифровать его всеми другими уже известными парольными фразами и снова вызывает команду получения парольной фразы, только если ни одна из них не подошла.

ssl-propquery <query>

ssl-propquery <query>

Этот параметр доступен только при сборке с поддержкой OpenSSL версии не ниже 3.0. Он позволяет задать строку свойств по умолчанию, используемую при получении алгоритмов у провайдеров. Работает так же, как параметр openssl propquery, и использует тот же синтаксис (описан в https://www.openssl.org/docs/man3.0/man7/property.html ). Например, если загружены два провайдера, foo и default, запрос propquery “?provider=foo” позволяет по умолчанию выбирать реализации алгоритмов из провайдера foo и обращаться к реализации провайдера default, если нужная реализация не найдена.

ssl-provider <name>

ssl-provider <name>

Этот параметр доступен только при сборке с поддержкой OpenSSL версии не ниже 3.0. Он позволяет загрузить провайдер во время инициализации. При успешной загрузке HAProxy может использовать любые возможности, предоставляемые этим провайдером. В конфигурационном файле можно задать несколько параметров ‘ssl-provider’. Провайдеры загружаются в порядке их появления.

Обратите внимание: явная загрузка провайдера не позволяет OpenSSL автоматически загрузить провайдер ‘default’. OpenSSL также позволяет задать провайдеры, которые следует загрузить, непосредственно в своём конфигурационном файле (например, openssl.cnf), поэтому для их загрузки необязательно использовать параметр ‘ssl-provider’. Команда CLI “show ssl providers” позволяет показать все успешно загруженные провайдеры.

Путь поиска провайдеров OpenSSL по умолчанию можно найти в выводе команды “openssl version -a”. Если провайдер находится в другом каталоге, можно задать переменную окружения OPENSSL_MODULES, указав в ней каталог с провайдером.

См. также “ssl-propquery” и “ssl-provider-path”.

ssl-provider-path <path>

ssl-provider-path <path>

Этот параметр доступен только при сборке с поддержкой OpenSSL версии не ниже 3.0. Он позволяет задать путь, по которому OpenSSL ищет провайдеры. Работает так же, как переменная окружения OPENSSL_MODULES. Используется для всех последующих параметров ‘ssl-provider’ до задания нового ‘ssl-provider-path’. См. также “ssl-provider”.

ssl-load-extra-del-ext

ssl-load-extra-del-ext

Этот параметр позволяет настроить способ поиска дополнительных файлов SSL в HAProxy. По умолчанию HAProxy добавляет новое расширение к имени файла (например, для “foobar.crt” загружает “foobar.crt.key”). При включённом параметре HAProxy удаляет расширение перед добавлением нового (например, для “foobar.crt” загружает “foobar.key”).

Для работы этого параметра файл crt должен иметь расширение “.crt”.

Этот параметр несовместим с расширениями пакетов сертификатов (.ecdsa, .rsa. .dsa) и не пытается удалять их.

По умолчанию этот параметр отключён. См. также “ssl-load-extra-files”.

ssl-load-extra-files <none|all|bundle|sctl|ocsp|issuer|key>*

ssl-load-extra-files <none|all|bundle|sctl|ocsp|issuer|key>*

Этот параметр изменяет способ поиска файлов, не указанных явно, при загрузке сертификатов SSL в HAProxy. Он применяется к сертификатам строк “bind” и “server”, однако некоторые дополнительные файлы не влияют на работу сертификатов строк “server”.

По умолчанию HAProxy автоматически находит множество файлов, не указанных в конфигурации. Для сокращения времени запуска это поведение можно отключить.

“none”: загружать только файлы, указанные в конфигурации. Не пытаться загружать пакет сертификатов, если файл отсутствует. При загрузке каталога не пытаться объединять сертификаты с одинаковым базовым именем в пакет.

“all”: поведение по умолчанию; пытаться загрузить всё: пакеты сертификатов, sctl, ocsp, issuer, key.

“bundle”: если файл, указанный в конфигурации, отсутствует, HAProxy пытается загрузить пакет сертификатов. Пакеты сертификатов поддерживаются только на стороне фронтенда и не работают для сертификатов бэкенда.

Начиная с HAProxy 2.3 пакеты больше не загружаются в одно хранилище сертификатов OpenSSL: каждый сертификат загружается в отдельное хранилище, что эквивалентно объявлению нескольких “crt”. Для этого требуется OpenSSL 1.1.1. Следовательно, пакеты теперь используются только для обратной совместимости и больше не обязательны для гибридной конфигурации bind с RSA/ECC.

Чтобы объединить эти файлы PEM в пакет сертификатов, распознаваемый HAProxy, их нужно назвать следующим образом: все файлы PEM в пакете должны иметь одинаковое базовое имя и суффикс, обозначающий тип ключа. Сейчас поддерживаются три суффикса: rsa, dsa и ecdsa. Например, если у www.example.com есть два файла PEM, RSA и ECDSA, они должны называться “example.pem.rsa” и “example.pem.ecdsa”. Первая часть имени файла произвольна; имеет значение только суффикс. Для загрузки этого пакета в HAProxy следует указать только базовое имя:

Пример: bind :8443 ssl crt example.pem

Обратите внимание: суффикс не передаётся HAProxy; это указывает HAProxy, что нужно искать пакет сертификатов.

HAProxy загружает все файлы PEM пакета так, будто каждый из них задан отдельно в нескольких “crt”.

Загрузка пакетов больше не влияет на загрузку каталога, поскольку файлы загружаются отдельно.

В CLI пакеты представлены отдельными файлами, и для применения изменений в них требуется расширение пакета.

При объединении нескольких сертификатов в пакет поддерживаются файлы OCSP (.ocsp), файлы издателя (.issuer), Certificate Transparency (.sctl) и закрытые ключи (.key).

“sctl”: пытаться загрузить “<basename>.sctl” для каждого ключевого слова crt. Если файл указан для сертификата бэкенда, он загружается, но не влияет на работу.

“ocsp”: пытаться загрузить “<basename>.ocsp” для каждого ключевого слова crt. Если файл указан для сертификата бэкенда, он загружается, но не влияет на работу.

“issuer”: пытаться загрузить “<basename>.issuer”, если издатель файла OCSP не указан в файле PEM. Если файл указан для сертификата бэкенда, он загружается, но не влияет на работу.

“key”: если закрытый ключ отсутствует в файле PEM, пытаться загрузить файл “<basename>.key”, содержащий закрытый ключ.

Поведение по умолчанию — “all”.

Пример:

ssl-load-extra-files bundle sctl
ssl-load-extra-files sctl ocsp issuer
ssl-load-extra-files none

См. также: “crt”, раздел 5.1 о параметрах bind и раздел 5.2 о параметрах server.

ssl-security-level <number>

ssl-security-level <number>

Эта директива позволяет выбрать уровень безопасности OpenSSL, описанный в https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_security_level.html . Уровень безопасности применяется ко всем контекстам SSL в HAProxy. Поддерживаются только значения от 0 до 5.

Значение по умолчанию зависит от версии OpenSSL, дистрибутива и способа сборки библиотеки.

Для этой директивы требуется OpenSSL версии не ниже 1.1.1.

ssl-server-verify [none|required]

ssl-server-verify [none|required]

Поведение проверки SSL по умолчанию на стороне серверов. Если задано ’none’, сертификаты серверов не проверяются. Значение по умолчанию — ‘required’, если оно не переопределено параметром командной строки ‘-dV’.

ssl-skip-self-issued-ca

ssl-skip-self-issued-ca

CA, выпустивший сертификат для самого себя, он же корневой CA x509, служит якорем для проверки цепочки: серверу нет смысла отправлять его, а у клиента он должен быть. Стандартная конфигурация не должна включать такой CA в файл PEM. Этот параметр позволяет оставить такой CA в файле PEM, не отправляя его клиенту. Это позволяет предоставить издателя для ocsp без файла ‘.issuer’ и использовать его совместно с ‘issuers-chain-path’. Это касается всех сертификатов без промежуточных сертификатов. Для BoringSSL параметр бесполезен: .issuer игнорируется, поскольку механизму ocsp он не нужен. Требуется OpenSSL версии не ниже 1.0.2.

stats calculate-max-counters [on|off]

stats calculate-max-counters [on|off]

Включает или отключает вычисление максимальных значений статистических счётчиков. Если они не нужны, их отключение может немного повысить производительность. По умолчанию — on.

stats maxconn <connections>

stats maxconn <connections>

По умолчанию сокет статистики ограничен 10 одновременными соединениями. Изменить это значение можно с помощью “stats maxconn”.

stats socket [<address:port>|<path>] [param*]

stats socket [<address:port>|<path>] [param*]

Привязывает сокет UNIX к <path> или адрес TCPv4/v6 к <address:port>. Соединения с этим сокетом позволяют получать различные статистические данные и даже выполнять некоторые команды для изменения параметров во время работы. Подробнее см. раздел 9.3 «Команды Unix-сокета» руководства по управлению.

Поддерживаются все параметры строк “bind”, например для ограничения доступа некоторым пользователям или ограничения их прав доступа. Подробнее см. раздел 5.1 .

stats timeout <timeout, in milliseconds>

stats timeout <timeout, in milliseconds>

Тайм-аут сокета статистики по умолчанию составляет 10 секунд. Изменить его можно с помощью “stats timeout”. Значение должно передаваться в миллисекундах либо с суффиксом единицы времени из набора { us, ms, s, m, h, d }.

stats-file <path>

stats-file <path>

Путь к созданному файлу stats-file haproxy. При запуске haproxy предварительно загружает значения из него во внутренние счётчики. Для создания такого файла stats-file используется команда CLI “dump stats-file”. Подробнее см. руководство по управлению.

stress-level <level>

stress-level <level>

Включает альтернативный код для стрессовой нагрузки на исполняемый файл haproxy. Уровень — целое число от 0 до 9. Значение по умолчанию 0 отключает любое выполнение стрессового кода. Уровни от 1 до 9 увеличивают стрессовую нагрузку на исполняемый файл haproxy. Обратите внимание: любое положительное значение может существенно снизить производительность. Поэтому этот режим никогда не следует включать, кроме как для отладки по запросу разработчика.

strict-limits

strict-limits

Вызывает отказ при запуске процесса в случае неудачного вызова setrlimit. HAProxy пытается установить наилучшие ограничения setrlimit согласно расчётам. Если это не удаётся, он выводит предупреждение. Этот параметр обеспечивает явный отказ HAProxy при невозможности установить эти ограничения. По умолчанию включён. Его всё равно можно принудительно отключить, добавив перед ним ключевое слово “no”.

thread-group <group> [<thread-range>...]

thread-group <group> [<thread-range>...]

Этот параметр доступен только при сборке с поддержкой потоков. Он перечисляет потоки, которые входят в группу потоков <group>. Нумерация потоков и групп начинается с 1. Диапазоны потоков задаются либо отдельными номерами, либо нижней и верхней границами, разделёнными дефисом ‘-’ (например, “1-16”). Нераспределённые потоки автоматически назначаются группам потоков, которые ещё не распределены; группы, заданные этой директивой, никогда не получают больше потоков, чем указано. Повторное определение одной и той же группы заменяет предыдущие определения новым. См. также “nbthread” и “thread-groups”.

thread-groups <number>

thread-groups <number>

Этот параметр доступен только при сборке с поддержкой потоков. Он разбивает потоки HAProxy на <number> независимых групп. В настоящее время значение по умолчанию — 1. Группы потоков позволяют уменьшить объём совместно используемых данных между потоками и тем самым снизить конкуренцию за ресурсы ценой некоторой дополнительной настройки. Это также единственный способ использовать больше 64 потоков, поскольку в каждой группе можно настроить до 64 потоков. Максимальное число групп задаётся при компиляции и по умолчанию равно 16. См. также “nbthread”.

thread-hard-limit <number>

thread-hard-limit <number>

Этот параметр задаёт предел числа потоков, определённого автоматически или заданного в конфигурации. Особенно полезен в ОС с автоматическим определением числа потоков, когда в универсальных переносимых конфигурациях требуется меньше потоков, чем CPU. Параметр “nbthread” задаёт число потоков, которое при превышении числа доступных CPU приводит к предупреждению и низкой производительности, тогда как thread-hard-limit лишь ограничивает максимальное значение и автоматически не допускает превышения этого числа потоков, но не увеличивает меньшие значения. Если “nbthread” принудительно задан выше этого предела, приоритет имеет thread-hard-limit, а предупреждение позволяет исправить ошибку конфигурации. По умолчанию ограничения нет. См. также “nbthread”.

uid <number>

uid <number>

Изменяет идентификатор пользователя процесса на <number>. Рекомендуется выделить этот идентификатор пользователя для HAProxy или небольшой группы сходных демонов. Для возможности перехода к другому пользователю HAProxy должен быть запущен с правами суперпользователя. См. также “gid” и “user”.

ulimit-n <number>

ulimit-n <number>

Задаёт максимальное число файловых дескрипторов на процесс равным <number>. По умолчанию оно вычисляется автоматически, поэтому использовать этот параметр не рекомендуется. Если нужно лишь ограничить число файловых дескрипторов, лучше использовать “fd-hard-limit”.

Обратите внимание: динамические серверы не учитываются в этом автоматическом расчёте ресурсов. Если их много, может потребоваться задать значение вручную.

См. также: fd-hard-limit, maxconn

unix-bind [ prefix <prefix> ] [ mode <mode> ] [ user <user> ] [ uid <uid> ] [ group <group> ] [ gid <gid> ]

Задаёт общие параметры слушающих сокетов UNIX, объявленных в директивах “bind”. Это в основном упрощает объявление таких сокетов UNIX и снижает риск ошибок, поскольку эти параметры обычно необходимы, но зависят от процесса. Параметр <prefix> позволяет принудительно сделать все пути сокетов относительными к этому каталогу. Это может понадобиться для доступа к chroot другого компонента. Обратите внимание: эти пути разрешаются до перехода самого HAProxy в chroot, поэтому они абсолютные. Параметры <mode>, <user>, <uid>, <group> и <gid> имеют тот же смысл, что и одноимённые параметры директивы “bind”. Если заданы оба варианта, приоритет имеет директива “bind”, то есть параметры “unix-bind” можно считать значениями по умолчанию для всего процесса.

unsetenv [<name> ...]

unsetenv [<name> ...]

Удаляет переменные окружения, указанные в аргументах. Это может быть полезно для сокрытия конфиденциальной информации, иногда наследуемой из окружения пользователя во время некоторых операций. Несуществующие переменные молча игнорируются, поэтому после операции гарантированно не остаётся ни одной из указанных переменных. Изменения вступают в силу немедленно: следующая строка конфигурационного файла уже не видит эти переменные. См. также “setenv”, “presetenv” и “resetenv”.

user <user name>

user <user name>

Аналогично “uid”, но используется UID пользователя с именем <user name> из /etc/passwd. См. также “uid” и “group”.

node <name>

node <name>

Как и в именах DNS, разрешены только буквы, цифры, дефис и подчёркивание.

Эта директива полезна в конфигурациях HA, где два или более процесса или сервера используют один IP-адрес. Разные значения node-name на всех узлах позволяют сразу определить, какой сервер обрабатывает трафик.

wurfl-cache-size <size>

wurfl-cache-size <size>

Задаёт размер кэша агентов пользователя WURFL. Для ускорения поиска уже обработанные агенты пользователя хранятся в кэше LRU:

  • “0” : кэш не используется.
  • <size> : размер кэша lru в элементах.

Обратите внимание: этот параметр доступен только при сборке HAProxy с USE_WURFL=1.

wurfl-data-file <file path>

wurfl-data-file <file path>

Путь к файлу данных WURFL для служб распознавания устройств. HAProxy следует иметь доступ к этому файлу с соответствующими правами.

Обратите внимание: этот параметр доступен только при сборке HAProxy с USE_WURFL=1.

wurfl-information-list [<capability>]*

wurfl-information-list [<capability>]*

Разделённый пробелами список характеристик WURFL, виртуальных характеристик и имён свойств, которые предполагается использовать в добавляемых заголовках. Полный список имён характеристик и виртуальных характеристик доступен на сайте Scientiamobile:

https://www.scientiamobile.com/wurflCapability

Допустимые свойства WURFL:

  • wurfl_id: содержит идентификатор распознанного устройства.

  • wurfl_root_id: содержит корневой идентификатор распознанного устройства.

  • wurfl_isdevroot: указывает, является ли распознанное устройство корневым. Возможные значения — “TRUE” и “FALSE”.

  • wurfl_useragent: исходный агент пользователя, переданный в этом веб-запросе.

  • wurfl_api_version: содержит строку с текущей используемой версией API Libwurfl.

  • wurfl_info: строка с информацией о разобранном файле wurfl.xml и его полном пути.

  • wurfl_last_load_time: содержит временную метку UNIX последней успешной загрузки WURFL.

  • wurfl_normalized_useragent: нормализованный агент пользователя.

Обратите внимание: этот параметр доступен только при сборке HAProxy с USE_WURFL=1.

wurfl-information-list-separator <char>

wurfl-information-list-separator <char>

Символ для разделения значений в заголовке ответа с результатами WURFL. Если не задан, по умолчанию используется запятая (’,’).

Обратите внимание: этот параметр доступен только при сборке HAProxy с USE_WURFL=1.

wurfl-patch-file [<file path>]

wurfl-patch-file [<file path>]

Список путей к файлам исправлений WURFL. Обратите внимание: исправления загружаются при запуске, то есть до перехода в chroot.

Обратите внимание: этот параметр доступен только при сборке HAProxy с USE_WURFL=1.

3.2. Настройка производительности

busy-polling

busy-polling

В некоторых ситуациях, особенно при работе с малой задержкой на процессорах с переменной частотой или внутри виртуальных машин, всякий раз, когда процесс ожидает ввода-вывода через механизм опроса, процессор засыпает либо надолго передаётся другой VM, что вызывает чрезмерно высокие задержки. Этот параметр решает проблему, предотвращая засыпание процессора за счёт постоянного использования нулевого тайм-аута в механизмах опроса. Это значительно сокращает задержку (наблюдалось снижение на 30–100 микросекунд), но создаёт риск перегрева процессора. Параметр можно использовать и с потоками; тогда неверно привязанные потоки могут сильно конкурировать, ухудшая производительность и повышая значения полей CPU stolen в выводе “show info”, которые указывают на неправильно настроенные потоки. При использовании этого параметра важно не запускать процесс на том же процессоре, где обрабатываются сетевые прерывания. Также лучше не использовать его для нескольких потоков CPU, разделяющих одно ядро. По умолчанию параметр отключён. Если он включён, его всё равно можно принудительно отключить, добавив перед ним ключевое слово “no”. Механизмы опроса “select” и “poll” игнорируют этот параметр.

При бесшовной перезагрузке этот параметр автоматически отключается в старых процессах; это позволяет избежать чрезмерной конкуренции за CPU, когда несколько процессов некоторое время продолжают работать, ожидая завершения текущих соединений.

max-spread-checks <delay in milliseconds>

max-spread-checks <delay in milliseconds>

По умолчанию HAProxy пытается распределить начало проверок работоспособности в пределах наименьшего интервала проверок среди всех серверов группы. Это позволяет избежать чрезмерной нагрузки на службы, работающие на одном сервере. Но при больших интервалах проверок (10 секунд или больше) последние серверы группы начинают проверяться с задержкой, что может стать проблемой. Этот параметр задаёт верхнюю границу задержки между первой и последней проверкой, даже если интервалы проверок серверов больше. Однако если серверы используют меньшие интервалы, они соблюдаются.

maxcompcpuusage <number>

maxcompcpuusage <number>

Задаёт максимальное использование CPU, при достижении которого HAProxy прекращает сжатие новых запросов или снижает уровень сжатия текущих запросов. Работает как ‘maxcomprate’, но измеряет использование CPU вместо пропускной способности входящих данных. Значение выражается в процентах CPU, используемого HAProxy. Значение 100 отключает ограничение. Значение по умолчанию — 100. Меньшее значение не позволяет сжатию замедлять весь процесс и создавать высокие задержки.

maxcomprate <number>

maxcomprate <number>

Задаёт максимальную скорость входящих данных для сжатия на процесс равной <number> килобайт в секунду. Если максимум достигнут, уровень сжатия каждого потока снижается во время его обработки. Если максимум достигнут в начале потока, этот поток совсем не сжимается. Если максимум не достигнут, уровень сжатия повышается вплоть до tune.comp.maxlevel. Нулевое значение означает отсутствие ограничения; это значение по умолчанию.

maxconn <number>

maxconn <number>

Задаёт максимальное число одновременных соединений на процесс равным <number>. Эквивалентно аргументу командной строки “-n”. Значение, переданное аргументом “-n”, имеет приоритет над maxconn в секции global. Процесс HAProxy также может быть собран с переменной времени компиляции SYSTEM_MAXCONN, которая тогда служит системным максимумом maxconn. Аргумент командной строки “-n” также позволяет во время работы обойти ограничение SYSTEM_MAXCONN, если оно задано. При достижении maxconn прокси прекращают принимать соединения. Мягкий предел файловых дескрипторов процесса (его можно узнать командой “ulimit -n”) автоматически подстраивается под заданный maxconn. См. также “ulimit-n”. Примечание: на некоторых платформах механизм опроса “select” не может надёжно использовать больше 1024 файловых дескрипторов. Если платформа поддерживает только select и при запуске сообщает “select FAILED”, нужно уменьшать maxconn, пока запуск не станет успешным (обычно до значения чуть ниже 500). Если maxconn не задан, он автоматически вычисляется по текущим ограничениям файловых дескрипторов, выводимым командой “ulimit -nH” (берётся максимум из жёсткого и мягкого значений). Затем автоматически выбранное значение может быть уменьшено параметром “fd-hard-limit” и ограничением памяти, если оно задано параметром командной строки “-m”. Автоматическое значение также зависит от размера буфера, памяти для сжатия, размера кэша SSL, использования SSL и соответствующего maxsslconn, который тоже может выбираться автоматически.

См. также: fd-hard-limit, ulimit-n

maxconnrate <number>

maxconnrate <number>

Задаёт максимальное число соединений в секунду на процесс равным <number>. При достижении предела прокси прекращают принимать соединения. Параметр позволяет ограничить общую производительность независимо от возможностей каждого фронтенда. Следует учитывать, что он пригоден только как мера защиты службы: при достижении предела ресурсы не обязательно распределяются между фронтендами справедливо, поэтому полезно также ограничить каждый фронтенд значением, близким к его ожидаемой доле. Кроме того, уменьшение tune.maxaccept может повысить справедливость распределения.

maxpipes <number>

maxpipes <number>

Задаёт максимальное число каналов на процесс равным <number>. Сейчас каналы используются только для tcp splicing средствами ядра. Поскольку канал содержит два файловых дескриптора, значение “ulimit-n” соответственно увеличивается. Значение по умолчанию — maxconn/4, чего, по-видимому, более чем достаточно для большинства случаев интенсивного использования. Код splice динамически выделяет и освобождает каналы и может вернуться к обычному копированию, поэтому слишком низкое значение может повлиять лишь на производительность.

maxsessrate <number>

maxsessrate <number>

Задаёт максимальное число сеансов в секунду на процесс равным <number>. При достижении предела прокси прекращают принимать соединения. Параметр позволяет ограничить общую производительность независимо от возможностей каждого фронтенда. Следует учитывать, что он пригоден только как мера защиты службы: при достижении предела ресурсы не обязательно распределяются между фронтендами справедливо, поэтому полезно также ограничить каждый фронтенд значением, близким к его ожидаемой доле. Кроме того, уменьшение tune.maxaccept может повысить справедливость распределения.

maxsslconn <number>

maxsslconn <number>

Задаёт максимальное число одновременных соединений SSL на процесс равным <number>. По умолчанию отдельного ограничения для SSL нет, то есть глобальное значение maxconn применяется ко всем соединениям. Этот предел не позволяет openssl использовать слишком много памяти и аварийно завершаться, когда malloc возвращает NULL (к сожалению, он не всегда надёжно проверяет такие ситуации). Обратите внимание: ограничение касается как входящих, так и исходящих соединений, поэтому одно соединение, которое расшифровывается, а затем шифруется, учитывается как 2 соединения SSL. Если значение не задано, но есть ограничение памяти, оно автоматически вычисляется по этому ограничению, maxconn, размеру буфера, памяти для сжатия, размеру кэша SSL и использованию SSL во фронтендах, бэкендах или с обеих сторон. Если при ограничении памяти не заданы ни maxconn, ни maxsslconn, HAProxy автоматически подбирает их так, чтобы 100% соединений могли безопасно использовать SSL, с учётом сторон, где он включён (фронтенд, бэкенд или обе).

maxsslrate <number>

maxsslrate <number>

Задаёт максимальное число сеансов SSL в секунду на процесс равным <number>. При достижении предела слушатели SSL прекращают принимать соединения. Параметр позволяет ограничить общее использование CPU для SSL независимо от возможностей каждого фронтенда. Следует учитывать, что он пригоден только как мера защиты службы: при достижении предела ресурсы не обязательно распределяются между фронтендами справедливо, поэтому полезно также ограничить каждый фронтенд значением, близким к его ожидаемой доле. Следует также учитывать, что сеансы учитываются до попадания в стек SSL, а не после, что защищает стек и от некорректных рукопожатий. Кроме того, уменьшение tune.maxaccept может повысить справедливость распределения.

maxzlibmem <number>

maxzlibmem <number>

Задаёт максимальный объём RAM в мегабайтах на процесс, доступный zlib. При достижении максимума последующие потоки не сжимаются, пока RAM недоступна. Значение 0 означает отсутствие ограничения. Значение по умолчанию — 0. В сокете UNIX значение доступно в байтах в выводе “show info” в строке “MaxZlibMemUsage”; используемая zlib память указана в “ZlibMemUsage” в байтах.

no-memory-trimming

no-memory-trimming

Отключает возврат памяти системе (“malloc_trim”) в некоторых ситуациях, когда предпринимаются попытки освободить много памяти: при её нехватке или при перезагрузке. Такой возврат заставляет системный распределитель памяти просмотреть все неиспользуемые области и освободить их. Обычно это полезно, поскольку новому процессу остаётся больше доступной памяти, а старый едва ли будет активно её использовать. Но в некоторых системах с десятками или сотнями тысяч одновременных соединений сильная фрагментация памяти может сделать освобождение чрезвычайно длительным. В это время трафик через процесс больше не проходит, новые соединения не принимаются, некоторые проверки работоспособности могут завершаться неудачей, а сторожевой таймер может сработать и завершить неотвечающий процесс, оставив огромный дамп памяти. Если это происходит, рекомендуется использовать этот параметр, чтобы отключить возврат памяти и прекратить попытки уступать её новому процессу. Обратите внимание: современные распределители памяти обычно не страдают от такой проблемы.

noepoll

noepoll

Отключает систему опроса событий “epoll” в Linux. Эквивалентно аргументу командной строки “-de”. Следующей системой опроса обычно становится “poll”. См. также “nopoll”.

noevports

noevports

Отключает систему опроса событий event ports в системах SunOS на основе Solaris 10 и новее. Эквивалентно аргументу командной строки “-dv”. Следующей системой опроса обычно становится “poll”. См. также “nopoll”.

nogetaddrinfo

nogetaddrinfo

Отключает getaddrinfo(3) для разрешения имён. Эквивалентно аргументу командной строки “-dG”. Используется устаревшая функция gethostbyname(3).

nokqueue

nokqueue

Отключает систему опроса событий “kqueue” в BSD. Эквивалентно аргументу командной строки “-dk”. Следующей системой опроса обычно становится “poll”. См. также “nopoll”.

noktls

noktls

Отключает ktls. Эквивалентно аргументу командной строки “-dT”.

nopoll

nopoll

Отключает систему опроса событий “poll”. Эквивалентно аргументу командной строки “-dp”. Следующей системой опроса становится “select”. Отключать “poll” никогда не должно требоваться, поскольку он доступен на всех платформах, поддерживаемых HAProxy. См. также “nokqueue”, “noepoll” и “noevports”.

noreuseport

noreuseport

Отключает SO_REUSEPORT; см. socket(7). Эквивалентно аргументу командной строки “-dR”.

nosplice

nosplice

Отключает tcp splicing средствами ядра между сокетами в Linux. Эквивалентно аргументу командной строки “-dS”. После этого данные копируются обычными, более переносимыми вызовами recv/send. tcp splicing средствами ядра доступен лишь в некоторых самых новых вариантах ядра 2.6. Большинство версий от 2.6.25 до 2.6.28 содержат ошибки и пересылают повреждённые данные, поэтому их нельзя использовать. Этот параметр упрощает глобальное отключение splicing при сомнениях. См. также “option splice-auto”, “option splice-request” и “option splice-response”.

profiling.memory { on | off }

profiling.memory { on | off }

Включает (‘on’) или отключает (‘off’) профилирование памяти по функциям. Оно собирает статистику вызовов malloc/calloc/realloc/free во всём процессе, включая библиотеки; она доступна в CLI по команде “show profiling”. В основном это предназначено для случаев необычного использования памяти, которое нельзя объяснить пулами и для которого нужны дополнительные сведения. Потеря производительности обычно составляет около 1%, возможно немного больше на машинах с большим числом потоков, поэтому механизм обычно подходит для использования в рабочей среде. Того же результата можно добиться во время работы командой CLI “set profiling memory”; см. руководство по управлению.

profiling.tasks { auto | on | off | lock | no-lock | memory | no-memory }*

profiling.tasks { auto | on | off | lock | no-lock | memory | no-memory }*

Включает (‘on’) или отключает (‘off’) профилирование CPU по задачам. При значении ‘auto’ профилирование автоматически включается для потока, когда его средняя задержка достигает 1000 микросекунд или больше, согласно полю активности “avg_loop_us”, и автоматически отключается, когда задержка становится ниже 990 микросекунд. Это значение усредняется по последним 1024 циклам, поэтому меняется медленно и существенно сглаживает короткие всплески. Профилирование может также время от времени самопроизвольно включаться в перегруженных системах, контейнерах или виртуальных машинах либо при использовании системой подкачки, чего на балансировщике нагрузки категорически нельзя допускать.

При включённом профилировании задач HAProxy может также собирать время, которое каждая задача проводит с удерживаемой блокировкой или в ожидании блокировки, а также время ожидания успешного выделения памяти при промахе кэша пула. Иногда это помогает понять причины задержек. Для этого можно дополнительно передать ключевые слова “lock” (включить сбор времени блокировок), “no-lock” (отключить его), “memory” (включить сбор времени выделения памяти) или “no-memory” (отключить его). По умолчанию сбор этих данных не включён, поскольку на сильно нагруженных системах он может заметно влиять на использование CPU (3-10%). Обратите внимание: накладные расходы возникают только при фактически работающем профилировании, поэтому в режиме “auto” они появляются только тогда, когда HAProxy решает включить его.

Профилирование CPU по задачам удобно для определения, на что расходуется время и как одни запросы влияют на другие. Его включение обычно влияет на общую производительность менее чем на 1%, поэтому рекомендуется оставить значение по умолчанию ‘auto’, чтобы оно работало только при обнаружении проблемы. Для этой возможности нужна система с поддержкой системного вызова clock_gettime(2) с идентификаторами часов CLOCK_MONOTONIC и CLOCK_THREAD_CPUTIME_ID; в противном случае указанное время будет нулевым. Параметр можно изменить во время работы командой “set profiling” в CLI.

spread-checks <0..50, in percent>

spread-checks <0..50, in percent>

Иногда желательно не отправлять агентские проверки и проверки работоспособности серверам через строго одинаковые интервалы, например когда много логических серверов находятся на одном физическом сервере. Этот параметр позволяет добавить случайное отклонение интервала проверок в пределах от 0 до +/- 50%. Значения от 2 до 5, по-видимому, дают хорошие результаты. Значение по умолчанию остаётся 0.

ssl-engine <name> [algo <comma-separated list of algorithms>]

ssl-engine <name> [algo <comma-separated list of algorithms>]

Задаёт механизм OpenSSL равным <name>. Список допустимых значений <name> можно получить командой “openssl engine”. Директиву можно использовать несколько раз, что включит несколько криптографических механизмов. Указание неподдерживаемого механизма не позволит HAProxy запуститься. Обратите внимание: многие механизмы дают более низкую производительность HTTPS, чем чисто программная реализация на современных процессорах. Необязательная команда “algo” задаёт алгоритмы по умолчанию, предоставляемые ENGINE, с помощью функции OPENSSL ENGINE_set_default_string(). Значение “ALL” использует механизм для всех криптографических операций. Если список algo не задан, используется “ALL”. Можно задать разделённый запятыми список алгоритмов, в том числе RSA, DSA, DH, EC, RAND, CIPHERS, DIGESTS, PKEY, PKEY_CRYPTO, PKEY_ASN1. Этот же формат используется в конфигурационном файле openssl: https://www.openssl.org/docs/man1.0.2/apps/config.html

В HAProxy версии 2.6 поддержка криптографических механизмов отключена в сборке по умолчанию. Этот параметр доступен только при сборке HAProxy с соответствующей поддержкой. Если требуется ssl-engine, HAProxy можно пересобрать с флагом USE_ENGINE=1.

ssl-mode-async

ssl-mode-async

Добавляет режим SSL_MODE_ASYNC в контекст SSL. Это включает асинхронные операции ввода-вывода TLS при использовании механизмов SSL с поддержкой асинхронной работы. Текущая реализация поддерживает не более 32 механизмов. API ASYNC в OpenSSL не поддерживает перемещение буферов чтения/записи и несовместим с управлением буферами HAProxy. Поэтому асинхронный режим отключён для операций чтения/записи: он включён только во время начального рукопожатия и повторного согласования.

tune.applet.zero-copy-forwarding { on | off }

tune.applet.zero-copy-forwarding { on | off }

Включает (‘on’) или отключает (‘off’) пересылку данных без копирования для апплетов. По умолчанию включена.

См. также: tune.disable-zero-copy-forwarding.

tune.buffers.limit <number>

tune.buffers.limit <number>

Задаёт жёсткий предел числа буферов, которые можно выделить на процесс. Значение по умолчанию — ноль, то есть без ограничения. Предел автоматически корректируется с учётом буферов, зарезервированных для аварийных ситуаций, поэтому пользователю не нужны сложные расчёты. Явное задание этого значения особенно полезно для ограничения памяти процесса с сохранением нормального поведения. При достижении предела задача, запрашивающая буфер, ожидает освобождения другого буфера. Обычно ожидание очень короткое и незаметное, если ограничения остаются разумными. Однако некоторые исторические ограничения ослабляли этот механизм от версии к версии. Известно, что в определённых ситуациях длительной нехватки некоторые задачи могут зависать до истечения тайм-аута, поэтому безопаснее не использовать этот параметр без строгой необходимости.

tune.buffers.reserve <number>

tune.buffers.reserve <number>

Задаёт число буферов на поток, которые предварительно выделяются и резервируются исключительно для условий нехватки памяти, приводящих к неудачному выделению памяти. Минимальное значение — 0, значение по умолчанию — 4. Изменять его нет причин, если только один из основных разработчиков не рекомендует это по совершенно конкретной причине.

tune.bufsize <size>

tune.bufsize <size>

Задаёт размер буфера в байтах. Меньшие значения позволяют большему числу потоков одновременно работать при том же объёме RAM, а большие — работать приложениям с очень большими cookie. Значение по умолчанию — 16384, его можно изменить при сборке. Настоятельно рекомендуется оставить значение по умолчанию: слишком малые значения нарушают работу некоторых служб, например статистики, а значения выше значения по умолчанию увеличивают потребление памяти и могут привести к её исчерпанию в системе. Как минимум глобальный параметр maxconn следует уменьшить во столько раз, во сколько увеличен этот размер. Кроме того, при использовании HTTP/2 значение обязательно должно быть не меньше 16384. Оно также должно быть меньше 256 MB (268435456 байт). Если блок заголовков запроса HTTP больше (tune.bufsize - tune.maxrewrite), HAProxy возвращает ошибку HTTP 400 (Bad Request). Аналогично, если блок заголовков ответа HTTP больше этого размера, HAProxy возвращает HTTP 502 (Bad Gateway). Обратите внимание: заданное этим параметром значение автоматически округляется вверх до ближайшего числа, кратного 8 на 32-битных машинах или 16 на 64-битных. См. также: tune.bufsize.large, tune.bufsize.small.

tune.bufsize.large <size>

tune.bufsize.large <size>

Задаёт размер больших буферов в байтах. По умолчанию поддержка больших буферов отключена; её нужно явно включить, задав это значение.

Эти буферы предназначены для отдельных ситуаций, когда нужно буферизовать больше данных, не меняя размер обычных буферов. Большие буферы не используются неявно. См. также: tune.bufsize.

Обратите внимание: при настройке больших буферов во время запуска для каждого потока выделяются три специальных больших буфера для внутреннего использования.

tune.bufsize.small <size>

tune.bufsize.small <size>

Задаёт размер малых буферов в байтах. Значение по умолчанию — 1024.

Эти буферы предназначены для отдельных ситуаций, когда потребление памяти ограничено, а выделение полного буфера кажется ненужным. Если малого буфера всё же недостаточно, автоматически выполняется повторное выделение памяти для перехода к буферу стандартного размера.

Сейчас малые буферы автоматически используются только протоколом HTTP/3 для отправки заголовков ответа. В остальных случаях их поддержку можно включить для отдельных прокси параметром “use-small-buffers”. См. также: tune.bufsize.

См. также: option use-small-buffers

tune.cli.max-payload-size <size>

tune.cli.max-payload-size <size>

Задаёт максимально допустимый размер полезной нагрузки, передаваемой команде в CLI.

В CLI длина командной строки ограничена размером буфера. Поэтому все команды и их аргументы должны помещаться в буфер для обработки, кроме полезной нагрузки, которую можно передать последней команде строки. При необходимости эта нагрузка может размещаться в отдельной области памяти. Её размер ограничивается этим параметром. Значение по умолчанию — 128KB.

Хотя этого значения должно хватать для большинства случаев, при изменении его нужно выбирать осторожно. Слишком большое значение может повлиять на производительность HAProxy. В зависимости от команды обработка огромной полезной нагрузки может занять достаточно много времени и привести к срабатыванию сторожевого таймера.

Подробности о CLI см. в руководстве по управлению.

tune.comp.maxlevel <number>

tune.comp.maxlevel <number>

Задаёт максимальный уровень сжатия. Уровень сжатия влияет на использование CPU при сжатии. Это значение влияет на использование CPU при сжатии. Каждый поток со сжатием инициализирует алгоритм сжатия этим значением. Значение по умолчанию — 1.

tune.defaults.purge

tune.defaults.purge

Для поддержки динамических бэкендов все именованные секции defaults теперь сохраняются в памяти после разбора. Это необходимо, поскольку конфигурация бэкенда, добавленного во время работы, должна основываться на именованной секции defaults.

Это может потреблять много памяти при большом числе экземпляров defaults. В таком случае, если динамические бэкенды не нужны, этим параметром можно принудительно удалять секции defaults после разбора. Однако секции defaults, на которые есть ссылки и которые содержат параметры, не копируемые ссылающимися на них прокси, по-прежнему обязательно сохранять. Например, это касается секций defaults, определяющих правила TCP/HTTP или набор правил tcpcheck.

tune.disable-fast-forward

tune.disable-fast-forward

Отключает ускоренную пересылку данных. Этот механизм оптимизирует пересылку, передавая данные напрямую с одной стороны на другую без пробуждения потока. Директива позволяет отключить эту оптимизацию. Обратите внимание: она также отключает любое tcp splicing средствами ядра и пересылку без копирования. Команда не предназначена для обычного использования; как правило, разработчики рекомендуют её лишь во время сложной отладки.

tune.disable-zero-copy-forwarding

tune.disable-zero-copy-forwarding

Глобально отключает пересылку данных без копирования. Этот механизм оптимизирует ускоренную пересылку, обходясь без буфера канала. Директива позволяет отключить эту оптимизацию. Обратите внимание: она также отключает любое tcp splicing средствами ядра.

См. также: tune.pt.zero-copy-forwarding, tune.applet.zero-copy-forwarding, tune.h1.zero-copy-fwd-recv, tune.h1.zero-copy-fwd-send, tune.h2.zero-copy-fwd-send, tune.quic.zero-copy-fwd-send

tune.epoll.mask-events <event[,...]>

tune.epoll.mask-events <event[,...]>

За время существования HAProxy встречались некоторые сложные проблемы, вызванные ошибками механизма epoll в ядре Linux. Обычно они очень редки и невоспроизводимы вне среды автора сообщения; обойти их иногда можно только отключением epoll и переходом на poll, что не очень подходит для сред с высокой производительностью. Каждый раз проблемы затрагивают лишь совершенно определённые и редкие типы событий, а возможность их маскирования может стать более приемлемым обходным решением. Этот параметр предоставляет такую возможность: он позволяет молча игнорировать некоторые необычные события и заменять их входным событием, сообщающим о неопределённом входящем событии. В результате в некоторых местах не используются быстрые пути обработки ошибок, а применяются только обычные пути. Параметр никогда не следует использовать, если специалист не предложил это для диагностики или обхода ошибки ядра.

Параметр принимает один аргумент: разделённый запятыми список слов, каждое из которых обозначает маскируемое событие. Сейчас поддерживаются следующие события: - “err”: маскировать событие EPOLLERR - “hup”: маскировать события EPOLLHUP - “rdhup”: маскировать события EPOLLRDHUP

Пример:

# mask all non-traffic epoll events:
tune.epoll.mask-events err,hup,rdhup

tune.events.max-events-at-once <number>

tune.events.max-events-at-once <number>

Задаёт число событий, которые обработчик асинхронной задачи (из API event_hdl) может обработать за один раз. <number> следует выбирать в пределах от 1 до 10000. Большое число может вызвать конкуренцию между потоками, поскольку задача выполняет тяжёлую работу без прерываний; малое, напротив, может приводить к постоянному повторному планированию задачи, поскольку за один запуск она обрабатывает недостаточно событий и не успевает за их производителем. Значение по умолчанию можно задать при сборке; иначе оно равно 100.

tune.fail-alloc

tune.fail-alloc

При сборке с DEBUG_FAIL_ALLOC или запуске с “-dMfail” задаёт вероятность неудачи попытки выделения памяти в процентах. Она должна находиться в пределах от 0 (без неудач) до 100 (без успехов). Это полезно для отладки и проверки корректной обработки отказов выделения памяти. Если не задана, доля равна 0. Однако параметр командной строки “-dMfail” автоматически устанавливает частоту отказов 1%, поэтому для тестирования необязательно менять конфигурацию.

tune.fd.edge-triggered { on | off } [ EXPERIMENTAL ]

tune.fd.edge-triggered { on | off }  [ EXPERIMENTAL ]

Включает (‘on’) или отключает (‘off’) режим опроса по фронту события для поддерживающих его FD. Сейчас он поддерживается только с epoll. Он может заметно сократить число вызовов epoll_ctl() и немного повысить производительность в некоторых сценариях. Режим всё ещё экспериментальный: при наличии ошибок он может приводить к зависанию соединений и по умолчанию отключён.

tune.glitches.kill.cpu-usage <number>

tune.glitches.kill.cpu-usage <number>

Задаёт минимальное использование CPU от 0 до 100, при котором соединения со слишком большим числом нарушений будут принудительно закрываться. Это касается соединений, достигших предела glitches-threshold. В средах, где очень долгие соединения часто ведут себя некорректно, но не влияют на производительность, может быть желательно сохранять их, пока они не вредят, и начинать закрывать только при высокой загрузке CPU. Параметр задаёт, что соединение, достигшее порога нарушений, принудительно закрывается при использовании CPU на этом уровне или выше, но никогда не закрывается при меньшем уровне. Обратите внимание: использование CPU измеряется для каждого потока, поэтому может быть закрыто даже одно некорректно работающее соединение. Значение по умолчанию — ноль: соединение, достигшее glitches-threshold, автоматически закрывается. В качестве ориентира можно задать значение, равное удвоенному обычному использованию CPU либо обычному использованию CPU плюс половина незанятой доли (например, если CPU обычно достигает 60%, значение 80 может быть разумным). Параметр не действует без tune.h2.fe.glitches-threshold, tune.quic.fe.sec.glitches-threshold или tune.h1.fe.glitches-threshold. См. также глобальные параметры “tune.h2.fe.glitches-threshold”, “tune.h1.fe.glitches-threshold” и “tune.quic.fe.sec.glitches-threshold”.

tune.h1.be.glitches-threshold <number>

tune.h1.be.glitches-threshold <number>

Задаёт порог числа нарушений в соединении HTTP/1 с бэкендом, по достижении которого соединение автоматически принудительно закрывается. Это позволяет закрывать некорректно работающие соединения без явных правил. Значение по умолчанию — ноль: порог не задан, поэтому никакое событие не приводит к закрытию соединения. Типичные события — неверно оформленные заголовки, которые всё же были приняты благодаря “accept-unsafe-violations-in-http-response”. Ненулевое значение, вероятно, следует выбирать в сотнях или тысячах, чтобы механизм работал эффективно, не затрагивая серверы с небольшими отклонениями. С помощью “tune.glitches.kill.cpu-usage” можно также закрывать соединения только при достижении определённого уровня использования CPU. Обратите внимание: при 75% заданного порога предпринимается попытка плавного закрытия путём перехода в режим закрытия соединения и объявления “Connection: close”, когда это применимо. Это гарантирует, что соединение с небольшими ошибками через некоторое время перестанет использоваться без риска прервать текущую передачу данных.

См. также: tune.h1.fe.glitches-threshold, bc_glitches и tune.glitches.kill.cpu-usage

tune.h1.fe.glitches-threshold <number>

tune.h1.fe.glitches-threshold <number>

Задаёт порог числа нарушений в соединении HTTP/1 с фронтендом, по достижении которого соединение автоматически принудительно закрывается. Это позволяет закрывать некорректно работающие соединения без явных правил. Значение по умолчанию — ноль: порог не задан, поэтому никакое событие не приводит к закрытию соединения. Типичные события — неверно оформленные заголовки, которые всё же были приняты благодаря “accept-unsafe-violations-in-http-request”. Ненулевое значение, вероятно, следует выбирать в сотнях или тысячах, чтобы механизм работал эффективно, не затрагивая клиентов с небольшими отклонениями. С помощью “tune.glitches.kill.cpu-usage” можно также закрывать соединения только при достижении определённого уровня использования CPU. Обратите внимание: при 75% заданного порога предпринимается попытка плавного закрытия путём перехода в режим закрытия соединения и объявления “Connection: close”, когда это применимо. Это позволяет клиенту с небольшими отклонениями от протокола создать новое соединение и продолжить работу без помех, не вызывая принудительного закрытия с риском прерывания текущей передачи данных.

См. также: tune.h1.be.glitches-threshold, fc_glitches и tune.glitches.kill.cpu-usage

tune.h1.zero-copy-fwd-recv { on | off }

tune.h1.zero-copy-fwd-recv { on | off }

Включает (‘on’) или отключает (‘off’) приём данных без копирования для мультиплексора H1. По умолчанию включён.

См. также: tune.disable-zero-copy-forwarding, tune.h1.zero-copy-fwd-send

tune.h1.zero-copy-fwd-send { on | off }

tune.h1.zero-copy-fwd-send { on | off }

Включает (‘on’) или отключает (‘off’) отправку данных без копирования для мультиплексора H1. По умолчанию включена.

См. также: tune.disable-zero-copy-forwarding, tune.h1.zero-copy-fwd-recv

tune.h2.be.glitches-threshold <number>

tune.h2.be.glitches-threshold <number>

Задаёт порог числа нарушений в соединении с бэкендом, по достижении которого соединение автоматически принудительно закрывается. Это позволяет закрывать некорректно работающие соединения без явных правил. Значение по умолчанию — ноль: порог не задан, поэтому никакое событие не приводит к закрытию соединения. Следует учитывать, что некоторые серверы H2 иногда вызывают несколько нарушений за время долгого соединения, поэтому ненулевое значение, вероятно, следует выбирать в сотнях или тысячах, чтобы механизм работал эффективно, не затрагивая серверы с небольшими отклонениями. С помощью “tune.glitches.kill.cpu-usage” можно также закрывать соединения только при достижении определённого уровня использования CPU. Обратите внимание: при 75% заданного порога предпринимается попытка плавного закрытия путём объявления GOAWAY для будущего потока. Это гарантирует, что соединение с небольшими ошибками через некоторое время перестанет использоваться без риска прервать текущую передачу данных.

См. также: tune.h2.fe.glitches-threshold, bc_glitches и tune.glitches.kill.cpu-usage

tune.h2.be.initial-window-size <number>

tune.h2.be.initial-window-size <number>

Задаёт начальный размер окна HTTP/2 для исходящих соединений: число байт, которые сервер может отправить в ответ до ожидания подтверждения от HAProxy. Параметр влияет только на полезную нагрузку, а не на заголовки. Если не задан, применяется общее значение по умолчанию tune.h2.initial-window-size. Небольшое увеличение может ускорить загрузки или уменьшить использование CPU на серверах ценой несправедливого распределения ресурсов между клиентами. Вместо этого лучше использовать tune.h2.be.rxbuf, который не вызывает такого неравенства. На использование ресурсов параметр не влияет.

См. также: tune.h2.initial-window-size.

tune.h2.be.max-concurrent-streams <number>

tune.h2.be.max-concurrent-streams <number>

Задаёт максимальное число одновременных потоков HTTP/2 на исходящее соединение, то есть число незавершённых запросов в одном соединении с сервером. Если не задан, применяется значение по умолчанию tune.h2.max-concurrent-streams. Значение ниже значения по умолчанию 100 может улучшить отзывчивость сайта ценой большего числа установленных соединений с серверами. При значении “always” параметра “http-reuse” рекомендуется уменьшить это число, чтобы не смешивать слишком много разных клиентов в одном соединении: если один клиент медленнее других, механизм «блокировки начала очереди» может каскадно снижать скорость загрузки для всех клиентов, разделяющих соединение (в таком случае tune.h2.be.initial-window-size следует держать низким). Настоятельно рекомендуется не увеличивать это значение; в некоторых случаях оптимальны малые значения, обычно 1..5.

tune.h2.be.max-frames-at-once <number>

tune.h2.be.max-frames-at-once <number>

Задаёт максимальное число входящих кадров HTTP/2, обрабатываемых за один раз в соединении с бэкендом. При очень больших буферах полезно задать малое значение, от нескольких десятков до нескольких сотен, чтобы сохранить низкую задержку и более справедливое распределение ресурсов между соединениями. Значение по умолчанию — ноль, то есть ограничение не применяется.

tune.h2.be.rxbuf <size>

tune.h2.be.rxbuf <size>

Задаёт размер буфера приёма HTTP/2 для исходящих соединений в байтах. Размер округляется вверх до ближайшего числа, кратного tune.bufsize, и разделяется между всеми потоками, отправляющими данные (кадры HEADERS и DATA). В любом случае каждому потоку всегда предоставляется один буфер, а 7/8 неиспользуемых буферов разделяются между потоками, получающими полезную нагрузку. Это значительно повышает производительность отправки данных и устраняет блокировку начала очереди (HoL) в соединениях с бэкендом, разделяемых несколькими клиентами при значении “always” параметра http-reuse. Объявляемое окно каждого потока автоматически подстраивается под доступное пространство, поэтому на практике менять tune.h2.be.initial-window-size не должно требоваться. Если задан размер меньше необходимого для всех потоков, используется этот минимум. Значение по умолчанию — около 1600k (100 потоков с буферами по 16kB).

См. также: tune.h2.be.initial-window-size, tune.h2.fe.rxbuf, http-reuse.

tune.h2.fe.glitches-threshold <number>

tune.h2.fe.glitches-threshold <number>

Задаёт порог числа нарушений в соединении с фронтендом, по достижении которого соединение автоматически принудительно закрывается. Это позволяет закрывать некорректно работающие соединения без явных правил. Значение по умолчанию — ноль: порог не задан, поэтому никакое событие не приводит к закрытию соединения. Следует учитывать, что некоторые клиенты H2 иногда вызывают несколько нарушений за время долгого соединения, поэтому ненулевое значение, вероятно, следует выбирать в сотнях или тысячах, чтобы механизм работал эффективно, не затрагивая клиентов с небольшими отклонениями. С помощью “tune.glitches.kill.cpu-usage” можно также закрывать соединения только при достижении определённого уровня использования CPU. Обратите внимание: при 75% заданного порога предпринимается попытка плавного закрытия путём объявления GOAWAY для будущего потока. Это позволяет клиенту с небольшими отклонениями от протокола создать новое соединение и продолжить работу без помех, не вызывая принудительного закрытия с риском прерывания текущей передачи данных.

См. также: tune.h2.be.glitches-threshold, fc_glitches и tune.glitches.kill.cpu-usage

tune.h2.fe.initial-window-size <number>

tune.h2.fe.initial-window-size <number>

Задаёт начальный размер окна HTTP/2 для входящих соединений: число байт, которые клиент может отправить до ожидания подтверждения от HAProxy. Параметр влияет только на полезную нагрузку, то есть тело запросов POST, а не на заголовки. Если не задан, применяется общее значение по умолчанию tune.h2.initial-window-size. Увеличение может ускорить отправку данных. Значение по умолчанию равно tune.bufsize (16384) и обеспечивает пропускную способность не менее 1.25 Mbps на поток при времени ping 100 ms и 125 Mbps при времени ping 1 ms. На использование ресурсов оно не влияет. Слишком большие значения могут снижать отзывчивость для клиентов, которые обращаются к страницам одновременно с отправкой больших объёмов данных. Вместо этого лучше использовать tune.h2.fe.rxbuf, который не вызывает неравенства в распределении ресурсов.

См. также: tune.h2.initial-window-size.

tune.h2.fe.max-concurrent-streams <number> [args...]

tune.h2.fe.max-concurrent-streams <number> [args...]

Задаёт максимальное число одновременных потоков HTTP/2 на входящее соединение, то есть число незавершённых запросов в одном соединении от клиента. Если не задан, применяется значение по умолчанию tune.h2.max-concurrent-streams. Значение выше значения по умолчанию 100 иногда может немного ускорить загрузку страниц сложных сайтов с множеством небольших объектов в сетях с высокой задержкой, но также увеличивает использование памяти, позволяя клиенту выделять больше ресурсов одновременно. Значение по умолчанию 100 обычно подходит, и менять его не рекомендуется. Больший параллелизм также влияет на вычислительную нагрузку и задержки при большом числе соединений, каждое из которых использует много потоков, и может снижать порог для атак отказа в обслуживании. После числа команда поддерживает следующие необязательные аргументы:

  • rq-load { <number> | auto | ignore }:
Необязательный аргумент "rq-load" позволяет динамически изменять объявляемый
уровень параллелизма в зависимости от загрузки очереди выполнения текущего
потока: пока загрузка потока остаётся ниже указанного порога, объявляется
настроенный предел числа потоков HTTP. Когда загрузка потока выполнения
превышает настроенный предел, объявляемый предел числа потоков HTTP
уменьшается пропорционально квадрату коэффициента превышения. Целевые
уровни загрузки от 50 до 100 обычно обеспечивают очень хорошее ограничение
при высокой нагрузке. Вместо явного числа ключевое слово также принимает
"ignore" — значение по умолчанию, при котором загрузка очереди выполнения
потока не учитывается при ограничении объявляемого числа потоков HTTP, —
и "auto", которое устанавливает предел равным значению "tune.runqueue-depth".
Последнее обычно даёт хорошие результаты без дальнейшей подстройки
конфигурации.
  • min <number>:
Задаёт минимальный объявляемый уровень параллелизма при использовании rq-load,
даже если это приводит к более высокой загрузке, чем заданная целевая.
Это позволяет сохранить хорошую отзывчивость сайта при очень высокой
нагрузке. Минимальное значение и значение по умолчанию — 1, но значения
от 5 до 15 могут улучшить удобство работы пользователей.

Пример:

tune.h2.fe.max-concurrent-streams 100 rq-load auto min 15

tune.h2.fe.max-frames-at-once <number>

tune.h2.fe.max-frames-at-once <number>

Задаёт максимальное число входящих кадров HTTP/2, обрабатываемых за один раз в соединении с фронтендом. При очень больших буферах полезно задать малое значение, от нескольких десятков до нескольких сотен, чтобы сохранить низкую задержку и более справедливое распределение ресурсов между соединениями. Значение по умолчанию — ноль, то есть ограничение не применяется.

tune.h2.fe.max-rst-at-once <number>

tune.h2.fe.max-rst-at-once <number>

Задаёт максимальное число входящих RST_STREAM HTTP/2, обрабатываемых за один раз в соединении с фронтендом. После получения указанного числа кадров RST_STREAM обработчик соединения помещается в очередь с низким приоритетом и обрабатывается после всех остальных задач. Очень малое значение, 1 или несколько единиц, может значительно уменьшить последствия массовой отправки кадров RST_STREAM. Такие RST_STREAM возникают и при нажатии пользователем кнопки остановки в браузере, но дополнительные несколько миллисекунд из-за смены очереди обычно незаметны и при этом эффективно снижают нагрузку от такого наплыва кадров. Значение по умолчанию — ноль, то есть ограничение не применяется.

tune.h2.fe.max-total-streams <number>

tune.h2.fe.max-total-streams <number>

Задаёт максимальное общее число потоков HTTP/2, обрабатываемых на входящее соединение. При достижении предела HAProxy отправляет кадр GOAWAY для плавного закрытия, сообщая клиенту, что соединение будет закрыто после завершения всех ожидающих потоков. На практике клиенты обычно закрывают соединение как можно быстрее после получения кадра и устанавливают новое для следующих запросов. Иногда это полезно и желательно, если клиенты очень долго остаются подключёнными и вызывают неравномерное распределение нагрузки в группе серверов. Например, в некоторых очень динамичных средах новые балансировщики нагрузки создаются на лету при росте нагрузки, а после её снижения их следует останавливать, не разрывая установленные соединения. При задании предела соединения имеют ограниченный срок жизни и часто обновляются; некоторые новые соединения могут устанавливаться с другими узлами, поэтому существующие ресурсы быстро освобождаются.

Следует понимать, что этот предел неявно связан с указанным выше “tune.h2.fe.max-concurrent-streams”. HAProxy всегда принимает к обработке любые возможные ожидающие потоки, которые могут находиться в пути между клиентом и фронтендом, поэтому объявляемый предел всегда автоматически увеличивается на значение max-concurrent-streams. Полученное значение служит жёстким пределом: его превышение клиентом, не соблюдающим протокол, приводит к закрытию соединения. Поэтому при подсчёте запросов на соединение по журналам может наблюдаться любое число от max-total-streams до (max-total-streams + max-concurrent-streams) в зависимости от скорости создания потоков клиентом.

Значение по умолчанию — ноль: ограничений сверх установленных протоколом нет (2^30 ~= 1.07 миллиарда). Значения около 1000 уже могут вызывать частое обновление соединений без заметной задержки для большинства клиентов. Слишком малое значение может повысить использование CPU из-за частых повторных соединений TLS и увеличить время загрузки страниц. Обратите внимание: некоторые инструменты нагрузочного тестирования не поддерживают повторные соединения и могут сообщать об ошибках с этим параметром, поэтому при измерении производительности его может потребоваться отключить. См. также “tune.h2.fe.max-concurrent-streams”.

tune.h2.fe.rxbuf <size>

tune.h2.fe.rxbuf <size>

Задаёт размер буфера приёма HTTP/2 для входящих соединений в байтах. Размер округляется вверх до ближайшего числа, кратного tune.bufsize, и разделяется между всеми потоками, отправляющими данные (кадры HEADERS и DATA). В любом случае каждому потоку всегда предоставляется один буфер, а 7/8 неиспользуемых буферов разделяются между потоками, отправляющими полезную нагрузку, что значительно повышает производительность отправки данных. Объявляемое окно каждого потока автоматически подстраивается под доступное пространство, поэтому на практике менять tune.h2.fe.initial-window-size не должно требоваться. Если задан размер меньше необходимого для всех потоков, используется этот минимум. Значение по умолчанию 1600k (100 потоков с буферами по 16kB) обеспечивает клиенту скорость отправки примерно 130 Mbps при RTT 100ms.

См. также: tune.h2.fe.initial-window-size и tune.h2.be.rxbuf.

tune.h2.header-table-size <number>

tune.h2.header-table-size <number>

Задаёт размер динамической таблицы заголовков HTTP/2. По умолчанию — 4096 байт, максимум — 65536 байт. Большее значение может помочь некоторым клиентам отправлять более компактные запросы в зависимости от их возможностей. Этот объём памяти расходуется на каждое соединение HTTP/2. Менять значение не рекомендуется.

tune.h2.initial-window-size <number>

tune.h2.initial-window-size <number>

Задаёт значение начального размера окна HTTP/2 по умолчанию для входящих и исходящих соединений. Оно используется для входящих соединений, если не задан tune.h2.fe.initial-window-size, и для исходящих, если не задан tune.h2.be.initial-window-size. Параметр задаёт как начальное значение, так и минимум на поток. Значение по умолчанию — 16384 (tune.bufsize), что при отправке данных примерно обеспечивает пропускную способность не менее 1.25 Mbps на поток в сети со временем ping 100 ms либо 125 Mbps в локальной сети с задержкой в 1 миллисекунду. Когда буферов приёма используется меньше максимума, в пределах tune.h2.be.rxbuf и tune.h2.fe.rxbuf, неиспользуемые буферы разделяются между принимающими потоками. Поэтому менять это значение по умолчанию обычно нет смысла. Поскольку его изменение одновременно повышает скорость отправки и усиливает неравенство между клиентами при получении данных, рекомендуется вместо него использовать отдельные параметры сторон: tune.h2.fe.initial-window-size и tune.h2.be.initial-window-size.

tune.h2.log-errors { none | connection | stream }

tune.h2.log-errors { none | connection | stream }

Задаёт уровень ошибок демультиплексора H2, при котором создаётся запись журнала. По умолчанию — “stream”: любая ошибка декодирования в демультиплексоре вызывает запись журнала. Значение “connection” означает, что журналируется только то, что делает соединение недействительным. Наконец, “none” означает, что ни одна ошибка декодирования не вызывает записи журнала. Для обнаружения аномалий протокола рекомендуется задать как минимум “connection”, даже если в трудные периоды приходится временно переключаться на “none”.

tune.h2.max-concurrent-streams <number>

tune.h2.max-concurrent-streams <number>

Задаёт максимальное число одновременных потоков HTTP/2 на соединение по умолчанию, то есть число незавершённых запросов в одном соединении. Используется для входящих соединений, если не задан tune.h2.fe.max-concurrent-streams, и для исходящих, если не задан tune.h2.be.max-concurrent-streams. Значение по умолчанию — 100. Влияние зависит от стороны; подробнее см. два параметра выше. Рекомендуется отказаться от этого параметра в пользу отдельных параметров сторон. Нулевое значение отключает ограничение, и один клиент может создать столько потоков, сколько HAProxy способен выделить. Настоятельно рекомендуется не менять это значение.

tune.h2.max-frame-size <number>

tune.h2.max-frame-size <number>

Задаёт максимальный размер кадра HTTP/2, который HAProxy сообщает одноранговым узлам как допустимый для приёма. По умолчанию используется большее из 16384 и размера буфера (tune.bufsize). В любом случае HAProxy не объявляет поддержку кадров больше буферов. Основная цель параметра — ограничить максимальный размер кадра при больших буферах. Слишком большие кадры могут повлиять на производительность или вызвать некорректное поведение некоторых одноранговых узлов. Настоятельно рекомендуется не менять значение.

tune.h2.zero-copy-fwd-send { on | off }

tune.h2.zero-copy-fwd-send { on | off }

Включает (‘on’) или отключает (‘off’) отправку данных без копирования для мультиплексора H2. По умолчанию включена.

См. также: tune.disable-zero-copy-forwarding

tune.http.cookielen <number>

tune.http.cookielen <number>

Задаёт максимальную длину захватываемых cookie. Это максимальное значение, разрешённое для “capture cookie xxx len yyy”; любое большее значение автоматически усекается до него. Важно не задавать слишком большое значение, поскольку каждый захват cookie всё равно выделяет такой объём независимо от своей настройки: все захваты используют один пул. Этот объём выделяется отдельно на запрос и на ответ, поэтому на соединение расходуется вдвое больше памяти. Если не задано, ограничение составляет 63 символа. Менять значение не рекомендуется.

tune.http.logurilen <number>

tune.http.logurilen <number>

Задаёт максимальную длину URI запроса в журналах. Это предотвращает усечение длинных URI запросов с полезными строками параметров в записях журнала. Параметр не связан с ограничениями syslog. При увеличении предела можно также увеличить параметр ’log … len yyy’. Демону syslog тоже могут потребоваться специальные директивы конфигурации. Значение по умолчанию — 1024.

tune.http.maxhdr <number>

tune.http.maxhdr <number>

Задаёт максимальное число заголовков в получаемых сообщениях HTTP. Если число заголовков сообщения, включая первую строку, превышает это значение, запрос отклоняется с кодом состояния “400 Bad Request”, а ответ — с “502 Bad Gateway”. Значение по умолчанию — 101; его достаточно для всех случаев, поскольку широко распространённый сервер Apache использует тот же предел. Увеличение может временно позволить работать приложению с ошибками до его исправления. Допустимый диапазон — 1..32767. Следует учитывать, что каждый новый заголовок расходует 32bits памяти на каждый поток, поэтому не следует повышать предел слишком сильно.

Обратите внимание: HTTP/1.1 — текстовый протокол, поэтому при отправке сообщения отдельного ограничения нет. Ограничения при разборе достаточно. HTTP/2 и HTTP/3 — двоичные протоколы, требующие этапа кодирования. При кодировании заголовков также устанавливается предел для соблюдения ограничений протоколов. Он достаточно велик, но намеренно не документирован. По той же причине этот предел применяется и на первых этапах декодирования.

tune.idle-pool.shared { full | on | off }

tune.idle-pool.shared { full | on | off }

Управляет совместным использованием пулов простаивающих соединений потоками для одного сервера. Его можно включить для всех потоков одной группы (‘on’), для всех потоков (‘full’) или отключить (‘off’). По умолчанию пулы совместно используются потоками одной группы (‘on’), чтобы сократить число постоянных соединений с сервером и повысить долю повторного использования соединений. Совместное использование потоками других групп может влиять на производительность и по умолчанию отключено, но полезно, если максимальное повторное использование соединений приоритетно. Для отладки или при подозрении на ошибку HAProxy в повторном использовании соединений удобно принудительно отключить совместное использование пула несколькими потоками, задав “off”. Настоятельно не рекомендуется отключать этот параметр без консервативного значения “pool-low-conn” для всех серверов, чья высокая производительность зависит от повторного использования соединений; иначе с ростом числа потоков соединения могут закрываться очень часто.

tune.idletimer <timeout>

tune.idletimer <timeout>

Задаёт время, после которого HAProxy считает, что пустой буфер, вероятно, связан с простаивающим потоком. Это позволяет оптимально менять размеры некоторых пакетов при чередовании пересылки больших и малых объёмов данных. Параметр влияет на решение использовать splice() или отправлять большие буферы по SSL. Значение задаётся в миллисекундах от 0 до 65535. Ноль означает, что HAProxy не пытается обнаруживать простаивающие потоки. Значение по умолчанию — 1000; оно, по-видимому, правильно обнаруживает паузы пользователя, например чтение страницы перед щелчком. Причин для изменения этого значения быть не должно. См. ниже tune.ssl.maxrecord.

tune.listener.default-shards { by-process | by-thread | by-group }

tune.listener.default-shards { by-process | by-thread | by-group }

Обычно все строки “bind” создают один шард: один сокет, который слушают все потоки процесса. При большом числе потоков это не очень эффективно и может создавать значительные накладные расходы ядра при обновлении состояния опроса или распределении событий между потоками. Современные ОС поддерживают балансировку входящих соединений: несколько сокетов могут быть привязаны к одному адресу и порту, а все входящие соединения равномерно распределяются между ними, поэтому каждый поток видит только соединения, ожидающие в сокете, к которому он привязан. Это значительно сокращает накладные расходы ядра и повышает производительность при обработке входящих соединений. В HAProxy это обычно включается параметром “shards” строк “bind” со значением по умолчанию 1, при котором каждому слушателю в процессе соответствует единственный сокет. В системах с множеством процессоров удобнее изменить значение по умолчанию на “by-thread”, чтобы всегда создавать один слушающий сокет на поток, либо на “by-group”, чтобы создавать один слушающий сокет на группу потоков. При “by-thread” следует учитывать использование файловых дескрипторов: каждому слушателю нужно столько сокетов, сколько потоков. Кроме того, некоторые ОС, например FreeBSD, ограничивают число сокетов на одном адресе значением 256. Обратите внимание: “by-group” остаётся эквивалентом “by-process” в конфигурациях по умолчанию с одной группой потоков и возвращается к общему сокету в системах без поддержки этого механизма. Значение по умолчанию — “by-group” с переходом на “by-process” для систем или семейств сокетов, не поддерживающих множественные привязки.

tune.listener.multi-queue { on | fair | off }

tune.listener.multi-queue { on | fair | off }

Включает (‘on’ / ‘fair’) или отключает (‘off’) приём соединений слушателем с несколькими очередями. Он распределяет входящий трафик между всеми потоками, на которых разрешено работать строке “bind”, вместо приёма только для себя. Это даёт более плавное распределение трафика и гораздо лучше масштабируется, особенно если потоки нагружены неравномерно из-за внешней активности, например сетевых прерываний на одном из потоков. Режим по умолчанию “on” оптимизирует выбор потока, выбирая из выборки поток с наименьшим числом соединений. Часто это лучший выбор для долгих соединений, поскольку он поддерживает занятость всех потоков. Второй режим, “fair”, последовательно обходит все потоки независимо от их текущей нагрузки. Он может лучше подходить для коротких соединений или машин с очень большим числом потоков, где вероятность найти самый свободный поток в первом режиме мала. Наконец, “off” позволяет принудительно отключить перераспределение для устранения неполадок либо для коротких соединений, когда считается, что ОС уже достаточно хорошо распределяет их. Значение по умолчанию — “on”.

tune.lua.bool-sample-conversion { normal | pre-3.1-bug }

tune.lua.bool-sample-conversion { normal | pre-3.1-bug }

Явно задаёт haproxy способ обработки объектов образцов haproxy при передаче в Lua. Например, при использовании встроенных преобразователей, функций извлечения образцов или переменных из сценария Lua haproxy преобразует внутренний тип smp в соответствующий тип Lua. Из-за исторической реализации обработка логических значений неоднозначна: при преобразовании Lua -> haproxy smp логические значения сохраняются правильно, но при преобразовании haproxy smp -> Lua они ошибочно преобразовывались в целые числа. Поэтому функция извлечения образца или преобразователь, возвращающий логическое значение, при использовании из Lua возвращал целое число 0 или 1. К сожалению, в Lua логические значения и целые числа не взаимозаменяемы. Во избежание неоднозначности параметр “tune.lua.bool-sample-conversion” должен быть явно задан либо как “normal”, отказавшись от прежнего поведения ради согласованности, либо как “pre-3.1-bug”, сохранив прежнее поведение, чтобы не нарушить логику существующих сценариев. Если параметр не задан явно, а из конфигурации загружается сценарий Lua, haproxy выводит предупреждение, и неявно применяется “pre-3.1-bug” для сохранения прежнего поведения. Рекомендуется задать “normal”, предварительно убедившись, что используемые сценарии Lua правильно обрабатывают образцы bool haproxy как логические значения.

Чтобы параметр учитывался, он должен быть задан до любой директивы “lua-load” или “lua-load-per-thread”; иначе он игнорируется.

tune.lua.burst-timeout <timeout>

tune.lua.burst-timeout <timeout>

Тайм-аут выполнения “burst” применяется к любому обработчику Lua. Если обработчик не завершится или не уступит выполнение до достижения тайм-аута, он будет прерван, чтобы предотвратить конкуренцию между потоками, слишком долгое необслуживание трафика и в конечном счёте аварийное завершение процесса при срабатывании сторожевого таймера. В отличие от других тайм-аутов Lua, суммируемых между уступками выполнения, burst-timeout ограничивает время одного непрерывного окна выполнения Lua заданным тайм-аутом.

Уступка выполнения здесь означает, что выполнение Lua фактически прерывается либо явным вызовом функции, уступающей выполнение, например core.(m)sleep() или core.yield(), либо автоматической принудительной уступкой (см. tune.lua.forced-yield). Оно возобновится позднее, когда соответствующая задача будет запланирована заново. Не все обработчики Lua могут уступать выполнение: следует различать обработчики с такой возможностью и без неё.

Для обработчиков, способных уступать выполнение, например задач и действий, достижение тайм-аута может означать, что “tune.lua.forced-yield” слишком велик для системы и его уменьшение улучшит ситуацию. Можно также проверить, помогают ли явные уступки выполнения в ключевых точках функции Lua. Это может указывать и на то, что обработчик слишком долго находится в определённой библиотечной функции Lua, которую нельзя прервать.

Для обработчиков, неспособных уступать выполнение, например преобразователей Lua и функций извлечения образцов, это может означать слишком большой объём вычислений из-за неудачного проектирования: такие обработчики часто блокируют ход выполнения запроса и от них ожидается быстрое завершение, чтобы его обработка могла продолжиться. Обычно стоит попытаться оптимизировать функцию Lua по скорости, поскольку уменьшение “tune.lua.forced-yield” не поможет.

Этот тайм-аут учитывает только чистое время выполнения Lua. Если Lua вызывает core.sleep, время сна не учитывается. Тайм-аут по умолчанию — 1000ms.

Примечание: если обработчик запускает цикл GC Lua, явно либо автоматически по инициативе Lua через некоторое время, длительность цикла GC также учитывается.

Время цикла GC невозможно определить, поэтому на насыщенных системах возможны ложные срабатывания: GC не успевает за нагрузкой и занимает большую часть доступного времени выполнения. В таком случае можно попробовать следующие решения:

- проверить, можно ли оптимизировать сценарий, чтобы уменьшить потребление памяти Lua
- настроить параметры GC Lua и / или явно запрашивать циклы GC
  (см.: https://www.lua.org/manual/5.4/manual.html#pdf-collectgarbage)
- увеличить tune.lua.burst-timeout

Значение 0 полностью отключает эту защиту.

tune.lua.forced-yield <number>

tune.lua.forced-yield <number>

Эта директива заставляет механизм Lua уступать выполнение через каждые <number> выполненных инструкций. Это позволяет прерывать длинный сценарий и даёт планировщику HAProxy возможность обрабатывать другие задачи, например принимать соединения или пересылать трафик. Значение по умолчанию — 10000 инструкций для сценариев, загруженных через “lua-load-per-thread”, и MAX(500, 10000 / nbthread) инструкций для сценариев, загруженных через “lua-load”. Экспериментально это оказалось оптимальным для производительности с учётом предотвращения конкуренции нескольких потоков за глобальную блокировку Lua.

Если HAProxy часто выполняет код Lua, но требуется большая отзывчивость, значение можно уменьшить. Если код Lua достаточно длинный и его результат совершенно необходим для обработки данных, <number> можно увеличить, но значение следует выбирать разумно: в многопоточной среде оно может усилить конкуренцию за ресурсы.

tune.lua.log.loggers { on | off }

tune.lua.log.loggers { on | off }

Включает (‘on’) или отключает (‘off’) запись вывода сценариев LUA через средства ведения журнала текущего прокси, если они есть.

По умолчанию — ‘on’.

tune.lua.log.stderr { on | auto | off }

tune.lua.log.stderr { on | auto | off }

Включает (‘on’) или отключает (‘off’) запись вывода сценариев LUA через stderr. При значении ‘auto’ запись через stderr условно включается (‘on’), если выполняется хотя бы одно из условий:

- tune.lua.log.loggers имеет значение 'off'
- сценарий выполняется вне контекста прокси и глобального средства ведения журнала нет
- сценарий выполняется в контексте прокси, к которому не подключено средство ведения журнала

Обратите внимание: при включении эта запись дополняет ведение журнала, настроенное через tune.lua.log.loggers.

По умолчанию — ‘auto’.

tune.lua.maxmem <number>

tune.lua.maxmem <number>

Задаёт максимальный объём RAM в мегабайтах на процесс, доступный Lua. По умолчанию — ноль, то есть без ограничения. Важно задать предел, чтобы ошибка сценария не привела к исчерпанию памяти системы.

tune.lua.openlibs [all | none | <lib>[,<lib>...]]

tune.lua.openlibs [all | none | <lib>[,<lib>...]]

Выбирает стандартные библиотеки Lua, загружаемые при инициализации состояния Lua. Аргумент — разделённый запятыми список имён библиотек из набора table, io, os, string, math, utf8, package, debug. Вместо списка можно использовать специальные значения “all” и “none”. Значение “none” нельзя сочетать с именами библиотек. Значение по умолчанию — “all”.

Библиотеки base и coroutine всегда загружаются независимо от этого параметра: base предоставляет основные функции Lua, необходимые HAProxy, а coroutine требуется, поскольку HAProxy заменяет coroutine.create() собственной безопасной реализацией.

Обратите внимание: fork() и создание новых потоков уже заблокированы в HAProxy по умолчанию независимо от этого параметра и могут быть снова включены только глобальной директивой “insecure-fork-wanted”. Ограничение набора загружаемых библиотек дополнительно уменьшает поверхность атаки, доступную сценариям Lua. В частности: - исключение “os” запрещает os.execute() и os.exit() - исключение “io” запрещает io.open() и io.popen() - исключение “package” запрещает загрузку нативных модулей C через require() - исключение “debug” запрещает изучение внутреннего состояния HAProxy через debug.getupvalue(), debug.getmetatable() или debug.sethook()

Примеры:

tune.lua.openlibs none                    # only base + coroutine
tune.lua.openlibs string,math,table,utf8  # safe subset, no I/O or OS
tune.lua.openlibs all                     # default, load everything

Этот параметр должен быть задан до любой директивы “lua-load”, “lua-load-per-thread” или “lua-prepend-path”; иначе возвращается ошибка разбора.

tune.lua.service-timeout <timeout>

tune.lua.service-timeout <timeout>

Тайм-аут выполнения служб Lua. Полезен для предотвращения бесконечных циклов или чрезмерно долгой работы Lua. Учитывает только чистое время выполнения Lua. Если Lua переходит в сон, время сна не учитывается. Тайм-аут по умолчанию — 4s.

tune.lua.session-timeout <timeout>

tune.lua.session-timeout <timeout>

Тайм-аут выполнения сеансов Lua. Полезен для предотвращения бесконечных циклов или чрезмерно долгой работы Lua. Учитывает только чистое время выполнения Lua. Если Lua переходит в сон, время сна не учитывается. Тайм-аут по умолчанию — 4s.

tune.lua.task-timeout <timeout>

tune.lua.task-timeout <timeout>

Назначение то же, что у “tune.lua.session-timeout”, но тайм-аут предназначен для задач. По умолчанию он не задан, поскольку задача может существовать всё время работы HAProxy, например задача проверки серверов.

tune.max-checks-per-thread <number>

tune.max-checks-per-thread <number>

Задаёт число активных проверок на поток, выше которого поток активно пытается найти менее нагруженный поток для проверки работоспособности либо ставит её в очередь до уменьшения числа выполняемых на нём проверок. Значение по умолчанию — ноль: такого ограничения нет. Параметр может понадобиться в средах с чрезвычайно большим числом дорогих проверок и множеством потоков, если нагрузка распределяется неравномерно и проверки работоспособности могут случайно достигать тайм-аута при запуске. Типичный случай — OpenSSL 3.0, где проверки работоспособности примерно в 20 раз сильнее нагружают CPU, чем в более ранних версиях. В результате работа по проверкам выравнивается между всеми потоками. Для подавляющего большинства конфигураций менять параметр не нужно. Обратите внимание: слишком малые значения могут значительно замедлить проверки работоспособности, если они выполняются медленно.

tune.maxaccept <number>

tune.maxaccept <number>

Задаёт максимальное число соединений, которые процесс может принять подряд перед переходом к другой работе. В однопроцессном режиме большие числа раньше повышали производительность при высокой интенсивности соединений, но с несколькими очередями это больше не так. Значение применяется отдельно к каждому слушателю с учётом числа процессов, к которым он привязан. Значение по умолчанию — 4, показавшее лучшие результаты. Если из старой конфигурации унаследовано значительно большее значение, его имеет смысл удалить: это повысит производительность и уменьшит время ответа. В многопроцессном режиме оно делится на удвоенное число процессов, к которым привязан слушатель. Значение -1 полностью отключает ограничение. Обычно подстраивать это значение не должно требоваться.

tune.maxpollevents <number>

tune.maxpollevents <number>

Задаёт максимальное число событий, обрабатываемых за один вызов системы опроса. Значение по умолчанию подбирается под ОС. Замечено, что уменьшение ниже 200 обычно немного снижает задержку ценой пропускной способности сети, а увеличение выше 200 обычно повышает задержку ради небольшого роста пропускной способности. Заданное значение должно быть не больше 1000000.

tune.maxrewrite <number>

tune.maxrewrite <number>

Задаёт размер зарезервированного пространства буфера в байтах. Оно используется для изменения или добавления заголовков. Первые чтения из сокетов никогда не заполняют больше bufsize-maxrewrite. Исторически значение по умолчанию составляло половину bufsize, хотя это не очень разумно, поскольку редко требуется добавлять много заголовков. Слишком большое значение не позволяет обрабатывать большие запросы или ответы. Слишком малое не позволяет добавлять заголовки в уже большие запросы или запросы POST. Обычно разумно выбрать около 1024. Если значение больше половины bufsize, оно автоматически уменьшается до этой половины. Поэтому при изменении bufsize об этом беспокоиться не нужно.

tune.max-rules-at-once <number>

tune.max-rules-at-once <number>

Задаёт максимальное число правил, вычисляемых за один раз функциями обработки наборов правил, если они поддерживают уступку выполнения. Например, нередки конфигурации с множеством правил “tcp-request content” или “http-request”. Большое число правил в сочетании с действиями, требующими много CPU, например работающими с содержимым, может вызвать конкуренцию между потоками: если вычисление не прерывается, все правила набора выполняются в одном цикле опроса. Для наборов правил, ориентированных на содержимое и уже поддерживающих уступку выполнения при его проверке, параметр гарантирует выполнение не более <number> правил в одном цикле опроса. Он принудительно заставляет функцию вычисления уступить выполнение, чтобы продолжить обработку в следующем цикле опроса.

Затрагиваемые наборы правил:

  • “tcp-request content”
  • “tcp-response content”
  • “http-request”
  • “http-response”

Значение по умолчанию — 50.

tune.memory.hot-size <number>

tune.memory.hot-size <number>

Задаёт объём памяти на поток, который сохраняется готовым к использованию в локальном кэше и никогда не может быть освобождён другими потоками. Доступ к этой памяти очень быстрый, без блокировок, а достаточный объём критичен для производительности при сильной конкуренции потоков. Значение выражается в байтах; значение по умолчанию задаётся при сборке через CONFIG_HAP_POOL_CACHE_SIZE и составляет 524288 (512 kB). Большее значение может повысить производительность в некоторых сценариях, особенно когда профили показывают высокую нагрузку на выделение памяти. По опыту, удачное значение находится между размером кэша L2 одного ядра CPU и удвоенным этим размером. Слишком большие значения ухудшают производительность из-за неэффективного использования кэшей L3 в CPU и потребляют больше памяти. Рекомендуется не менять значение либо увеличивать его небольшими шагами. Для полного отключения кэшей CPU на поток может подойти очень малое значение, но лучше использовать “-dMno-cache” в командной строке.

tune.notsent-lowat.client <size>

tune.notsent-lowat.client <size>
tune.notsent-lowat.server <size>

Подстраивает буферизацию ядра на сокет так, чтобы сторона отправки сокета считалась заполненной, когда объём буферизованных данных равен этому значению плюс измеренный размер окна. Принцип — оставлять в буферах сокета лишь строго необходимый минимум байт и небольшой запас, соответствующий объёму, который будет отправлен до следующей попытки отправки haproxy. Малое значение, обычно около tune.bufsize, значительно снижает потребление памяти системными буферами и задержку приложения при отправке буферизованных данных. В поддерживающих системах этот параметр обычно эффективнее и точнее, чем tune.sndbuf.client и tune.sndbuf.client. Применяется на соединение, от клиента или к серверу в зависимости от параметра, и используется только для TCP. Значение по умолчанию — ноль, то есть без ограничения. Доступен только в Linux.

tune.pattern.cache-size <number>

tune.pattern.cache-size <number>

Задаёт размер кэша поиска шаблонов равным <number> записей. Это кэш LRU, запоминающий предыдущие поиски и их результаты. Он используется ACL и таблицами соответствий для медленного поиска шаблонов: методов “sub”, “reg”, “dir”, “dom”, “end”, “bin” и строк без учёта регистра. Применяется к выражениям шаблонов, поэтому запоминает результат поиска среди всех шаблонов строки конфигурации, включая загруженные из файлов. Записи, обновлённые действиями HTTP или через CLI, автоматически становятся недействительными. Размер кэша по умолчанию — 10000 записей, что ограничивает объём памяти примерно 5 MB на процесс/поток в 32-битных системах и 8 MB на процесс/поток в 64-битных, поскольку кэши локальны для потока/процесса. Риск коллизии очень мал, порядка размера кэша, делённого на 2^64. Обычно при 10000 запросов в секунду и кэше по умолчанию из 10000 записей вероятность одной коллизии от атаки перебором составляет 1% за 60 лет или 0.1% за 6 лет. Это считается гораздо ниже риска повреждения памяти из-за старения компонентов. Если такой риск неприемлем, кэш можно отключить значением 0.

tune.peers.max-updates-at-once <number>

tune.peers.max-updates-at-once <number>

Задаёт максимальное число обновлений stick-table, которые haproxy пытается обработать за один раз при отправке сообщений. Получение данных обновлений требует блокировок, которые без ограничения могут сильно нагружать CPU на машинах с множеством потоков и увеличивать задержку трафика при начальной пакетной передаче между старым и новым процессом. Малые значения, напротив, тоже могут увеличить накладные расходы CPU и время завершения. Значение по умолчанию — 200, менять его не рекомендуется.

tune.pipesize <size>

tune.pipesize <size>

Задаёт размер буфера канала ядра в байтах. По умолчанию каналы имеют стандартный для системы размер. Иногда при TCP splicing увеличение каналов повышает производительность, особенно если предполагается, что каналы не заполняются и выполняется много вызовов splice(). Это влияет на потребление памяти ядром, поэтому значение нельзя менять без понимания последствий.

tune.pool-high-fd-ratio <number>

tune.pool-high-fd-ratio <number>

Задаёт максимальное число файловых дескрипторов, используемых HAProxy глобально, в процентах от максимума доступных HAProxy дескрипторов, при котором начинается принудительное закрытие простаивающих соединений, если соединение нельзя использовать повторно и нужно создать новое. Значение по умолчанию — 25: четверть файловых дескрипторов означает, что примерно половина максимально допустимых соединений с фронтендом может поддерживать простаивающее соединение с другой стороны. При ориентации на повторное использование соединений большее значение, вероятно, обычно не имеет смысла.

tune.pool-low-fd-ratio <number>

tune.pool-low-fd-ratio <number>

Задаёт максимальное число файловых дескрипторов, используемых HAProxy глобально, в процентах от максимума доступных HAProxy дескрипторов, при котором прекращается добавление соединений в пул простаивающих соединений для повторного использования. Значение по умолчанию — 20.

tune.pt.zero-copy-forwarding { on | off }

tune.pt.zero-copy-forwarding { on | off }

Включает (‘on’) или отключает (‘off’) пересылку данных без копирования для транзитного мультиплексора. Для её использования также должно быть настроено splicing средствами ядра. По умолчанию включена.

См. также: tune.disable-zero-copy-forwarding, option splice-auto, option splice-request и option splice-response

tune.quic.be.cc.cubic-min-losses <number>

tune.quic.be.cc.cubic-min-losses <number>
tune.quic.fe.cc.cubic-min-losses <number>

Определяет число потерянных пакетов, необходимое алгоритму управления перегрузкой Cubic для признания события потери. Обычно любое событие потери считается результатом перегрузки, и его достаточно, чтобы Cubic снова начал с меньшего окна. Но эксперименты показывают, что у потерь бывают разные причины, совершенно не связанные с перегрузкой: такие потери можно считать ложными, а изменение окна лишь замедляет связь, не давая другого эффекта. Частые причины — слабый радиосигнал, доставка не по порядку, высокое использование CPU клиента со случайными задержками и неточность системного таймера. Этот параметр делает Cubic немного терпимее к ложным потерям, изменяя минимальное суммарное число потерь между двумя ACKs, которое считается событием потери; по умолчанию оно равно 1. Экспериментально наблюдались значительные улучшения, но всегда с ростом пропускной способности, расходуемой на повторные передачи, и риска насыщения перегруженных каналов. Значение 2 можно кратковременно использовать для сравнения метрик. Нельзя превышать 2 без предварительного анализа ситуации специалистом. Значение по умолчанию и минимум — 1. Всегда используйте 1.

tune.quic.cc.cubic.min-losses <number> (deprecated)

tune.quic.cc.cubic.min-losses <number> (deprecated)

Это ключевое слово объявлено устаревшим в 3.3 и будет удалено в 3.5. Это часть упрощения конфигурации QUIC. Если параметр используется, он применяется только к соединениям фронтенда.

tune.quic.be.cc.hystart { on | off }

tune.quic.be.cc.hystart { on | off }
tune.quic.fe.cc.hystart { on | off }

Включает (‘on’) или отключает (‘off’) алгоритм HyStart++ (RFC 9406) для соединений QUIC вместо фазы медленного старта алгоритмов управления перегрузкой, которые могут вызывать большие потери пакетов. По умолчанию отключён.

tune.quic.cc-hystart { on | off } (deprecated)

tune.quic.cc-hystart { on | off } (deprecated)

Это ключевое слово объявлено устаревшим в 3.3 и будет удалено в 3.5. Это часть упрощения конфигурации QUIC. Если параметр используется, он применяется только к соединениям фронтенда.

tune.quic.be.cc.max-frame-loss <number>

tune.quic.be.cc.max-frame-loss <number>
tune.quic.fe.cc.max-frame-loss <number>

Задаёт предел числа раз, когда один кадр QUIC может быть отмечен как потерянный. При превышении соединение считается неисправным и немедленно закрывается.

Значение по умолчанию — 10.

tune.quic.max-frame-loss <number> (deprecated)

tune.quic.max-frame-loss <number> (deprecated)

Это ключевое слово объявлено устаревшим в 3.3 и будет удалено в 3.5. Это часть упрощения конфигурации QUIC. Если параметр используется, он применяется только к соединениям фронтенда.

tune.quic.be.cc.max-win-size <size>

tune.quic.be.cc.max-win-size <size>
tune.quic.fe.cc.max-win-size <size>

Задаёт максимальный размер окна по умолчанию для контроллера перегрузки одного соединения QUIC на стороне фронтенда или бэкенда. Значение должно быть целым числом с необязательным суффиксом ‘k’, ’m’ или ‘g’ и находиться в пределах от 10k до 4g.

Мультиплексор QUIC также использует текущий размер окна перегрузки, чтобы определить, можно ли выделить новые буферы потоков при отправке данных. Поэтому максимальный размер окна перегрузки ограничивает и этот распределитель памяти.

Значение по умолчанию — 480k.

См. также параметры “quic-cc-algo” для bind и server.

tune.quic.frontend.default-max-window-size <size> (deprecated)

tune.quic.frontend.default-max-window-size <size> (deprecated)

Это ключевое слово объявлено устаревшим в 3.3 и будет удалено в 3.5. Это часть упрощения конфигурации QUIC. Если параметр используется, он применяется только к соединениям фронтенда.

tune.quic.be.cc.reorder-ratio <0..100, in percent>

tune.quic.be.cc.reorder-ratio <0..100, in percent>
tune.quic.fe.cc.reorder-ratio <0..100, in percent>

Коэффициент, применяемый к вычисленному порогу переупорядочения пакетов. Слишком малое значение может привести к обнаружению большого числа потерянных пакетов.

Значение по умолчанию — 50.

tune.quic.reorder-ratio <0..100, in percent> (deprecated)

tune.quic.reorder-ratio <0..100, in percent> (deprecated)

Это ключевое слово объявлено устаревшим в 3.3 и будет удалено в 3.5. Это часть упрощения конфигурации QUIC. Если параметр используется, он применяется только к соединениям фронтенда.

tune.quic.be.max-idle-timeout <timeout>

tune.quic.be.max-idle-timeout <timeout>
tune.quic.fe.max-idle-timeout <timeout>

Задаёт транспортный параметр QUIC max_idle_timeout на стороне фронтенда или бэкенда. Использует формат времени HAProxy и выражается в миллисекундах. Определяет время, после которого соединение молча закрывается, если оставалось неактивным в течение соответствующего периода. Обе стороны используют одно согласованное значение: - минимум двух параметров, если оба ненулевые, - максимум, если ненулевым является только один, - если оба параметра нулевые, механизм отключён.

Значение по умолчанию — 30s.

tune.quic.frontend.max-idle-timeout <timeout> (deprecated)

tune.quic.frontend.max-idle-timeout <timeout> (deprecated)

Это ключевое слово объявлено устаревшим в 3.3 и будет удалено в 3.5. Это часть упрощения конфигурации QUIC. Если параметр используется, он применяется только к соединениям фронтенда.

tune.quic.be.sec.glitches-threshold <number>

tune.quic.be.sec.glitches-threshold <number>
tune.quic.fe.sec.glitches-threshold <number>

Задаёт порог числа нарушений на соединение на стороне фронтенда или бэкенда, по достижении которого соединение автоматически принудительно закрывается. Это позволяет закрывать некорректно работающие соединения без явных правил. Значение по умолчанию — ноль: порог не задан, поэтому никакое событие не приводит к закрытию соединения. Следует учитывать, что некоторые клиенты QUIC иногда вызывают несколько нарушений за время долгого соединения, поэтому ненулевое значение, вероятно, следует выбирать в сотнях или тысячах, чтобы механизм работал эффективно, не затрагивая клиентов с небольшими отклонениями. С помощью “tune.glitches.kill.cpu-usage” можно также закрывать соединения только при достижении определённого уровня использования CPU.

См. также: fc_glitches, tune.glitches.kill.cpu-usage

tune.quic.frontend.glitches-threshold <number> (deprecated)

tune.quic.frontend.glitches-threshold <number> (deprecated)

Это ключевое слово объявлено устаревшим в 3.3 и будет удалено в 3.5. Это часть упрощения конфигурации QUIC. Если параметр используется, он применяется только к соединениям фронтенда.

tune.quic.fe.sec.retry-threshold <number>

tune.quic.fe.sec.retry-threshold <number>

Динамически включает Retry для всех настроенных слушателей QUIC при достижении указанного числа полуоткрытых соединений. Полуоткрытое соединение — соединение, рукопожатие которого ещё не завершилось успешно или неудачей. Для работы параметра должен быть задан секрет кластера; иначе он молча игнорируется (см. “cluster-secret”). Параметр также молча игнорируется при принудительном использовании QUIC Retry (см. “quic-force-retry”).

Значение по умолчанию — 100.

Подробнее о QUIC retry см. https://www.rfc-editor.org/rfc/rfc9000.html#section-8.1.2 .

tune.quic.retry-threshold <number> (deprecated)

tune.quic.retry-threshold <number> (deprecated)

Это ключевое слово объявлено устаревшим в 3.3 и будет удалено в 3.5. Это часть упрощения конфигурации QUIC. Если параметр используется, он применяется только к соединениям фронтенда.

tune.quic.fe.sock-per-conn { default-on | force-off }

tune.quic.fe.sock-per-conn { default-on | force-off }

Глобально задаёт способ использования сокета соединениями QUIC фронтенда для приёма и отправки. Соединения могут совместно использовать сокет слушателя либо выделять собственный сокет для каждого соединения.

Значение по умолчанию — “default-on”: для каждого соединения QUIC выделяется отдельный сокет. Этот вариант предпочтителен для наилучшей производительности при большом трафике QUIC. Это также единственный способ гарантировать корректную мягкую остановку без потери данных для соединений QUIC и эффективную обработку временных ошибок sendto(). Однако он зависит от некоторых расширенных возможностей сетевого стека UDP. Если платформа считается несовместимой, haproxy при запуске автоматически переключается в режим “force-off”. Обратите внимание: слушатели QUIC на привилегированных портах могут требовать работы с uid 0 либо настройки ОС, разрешающей целевому uid привязываться к таким портам, например системных полномочий. См. также глобальную директиву “setcap”.

Значение “force-off” означает, что передача QUIC выполняется через общий сокет слушателя. Это может быть хорошим компромиссом при небольшом трафике, поскольку снижает потребление FD. Но производительность не будет оптимальной из-за более высокого использования CPU, если слушатели разделяются многими потоками или одновременно используется много соединений QUIC.

Этот параметр применяется совместно с параметрами bind “quic-socket”. При глобальном режиме “default-on” он включается для каждого слушателя, кроме настроенных с “quic-socket listener”. Однако глобальное значение “force-off” применяется ко всем экземплярам слушателей независимо от их индивидуальной конфигурации.

tune.quic.socket-owner { connection | listener } (deprecated)

tune.quic.socket-owner { connection | listener } (deprecated)

Это ключевое слово объявлено устаревшим в 3.3 и будет удалено в 3.5. Это часть упрощения конфигурации QUIC. Новый параметр называется “tune.quic.fe.sock-per-conn”; прежнее значение “connection” соответствует “default-on”, а “listener” — “force-off”.

tune.quic.be.stream.data-ratio <0..100, in percent>

tune.quic.be.stream.data-ratio <0..100, in percent>
tune.quic.fe.stream.data-ratio <0..100, in percent>

Позволяет задать жёсткий предел числа байт данных в пути по каждому потоку. Выражается в процентах относительно параметра rxbuf потоков соединения QUIC; результат округляется вверх до bufsize.

Значение по умолчанию — 90. Оно подходит для наиболее частого веб-сценария, где данные отправляются лишь по одному или нескольким потокам, а остальные используются только для получения данных. Если предел rxbuf потоков соединения остаётся разумным, это гарантирует, что лишь часть открытых потоков может выделить свой максимальный объём памяти.

Если приложение использует много параллельных потоков отправки и сталкивается с несправедливым распределением ресурсов между ними, имеет смысл уменьшить этот коэффициент, повысив справедливость и снизив пропускную способность на поток.

См. также: “tune.quic.be.stream.rxbuf”, “tune.quic.fe.stream.rxbuf”, “tune.quic.be.stream.max-concurrent”, “tune.quic.fe.stream.max-concurrent”

tune.quic.frontend.stream-data-ratio <0..100, in percent> (deprecated)

tune.quic.frontend.stream-data-ratio  <0..100, in percent> (deprecated)

Это ключевое слово объявлено устаревшим в 3.3 и будет удалено в 3.5. Это часть упрощения конфигурации QUIC. Если параметр используется, он применяется только к соединениям фронтенда.

tune.quic.be.stream.max-concurrent <number>

tune.quic.be.stream.max-concurrent <number>
tune.quic.fe.stream.max-concurrent <number>

На стороне фронтенда используется как объявляемое значение транспортного параметра initial_max_streams_bidi. Задаёт максимальное число двунаправленных потоков, которые удалённый одноранговый узел вправе открыть одновременно за время соединения. Фактически ограничивает число одновременных запросов HTTP/3 клиента.

Значение по умолчанию — 100. Обратите внимание: его уменьшение может ограничить возможности буферизации потоков при приёме и ухудшить пропускную способность отправки данных. Это можно исправить увеличением параметра rxbuf потоков соединения QUIC.

На стороне бэкенда haproxy локально ограничивает число одновременных запросов, мультиплексируемых в одном соединении. Управление потоком у однорангового узла может дополнительно снизить этот предел. Может потребоваться уменьшить значение по умолчанию 100 для улучшения отзывчивости сайта ценой большего числа открытых соединений с бэкендом. Как и на стороне фронтенда, параметр напрямую влияет на возможности буферизации Rx, но здесь ограничивает получение данных HTTP. Параметр rxbuf потоков QUIC можно увеличить, если большинство ответов HTTP больше “tune.bufsize”.

См. также: “tune.quic.be.stream.rxbuf”, “tune.quic.fe.stream.rxbuf”, “tune.quic.be.stream.data-ratio”, “tune.quic.fe.stream.data-ratio”

tune.quic.fe.stream.max-total <number>

tune.quic.fe.stream.max-total <number>

Задаёт максимальное число запросов, обслуживаемых одним соединением QUIC. При достижении общего числа начинается плавное завершение соединения. В HTTP/3 это означает отправку кадра GOAWAY. Окончательно соединение закрывается после завершения всех оставшихся передач данных.

Применяется как жёсткий предел соединения через механизм управления потоком QUIC. Если одноранговый узел нарушает его, соединение немедленно закрывается.

Позволяет заставить клиентов время от времени открывать новые соединения для продолжения отправки запросов, избегая чрезмерно долгого сохранения соединений. Однако малые значения увеличивают задержку на стороне клиента и использование CPU с обеих сторон из-за рукопожатий TLS.

Значение по умолчанию — 0: отдельного ограничения сверх ограничения кодирования протокола QUIC нет (2^60, более миллиарда миллиардов).

tune.quic.frontend.max-streams-bidi <number> (deprecated)

tune.quic.frontend.max-streams-bidi <number> (deprecated)

Это ключевое слово объявлено устаревшим в 3.3 и будет удалено в 3.5. Это часть упрощения конфигурации QUIC. Если параметр используется, он применяется только к соединениям фронтенда.

tune.quic.be.stream.rxbuf <size>

tune.quic.be.stream.rxbuf <size>
tune.quic.fe.stream.rxbuf <size>

Жёсткий предел числа байт данных в пути по соединению QUIC фронтенда. Используется как значение транспортного параметра initial_max_data. Напрямую влияет на пропускную способность отправки однорангового узла в зависимости от задержки и на потребление памяти одним соединением в haproxy.

По умолчанию — 0: значение должно автоматически вычисляться как произведение max-concurrent и bufsize. Его можно увеличить, например если приложение бэкенда зависит от отправки больших объёмов данных в сетях с высокой задержкой.

См. также: “tune.quic.be.stream.max-concurrent”, “tune.quic.fe.stream.max-concurrent”, “tune.quic.be.stream.data-ratio”, “tune.quic.fe.stream.data-ratio”

tune.quic.frontend.max-data-size <size> (deprecated)

tune.quic.frontend.max-data-size <size> (deprecated)

Это ключевое слово объявлено устаревшим в 3.3 и будет удалено в 3.5. Это часть упрощения конфигурации QUIC. Если параметр используется, он применяется только к соединениям фронтенда.

tune.quic.be.tx.pacing { on | off }

tune.quic.be.tx.pacing { on | off }
tune.quic.fe.tx.pacing { on | off }

Включает (‘on’) или отключает (‘off’) равномерную отправку данных QUIC. По умолчанию включена. Цель — сгладить отправку данных и уменьшить потери в сети. В большинстве сценариев это значительно повышает пропускную способность, избегая повторных передач. Но в сетях с очень высокой пропускной способностью и низкой задержкой отключение может быть полезно для предотвращения нежелательной задержки и уменьшения использования CPU.

См. также параметры “quic-cc-algo” для bind и server.

tune.quic.disable-tx-pacing (deprecated)

tune.quic.disable-tx-pacing (deprecated)

Это ключевое слово объявлено устаревшим в 3.3 и будет удалено в 3.5. Это часть упрощения конфигурации QUIC. Если параметр используется, он применяется только к соединениям фронтенда.

tune.quic.be.tx.udp-gso { on | off }

tune.quic.be.tx.udp-gso { on | off }
tune.quic.fe.tx.udp-gso { on | off }

Включает (‘on’) или отключает (‘off’) поддержку UDP GSO для отправки QUIC. По умолчанию включена. Эта возможность ядра позволяет отправлять несколько датаграмм одним системным вызовом, что эффективнее при больших передачах. При подозрении на проблему отправки может быть полезно отключить её по рекомендации разработчиков.

tune.quic.disable-udp-gso (deprecated)

tune.quic.disable-udp-gso (deprecated)

Это ключевое слово объявлено устаревшим в 3.3 и будет удалено в 3.5. Это часть упрощения конфигурации QUIC. Если параметр используется, он применяется только к соединениям фронтенда.

tune.quic.listen { on | off }

tune.quic.listen { on | off }

Отключает транспортный протокол QUIC на стороне фронтенда. Все слушатели QUIC по-прежнему создаются, но не принимают входящие датаграммы. Поэтому haproxy не обрабатывает трафик QUIC на стороне фронтенда.

Значение по умолчанию — “on”. При подозрении на проблему с трафиком QUIC параметр позволяет легко переключать слушатели QUIC, не меняя каждую отдельную строку конфигурации.

См. также функцию извлечения образца “quic_enabled”.

tune.quic.mem.tx-max <size>

tune.quic.mem.tx-max <size>

Задаёт максимальный объём памяти, доступный стеку QUIC для отправки на транспортном уровне. Ограничивает как байты в пути, так и выходные буферы мультиплексора. Обратите внимание: для предотвращения конкуренции потоков предел не соблюдается строго и иногда может быть превышен. Кроме того, каждое соединение всегда может использовать окно не менее 2 датаграмм, поэтому вместе с этим параметром следует задать подходящий maxconn.

tune.quic.frontend.max-tx-mem <size> (deprecated)

tune.quic.frontend.max-tx-mem <size> (deprecated)

Это ключевое слово объявлено устаревшим в 3.3 и будет удалено в 3.5. Это часть упрощения конфигурации QUIC. Если параметр используется, он применяется только к соединениям фронтенда.

tune.quic.zero-copy-fwd-send { on | off }

tune.quic.zero-copy-fwd-send { on | off }

Включает (‘on’) или отключает (‘off’) отправку данных без копирования для мультиплексора QUIC. По умолчанию включена.

См. также: tune.disable-zero-copy-forwarding

tune.renice.runtime <number>

tune.renice.runtime <number>

Этот параметр конфигурации принимает значения от -20 до 19. Задаёт приоритет планирования согласно man 2 setpriority. Приоритет применяется после разбора конфигурации, то есть только рабочим или самостоятельным процессом. Обычно он задаёт более высокий приоритет, чем у процесса, разбирающего конфигурацию (tune.renice.startup).

См. также: tune.renice.startup

tune.renice.startup <number>

tune.renice.startup <number>

Этот параметр конфигурации принимает значения от -20 до 19. Задаёт приоритет планирования согласно man 2 setpriority. Приоритет применяется перед остальной конфигурацией, что полезно для снижения приоритета её разбора. Он применяется к самостоятельному или рабочему процессу до разбора конфигурации. После разбора прежний приоритет восстанавливается, если не используется tune.renice.runtime.

См. также: tune.renice.runtime

tune.rcvbuf.backend <size>

tune.rcvbuf.backend  <size>
tune.rcvbuf.frontend <size>

Задаёт размер буфера приёма сокета ядра для неподключённых сокетов. Может использоваться для QUIC в режиме слушателя и log-forward на фронтенде. Системные буферы по умолчанию иногда слишком малы для сокетов, принимающих большой суммарный трафик, что вызывает потери и, в случае QUIC, возможные повторные передачи, а также может замедлять установление соединений при высокой нагрузке. Значение выражается в байтах и применяется к каждому сокету. В режиме слушателя сокеты разделяются всеми соединениями, а их общее число зависит от “shards” строки “bind”. Единого удачного значения нет: оно соответствует ожидаемому размеру на соединение, умноженному на ожидаемое число соединений. Ядро может уменьшать большие значения. См. также аналоги для подключённых сокетов “tune.rcvbuf.client” и “tune.rcvbuf.server”, а также параметры отправки “tune.sndbuf.backend” и “tune.sndbuf.frontend”.

tune.rcvbuf.client <size>

tune.rcvbuf.client <size>
tune.rcvbuf.server <size>

Принудительно задаёт размер буфера приёма сокета ядра на стороне клиента или сервера указанным значением в байтах. Применяется ко всем фронтендам и бэкендам TCP/HTTP. Обычно его никогда не следует задавать: размер по умолчанию 0 позволяет ядру автоматически подбирать значение по доступной памяти. Однако иногда очень малые значения, например 4096, помогают экономить память ядра, не позволяя буферизовать слишком много принятых данных. При этом малые значения значительно повышают использование CPU.

tune.recv_enough <size>

tune.recv_enough <size>

HAProxy использует несколько признаков, чтобы определить, что короткое чтение означает конец данных в буферах сокета. Один из них — чтение возвращает больше <recv_enough> байт; по умолчанию это 10136 (7 сегментов по 1448). Этим параметром можно изменить значение по умолчанию для лучшей работы с нагрузками, содержащими много коротких сообщений, например сеансами telnet или SSH.

tune.ring.queues <number>

tune.ring.queues <number>

Задаёт число очередей записи перед кольцевыми буферами. Это может влиять на использование CPU трассировками во время отладки; и слишком малые, и слишком большие значения могут сильно влиять на него. Удачное значение определено разработчиками экспериментально, и менять его нет причин, если только это не предложено для решения конкретной проблемы. Такую настройку не следует сохранять в конфигурации при обновлении версий, поскольку оптимальное значение может меняться со временем.

tune.runqueue-depth <number>

tune.runqueue-depth <number>

Задаёт максимальное число задач, обрабатываемых за один раз при выполнении задач. Значение по умолчанию зависит от числа потоков, но находится между 35 и 280: такие значения обычно дают наибольшую интенсивность запросов и наименьшие задержки. Увеличение может добавить задержку при вводе-выводе, а слишком малое значение — дополнительные накладные расходы. При большем числе потоков полезны меньшие значения. При экспериментах со значительно большими значениями может быть полезно также включить tune.sched.low-latency и, возможно, tune.fd.edge-triggered, чтобы максимально снизить наибольшую задержку.

tune.sched.low-latency { on | off }

tune.sched.low-latency { on | off }

Включает (‘on’) или отключает (‘off’) планировщик задач с низкой задержкой. По умолчанию HAProxy обрабатывает задачи нескольких классов по одному классу за раз, поскольку это наиболее эффективно. Но при больших значениях tune.runqueue-depth это может заметно влиять на задержку запросов или соединений. При включении этого параметра задачи классов с более низким приоритетом, если они есть, всегда выполняются раньше остальных. Это уменьшает максимальную задержку новых запросов или соединений на фоне большого трафика, но сильнее влияет на этот большой трафик. Для обычного использования лучше оставить параметр выключенным. Значение по умолчанию — off.

tune.sndbuf.backend <size>

tune.sndbuf.backend  <size>
tune.sndbuf.frontend <size>

Задаёт размер буфера отправки сокета ядра для неподключённых сокетов. Используется для ведения журнала через сокет UNIX и UDP на стороне бэкенда и для QUIC в режиме слушателя на фронтенде. Системные буферы по умолчанию иногда слишком малы для сокетов, разделяемых множеством соединений или отправителей журналов, что вызывает потери, возможные повторные передачи и замедляет установление новых соединений при высоком трафике. Значение выражается в байтах и применяется к каждому сокету. В режиме слушателя сокеты разделяются всеми соединениями, а их общее число зависит от “shards” строки “bind”. Единого удачного значения нет: оно соответствует ожидаемому размеру на соединение, умноженному на ожидаемое число соединений. Ядро может уменьшать большие значения. См. также аналоги для подключённых сокетов “tune.sndbuf.client” и “tune.sndbuf.server”, а также параметры приёма “tune.rcvbuf.backend” и “tune.rcvbuf.frontend”.

tune.sndbuf.client <size>

tune.sndbuf.client <size>
tune.sndbuf.server <size>

Принудительно задаёт размер буфера отправки сокета ядра на стороне клиента или сервера указанным значением в байтах. Применяется ко всем фронтендам и бэкендам TCP/HTTP. Обычно его никогда не следует задавать: размер по умолчанию 0 позволяет ядру автоматически подбирать значение по доступной памяти. Однако иногда очень малые значения, например 4096, помогают экономить память ядра, не позволяя буферизовать слишком много принятых данных. При этом малые значения значительно повышают использование CPU. Ещё один случай использования — предотвращение тайм-аутов записи с чрезвычайно медленными клиентами, когда ядро ждёт чтения большой части буфера перед повторным уведомлением HAProxy. См. также tune.notsent-lowat.client и tune.notsent-lowat.server: в Linux они позволяют эффективнее и точнее управлять памятью и отзывчивостью без потери производительности.

tune.ssl.cachesize <number>

tune.ssl.cachesize <number>

Задаёт размер глобального кэша сеансов SSL в блоках. Блок достаточно велик для закодированного сеанса без сертификата однорангового узла. Сеанс с таким сертификатом хранится в нескольких блоках в зависимости от размера сертификата. Блок использует примерно 200 байт памяти согласно расчёту sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE для функции shctx_init. Значение по умолчанию можно задать при сборке; иначе оно равно 20000. При заполнении кэша дольше всех неиспользуемые записи удаляются и назначаются заново. Большие значения сокращают такие удаления и число сильно нагружающих CPU рукопожатий SSL, позволяя всем пользователям сохранять сеансы как можно дольше. Все записи предварительно выделяются при запуске. Значение 0 отключает кэш сеансов SSL.

tune.ssl.capture-buffer-size <number>

tune.ssl.capture-buffer-size <number>
tune.ssl.capture-cipherlist-size <number> (deprecated)

Задаёт максимальный размер буфера для захвата списка шифров client hello, списка расширений, списка эллиптических кривых и форматов точек эллиптических кривых. При значении 0, используемом по умолчанию, захват отключён; иначе для каждого соединения SSL/TLS выделяется буфер.

tune.ssl.certificate-compression { auto | off }

tune.ssl.certificate-compression { auto | off }

Позволяет настроить поддержку сжатия сертификатов — расширения TLS 1.3 (RFC 8879).

При “auto” используется значение по умолчанию библиотеки TLS.

При “off” выполняется попытка явно отключить поддержку этой возможности. HAProxy больше не пытается отправлять сжатые сертификаты и не принимает их.

Настраивает стороны бэкенда и фронтенда.

Это ключевое слово поддерживается OpenSSL >= 3.2.0.

Значение по умолчанию — auto.

tune.ssl.default-dh-param <number>

tune.ssl.default-dh-param <number>

Задаёт максимальный размер параметров Диффи — Хеллмана для генерации эфемерного или временного ключа при обмене DHE. Конечный размер стремится совпасть с размером ключа RSA или DSA сервера, например временный ключ DH в 2048 бит для ключа RSA в 2048 бит, но не превышает этот максимум. Разрешены только значения 1024 или выше. Большие значения повышают нагрузку CPU; значения больше 1024 бит не поддерживаются клиентами Java 7 и более ранними. Параметр не используется, если статические параметры Диффи — Хеллмана заданы непосредственно в файле сертификата либо через ssl-dh-param-file. Если не определены ни default-dh-param, ни ssl-dh-param-file и файл PEM сервера данного фронтенда не содержит собственных параметров DH, шифры DHE недоступны для этого фронтенда.

tune.ssl.force-private-cache

tune.ssl.force-private-cache

Отключает совместное использование кэша сеансов SSL всеми процессами. Обычно параметр не следует использовать: попадание клиентов в случайный процесс вызывает много повторных согласований. Но он может требоваться в ОС, где нельзя использовать ни один способ синхронизации кэша SSL. Тогда первый уровень балансировки на основе хеша перед слоем SSL может уменьшить последствия отсутствия совместного использования сеансов.

tune.ssl.hard-maxrecord <number>

tune.ssl.hard-maxrecord <number>

Задаёт максимальное число байт, передаваемых SSL_write() за один раз. Значение по умолчанию 0 означает отсутствие ограничения. В отличие от tune.ssl.maxrecord этот параметр не подстраивается динамически. Меньшие записи могут снизить пропускную способность, но могут требоваться для клиентов с малым объёмом ресурсов.

tune.ssl.keylog { on | off }

tune.ssl.keylog { on | off }

Включает запись ключей TLS в журнал. Использовать следует осторожно: расходуется больше памяти на сеанс SSL и может снижаться производительность. По умолчанию отключено.

Эти функции извлечения образцов следует использовать для создания SSLKEYLOGFILE, необходимого для расшифровки трафика в wireshark.

https://tlswg.org/sslkeylogfile/draft-ietf-tls-keylogfile.html

SSLKEYLOG представляет собой последовательность строк следующего формата:

<Label> <space> <ClientRandom> <space> <Secret>

Значение ClientRandom предоставляет функция извлечения образца %[ssl_fc_client_random,hex]; секрет и метку Label можно найти в таблице ниже. Нужно создать SSLKEYLOGFILE со всеми метками из этой таблицы.

Следующие функции извлечения образцов возвращают шестнадцатеричные строки, которым не требуется преобразование.

  Метка SSLKEYLOGFILE             |  Извлечение образцов секретов
  --------------------------------|-----------------------------------------
  CLIENT_EARLY_TRAFFIC_SECRET     |  %[ssl_xx_client_early_traffic_secret]
  CLIENT_HANDSHAKE_TRAFFIC_SECRET |  %[ssl_xx_client_handshake_traffic_secret]
  SERVER_HANDSHAKE_TRAFFIC_SECRET |  %[ssl_xx_server_handshake_traffic_secret]
  CLIENT_TRAFFIC_SECRET_0         |  %[ssl_xx_client_traffic_secret_0]
  SERVER_TRAFFIC_SECRET_0         |  %[ssl_xx_server_traffic_secret_0]
  EXPORTER_SECRET                 |  %[ssl_xx_exporter_secret]
  EARLY_EXPORTER_SECRET           |  %[ssl_xx_early_exporter_secret]

Эти функции извлечения существуют для стороны фронтенда (fc) или бэкенда (bc); для нужной стороны следует заменить “xx” на “fc” или “bc”.

Доступно только с OpenSSL 1.1.1 и полезно для сеанса TLS1.3.

Для создания содержимого SSLKEYLOGFILE с TLS < 1.3 нужна только эта строка:

“CLIENT_RANDOM %[ssl_fc_client_random,hex] %[ssl_fc_session_key,hex]”

Полный журнал ключей можно создать следующим log-format, хотя для syslog это неидеально:

log-format "CLIENT_EARLY_TRAFFIC_SECRET %[ssl_bc_client_random,hex] %[ssl_bc_client_early_traffic_secret]\n
            CLIENT_HANDSHAKE_TRAFFIC_SECRET %[ssl_bc_client_random,hex] %[ssl_bc_client_handshake_traffic_secret]\n
            SERVER_HANDSHAKE_TRAFFIC_SECRET %[ssl_bc_client_random,hex] %[ssl_bc_server_handshake_traffic_secret]\n
            CLIENT_TRAFFIC_SECRET_0 %[ssl_bc_client_random,hex] %[ssl_bc_client_traffic_secret_0]\n
            SERVER_TRAFFIC_SECRET_0 %[ssl_bc_client_random,hex] %[ssl_bc_server_traffic_secret_0]\n
            EXPORTER_SECRET %[ssl_bc_client_random,hex] %[ssl_bc_exporter_secret]\n
            EARLY_EXPORTER_SECRET %[ssl_bc_client_random,hex] %[ssl_bc_early_exporter_secret]"

HAProxy также предоставляет эти форматы как предопределённые переменные окружения, которые можно напрямую использовать в директиве “log-format”:

$HAPROXY_KEYLOG_FC_LOG_FMT   ключи соединения фронтенда (со стороны клиента)
$HAPROXY_KEYLOG_BC_LOG_FMT   ключи соединения бэкенда (со стороны сервера)

tune.ssl.keyupdate-rate-limit <limit>

tune.ssl.keyupdate-rate-limit <limit>

Ограничивает принимаемое число KeyUpdate в секунду значением <limit>, после которого это считается потоком избыточных обновлений и соединение принудительно закрывается. Обработка KeyUpdate требует много CPU, и мало оснований получать их в большом числе. Значение “0” отключает ограничение интенсивности. Значение по умолчанию — 100.

tune.ssl.lifetime <timeout>

tune.ssl.lifetime <timeout>

Задаёт срок действия кэшированного сеанса SSL. Время выражается в секундах; по умолчанию — 300 (5 min). Следует понимать, что это не гарантирует сохранение сеансов на такой срок: при заполнении кэша дольше всех неиспользуемые сеансы удаляются независимо от заданного срока действия. Главная польза параметра — предотвращение слишком долгого использования сеансов.

tune.ssl.maxrecord <number>

tune.ssl.maxrecord <number>

Задаёт максимальное число байт, передаваемых SSL_write() в начале передачи данных. Значение по умолчанию 0 означает отсутствие ограничения. При SSL/TLS клиент может расшифровать данные только после получения полной записи. При больших записях ему может потребоваться загрузить до 16kB данных перед началом обработки. Ограничение может ускорить загрузку страниц в браузерах в сетях с высокой задержкой или низкой пропускной способностью. Рекомендуется подобрать оптимальные значения, помещающиеся в 1 или 2 сегмента TCP: обычно 1448 байт в Ethernet с включёнными временными метками TCP или 1460 при отключённых. Следует учитывать накладные расходы SSL/TLS. Типичные значения 1419 и 2859 показали хорошие результаты в тестах. Для выбора лучшего значения используется “strace -e trace=write”. HAProxy автоматически переключается на этот параметр после обнаружения простаивающего потока (см. выше tune.idletimer). См. также tune.ssl.hard-maxrecord.

tune.ssl.ssl-ctx-cache-size <number>

tune.ssl.ssl-ctx-cache-size <number>

Задаёт размер кэша созданных сертификатов равным <number> записей. Это кэш LRU. Динамическое создание сертификата SSL затратно, поэтому сертификаты кэшируются. Размер кэша по умолчанию — 1000 записей.

tune.streams-elasticity <number>

tune.streams-elasticity <number>

Задаёт целевой процент потоков на соединение фронтенда относительно максимального числа одновременных соединений (maxconn), когда все соединения установлены. Метрика применяется к мультиплексируемым протоколам, например HTTP/2 и QUIC, где каждое соединение может получать несколько потоков. Всегда гарантируется хотя бы один, поэтому процент должен быть не меньше 100%. При установлении соединений HAProxy динамически объявляет дополнительные потоки до заданного предела, сохраняя целевое соотношение. При установлении каждое соединение фронтенда получает хотя бы один поток; дополнительные назначаются по целевому проценту и настроенным ограничениям потоков. Это обеспечивает эффективное распределение потоков при меняющейся нагрузке: больше при низкой, меньше при высокой.

Очень динамичные сайты с множеством объектов на странице выигрывают от высоких коэффициентов, позволяющих использовать много потоков на соединение. Сайты с меньшим средним числом потоков, например WebSocket или код приложения, могут предпочесть малые коэффициенты около 120 или 150: потоков на 20–50% больше, чем соединений. Это предотвращает чрезмерное число потоков при длительной нагрузке.

Значение по умолчанию — 0: на этом уровне ограничение не применяется, действуют лишь настройки H2 и QUIC. При значении по умолчанию 100 потоков на соединение это соответствует 10000%. Это остаётся рекомендуемым вариантом для небольших развёртываний, где maxconn около тысячи. Конфигурации среднего размера, от нескольких тысяч до десятков тысяч соединений, обычно задают коэффициент от 1000 до 5000, позволяющий от 10 до 50 потоков на соединение при полной нагрузке. Крупные развёртывания, от сотен тысяч до миллионов соединений, могут использовать меньшие значения от 120 до 200, в среднем от 1.2 до 2 потоков на соединение при полной нагрузке.

В отличие от HTTP/2, QUIC способен динамически менять число одновременных потоков за время соединения. Однако управление потоком QUIC строже, чем в HTTP/2, поэтому лучше задавать достаточно большие значения, чтобы избежать дополнительной задержки соединения. Есть также ограничение для слушателей QUIC с включённым 0-RTT: начальное значение, объявляемое одноранговому узлу, игнорирует эластичность потоков и зависит только от “tune.quic.fe.stream.max-concurrent”. Но после этого начального объявления эластичность потоков продолжает действовать за время соединения.

Мониторинг общего числа активных потоков на бэкендах, включая очереди, даёт практический показатель устойчивой целевой нагрузки и помогает избежать избыточного выделения ресурсов.

tune.stick-counters <number>

tune.stick-counters <number>

Задаёт число счётчиков привязок, одновременно отслеживаемых соединением или запросом действиями “track-sc*” в правилах “tcp-request” или “http-request”. Значение по умолчанию задаётся при сборке макросом MAX_SESS_STK_CTR и равно 3. Параметр позволяет изменить его, игнорируя значение сборки, но нельзя задать больше 100. Увеличение может понадобиться при переносе сложных конфигураций в haproxy, однако следует учитывать затраты: каждая запись занимает 16 байт на соединение и 16 байт на запрос; для всех запросов эту память нужно выделять и обнулять, даже когда она не используется. Поэтому значение 10 увеличивает расход памяти на запрос на 320 байт и заставляет очищать её при каждом запросе, что заметно влияет на CPU. Если правил “track-sc” нет, значение, напротив, можно уменьшить; 0 допустим для полного отключения счётчиков привязок.

tune.takeover-other-tg-connections <value>

tune.takeover-other-tg-connections <value>

По умолчанию попыток использовать простаивающие соединения других групп потоков нет, но это можно изменить. Допустимые значения <value>: “none”, значение по умолчанию, не пытается использовать простаивающие соединения других групп; “restricted” пытается получить простаивающее соединение другого потока только при протоколах, которые не могут создавать новые соединения, например reverse http, а также при strict-maxconn; “full” всегда ищет простаивающие соединения в других группах потоков. Обратите внимание: соединения других групп могут снижать производительность, поэтому использовать их не следует без действительной необходимости. Теперь это поведение управляется tune.idle-pool.shared; это ключевое слово оставлено лишь для совместимости со старыми конфигурациями и будет объявлено устаревшим.

tune.vars.global-max-size <size>

tune.vars.global-max-size <size>
tune.vars.proc-max-size <size>
tune.vars.reqres-max-size <size>
tune.vars.sess-max-size <size>
tune.vars.txn-max-size <size>

Эти пять параметров помогают управлять максимальным объёмом памяти системы переменных. “global” ограничивает общую память всех областей действия; “proc” — память области процесса; “sess” — области сеанса; “txn” — области транзакции; “reqres” — обработки каждого запроса или ответа. Учёт памяти иерархический: более общие ограничения включают более узкие. “proc” включает “sess”, “sess” — “txn”, а “txn” — “reqres”.

Например, при ограничении “tune.vars.sess-max-size” до 100 значения “tune.vars.txn-max-size” и “tune.vars.reqres-max-size” тоже не могут превышать 100. Переменная “txn.var” со 100 байтами занимает всё доступное пространство. Обратите внимание: превышение ограничений во время работы не вызывает сообщения об ошибке, но значения могут усекаться или повреждаться. Поэтому следует точно планировать пространство для хранения всех переменных.

tune.zlib.memlevel <number>

tune.zlib.memlevel <number>

Задаёт параметр memLevel при инициализации zlib для каждого потока. Он определяет, сколько памяти следует выделить для внутреннего состояния сжатия. Значение 1 использует минимум памяти, но работает медленно и снижает степень сжатия; 9 использует максимум памяти для оптимальной скорости. Допустимы значения от 1 до 9. Значение по умолчанию — 8.

tune.zlib.windowsize <number>

tune.zlib.windowsize <number>

Задаёт размер окна, то есть буфера истории, как параметр инициализации zlib для каждого потока. Большие значения улучшают сжатие ценой потребления памяти. Допустимы значения от 8 до 15. Значение по умолчанию — 15.

3.3. Отладка

anonkey <key>

anonkey <key>

Задаёт глобальный ключ анонимизации <key>, который должен быть 32-битным числом от 0 до 4294967295. Он используется по умолчанию командами CLI при включённом режиме анонимизации. Его можно также задать во время работы командой CLI “set anon global-key”. См. также аргумент командной строки “-dC” в руководстве по управлению.

debug.counters { on | off }

debug.counters { on | off }

Включает (‘on’) или отключает (‘off’) обновление счётчиков событий в коде. Они выводятся под типом “CNT” командой CLI “debug counters”. Счётчики доступны только при сборке с DEBUG_COUNTERS не меньше 1. При значении 1 они по умолчанию не обновляются (“debug.counters off”), а при 2 обновляются (“debug.counters on”). Обычно менять параметр нет причин, если только этого не просит разработчик или не подозревается необычно большое использование CPU; в последнем случае необходимо отправить разработчикам сообщение с дампом счётчиков. Состояние можно также изменить во время работы командой CLI “debug counters”. См. руководство по управлению.

force-cfg-parser-pause <timeout>

force-cfg-parser-pause <timeout>

Приостанавливает разбор конфигурации на <timeout> миллисекунд. Полезно для разработки или проверки тайм-аутов сценариев инициализации, особенно для имитации очень долгой перезагрузки. Требует заданного expose-experimental-directives.

<timeout> — значение тайм-аута, по умолчанию в миллисекундах. Можно использовать любую другую единицу, добавив её суффиксом к числу, как объясняется в начале документа.

Пример:

global
    expose-experimental-directives
    force-cfg-parser-pause 10s

quick-exit

quick-exit

Ускоряет выход старого процесса при перезагрузке, пропуская освобождение объектов памяти и слушателей: ОС сама возвращает их при завершении процесса. Выигрыш невелик — максимум порядка нескольких сотен миллисекунд для огромных конфигураций. Основной случай использования — обнаруженная ошибка кода deinit(), которую таким образом можно обойти. Лучше не использовать параметр без указания разработчиков.

quiet

quiet

Не выводит никаких сообщений при запуске. Эквивалентно аргументу командной строки “-q”.

warn-blocked-traffic-after <time>

warn-blocked-traffic-after <time>

Позволяет задать задержку, после которой зависшая задача, блокирующая трафик, вызывает предупреждение в стандартном потоке ошибок. Задержка выражается в миллисекундах; по умолчанию — 100 ms. Допустимые значения должны находиться в пределах от 1 ms до 1000 ms включительно. Малые значения вызывают частые предупреждения, большие — редкие. В любом случае сторожевой таймер завершает вышедшую из-под контроля задачу, которая дважды по одной секунде не отвечает, поэтому задержка предупреждения 1000 ms обычно не вызывает предупреждений. Рекомендуется оставаться в пределах от 10 до 100ms для обнаружения ошибок конфигурации, ухудшающих работу пользователя долгими ответами или рывками интерактивных сеансов. Например, это может вызывать неудачно спроектированная функция извлечения образца Lua с тяжёлыми вычислениями либо очень большой файл таблицы соответствий map_reg или map_regm с высокой стоимостью вычисления. Для сравнения: рукопожатие TLS может занимать от одной до двух миллисекунд, а сжатие буфера ответа HTTP размером 16kB — около одной миллисекунды. Вывод содержит дамп потока проблемной задачи с трассировкой стека и контекстом, помогающим понять, на что расходуется время.

zero-warning

zero-warning

При заданном параметре HAProxy отказывается запускаться, если при разборе и применении конфигурации выдано хотя бы одно предупреждение. Предупреждения о неверных сочетаниях параметров, слишком высоких ограничениях, которые не удалось установить, и тому подобном завершают процесс с ошибкой при запуске. Некоторые поздние предупреждения запуска перехватить нельзя, например невозможность удалить дополнительные группы при смене идентификатора группы в режимах “daemon” или “master-worker” либо невозможность разрешить создание дампа процесса после fork(). Параметр не перехватывает предупреждения во время работы. Настоятельно рекомендуется включать его для редко изменяемых конфигураций: это помогает обнаруживать неочевидные ошибки и сохранять конфигурацию чистой и совместимой с будущими версиями. Обратите внимание: “haproxy -c” в таком случае тоже сообщает об ошибках. Параметр эквивалентен аргументу командной строки “-dW”.

3.4. Настройка HTTPClient

HTTPClient — внутренняя библиотека HTTP, доступная различным подсистемам, например сценариям LUA. Она не используется в тракте данных и не связана с трафиком HTTP, проходящим через HAProxy.

httpclient.resolvers.disabled <on|off>

httpclient.resolvers.disabled <on|off>

Отключает разрешение DNS httpclient. Предотвращает создание секции resolvers “default”.

Значение по умолчанию — off.

httpclient.resolvers.id <resolvers id>

httpclient.resolvers.id <resolvers id>

Определяет секцию resolvers, с которой httpclient пытается разрешать имена.

По умолчанию используется идентификатор resolvers “default”. Если параметр не задан, при отсутствии секции разрешение имён просто отключается.

Однако при явном включении этого параметра неудачная загрузка вызывает ошибку конфигурации.

httpclient.resolvers.prefer <ipv4|ipv6>

httpclient.resolvers.prefer <ipv4|ipv6>

Позволяет выбрать семейство IP при разрешении имён, что удобно, если в сети нет IPv6. По умолчанию — “ipv6”.

httpclient.retries <number>

httpclient.retries <number>

Позволяет настроить число повторных попыток httpclient при неудачном запросе. Работает так же, как ключевое слово “retries” в бэкенде.

Значение по умолчанию — 3.

httpclient.ssl.ca-file <cafile>

httpclient.ssl.ca-file <cafile>

Определяет ca-file, который следует использовать для проверки сертификата сервера. Принимает те же параметры, что “ca-file” в строке server.

По умолчанию, если параметр не задан, используется “@system-ca”, пытающийся загрузить системные CA. При неудаче SSL для httpclient отключается.

Однако при явном включении этого параметра неудача вызывает ошибку конфигурации.

httpclient.ssl.verify [none|required]

httpclient.ssl.verify [none|required]

Работает так же, как параметр verify строк server. При ’none’ сертификаты серверов не проверяются. По умолчанию — “required”.

По умолчанию, если параметр не задан, используется “required”. При неудаче SSL для httpclient отключается.

Однако при явном включении этого параметра неудача вызывает ошибку конфигурации.

httpclient.timeout.connect <timeout>

httpclient.timeout.connect <timeout>

Задаёт максимальное время ожидания попытки соединения по умолчанию для httpclient.

Аргументы:

<timeout> — значение тайм-аута, по умолчанию в миллисекундах. Можно использовать
            и другую единицу измерения, добавив её к числу в качестве суффикса,
            как объясняется в начале этого документа.

Значение по умолчанию — 5000ms.

13 - 4. Прокси

Настройки по умолчанию, фронтенды, бэкенды, слушатели, справочники ключевых слов прокси и действий

Конфигурация прокси может размещаться в нескольких типах секций:

  • defaults [<name>] [ from <defaults_name> ]
  • frontend <name> [ from <defaults_name> ]
  • backend <name> [ from <defaults_name> ]
  • listen <name> [ from <defaults_name> ]

Секция “frontend” описывает набор слушающих сокетов, принимающих клиентские соединения.

Секция “backend” описывает набор серверов, к которым прокси подключается для пересылки входящих соединений.

Секция “listen” определяет полноценный прокси, у которого фронтенд и бэкенд объединены в одной секции. Обычно она удобна для трафика, использующего только TCP.

Секция “defaults” сбрасывает все настройки до документированных значений и задаёт новые значения для последующих секций. Все секции “frontend”, “backend” и “listen” всегда получают начальные настройки из секции defaults; по умолчанию это последняя такая секция перед вновь создаваемой секцией. Можно явно указать конкретную секцию “defaults”, из которой нужно загрузить начальные настройки: для этого в строке секции после необязательного ключевого слова “from” указывают её имя. Хотя имя секции “defaults” не обязательно, рекомендуется задавать его для удобства чтения. Кроме того, это единственный способ выбрать конкретную секцию вместо предыдущей, используемой по умолчанию. Поскольку имена секций “defaults” необязательны, по умолчанию к ним применяются очень мягкие требования и даже допускаются совпадающие имена. Однако если на секцию “defaults” ссылается любая другая секция, её имя должно соответствовать синтаксису имён прокси и быть уникальным среди секций defaults. Независимо от того, что допускается сейчас, в целом рекомендуется избегать повторяющихся имён секций и соблюдать тот же синтаксис, что и для имён прокси. В будущей версии это правило может стать обязательным. Кроме того, выдаётся предупреждение, если один прокси явно использует секцию defaults, а другой одновременно использует её неявно, поскольку она определена последней. Настоятельно рекомендуется не смешивать эти способы: либо всегда использовать явные ссылки, либо добавить в конце общую секцию defaults, предназначенную для всех неявных обращений.

Секция defaults может даже получать начальные настройки из другой такой секции, наследуя настройки через несколько уровней секций defaults. Это удобно для создания профилей конфигурации с группами настроек по умолчанию (например, для TCP и HTTP либо с короткими и длинными тайм-аутами), однако в такой иерархии легко запутаться.

По умолчанию именованные секции defaults сохраняются после разбора конфигурации. Это позволяет повторно использовать их при динамическом создании бэкендов. Такое поведение можно изменить глобально с помощью ключевого слова “tune.defaults.purge”.

Все имена прокси должны состоять из прописных и строчных букв, цифр, символов ‘-’ (дефис), ‘_’ (подчёркивание), ‘.’ (точка) и ‘:’ (двоеточие). Имена ACL чувствительны к регистру, поэтому “www” и “WWW” — два разных прокси.

Раньше имена прокси могли совпадать при выполнении определённых условий (например, если наборы их возможностей фронтенда/бэкенда различались), однако это вызывало слишком много проблем в журналах, а также путаницу при операциях через CLI, именовании таблиц привязок и получении статистики. Теперь два прокси обязательно должны иметь разные имена независимо от их возможностей.

В настоящее время поддерживаются два основных режима прокси: “tcp”, также известный как режим уровня 4, и “http”, также известный как режим уровня 7. В режиме уровня 4 HAProxy просто пересылает двунаправленный трафик между двумя сторонами. В режиме уровня 7 HAProxy анализирует протокол и может взаимодействовать с ним: разрешать, блокировать, переключать, добавлять, изменять или удалять произвольное содержимое запросов и ответов на основе произвольных критериев.

В режиме HTTP обработка запросов и ответов, проходящих через соединение, зависит от сочетания параметров HTTP фронтенда и бэкенда. HAProxy поддерживает 3 режима соединений:

  • KAL: постоянное соединение (“option http-keep-alive”), режим по умолчанию: все запросы и ответы обрабатываются, а между ответами и новыми запросами соединения остаются открытыми, но неактивными.

  • SCL: закрытие соединения с сервером (“option http-server-close”): соединение со стороны сервера закрывается после получения конца ответа, а соединение со стороны клиента остаётся открытым.

  • CLO: закрытие (“option httpclose”): соединение закрывается после окончания ответа, а в обоих направлениях добавляется “Connection: close”.

Итоговый режим соединения, проходящего через фронтенд и бэкенд, определяется режимами обоих прокси по следующей матрице. Режимы симметричны: постоянное соединение имеет самый низкий приоритет, а закрытие — самый высокий.

               Режим бэкенда
                | KAL | SCL | CLO
            ----+-----+-----+----
            KAL | KAL | SCL | CLO
            ----+-----+-----+----
   режим    SCL | SCL | SCL | CLO
            ----+-----+-----+----
            CLO | CLO | CLO | CLO

Можно последовательно соединить фронтенд TCP с бэкендом HTTP. Если обрабатывается только трафик HTTP, это не имеет смысла. Однако такой подход позволяет обрабатывать несколько протоколов в одном фронтенде. В этом случае клиентское соединение сначала обрабатывается как обычное соединение tcp, а затем переводится в режим HTTP. До этого перехода обработка содержимого выполняется над необработанными данными. После перехода данные разбираются и хранятся во внутреннем представлении HTX, поэтому использовать их исходное представление больше невозможно. Обратный переход не предусмотрен.

Существует два типа переходов к HTTP: с сохранением прикладного потока и с его уничтожением. Первый тип — переход от TCP к HTTP/1. В HTTP/1 запросы обрабатываются последовательно, поэтому прикладной поток можно сохранить. Второй тип — переход от TCP к HTTP/2. Поскольку этот протокол использует мультиплексирование, прикладной поток нельзя связать с каким-либо потоком HTTP/2, и он уничтожается. Затем, когда HAProxy получает новые потоки HTTP/2 на нижнем уровне, в мультиплексоре H2, создаются новые прикладные потоки. Это различие необходимо понимать, поскольку оно существенно меняет способ обработки данных. При переходе к HTTP/1 результаты обработки содержимого, уже выполненной над необработанными данными, не теряются, а сама обработка не выполняется повторно. При переходе к HTTP/2 прикладные потоки различаются, и все правила фронтенда последовательно проверяются для каждого из них. Как уже было сказано, первый поток, то есть поток TCP, уничтожается, но только после проверки правил фронтенда.

При обработке HTTP из прокси TCP необходимо учитывать ещё один важный момент. HAProxy может разбирать HTTP/1 на лету в правилах tcp-request content, однако для HTTP/2 это невозможно: разобрать можно только преамбулу HTTP/2. Это серьёзно ограничивает анализ содержимого HTTP в TCP. По сути, можно лишь определить, являются ли полученные данные HTTP. Например, выбрать бэкенд по значению заголовка Host нельзя, хотя в HTTP/1 это делается легко. Однако существует способ смягчить это ограничение.

Перейти к HTTP можно двумя способами. Первый, используемый исторически, — выбрать бэкенд HTTP. Переход происходит при назначении бэкенда. Поэтому при переходе с сохранением потока для обработки данных HTTP учитывается только конфигурация бэкенда. При переходе с уничтожением потока прикладной поток уничтожается и его обработка прекращается. Как отмечено выше, при этом способе возможности выбора бэкенда для соединения HTTP/2 весьма ограничены и почти бесполезны, поскольку поток уничтожается. Второй способ — выполнить переход во время проверки правил tcp-request content с помощью действия “switch-mode http”. В этом случае переход выполняется в контексте фронтенда, в котором можно определить директивы HTTP. При переходе с сохранением потока это позволяет как можно раньше использовать все возможности анализа HTTP. Такой вариант мало отличается от фронтенда HTTP. При переходе с уничтожением потока это ничего не меняет, за исключением того, что выбирать бэкенд по ограниченным данным бессмысленно. Рекомендуется именно этот способ. Таким образом, для перехода к HTTP достаточно проверить протокол запроса в правилах tcp-request content. Остальную обработку HTTP можно перенести в набор правил http-request фронтенда. Однако правила tcp-request content по-прежнему проверяются для каждого потока; изменить это нельзя.

4.1. Матрица ключевых слов прокси

Поддерживается приведённый ниже список ключевых слов. Большинство из них можно использовать только в ограниченном наборе типов секций. Некоторые помечены как «устаревшие», поскольку они унаследованы от старого синтаксиса, который может быть неоднозначным или иметь функциональные ограничения, и для их замены рекомендуются новые ключевые слова. Действие ключевых слов с пометкой “(*)” при необходимости можно инвертировать с помощью префикса “no”, например “no option contstats”. Это имеет смысл, когда параметр включён по умолчанию, но его необходимо отключить для конкретного экземпляра. Перед такими параметрами также можно поставить “default”, чтобы восстановить настройки по умолчанию независимо от того, что было задано в предыдущей секции “defaults”. Ключевые слова, разрешённые в секциях defaults и отмеченные “(!)”, поддерживаются только в именованных секциях defaults, но не в анонимных.

Примечание: некоторые опасные и не рекомендуемые директивы намеренно не включены в следующую матрицу. Это сделано специально. Эти директивы описаны в документации, однако отсутствие их в таблице — ещё один способ предостеречь от их использования.

 ключевое слово                       defaults   frontend   listen    backend
------------------------------------+----------+----------+---------+---------
acl                                       X (!)      X         X         X
backlog                                   X          X         X         -
balance                                   X          -         X         X
be-unpublished                            -          -         X         X
bind                                      -          X         X         -
capture cookie                            -          X         X         -
capture request header                    -          X         X         -
capture response header                   -          X         X         -
clitcpka-cnt                              X          X         X         -
clitcpka-idle                             X          X         X         -
clitcpka-intvl                            X          X         X         -
compression                               X          X         X         X
cookie                                    X          -         X         X
crt                                       -          X         X         -
declare capture                           -          X         X         -
default-server                            X          -         X         X
default_backend                           X          X         X         -
description                               -          X         X         X
disabled                                  X          X         X         X
dispatch                    (устарело)    -          -         X         X
email-alert from                          X          X         X         X
email-alert level                         X          X         X         X
email-alert mailers                       X          X         X         X
email-alert myhostname                    X          X         X         X
email-alert to                            X          X         X         X
enabled                                   X          X         X         X
errorfile                                 X          X         X         X
errorfiles                                X          X         X         X
errorloc                                  X          X         X         X
errorloc302                               X          X         X         X
-- keyword -------------------------- defaults - frontend - listen -- backend -
errorloc303                               X          X         X         X
error-log-format                          X          X         X         -
external-check command                    X          -         X         X
external-check path                       X          -         X         X
force-persist                             -          -         X         X
force-be-switch                           -          X         X         -
filter                                    -          X         X         X
fullconn                                  X          -         X         X
guid                                      -          X         X         X
hash-balance-factor                       X          -         X         X
hash-preserve-affinity                    X          -         X         X
hash-type                                 X          -         X         X
http-after-response                       X (!)      X         X         X
http-check comment                        X          -         X         X
http-check connect                        X          -         X         X
http-check disable-on-404                 X          -         X         X
http-check expect                         X          -         X         X
http-check send                           X          -         X         X
http-check send-state                     X          -         X         X
http-check set-var                        X          -         X         X
http-check unset-var                      X          -         X         X
http-error                                X          X         X         X
http-request                              X (!)      X         X         X
http-response                             X (!)      X         X         X
http-reuse                                X          -         X         X
http-send-name-header                     X          -         X         X
id                                        -          X         X         X
ignore-persist                            -          -         X         X
load-server-state-from-file               X          -         X         X
log                                  (*)  X          X         X         X
log-format                                X          X         X         -
log-format-sd                             X          X         X         -
log-tag                                   X          X         X         X
log-steps                                 X          X         X         -
max-keep-alive-queue                      X          -         X         X
max-session-srv-conns                     X          X         X         -
maxconn                                   X          X         X         -
mode                                      X          X         X         X
monitor fail                              -          X         X         -
monitor-uri                               X          X         X         -
option abortonclose                  (*)  X          X         X         X
option allbackups                    (*)  X          -         X         X
option checkcache                    (*)  X          -         X         X
option clitcpka                      (*)  X          X         X         -
option contstats                     (*)  X          X         X         -
option disable-h2-upgrade            (*)  X          X         X         -
option dontlog-normal                (*)  X          X         X         -
option dontlognull                   (*)  X          X         X         -
-- keyword -------------------------- defaults - frontend - listen -- backend -
option external-check                     X          -         X         X
option forwardfor                         X          X         X         X
option forwarded                     (*)  X          -         X         X
option h1-case-adjust-bogus-client   (*)  X          X         X         -
option h1-case-adjust-bogus-server   (*)  X          -         X         X
option http-buffer-request           (*)  X          X         X         X
option http-drop-request-trailers    (*)  X          -         -         X
option http-drop-response-trailers   (*)  X          -         X         -
option http-ignore-probes            (*)  X          X         X         -
option http-keep-alive               (*)  X          X         X         X
option http-no-delay                 (*)  X          X         X         X
option http-pretend-keepalive        (*)  X          -         X         X
option http-restrict-req-hdr-names        X          X         X         X
option http-server-close             (*)  X          X         X         X
option http-use-proxy-header         (*)  X          X         X         -
option httpchk                            X          -         X         X
option httpclose                     (*)  X          X         X         X
option httplog                            X          X         X         -
option httpslog                           X          X         X         -
option idle-close-on-response        (*)  X          X         X         -
option independent-streams           (*)  X          X         X         X
option ldap-check                         X          -         X         X
option log-health-checks             (*)  X          -         X         X
option log-separate-errors           (*)  X          X         X         -
option logasap                       (*)  X          X         X         -
option mysql-check                        X          -         X         X
option nolinger                      (*)  X          X         X         X
option originalto                         X          X         X         X
option persist                       (*)  X          -         X         X
option pgsql-check                        X          -         X         X
option prefer-last-server            (*)  X          -         X         X
option redispatch                    (*)  X          -         X         X
option redis-check                        X          -         X         X
option smtpchk                            X          -         X         X
option socket-stats                  (*)  X          X         X         -
option splice-auto                   (*)  X          X         X         X
option splice-request                (*)  X          X         X         X
option splice-response               (*)  X          X         X         X
option spop-check                         X          -         X         X
option srvtcpka                      (*)  X          -         X         X
option ssl-hello-chk                      X          -         X         X
-- keyword -------------------------- defaults - frontend - listen -- backend -
option tcp-check                          X          -         X         X
option tcp-smart-accept              (*)  X          X         X         -
option tcp-smart-connect             (*)  X          -         X         X
option tcpka                              X          X         X         X
option tcplog                             X          X         X         -
option transparent      (устарело)   (*)  X          -         X         X
option use-small-buffers             (*)  X          -         X         X
persist rdp-cookie                        X          -         X         X
quic-initial                              X (!)      X         X         -
rate-limit sessions                       X          X         X         -
redirect                                  -          X         X         X
-- keyword -------------------------- defaults - frontend - listen -- backend -
retries                                   X          -         X         X
retry-on                                  X          -         X         X
server                                    -          -         X         X
server-state-file-name                    X          -         X         X
server-template                           -          -         X         X
source                                    X          -         X         X
srvtcpka-cnt                              X          -         X         X
srvtcpka-idle                             X          -         X         X
srvtcpka-intvl                            X          -         X         X
stats admin                               -          X         X         X
stats auth                                X          X         X         X
stats enable                              X          X         X         X
stats hide-version                        X          X         X         X
stats http-request                        -          X         X         X
stats realm                               X          X         X         X
stats refresh                             X          X         X         X
stats scope                               X          X         X         X
stats show-desc                           X          X         X         X
stats show-legends                        X          X         X         X
stats show-node                           X          X         X         X
stats show-version                        X          X         X         X
stats uri                                 X          X         X         X
-- keyword -------------------------- defaults - frontend - listen -- backend -
stick match                               -          -         X         X
stick on                                  -          -         X         X
stick store-request                       -          -         X         X
stick store-response                      -          -         X         X
stick-table                               -          X         X         X
tcp-check comment                         X          -         X         X
tcp-check connect                         X          -         X         X
tcp-check expect                          X          -         X         X
tcp-check send                            X          -         X         X
tcp-check send-lf                         X          -         X         X
tcp-check send-binary                     X          -         X         X
tcp-check send-binary-lf                  X          -         X         X
tcp-check set-var                         X          -         X         X
tcp-check unset-var                       X          -         X         X
tcp-request connection                    X (!)      X         X         -
tcp-request content                       X (!)      X         X         X
tcp-request inspect-delay                 X (!)      X         X         X
tcp-request session                       X (!)      X         X         -
tcp-response content                      X (!)      -         X         X
tcp-response inspect-delay                X (!)      -         X         X
timeout check                             X          -         X         X
timeout client                            X          X         X         -
timeout client-fin                        X          X         X         -
timeout client-hs                         X          X         X         -
timeout connect                           X          -         X         X
timeout http-keep-alive                   X          X         X         X
timeout http-request                      X          X         X         X
timeout queue                             X          -         X         X
timeout server                            X          -         X         X
timeout server-fin                        X          -         X         X
timeout tarpit                            X          X         X         X
timeout tunnel                            X          -         X         X
transparent                 (устарело)    X          -         X         X
unique-id-format                          X          X         X         X
unique-id-header                          X          X         X         -
use_backend                               -          X         X         -
use-fcgi-app                              -          -         X         X
use-server                                -          -         X         X
------------------------------------+----------+----------+---------+---------
 ключевое слово                       defaults   frontend   listen    backend

4.2. Алфавитный справочник ключевых слов

В этом разделе описаны все ключевые слова и их использование.

acl <aclname> <criterion> [flags] [operator] <value> ...

acl <aclname> <criterion> [flags] [operator] <value> ...

Объявить или дополнить список контроля доступа.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да(!) | да | да | да

Эта директива доступна только в именованных секциях defaults, а не в анонимных. Списки контроля доступа, определённые в секции defaults, недоступны из других секций, использующих её.

Пример:

acl invalid_src  src          0.0.0.0/7 224.0.0.0/3
acl invalid_src  src_port     0:1023
acl local_dst    hdr(host) -i localhost

Об использовании ACL см. раздел 7 .

backlog <conns>

backlog <conns>

Сообщить системе ориентировочный желаемый размер очереди входящих соединений

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы:

<conns>   — количество ожидающих соединений. В зависимости от операционной системы это может
          быть количество уже подтверждённых соединений, неподтверждённых соединений или
          соединений обоих типов.

Этот параметр имеет смысл только для потоковых слушателей, включая QUIC. Однако для экземпляров QUIC его поведение отличается.

Для всех слушателей, кроме QUIC, один из способов защиты от атак SYN flood — увеличить размер системной очереди SYN. В одних системах её размер настраивается системным параметром, в других вообще не поддаётся настройке, а в третьих система учитывает подсказки приложения, передаваемые при системном вызове listen(). По умолчанию HAProxy передаёт в listen() значение maxconn фронтенда. На системах, способных использовать это значение, иногда полезно задавать другое значение; для этого и предназначен параметр backlog.

В Linux 2.4 система игнорирует этот параметр. В Linux 2.6 он используется как подсказка: система принимает количество соединений не больше ближайшей большей степени двойки и в любом случае не превышает определённые ограничения (обычно 32768).

Для слушателей QUIC backlog задаёт общий предел как для максимального числа активных согласований соединений, так и для числа соединений, ожидающих принятия. Длительность согласования в основном зависит от сетевой задержки до удалённого узла, а второй этап зависит только от нагрузки на haproxy. Когда достигается любой из этих пределов, haproxy начинает отбрасывать входящие пакеты INITIAL, предотвращая выделение ресурсов под новые соединения до тех пор, пока избыток соединений не начнёт уменьшаться. Это может привести к незаметному для пользователя переходу браузеров на более раннюю версию HTTP и к использованию TCP.

См. также: “maxconn” и руководство по настройке целевой операционной системы.

balance <algorithm> [ <arguments> ]

balance <algorithm> [ <arguments> ]
balance url_param <param> [check_post]

Определить алгоритм балансировки нагрузки для бэкенда.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<algorithm> — алгоритм выбора сервера при балансировке нагрузки. Он применяется только при
            отсутствии информации о привязке сеанса или при повторном распределении соединения
            на другой сервер. <algorithm> может принимать одно из следующих значений:

  roundrobin  Серверы используются по очереди с учётом их весов. Этот алгоритм обеспечивает
              наиболее плавное и справедливое распределение, когда время обработки на серверах
              распределено равномерно. Алгоритм динамический: веса серверов можно изменять на
              лету, например для плавного запуска. По устройству алгоритма один бэкенд может
              содержать не более 4095 активных серверов. В некоторых крупных пулах серверов
              после очень кратковременной недоступности сервера иногда требуется несколько сотен
              запросов, прежде чем он снова будет включён в пул и начнёт получать трафик. Такое
              поведение нормально, хотя встречается крайне редко. Оно описано здесь, чтобы при
              его обнаружении не возникало беспокойства. Примечание: для бэкендов в режиме
              LOG веса игнорируются.

  static-rr   Серверы используются по очереди с учётом их весов. Алгоритм похож на roundrobin, но
              является статическим: изменение веса сервера на лету не оказывает эффекта. При
              этом в устройстве алгоритма нет ограничения на число серверов, а ставший доступным
              сервер всегда сразу возвращается в пул после полного пересчёта карты. Кроме того,
              алгоритм потребляет немного меньше ресурсов CPU (примерно -1%). Этот
              алгоритм нельзя использовать в режиме LOG.

  leastconn   Соединение получает сервер с наименьшим числом соединений. Внутри групп серверов с
              одинаковой нагрузкой применяется циклическое распределение, чтобы использовались
              все серверы. Этот алгоритм рекомендуется для очень длительных сеансов, например
              LDAP, SQL, TSE и т. д., но плохо подходит для протоколов с короткими
              сеансами, таких как HTTP. Алгоритм динамический: веса серверов можно изменять
              на лету, например для плавного запуска. Для уменьшения очередей он учитывает не
              только установленные соединения, но и соединения в очереди. Этот алгоритм нельзя
              использовать в режиме LOG.

  first       Соединение получает первый сервер, у которого есть свободный слот для соединения.
              Серверы выбираются в порядке возрастания числового идентификатора (см. параметр
              сервера "id"), который по умолчанию соответствует позиции сервера в пуле. Как
              только сервер достигает своего значения maxconn, используется следующий сервер.
              Применять этот алгоритм без задания maxconn не имеет смысла. Его цель — всегда
              задействовать минимальное число серверов, чтобы в часы низкой нагрузки лишние
              серверы можно было выключить. Алгоритм игнорирует вес сервера и приносит больше
              пользы для длительных сеансов, например RDP или IMAP, чем для HTTP, хотя
              может быть полезен и там. Для эффективного использования алгоритма рекомендуется
              регулярно проверять загрузку серверов с помощью облачного контроллера и выключать
              неиспользуемые серверы, а также регулярно проверять очередь бэкенда и включать
              дополнительные серверы при её росте. Другой вариант — сообщать серверам о нагрузке
              с помощью "http-check send-state". Этот алгоритм нельзя использовать в режиме LOG.

  hash        Принимает в качестве аргумента обычное выражение для извлечения образца. Выражение
              вычисляется для каждого запроса, а его результат хешируется согласно настройке
              hash-type. Результат хеширования делится на суммарный вес работающих серверов, чтобы
              определить сервер, который получит запрос. Этот алгоритм можно использовать вместо
              "source", "uri", "hdr()", "url_param()", "rdp-cookie", чтобы применить преобразователь,
              уточнить вычисление или, например, извлечь данные из локальных переменных. Если
              данные недоступны, применяется циклическое распределение. По умолчанию алгоритм
              статический: изменение веса сервера на лету не оказывает эффекта, но это можно
              изменить с помощью "hash-type". Алгоритм нельзя использовать для бэкендов в режиме
              LOG; вместо него следует использовать "log-hash".

  source      IP-адрес источника хешируется, затем результат делится на суммарный вес
              работающих серверов, чтобы определить сервер, который получит запрос. Это
              гарантирует, что один и тот же IP-адрес клиента всегда будет направляться на
              один и тот же сервер, пока ни один сервер не станет недоступным или не вернётся в
              работу. Если изменение числа работающих серверов меняет результат хеширования,
              многие клиенты будут направлены на другой сервер. Обычно этот алгоритм используют
              в режиме TCP, где невозможно вставить cookie. Его также можно использовать в
              Интернете для привязки сеанса по мере возможности у клиентов, которые не принимают
              сеансовые cookie. По умолчанию алгоритм статический: изменение веса сервера на
              лету не оказывает эффекта, но это можно изменить с помощью "hash-type". См. также
              параметр "hash" выше. Алгоритм нельзя использовать для бэкендов в режиме LOG.

  uri         Алгоритм хеширует либо левую часть URI (до знака вопроса), либо URI
              целиком (при наличии параметра "whole"), затем делит значение хеша на суммарный
              вес работающих серверов. Результат определяет сервер, который получит запрос. Это
              гарантирует, что один и тот же URI всегда будет направляться на один и тот же
              сервер, пока ни один сервер не вернётся в работу или не станет недоступным.
              Алгоритм используют с кеширующими и антивирусными прокси, чтобы обеспечить
              максимальную долю попаданий в кеш. Его можно использовать только в бэкенде
              HTTP. По умолчанию алгоритм статический: изменение веса сервера на лету не
              оказывает эффекта, но это можно изменить с помощью "hash-type".

              Алгоритм поддерживает два необязательных параметра "len" и "depth", после
              каждого из которых указывается положительное целое число. Они полезны, когда
              нагрузку нужно распределять по серверам только по началу URI. Параметр "len"
              задаёт число начальных символов URI, которые алгоритм должен учитывать при
              вычислении хеша. Значение "len", равное 1, редко имеет смысл, поскольку
              большинство URI начинаются с "/".

              Параметр "depth" указывает максимальную глубину каталога, используемую для
              вычисления хэша. Один уровень учитывается за каждый слэш в запросе. Если оба
              параметра указаны, вычисление прекращается при достижении любого из них.

              Параметр "path-only" указывает, что ключ хеширования начинается с первого символа
              '/' в пути. Это позволяет игнорировать компонент authority абсолютных URI
              и гарантировать, что URI HTTP/1 и HTTP/2 дадут одинаковый
              хеш. См. также параметр "hash" выше.

  url_param   Параметр URL, указанный в аргументе, будет искаться в строке запроса каждого
              запроса HTTP GET.

              При использовании модификатора "check_post" указанный параметр ищется в теле запроса
              HTTP POST, если он не найден в строке запроса после знака вопроса ('?')
              в URL. Анализ тела сообщения начинается только после получения объявленного
              объёма данных или заполнения буфера запроса. В маловероятном случае использования
              кодирования chunked просматривается только первый блок. Если значение параметра
              разделено границей блоков, распределение по серверам может оказаться случайным,
              если оно вообще будет выполнено. Раньше это ключевое слово поддерживало
              необязательный параметр <max_wait>, который теперь игнорируется.

              Если за найденным параметром следуют знак равенства ('=') и значение, это
              значение хешируется, затем результат делится на суммарный вес работающих серверов.
              Результат определяет сервер, который получит запрос.

              Этот механизм отслеживает идентификаторы пользователей в запросах и гарантирует,
              что один и тот же ID пользователя всегда будет направляться на один и тот же
              сервер, пока ни один сервер не вернётся в работу или не станет недоступным. Если
              значение не найдено или отсутствует сам параметр, применяется алгоритм
              циклического распределения. Алгоритм можно использовать только в бэкенде HTTP.
              По умолчанию он статический: изменение веса сервера на лету не оказывает эффекта,
              но это можно изменить с помощью "hash-type". См. также параметр "hash" выше.

  hdr(<name>) Заголовок HTTP <name> будет искаться в каждом запросе HTTP. Как и в
              эквивалентной функции ACL 'hdr()', имя заголовка в скобках не чувствительно к
              регистру. Если заголовок отсутствует или не содержит значения, вместо него
              применяется алгоритм roundrobin.

              Необязательный параметр 'use_domain_only' позволяет ограничить хеширование основной частью
              домена для некоторых заголовков, например 'Host'. Так, для значения Host "haproxy.1wt.eu"
              будет учитываться только "1wt".

              По умолчанию этот алгоритм является статическим, что означает, что изменение веса
              сервера в режиме реального времени не окажет никакого эффекта, но это поведение
              можно изменить с помощью "hash-type". См. также опцию "hash" выше.

  random
  random(<draws>)
              В качестве ключа для функции консистентного хеширования используется случайное
              число. Это означает, что веса серверов учитываются, а динамические изменения весов
              и добавление новых серверов немедленно вступают в силу. Случайная балансировка
              нагрузки полезна в крупных пулах или при частом добавлении и удалении серверов:
              она позволяет избежать резких всплесков нагрузки на отдельные серверы, которые в
              этих условиях могут возникать при roundrobin или leastconn. Директива hash-balance-factor
              позволяет ещё больше повысить равномерность распределения нагрузки, особенно если
              время ответа серверов сильно различается. Аргумент <draws>, если он указан, должен
              быть целым числом не меньше единицы и задаёт число случайных выборок перед выбором
              наименее загруженного из этих серверов. Показано, что для существенного улучшения
              равномерности алгоритма достаточно выбирать наименее загруженный из двух серверов:
              это всегда исключает выбор самого загруженного сервера в пуле и устраняет
              смещение, вызванное неравномерным распределением в списке консистентного
              хеширования. Большие значения N исключают N-1 наиболее загруженных серверов
              ценой производительности. При очень больших значениях результат приближается к
              leastconn, но вычисляется гораздо медленнее. Кроме того, в крупных пулах при очень
              низкой нагрузке (или идеальном балансе) нагрузки сравниваемых серверов часто
              оказываются одинаковыми. Если они равны у всех выбранных серверов, сравнивается
              интенсивность запросов за последнюю секунду. Это позволяет равномернее
              распределять использование серверов во времени, как при roundrobin, и сглаживает
              неравномерность консистентного хеширования. Значение по умолчанию — 2;
              обычно оно обеспечивает очень хорошее распределение и производительность. Для
              крупных пулов с низкой нагрузкой (менее нескольких запросов в секунду на сервер)
              может быть полезно увеличить его до 3 или даже 4. Этот алгоритм также
              известен как алгоритм двух случайных выборов (Power of Two Random Choices) и
              описан здесь: http://www.eecs.harvard.edu/~michaelm/postscripts/handbook2001.pdf

              Для бэкендов в режиме LOG число выборок игнорируется: выбирается один
              случайный сервер, поскольку понятие нагрузки на сервер отсутствует. Случайное
              распределение журналов полезно в крупных пулах или при частом добавлении и
              удалении серверов из пула доступных серверов. Оно позволяет избежать резких
              всплесков нагрузки на отдельные серверы, которые в этих условиях могут возникать
              при roundrobin.

  rdp-cookie
  rdp-cookie(<name>)
              В каждом входящем запросе TCP ищется и хешируется cookie RDP с именем
              <name> (или "mstshash", если имя не указано). Как и в эквивалентной функции ACL
              'req.rdp_cookie()', регистр имени не учитывается. Этот механизм полезен как режим привязки
              сеанса с ограниченными возможностями: он позволяет всегда направлять одного и того
              же пользователя (или один и тот же ID сеанса) на один и тот же сервер. Если
              cookie не найден, используется обычный алгоритм roundrobin.

              Для работы этого механизма фронтенд должен гарантировать, что cookie RDP уже
              присутствует в буфере запроса. Для этого необходимо использовать правило 'tcp-request content accept'
              совместно с ACL 'req.rdp_cookie_cnt'.

              По умолчанию этот алгоритм является статическим, что означает, что изменение веса
              сервера в режиме реального времени не окажет никакого эффекта, но это поведение
              можно изменить с помощью "hash-type". См. также опцию "hash" выше.

  log-hash    Принимает в качестве аргумента список преобразователей, разделённых запятыми. Эти
              преобразователи применяются последовательно к входному сообщению журнала,
              результат преобразования приводится к строке, затем хешируется в соответствии с
              настроенным hash-type. Полученный хеш используется для выбора сервера назначения
              среди серверов, объявленных в бэкенде журнала. Целью этого алгоритма является
              возможность извлечь ключ из конечного сообщения журнала с помощью строковых
              преобразователей, а затем благодаря хешу всегда направлять сообщения на один и тот
              же сервер. В настоящее время поддерживаются только хеши "map-based". Этот алгоритм
              доступен только для бэкендов в режиме LOG, для других режимов следует
              использовать "hash".

  sticky      Стремится максимально привязаться к одному и тому же серверу. Первый сервер в
              списке доступных серверов получает все сообщения журнала. Когда сервер переходит в
              состояние DOWN, следующий сервер в списке занимает его место. Когда ранее
              DOWN сервер снова становится UP, он добавляется в конец списка, чтобы
              привязанный сервер не менялся до тех пор, пока он не станет DOWN.

<arguments> — необязательный список аргументов, которые могут потребоваться некоторым алгоритмам. В
            настоящее время только "url_param", "uri" и "log-hash" поддерживают необязательный
            аргумент.

Алгоритм балансировки нагрузки бэкенда устанавливается в “random”, если не заданы ни другой алгоритм, ни режим, ни параметр. Для каждого бэкенда алгоритм можно задать только один раз.

При использовании схем аутентификации, требующих одного и того же соединения, например NTLM, нельзя использовать алгоритмы на основе URI: последующие запросы будут направляться на разные серверы бэкенда, что нарушит некорректные допущения, на которых основан NTLM.

Примеры TCP/HTTP:

balance roundrobin
balance url_param userid
balance url_param session_id check_post 64
balance hdr(User-Agent)
balance hdr(host)
balance hdr(Host) use_domain_only
balance hash req.cookie(clientid)
balance hash var(req.client_id)
balance hash req.hdr_ip(x-forwarded-for,-1),ipmask(24)

Примеры бэкендов LOG:

global
  log backend@mylog-rrb local0 # send all logs to mylog-rrb backend
  log backend@mylog-hash local0 # send all logs to mylog-hash backend

backend mylog-rrb
  mode log
  balance roundrobin

  server s1 udp@127.0.0.1:514 # will receive 50% of log messages
  server s2 udp@127.0.0.1:514

backend mylog-hash
  mode log

  # extract "METHOD URL PROTO" at the end of the log message,
  # and let haproxy hash it so that log messages generated from
  # similar requests get sent to the same syslog server:
  balance log-hash 'field(-2,\")'

  # server list here
  server s1 127.0.0.1:514
  #...

Примечание: при использовании расширения “check_post” с “url_param” необходимо учитывать следующие ограничения и особенности:

- Рассматриваются все запросы POST, поскольку невозможно определить,
  окажутся ли параметры в теле или сущности, которая может содержать
  двоичные данные. Поэтому может потребоваться другой способ, чтобы
  исключить из рассмотрения запросы POST, в теле которых нет параметров
  URL. (см. acl http_end)

- Значение `<max_wait>`, превышающее размер буфера запроса, не имеет
  смысла и бесполезно. Размер буфера задаётся при сборке и по умолчанию
  составляет 16 kB.

- Content-Encoding не поддерживается; поиск параметра, вероятно,
  завершится неудачей, и балансировка нагрузки вернётся к алгоритму
  циклического распределения (Round Robin).

- Expect: 100-continue не поддерживается; балансировка нагрузки
  вернётся к алгоритму циклического распределения (Round Robin).

- Transfer-Encoding (RFC7230 3.3.1) поддерживается только в первом
  фрагменте. Если полное значение параметра отсутствует в первом
  фрагменте, выбор сервера не определён (фактически он определяется
  тем, какая малая часть значения оказалась в первом фрагменте).

- Эта возможность не поддерживает формирование ответов 100, 411 или 501.

- В некоторых случаях указание "check_post" МОЖЕТ привести к попытке
  просканировать всё содержимое тела сообщения. Обычно сканирование
  прекращается при обнаружении линейных пробельных или управляющих
  символов, указывающих на конец возможного списка параметров URL.
  Вероятно, для тел сообщений типа SGML это не представляет проблемы.

См. также: “dispatch”, “cookie”, “transparent”, “hash-type”.

be-unpublished

be-unpublished

Указывает бэкенду начинать работу в неопубликованном состоянии.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend нет | нет | да | да

По сути, любые правила use_backend и default_backend из другого прокси, ссылающиеся на текущий прокси, игнорируются, и оцениваются следующие правила переключения содержимого. Это поведение можно обойти с помощью правила “force-be-switch”.

Это состояние похоже на отключённое, но имеет некоторые отличия. Во-первых, неопубликованный бэкенд по-прежнему полностью инициализируется, в том числе выполняются проверки работоспособности серверов, которые остаются активными. Наконец, бэкенд можно опубликовать командой “publish backend” через CLI. См. руководство по управлению.

См. также: “force-be-switch”

bind [<address>]:<port_range> [, ...] [param*]

bind [<address>]:<port_range> [, ...] [param*]
bind /<path> [, ...] [param*]

Определяет во фронтенде один или несколько адресов и/или портов для прослушивания.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend нет | да | да | нет

Аргументы:

<address>     — необязательный параметр: имя хоста, адрес IPv4, адрес IPv6 или '*'. Он задаёт
              адрес, который будет прослушивать фронтенд. Если параметр не задан, прослушиваются
              все адреса IPv4 системы. То же относится к '*' и специальному адресу системы
              "0.0.0.0". Эквивалент для IPv6 — '::'. Для UDP привязка к нескольким адресам
              требует специальных возможностей операционной системы (OS), чтобы в ответе
              использовались правильные сетевой интерфейс и исходный адрес. Иными словами,
              слушатели QUIC следует привязывать к нескольким адресам только при работе в
              достаточно современной системе.

              Перед адресом можно указать префикс семейства адресов, чтобы принудительно выбрать
                  семейство независимо от формата адреса. Это может быть полезно для задания
                  пути к сокету unix без слэша ('/'). Поддерживаются следующие префиксы:
                - 'ipv4@'  -> адрес всегда IPv4
                - 'ipv6@'  -> адрес всегда IPv6
                - 'udp@'   -> адрес разрешается как IPv4 или IPv6, используется протокол
                  UDP. Сейчас такие слушатели поддерживаются только в секциях log-forward.
                - 'udp4@'  -> адрес всегда IPv4, используется протокол UDP. Сейчас
                  такие слушатели поддерживаются только в секциях log-forward.
                - 'udp6@'  -> адрес всегда IPv6, используется протокол UDP. Сейчас
                  такие слушатели поддерживаются только в секциях log-forward.
                - 'unix@'  -> адрес — путь к локальному сокету unix
                - 'abns@'  -> адрес находится в абстрактном пространстве имён (только
                  Linux).
                - 'abnsz@'  -> адрес находится в абстрактном пространстве имён (только
                  Linux), но явно заканчивается нулевым символом. Это означает, что дополнение
                  до полной длины sun_path символами \0 не используется. Это полезно для
                  взаимодействия с программами, которые не реализуют применяемую в haproxy
                  стандартную логику именования abns.
                - 'fd@<n>' -> использовать файловый дескриптор <n>, унаследованный от
                  родительского процесса. Дескриптор fd должен быть привязан; он может как
                  находиться в состоянии прослушивания, так и ещё не прослушивать соединения.
                - 'sockpair@<n>'-> аналогично fd@, но необходимо использовать дескриптор fd
                  подключённого сокета unix или пары сокетов socketpair. bind ожидает получения
                  FD через сокет unix и использует его как FD, полученный от accept().
                  Следует применять с осторожностью.
                - 'quic4@' -> адрес разрешается как IPv4, используется протокол UDP. Для
                  наилучшей производительности при большом объёме трафика следует сохранить
                  настройку "tune.quic.fe.sock-per-conn default-on". В противном случае соединения QUIC будут
                  мультиплексироваться через сокет слушателя. Другой вариант — продублировать
                  экземпляры слушателя QUIC в нескольких потоках, например с помощью
                  ключевого слова "shards", чтобы хотя бы уменьшить конкуренцию между потоками.
                - 'quic6@' -> адрес разрешается как IPv6, используется протокол UDP.
                  Примечание о производительности QUIC поверх IPv4 также применимо.
                - 'rhttp@' [ ЭКСПЕРИМЕНТАЛЬНО ] -> используется для обратного HTTP. Адрес
                  должен указывать на сервер в формате '<backend>/<server>'. Этот сервер будет использоваться
                  для создания соединений с удалённым адресом. Слушатель будет пытаться
                  поддерживать "nbconn" соединений. Эта экспериментальная возможность требует
                  указать "expose-experimental-directives" в строке перед данным bind.

              В параметре адреса можно ссылаться на переменные окружения; см. раздел 2.3 о
              переменных окружения.

<port_range>  — один порт TCP или диапазон портов, на которых прокси принимает соединения для
              указанного выше адреса IP. Для слушателей TCP порт обязателен. В случае
              адреса IPv6 порт всегда задаётся числом после последнего двоеточия (':').
              Диапазон можно задать следующим образом:
               - номером порта (например, '80')
               - диапазоном портов через дефис с явно указанными нижней и верхней границами
                 (например, '2000-2100'); обе границы входят в диапазон.

              С диапазонами портов необходимо обращаться особенно осторожно: каждая пара <address:port>
              занимает один сокет (= файловый дескриптор), поэтому даже простой диапазон может
              занять много дескрипторов и привести к исчерпанию сокетов. Кроме того, каждая пара
              <address:port> должна использоваться только один раз среди всех экземпляров, работающих в
              одной системе. Для привязки к портам ниже 1024 обычно требуются особые
              привилегии при запуске программы; они не зависят от параметра 'uid'.

<path>        — путь к сокету UNIX, начинающийся со слэша ('/'). Это альтернатива порту
              прослушивания TCP. HAProxy будет принимать соединения UNIX через сокет,
              расположенный по этому пути. Путь должен начинаться со слэша и по умолчанию
              является абсолютным. Он может быть задан относительно префикса, определённого
              директивой "unix-bind" в секции global. Общая длина префикса и следующего за ним пути
              к сокету не должна превышать системных ограничений для сокетов UNIX, которые
              обычно составляют 107 символов.

<param*>      — список параметров, общих для всех сокетов, объявленных в одной строке. Эти
              многочисленные параметры зависят от операционной системы (OS) и параметров
              сборки; им посвящён отдельный раздел целиком. Подробности приведены в разделе
              5.

Можно указать разделённый запятыми список пар address:port. Фронтенд будет прослушивать все указанные адреса. Фиксированного ограничения на число адресов и портов, которые может прослушивать фронтенд, нет; число директив “bind” во фронтенде также не ограничено.

Пример:

listen http_proxy
    bind :80,:443
    bind 10.0.0.1:10080,10.0.0.1:10443
    bind /var/run/ssl-frontend.sock user root mode 600 accept-proxy

listen http_https_proxy
    bind :80
    bind :443 ssl crt /etc/haproxy/site.pem

listen http_https_proxy_explicit
    bind ipv6@:80
    bind ipv4@public_ssl:443 ssl crt /etc/haproxy/site.pem
    bind unix@ssl-frontend.sock user root mode 600 accept-proxy

listen external_bind_app1
    bind "fd@${FD_APP1}"

listen h3_quic_proxy
    bind quic4@10.0.0.1:8888 ssl crt /etc/mycrt

Примечание: для сокетов “abns” HAProxy в абстрактном пространстве имён Linux длина адреса равна полной длине sun_path. Некоторые другие программы, например socat, по умолчанию используют только длину строки. Чтобы определение абстрактного сокета в socat было совместимо с сокетами HAProxy, к нему нужно добавить параметр “,unix-tightsocklen=0”; другой вариант — использовать семейство сокетов “abnsz” HAProxy.

См. также: “source”, “option forwardfor”, “unix-bind” и документацию по протоколу PROXY, а также раздел 5 о параметрах bind.

capture cookie <name> len <length>

capture cookie <name> len <length>

Захватывает и записывает в журнал cookie из запроса и ответа.

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend нет | да | да | нет

Аргументы:

<name>    — начало имени cookie, который нужно захватить. Для точного совпадения имени
          достаточно добавить в его конец знак равенства ('='). В журнал попадёт полное имя;
          это полезно для серверов приложений, которые изменяют и имя, и значение cookie
          (например, ASPSESSIONXXX).

<length>  — максимальное число символов, записываемых в журнал, включая имя cookie, знак
          равенства и значение в стандартной форме "name=value". Если длина строки превышает <length>,
          строка обрезается справа.

Захватывается только первый cookie. Отслеживаются как заголовки запроса “cookie”, так и заголовки ответа “set-cookie”. Это особенно полезно для выявления ошибок приложений, приводящих к смешиванию или краже сеансов между пользователями, поскольку обычно cookie пользователя могут меняться только на странице входа.

Если клиент не передал cookie, в соответствующем столбце журнала указывается “-”. Если в результате запроса сервер не назначает cookie, в столбце ответа указывается “-”.

Захват выполняется только во фронтенде: формат журнала для одного фронтенда должен оставаться одинаковым независимо от бэкендов. В дальнейшем это может измениться. Во фронтенде допускается только одна директива “capture cookie”. Максимальная длина захвата задаётся глобальным параметром “tune.http.cookielen” и по умолчанию составляет 63 символа. В секции “defaults” задавать захват нельзя.

Пример:

capture cookie ASPSESSION len 32

См. также: “capture request header”, “capture response header”, а также раздел 8 о ведении журнала.

capture request header <name> len <length>

capture request header <name> len <length>

Захватывает и записывает в журнал последнее вхождение указанного заголовка запроса.

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend нет | да | да | нет

Аргументы:

<name>    — имя захватываемого заголовка. Регистр имён заголовков не учитывается, однако их
          принято писать так же, как в запросах, с заглавной первой буквой каждого слова. В
          журнал выводится только значение, без имени заголовка, но его позиция в журнале
          сохраняется.

<length>  — максимальное число символов, извлекаемых из значения и записываемых в журнал. Если
          длина строки превышает <length>, строка обрезается справа.

Захватывается полное значение последнего вхождения заголовка. Оно добавляется в журнал в фигурных скобках (’{}’). При захвате нескольких заголовков их значения разделяются вертикальной чертой (’|’) и выводятся в порядке объявления в конфигурации. Отсутствующие заголовки записываются как пустые строки. Обычно захватывают поле “Host” при виртуальном хостинге, “Content-length” при поддержке загрузки данных, “User-agent” для быстрого различения настоящих пользователей и роботов и “X-Forwarded-For” при работе через прокси, чтобы определить источник запроса.

При захвате заголовков, например “User-agent”, в журнал могут попадать пробелы, что усложняет его анализ. Поэтому следует осторожно выбирать записываемые данные, если известно, что используемый разборщик журналов не умеет определять границы по фигурным скобкам.

Число захватываемых заголовков запроса и их длина не ограничены, однако целесообразно поддерживать небольшие значения обоих параметров, чтобы ограничить расход памяти на поток. Для единого формата журнала в пределах одного фронтенда захват заголовков можно объявлять только во фронтенде. В секции “defaults” задавать захват нельзя.

Пример:

capture request header Host len 15
capture request header X-Forwarded-For len 15
capture request header Referer len 15

См. также: “capture cookie”, “capture response header”, а также раздел 8 о ведении журнала.

capture response header <name> len <length>

capture response header <name> len <length>

Захватывает и записывает в журнал последнее вхождение указанного заголовка ответа.

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend нет | да | да | нет

Аргументы:

<name>    — имя захватываемого заголовка. Регистр имён заголовков не учитывается, однако их
          принято писать так же, как в ответе, с заглавной первой буквой каждого слова. В журнал
          выводится только значение, без имени заголовка, но его позиция в журнале сохраняется.

<length>  — максимальное число символов, извлекаемых из значения и записываемых в журнал. Если
          длина строки превышает <length>, строка обрезается справа.

Захватывается полное значение последнего вхождения заголовка. Результат добавляется в журнал в фигурных скобках (’{}’) после захваченных заголовков запроса. При захвате нескольких заголовков их значения разделяются вертикальной чертой (’|’) и выводятся в порядке объявления в конфигурации. Отсутствующие заголовки записываются как пустые строки. Обычно захватывают заголовок “Content-length”, указывающий ожидаемое число байтов в ответе, и “Location” для отслеживания перенаправлений.

Число захватываемых заголовков ответа и их длина не ограничены, однако целесообразно поддерживать небольшие значения обоих параметров, чтобы ограничить расход памяти на поток. Для единого формата журнала в пределах одного фронтенда захват заголовков можно объявлять только во фронтенде. В секции “defaults” задавать захват нельзя.

Пример:

capture response header Content-length len 9
capture response header Location len 15

См. также: “capture cookie”, “capture request header”, а также раздел 8 о ведении журнала.

clitcpka-cnt <count>

clitcpka-cnt <count>

Задаёт максимальное число проверочных пакетов для поддержания соединения, которые TCP должен отправить перед закрытием соединения на стороне клиента.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы:

<count>   — максимальное число проверочных пакетов для поддержания соединения.

Это ключевое слово соответствует параметру сокета TCP_KEEPCNT. Если оно не указано, используется общесистемный параметр TCP (tcp_keepalive_probes). Доступность этой настройки зависит от операционной системы. Известно, что она работает в Linux.

См. также: “option clitcpka”, “clitcpka-idle”, “clitcpka-intvl”.

clitcpka-idle <timeout>

clitcpka-idle <timeout>

Задаёт время простоя соединения, после которого TCP начинает отправлять проверочные пакеты для поддержания соединения, если отправка пакетов TCP для поддержания соединения на стороне клиента включена.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы:

<timeout> — время простоя соединения до начала отправки проверочных пакетов TCP для
          поддержания соединения. По умолчанию задаётся в секундах, но можно использовать любую
          другую единицу, добавив её обозначение после числа, как описано в начале документа.

Это ключевое слово соответствует параметру сокета TCP_KEEPIDLE. Если оно не указано, используется общесистемный параметр TCP (tcp_keepalive_time). Доступность этой настройки зависит от операционной системы. Известно, что она работает в Linux.

См. также: “option clitcpka”, “clitcpka-cnt”, “clitcpka-intvl”.

clitcpka-intvl <timeout>

clitcpka-intvl <timeout>

Задаёт интервал между отдельными проверочными пакетами для поддержания соединения на стороне клиента.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы:

<timeout> — интервал между отдельными проверочными пакетами для поддержания соединения. По
          умолчанию задаётся в секундах, но можно использовать любую другую единицу, добавив её
          обозначение после числа, как описано в начале документа.

Это ключевое слово соответствует параметру сокета TCP_KEEPINTVL. Если оно не указано, используется общесистемный параметр TCP (tcp_keepalive_intvl). Доступность этой настройки зависит от операционной системы. Известно, что она работает в Linux.

См. также: “option clitcpka”, “clitcpka-cnt”, “clitcpka-idle”.

compression algo <algorithm> ...

compression algo <algorithm> ...
compression algo-req <algorithm>
compression algo-res <algorithm>
compression type <mime type> ...

Включает сжатие HTTP.

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

algo     — за ним следует список поддерживаемых алгоритмов сжатия ответов (устаревшее ключевое
         слово).
algo-req — за ним следует алгоритм сжатия запроса (указывается только один).
algo-res — за ним следует список поддерживаемых алгоритмов сжатия ответов.
type     — за ним следует список типов MIME, для которых сжимаются ответы (устаревшее
         ключевое слово).
type-req — за ним следует список типов MIME, для которых сжимаются запросы.
type-res — за ним следует список типов MIME, для которых сжимаются ответы.

В настоящее время поддерживаются следующие алгоритмы:

identity     — в основном предназначен для отладки; был полезен при разработке функции сжатия.
             Этот алгоритм не изменяет данные.

gzip         — применяет сжатие gzip. Этот параметр доступен только в том случае, если при
             сборке была включена поддержка zlib или libslz.

deflate      — аналогичен "gzip", но использует алгоритм deflate и формат zlib. Поддержка этого
             алгоритма во многих браузерах неоднозначна, а в новых браузерах полностью
             отсутствует. Настоятельно рекомендуется не использовать его ни для чего, кроме
             экспериментов. Этот параметр доступен только в том случае, если при сборке была
             включена поддержка zlib или libslz.

raw-deflate  аналог "deflate" без оболочки zlib, используемый как альтернатива, когда браузер
             запрашивает "deflate". Его понимают все основные браузеры; несмотря на нарушение
             стандартов, известно, что он работает лучше "deflate", по крайней мере в MSIE и
             некоторых версиях Safari. Не следует использовать его совместно с "deflate": нужно
             выбрать один из этих алгоритмов, поскольку оба соответствуют одному токену
             Accept-Encoding. Эта настройка доступна только в сборках с поддержкой zlib или
             libslz.

Сжатие включается в зависимости от заголовка запроса Accept-Encoding. При identity этот заголовок не учитывается. Если серверы бэкенда поддерживают сжатие HTTP, эти директивы не оказывают действия: HAProxy обнаруживает сжатый ответ и не сжимает его повторно. Если серверы бэкенда не поддерживают сжатие HTTP, а запрос содержит заголовок Accept-Encoding, HAProxy сжимает соответствующий ответ.

Сжатие отключается, когда: * запрос не объявляет поддерживаемый алгоритм сжатия в заголовке “Accept-Encoding” * ответ использует версию ниже HTTP/1.1 * код состояния HTTP не равен 200, 201, 202 или 203 * ответ не содержит ни заголовка “Content-Length”, ни заголовка “Transfer-Encoding” с последним значением “chunked” * ответ содержит заголовок “Content-Type”, первое значение которого начинается с “multipart” * ответ содержит значение “no-transform” в заголовке “Cache-control” * User-Agent соответствует “Mozilla/4”, кроме MSIE 6 с XP SP2 и MSIE 7 или более поздних версий * ответ содержит заголовок “Content-Encoding”, указывающий, что ответ уже сжат (см. compression offload) * ответ содержит некорректный заголовок “ETag” или несколько заголовков ETag * размер полезной нагрузки меньше минимального (см. compression minsize-res)

Примечание: механизм сжатия не добавляет заголовок Warning.

Примеры:

compression algo gzip
compression type text/html text/plain

См. также: “compression offload”, “compression direction”, “compression minsize-req” и “compression minsize-res”

compression minsize-req <size>

compression minsize-req <size>
compression minsize-res <size>

Задает минимальный размер полезной нагрузки в байтах, при котором применяется сжатие.

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Полезная нагрузка меньше этого размера не сжимается, чтобы не тратить ресурсы CPU на данные, для которых сжатие не даёт существенного выигрыша. “minsize-req” применяется к запросам, а “minsize-res” — к ответам. Значение по умолчанию — 0.

compression offload

compression offload

Задаёт для HAProxy роль узла, полностью принимающего на себя сжатие.

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend нет | да | да | да

Параметр “offload” заставляет HAProxy удалять заголовок Accept-Encoding, чтобы серверы бэкенда не сжимали ответы. Настоятельно рекомендуется этого не делать: вся работа по сжатию сосредоточится в одной точке, где находится HAProxy. Однако в некоторых схемах развёртывания HAProxy может находиться перед шлюзом с ошибочной реализацией сжатия HTTP, которую нельзя отключить. Тогда HAProxy может предотвратить отправку шлюзом некорректной полезной нагрузки. Простое удаление заголовка в конфигурации здесь не помогает: оно выполняется до разбора заголовка и лишает HAProxy возможности сжимать данные. В таких случаях следует использовать параметр “offload”.

Если этот параметр используется в секции defaults, будет выдано предупреждение и параметр будет проигнорирован.

См. также: “compression type”, “compression algo”, “compression direction”

compression direction <direction> (deprecated)

compression direction <direction> (deprecated)

Позволяет haproxy сжимать запросы и ответы. Допустимые значения: “request” — сжимать только запросы, “response” — только ответы, “both” — и запросы, и ответы. Значение по умолчанию — “response”.

Эта директива имеет значение только при включённом прежнем “filter compression”: с явными фильтрами comp-req и comp-res указание compression direction избыточно.

Можно использовать в следующих контекстах: http

См. также: “compression type”, “compression algo”, “compression offload”

cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ]

cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ]
              [ postonly ] [ preserve ] [ httponly ] [ secure ]
              [ domain <domain> ]* [ maxidle <idle> ] [ maxlife <life> ]
              [ dynamic ] [ attr <value> ]*

Включает в бэкенде привязку сеанса на основе cookie.

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<name>    — имя cookie, который отслеживается, изменяется или вставляется для привязки сеанса.
          Этот cookie отправляется клиенту в заголовке "Set-Cookie" ответа и возвращается клиентом в
          заголовке "Cookie" всех запросов. Следует особенно внимательно выбирать имя, чтобы оно
          не конфликтовало с возможными cookie приложения. Если одни и те же клиенты могут
          использовать одни и те же бэкенды (например, HTTP/HTTPS), следует задавать разные
          имена cookie для всех бэкендов, если привязка между ними не нужна.

rewrite   Это ключевое слово указывает, что cookie предоставляет сервер, а HAProxy должен
          изменить его значение, поместив туда идентификатор сервера. Режим удобен, когда
          обработка сложных сочетаний заголовков "Set-cookie" и "Cache-control" возложена на приложение.
          Тогда приложение само решает, следует ли отправлять cookie привязки. Поскольку
          необходимо отслеживать все ответы, этот режим не работает в режиме туннеля HTTP.
          Если поведение приложения не отличается чрезмерной сложностью и/или ошибками, для
          новых развёртываний рекомендуется не начинать с этого режима. Это ключевое слово
          несовместимо с "insert" и "prefix".

insert    Это ключевое слово указывает, что HAProxy должен вставлять cookie привязки в ответы
          сервера, если у клиента ещё нет

          cookie, который позволил бы ему обращаться к этому серверу. Без параметра "preserve"
          cookie с таким же именем, отправленный сервером, удаляется до обработки. Поэтому этот
          режим позволяет обновлять существующие конфигурации, работающие в режиме "rewrite".
          Cookie будет только сеансовым и не будет сохраняться на диске клиента. По умолчанию
          сервер видит cookie, отправленные клиентом, если не добавлен параметр "indirect". Из-за
          влияния кеширования обычно целесообразно добавлять ключевые слова "nocache" или "postonly"
          (см. ниже). Ключевое слово "insert" несовместимо с "rewrite" и "prefix".

prefix    Это ключевое слово указывает, что вместо отдельного cookie привязки дополняется
          существующий cookie. Это может понадобиться в средах, где клиент поддерживает лишь
          один cookie, уже необходимый приложению. Тогда при каждом задании сервером cookie с
          именем <name> к его началу добавляются идентификатор сервера и разделитель. Префикс
          удаляется из всех клиентских запросов, чтобы сервер получал тот cookie, который он
          отправил. Поскольку изменяться могут все запросы и ответы, этот режим не работает в
          режиме туннеля. Ключевое слово "prefix" несовместимо с "rewrite" и "insert". Примечание:
          настоятельно рекомендуется не сочетать "indirect" с "prefix", иначе обновления cookie
          сервера не будут передаваться клиентам.

indirect  При этом параметре cookie не отправляется клиенту, у которого уже есть действительный
          cookie для сервера, обработавшего запрос. Если сервер сам задаёт такой cookie, он
          удаляется, кроме случаев, когда также указан "preserve". В режиме "insert" cookie
          дополнительно удаляются из запросов, передаваемых серверу, поэтому механизм привязки
          полностью прозрачен для приложения. Примечание: настоятельно рекомендуется не сочетать
          "indirect" с "prefix", иначе обновления cookie сервера не будут передаваться клиентам.

nocache   Этот параметр рекомендуется сочетать с режимом insert, если между клиентом и HAProxy
          находится кеш: кешируемый ответ помечается как некешируемый, если нужно вставить
          cookie. Это важно: если cookie привязки добавляются, например, в кешируемую главную
          страницу, все клиенты будут получать её из внешнего кеша с одним и тем же cookie
          привязки, и один сервер получит значительно больше трафика, чем остальные. См. также
          параметры "insert" и "postonly".

postonly  Этот параметр обеспечивает вставку cookie только в ответы на запросы POST. Это
          альтернатива "nocache": ответы POST не кешируются, поэтому cookie привязки никогда не
          попадёт в кеш. Большинству сайтов привязка не нужна до первого POST, обычно запроса
          входа в систему, поэтому это очень эффективный способ оптимизировать кеширование без
          риска сохранить cookie привязки в кеше. См. также параметры "insert" и "nocache".

preserve  Этот параметр можно использовать только с "insert" и/или "indirect". Он позволяет серверу
          самому отправлять cookie привязки. Тогда HAProxy оставляет найденный в ответе cookie
          без изменений. Это удобно, например, для прекращения привязки после запроса выхода из
          системы: серверу достаточно отправить cookie с недопустимым значением (например,
          пустым) или датой в прошлом. Вместе с параметром проверки "disable-on-404" этот механизм
          позволяет полностью плавно завершить обслуживание: после выхода из системы
          пользователи гарантированно покинут сервер.

httponly  Этот параметр указывает HAProxy добавлять атрибут "HttpOnly" при вставке cookie, чтобы
          пользовательский агент не передавал cookie компонентам, не использующим HTTP.
          Подробнее об этом атрибуте см. RFC6265.

secure    Этот параметр указывает HAProxy добавлять атрибут "Secure" при вставке cookie, чтобы
          пользовательский агент никогда не отправлял этот cookie по незащищённым каналам.
          Cookie с этим флагом передаётся только по соединениям SSL/TLS. Подробнее об
          этом атрибуте см. RFC6265.

domain    Этот параметр задаёт домен вставляемого cookie. Он требует ровно один параметр —
          действительное имя домена. Если домен начинается с точки, браузеру разрешено
          использовать cookie для любого хоста, имя которого оканчивается этим доменом. Параметр
          можно повторять, указывая несколько доменов. В некоторых браузерах число доменов
          ограничено небольшим значением, что нужно учитывать. Например, передача 10
          доменов в MSIE 6 или Firefox 2 работает ожидаемым образом.

maxidle   Этот параметр позволяет игнорировать вставленные cookie после определённого времени
          бездействия. Он работает только с cookie режима insert. При отправке cookie клиенту
          также передаётся дата его отправки. При последующих предъявлениях cookie он
          игнорируется, если его возраст превышает заданный параметром интервал в секундах.
          Иначе при отправке ответа клиенту cookie при необходимости обновляется. Это особенно
          полезно, чтобы пользователи, никогда не закрывающие браузер, не оставались слишком
          долго на одном сервере, например после изменения размера группы серверов. Если
          параметр задан, а у cookie нет даты, он всегда принимается, но обновляется в ответе;
          это сохраняет администраторам возможность доступа к своим сайтам. Cookie с датой более
          чем на 24 часа в будущем игнорируются. Такой подход позволяет исправлять проблемы
          часового пояса, не рискуя отключить пользователей от сайта.

maxlife   Этот параметр позволяет игнорировать вставленные cookie по истечении определённого
          срока жизни независимо от их использования. Он работает только с cookie режима insert.
          При первой отправке cookie клиенту также передаётся дата его отправки. При последующих
          предъявлениях cookie он игнорируется, если его возраст превышает заданный параметром
          интервал в секундах. Cookie запроса без даты принимается, и для него задаётся дата.
          Cookie с датой более чем на 24 часа в будущем игнорируются; это позволяет
          исправлять проблемы часового пояса, не рискуя отключить пользователей от сайта. В
          отличие от maxidle, значение не обновляется: учитывается только дата первого
          посещения. maxidle и maxlife можно использовать одновременно. Это особенно полезно,
          чтобы пользователи, никогда не закрывающие браузер, не оставались слишком долго на
          одном сервере, например после изменения размера группы серверов. Этот метод действует
          строже maxidle: по истечении фиксированного интервала он принудительно
          перераспределяет запросы.

dynamic   Включает динамические cookie. Для каждого сервера динамически создаётся сеансовый
          cookie на основе IP и порта сервера и секретного ключа из директивы бэкенда
          "dynamic-cookie-key". Cookie создаётся заново при каждом изменении адреса IP и формируется
          только для IPv4/IPv6.

attr      Этот параметр указывает HAProxy добавлять дополнительный атрибут при вставке cookie.
          Значение атрибута может содержать любые символы, кроме управляющих и ";". Параметр
          можно повторять.

У каждого бэкенда HTTP может быть только один cookie привязки; его можно объявить в секции defaults. Значением cookie будет значение, указанное после ключевого слова “cookie” в директиве “server”. Если для сервера cookie не объявлен, он не задаётся.

Примеры:

cookie JSESSIONID prefix
cookie SRV insert indirect nocache
cookie SRV insert postonly indirect
cookie SRV insert indirect nocache maxidle 30m maxlife 8h

См. также: “balance source”, “capture cookie”, “server” и “ignore-persist”.

declare capture [ request | response ] len <length>

declare capture [ request | response ] len <length>

Объявляет слот захвата.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend нет | да | да | нет

Аргументы:

<length> — это максимально допустимая длина захвата.

Объявление доступно только в секциях frontend и listen, но зарезервированный слот можно использовать в бэкендах. Ключевое слово “request” выделяет слот захвата для запроса, а “response” — для ответа.

См. также: “capture-req”, “capture-res” (преобразователи образцов), “capture.req.hdr”, “capture.res.hdr” (извлечения образцов), “http-request capture” и “http-response capture”.

default-server [param*]

default-server [param*]

Изменяет параметры по умолчанию для сервера в бэкенде

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<param*>   — это список параметров для этого сервера. Ключевое слово "default-server" принимает большое
          количество опций и имеет отдельный раздел, посвящённый ему. Пожалуйста, обратитесь к
          разделу 5 для получения дополнительной информации.

Пример:

default-server inter 1000 weight 13

См. также: “server” и раздел 5 о параметрах серверов

default_backend <backend>

default_backend <backend>

Задаёт бэкенд, используемый, если не сработало ни одно правило “use_backend”.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы:

<backend> — это имя бэкенда, который будет использоваться.

При переключении содержимого между фронтендом и бэкендами с использованием ключевого слова “use_backend”, часто полезно указать, какой бэкенд будет использоваться, если ни одно правило не сработало. Обычно это динамический бэкенд, который перехватывает все неопределённые запросы.

Если бэкенд отключён или не опубликован, правила default_backend, нацеленные на него, будут проигнорированы, и обработка потока останется на исходном прокси.

Пример:

use_backend     dynamic  if  url_dyn
use_backend     static   if  url_css url_img extension_img
default_backend dynamic

См. также: “use_backend”

description <string>

description <string>

Описывает объект listen, фронтенд или бэкенд.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend нет | да | да | да

Аргументы: строка

Позволяет добавить предложение с описанием соответствующего объекта на HTML-странице статистики HAProxy. Описание выводится справа от имени объекта. Пробелы в аргументах <string> не нужно экранировать обратной косой чертой.

disabled

disabled

Отключает прокси, фронтенд или бэкенд.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы: отсутствуют

Ключевое слово “disabled” отключает экземпляр — обычно для освобождения прослушиваемого порта или временного отключения службы. Экземпляр всё равно создаётся, а его конфигурация проверяется, но он создаётся в состоянии “stopped” и так отображается в статистике. Он не принимает трафик, не отправляет проверки работоспособности и не ведёт журнал. Добавление “disabled” в секцию “defaults” позволяет отключить сразу несколько экземпляров.

По умолчанию отключённый бэкенд нельзя выбрать при переключении содержимого. Однако при использовании “force-be-switch” часть трафика может обойти это ограничение.

См. также: “enabled”, “force-be-switch”

dispatch <address>:<port> (deprecated)

dispatch <address>:<port>   (deprecated)

Задаёт адрес сервера по умолчанию

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend нет | нет | да | да

Аргументы:

<address> — адрес IPv4 сервера по умолчанию. Также можно указать имя хоста, которое удаётся
          разрешить, но оно будет разрешено при запуске.

<ports>   — обязательное указание порта. Все соединения направляются на этот порт; использовать
          смещения портов, как для обычных серверов, не допускается.

Ключевое слово “dispatch” задаёт сервер по умолчанию, используемый, когда ни один другой сервер не может принять соединение. Раньше его применяли для передачи соединений без привязки сеанса вспомогательному балансировщику нагрузки. Благодаря простому синтаксису его также использовали для простых ретрансляторов TCP. Для большей ясности рекомендуется отказаться от него и использовать директиву “server”.

Это ключевое слово объявлено устаревшим в 3.3 и будет удалено в 3.5 из-за внутренних ограничений, в том числе отсутствия поддержки SSL и простаивающих соединений. При его использовании выводится предупреждение; его можно подавить, включив директиву “expose-deprecated-directives” в секции global.

Чтобы правильно обойтись без этой директивы, достаточно объявить сервер с теми же адресом и портом. Если “dispatch” использовалась вместе с другими серверами, этим серверам следует задать нулевой вес, чтобы алгоритм балансировки нагрузки никогда их не выбирал.

Пример:

backend deprecated_setup
    dispatch 192.168.100.100:80 # external load balancer's address
    server s1 192.168.100.1:80 cookie S1 check
    server s2 192.168.100.2:80 cookie S2 check

backend modern_setup
    server external_lb 192.168.100.100:80
    server s1 192.168.100.1:80 cookie S1 check weight 0
    server s2 192.168.100.2:80 cookie S2 check weight 0

См. также: “server”

dynamic-cookie-key <string>

dynamic-cookie-key <string>

Задаёт секретный ключ динамических cookie для бэкенда.

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы: используемый секретный ключ.

При включённых динамических cookie (см. директиву “dynamic” для cookie) для каждого сервера создаётся динамический cookie, если он не задан явно в строке “server”. Для этого используется хеш адреса IP сервера, порта TCP и секретного ключа. Так обеспечивается привязка сеанса при работе нескольких балансировщиков нагрузки, даже если серверы добавляются или удаляются динамически.

enabled

enabled

Включает прокси, фронтенд или бэкенд.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы: отсутствуют

Ключевое слово “enabled” явно включает экземпляр, если в настройках по умолчанию задано “disabled”. Это используется очень редко.

См. также: “disabled”

errorfile <code> <file>

errorfile <code> <file>

Возвращает содержимое файла вместо ошибок, сформированных HAProxy

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

<code>    — код состояния HTTP. В настоящее время HAProxy может формировать коды 200,
          400, 401, 403, 404, 405, 407, 408, 410, 413,
          414, 425, 429, 431, 500, 501, 502, 503 и 504.

<file>    — файл, содержащий полный ответ HTTP. Рекомендуется следовать общепринятой
          практике и добавлять к имени файла ".http", чтобы ответ не путали со страницами ошибок
          HTML, а также использовать абсолютные пути: файлы читаются до выполнения любого
          chroot.

Эта директива предназначена для замены ошибок, обнаруженных и возвращённых HAProxy, а не ошибок, возвращённых сервером. Поэтому список поддерживаемых ошибок ограничен небольшим набором.

Код 200 возвращается в ответ на запросы, соответствующие правилу “monitor-uri”.

Файлы разбираются при запуске HAProxy и должны соответствовать спецификации HTTP. Их размер не следует делать больше настроенного размера буфера (BUFSIZE), который обычно составляет 16 kB; иначе будет возвращена внутренняя ошибка. Также целесообразно не включать ссылки на локальное содержимое, например изображения: если все серверы недоступны, вместо изображения возвращается ошибка, что может вызвать цикл между клиентом и HAProxy. Наконец, размер ответа не может превышать (tune.bufsize - tune.maxrewrite), чтобы у правил “http-after-response” оставалось место для работы (см. “tune.maxrewrite”).

Файлы читаются одновременно с конфигурацией и сохраняются в памяти. Поэтому ответы об ошибках продолжают возвращаться и после выполнения chroot, а изменения файлов не учитываются, пока процесс работает. Простой способ разрабатывать такие файлы — связать их с кодом состояния 403 и обращаться к заблокированному URL.

См. также: “http-error”, “errorloc”, “errorloc302”, “errorloc303”

Пример:

errorfile 400 /etc/haproxy/errorfiles/400badreq.http
errorfile 408 /dev/null  # work around Chrome pre-connect bug
errorfile 403 /etc/haproxy/errorfiles/403forbid.http
errorfile 503 /etc/haproxy/errorfiles/503sorry.http

errorfiles <name> [<code> ...]

errorfiles <name> [<code> ...]

Полностью или частично импортирует файлы ошибок, определённые в секции http-errors с именем <name>.

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

<name>  — имя существующей секции http-errors.

<code>  — код состояния HTTP. Можно перечислить несколько кодов. В настоящее время HAProxy
        может формировать коды 200, 400, 401, 403, 404, 405, 407,
        408, 410, 413, 414, 425, 429, 431, 500, 501,
        502, 503 и 504.

Ошибки, определённые в секции http-errors с именем <name>, импортируются в текущий прокси. Если коды состояния не указаны, импортируются все файлы ошибок этой секции http-errors. Иначе импортируются только файлы, связанные с перечисленными кодами. Эти файлы заменяют ранее заданные пользовательские ошибки прокси и, в свою очередь, могут быть заменены последующими определениями. Функционально это полностью равнозначно ручному объявлению всех файлов ошибок с помощью директив “errorfile”.

См. также: “http-error”, “errorfile”, “errorloc”, “errorloc302”, “errorloc303” и раздел 12.4 о http-errors.

Пример:

errorfiles generic
errorfiles site-1 403 404

errorloc <code> <url>

errorloc <code> <url>
errorloc302 <code> <url>

Возвращает перенаправление HTTP на URL вместо ошибок, сформированных HAProxy

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

<code>    — код состояния HTTP. В настоящее время HAProxy может формировать коды 200,
          400, 401, 403, 404, 405, 407, 408, 410, 413,
          414, 425, 429, 431, 500, 501, 502, 503 и 504.

<url>     — точное содержимое заголовка "Location". Это может быть относительный URI страницы
          ошибки на том же сайте или абсолютный URI страницы ошибки на другом сайте. С
          относительными URI следует обращаться особенно осторожно, чтобы не создавать
          циклические перенаправления, если сам URI может вызвать ту же ошибку (например,
          500).

Эта директива предназначена для замены ошибок, обнаруженных и возвращённых HAProxy, а не ошибок, возвращённых сервером. Поэтому список поддерживаемых ошибок ограничен небольшим набором.

Код 200 возвращается в ответ на запросы, соответствующие правилу “monitor-uri”.

Оба ключевых слова возвращают код состояния HTTP 302, предписывающий клиенту обратиться к указанному URL тем же методом HTTP. Это может создавать серьёзные проблемы для методов, отличных от GET, например POST: URL, отправленный клиенту, может допускать только GET. Для обхода этой проблемы следует использовать “errorloc303”, которая возвращает код состояния HTTP 303 и указывает клиенту, что URL необходимо получить запросом GET.

См. также: “http-error”, “errorfile”, “errorloc303”

errorloc303 <code> <url>

errorloc303 <code> <url>

Возвращает перенаправление HTTP на URL вместо ошибок, сформированных HAProxy

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

<code>    — код состояния HTTP. В настоящее время HAProxy может формировать коды 200,
          400, 401, 403, 404, 405, 407, 408, 410, 413,
          414, 425, 429, 431, 500, 501, 502, 503 и 504.

<url>     — точное содержимое заголовка "Location". Это может быть относительный URI страницы
          ошибки на том же сайте или абсолютный URI страницы ошибки на другом сайте. С
          относительными URI следует обращаться особенно осторожно, чтобы не создавать
          циклические перенаправления, если сам URI может вызвать ту же ошибку (например,
          500).

Эта директива предназначена для замены ошибок, обнаруженных и возвращённых HAProxy, а не ошибок, возвращённых сервером. Поэтому список поддерживаемых ошибок ограничен небольшим набором.

Код 200 возвращается в ответ на запросы, соответствующие правилу “monitor-uri”.

Оба ключевых слова возвращают код состояния HTTP 303, предписывающий клиенту получить указанный URL тем же методом HTTP GET. Это решает обычные проблемы, связанные с “errorloc” и кодом 302. Некоторые очень старые браузеры, созданные до HTTP/1.1, могут не поддерживать такое поведение, однако до настоящего времени о подобных проблемах не сообщалось.

См. также: “http-error”, “errorfile”, “errorloc”, “errorloc302”

email-alert from <emailaddr>

email-alert from <emailaddr>

Задаёт адрес отправителя электронных уведомлений как в конверте, так и в заголовке сообщения. С этого адреса отправляются уведомления.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

<emailaddr> — адрес отправителя электронных уведомлений

Также необходимо задать “email-alert mailers” и “email-alert to”; при выполнении этих условий отправка электронных уведомлений для прокси включается.

См. также: “email-alert level”, “email-alert mailers”, “email-alert myhostname”, “email-alert to”, раздел 12.3 о mailers.

email-alert level <level>

email-alert level <level>

Задаёт максимальный уровень журналирования сообщений, для которых отправляются электронные уведомления. Он служит фильтром отправки уведомлений.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

<level> Один из 8 уровней syslog:
          emerg alert crit err warning notice info  debug
        Эти уровни syslog перечислены в порядке возрастания.

По умолчанию используется уровень alert

Также необходимо задать “email-alert from”, “email-alert mailers” и “email-alert to”; при выполнении этих условий отправка электронных уведомлений для прокси включается.

Уведомления отправляются в следующих случаях:

  • Сервер, не находящийся на паузе, помечается как down, а <level> равен alert или ниже
  • Приостановленный сервер помечается как down, а <level> равен notice или ниже
  • Сервер помечается как up или переходит в состояние drain, а <level> равен notice или ниже
  • Включён “option log-health-checks”, <level> равен info или ниже и происходит обновление состояния проверки работоспособности

См. также: “email-alert from”, “email-alert mailers”, “email-alert myhostname”, “email-alert to”, раздел 12.3 о mailers.

email-alert mailers <mailersect>

email-alert mailers <mailersect>

Задаёт секцию mailers для отправки электронных уведомлений

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

<mailersect> — имя секции mailers, используемой для отправки электронных уведомлений.

Также необходимо задать “email-alert from” и “email-alert to”; при выполнении этих условий отправка электронных уведомлений для прокси включается.

См. также: “email-alert from”, “email-alert level”, “email-alert myhostname”, “email-alert to”, раздел 12.3 о mailers.

email-alert myhostname <hostname>

email-alert myhostname <hostname>

Задаёт имя хоста, используемое при взаимодействии с mailers.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

<hostname> — имя хоста, используемое при взаимодействии с mailers

По умолчанию используется имя хоста системы.

Также необходимо задать “email-alert from”, “email-alert mailers” и “email-alert to”; при выполнении этих условий отправка электронных уведомлений для прокси включается.

См. также: “email-alert from”, “email-alert level”, “email-alert mailers”, “email-alert to”, раздел 12.3 о mailers.

email-alert to <emailaddr>

email-alert to <emailaddr>

Задаёт адрес получателя электронных уведомлений и в конверте, и в заголовке сообщения. На этот адрес отправляются уведомления.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

<emailaddr> — адрес получателя электронных уведомлений

Также необходимо задать “email-alert mailers” и “email-alert to”; при выполнении этих условий отправка электронных уведомлений для прокси включается.

См. также: “email-alert from”, “email-alert level”, “email-alert mailers”, “email-alert myhostname”, раздел 12.3 о mailers.

error-log-format <fmt>

error-log-format <fmt>

Задаёт строку формата журнала для ошибок соединения на стороне фронтенда.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Эта директива задаёт строку формата для записей журнала с информацией об ошибках, тайм-аутах, повторных попытках, перераспределении запросов или кодах состояния HTTP 5xx. Этот формат используется для всех записей, на которые распространялся бы параметр “log-separate-errors”, включая ошибки соединения, описанные в разделе 8.2.5 .

Если директива используется в секции defaults, все последующие фронтенды используют один и тот же формат журнала. Подробное описание пользовательской строки формата журнала приведено в разделе 8.2.6 .

Директива “error-log-format” переопределяет предыдущие директивы “error-log-format”.

force-persist { if | unless } <condition>

force-persist { if | unless } <condition>

Задаёт условие принудительной привязки сеанса к недоступным серверам

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend нет | нет | да | да

По умолчанию запросы не направляются на недоступные серверы. Это можно принудительно изменить с помощью “option persist”, однако этот параметр действует безусловно и перенаправляет запрос на работающий сервер, если задана “option redispatch”. Поэтому возможностей направить отдельные запросы на сервер, искусственно помеченный как недоступный для проведения обслуживания, остаётся очень мало.

Директива “force-persist” позволяет задать различные условия на основе ACL. При их выполнении запрос игнорирует недоступное состояние сервера и всё равно пытается установить с ним соединение. Это позволяет запустить сервер, который ещё отвечает ошибкой на проверки работоспособности, и проверить службу с помощью специально настроенного браузера. Например, удобно использовать определённый исходный адрес IP или определённый cookie. У cookie есть и дополнительное преимущество: его легко добавить или удалить в браузере с тестовой страницы. После проверки службы её можно открыть для всех пользователей, начав возвращать корректные ответы на проверки работоспособности.

Принудительная привязка включается при выполнении условия “if” или при невыполнении условия “unless”. При её использовании окончательное перераспределение запроса всегда отключено.

См. также: “option redispatch”, “ignore-persist”, “persist” и раздел 7 об использовании ACL.

external-check command <command>

external-check command <command>

Исполняемый файл, запускаемый при выполнении external-check

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<command> — внешняя команда для запуска

Команде передаются следующие аргументы:

<proxy_address> <proxy_port> <server_address> <server_port>

Значения <proxy_address> и <proxy_port> берутся из первого слушателя IPv4, IPv6 или сокета UNIX. Для слушателя на сокете UNIX значение proxy_address содержит путь к сокету, а <proxy_port> — строку “NOT_USED”. В секции backend определить слушатель невозможно, поэтому и <proxy_address>, и <proxy_port> получают строковое значение “NOT_USED”.

Некоторые значения также передаются через переменные окружения.

Переменные окружения:

HAPROXY_PROXY_ADDR      Первый адрес привязки, если он доступен (или пустое значение, если неприменимо,
                        например в секции "backend").

HAPROXY_PROXY_ID        Идентификатор бэкенда.

HAPROXY_PROXY_NAME      Имя бэкенда.

HAPROXY_PROXY_PORT      Первый порт привязки, если он доступен (или пустое значение, если неприменимо,
                        например в секции "backend" или для сокета UNIX).

HAPROXY_SERVER_ADDR     Адрес сервера.

HAPROXY_SERVER_CURCONN  Текущее число соединений на сервере.

HAPROXY_SERVER_ID       Идентификатор сервера.

HAPROXY_SERVER_MAXCONN  Максимальное число соединений сервера.

HAPROXY_SERVER_NAME     Имя сервера.

HAPROXY_SERVER_PORT     Порт сервера, если он доступен (или пустое значение для сокета UNIX).

HAPROXY_SERVER_SSL      "0", если SSL не используется; "1", если используется

HAPROXY_SERVER_PROTO    Протокол, используемый этим сервером: "cli" (CLI haproxy), "syslog" (сервер
                        syslog TCP), "peers" (сервер peers TCP), "h1" (сервер
                        HTTP/1.x), "h2" (сервер HTTP/2) или "tcp" (любой другой
                        сервер TCP).

PATH                    Переменную окружения PATH, используемую при запуске команды, можно
                        задать с помощью "external-check path".

Если команда выполнена и завершилась с нулевым кодом, проверка считается успешной; в противном случае она считается неуспешной.

Пример:

external-check command /bin/true

См. также: “external-check”, “option external-check”, “external-check path”

external-check path <path>

external-check path <path>

Значение переменной окружения PATH, используемой при запуске external-check

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<path> — путь, используемый при выполнении внешней команды

Путь по умолчанию — “”.

Пример:

external-check path "/usr/bin:/bin"

См. также: “external-check”, “option external-check”, “external-check command”

force-be-switch { if | unless } <condition>

force-be-switch { if | unless } <condition>

Разрешает при переключении содержимого выбирать экземпляр бэкенда, даже если он отключён или не опубликован. Администраторы могут использовать это правило для проверки трафика к службам перед предоставлением внешнего доступа к ним.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend нет | да | да | нет

См. также: “be-unpublished”, “disabled”

filter <name> [param*]

filter <name> [param*]

Добавляет фильтр <name> в список фильтров, прикреплённый к прокси.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend нет | да | да | да

Аргументы:

<name>     — имя фильтра. Официально поддерживаемые фильтры перечислены в разделе 9.

<param*>   — список параметров, принимаемых фильтром <name>. За разбор этих параметров отвечает
           сам фильтр. Полные сведения о поддерживаемых параметрах приведены в документации
           соответствующего фильтра (раздел 9).

Для одного прокси можно использовать несколько строк filter. При необходимости один и тот же фильтр можно указать несколько раз.

Пример:

listen
  bind *:80

  filter trace name BEFORE-HTTP-COMP
  filter compression
  filter trace name AFTER-HTTP-COMP

  compression algo gzip
  compression offload

  server srv1 192.168.0.1:80

См. также: раздел 9 .

fullconn <conns>

fullconn <conns>

Задаёт нагрузку бэкенда, при которой серверы достигают своего maxconn

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<conns>   — число соединений на бэкенде, при котором серверы используют максимальное число
          соединений.

Параметр “maxconn” сервера задаёт верхнюю границу числа его одновременных соединений. Дополнительный параметр “minconn” задаёт динамический лимит, зависящий от нагрузки бэкенда. Сервер всегда допускает не менее <minconn> соединений, но никогда не более <maxconn>; пока число одновременных соединений бэкенда меньше <conns>, лимит плавно меняется между этими значениями. Это позволяет ограничивать нагрузку серверов в обычных условиях, увеличивать её при высокой нагрузке и не перегружать серверы при исключительных всплесках.

Поскольку правильно подобрать это значение сложно, HAProxy автоматически устанавливает его равным 10% суммы maxconn всех фронтендов, которые могут направлять трафик в этот бэкенд (по правилам “use_backend” и “default_backend”). Поэтому безопасно оставить значение незаданным. Однако правила “use_backend” с динамическими именами не учитываются: невозможно определить, смогут ли они совпасть.

Пример:

# The servers will accept between 100 and 1000 concurrent connections each
# and the maximum of 1000 will be reached when the backend reaches 10000
# connections.
backend dynamic
   fullconn   10000
   server     srv1   dyn1:80 minconn 100 maxconn 1000
   server     srv2   dyn2:80 minconn 100 maxconn 1000

См. также: “maxconn”, “server”

guid <string>

guid <string>

Задаёт для этого прокси глобально уникальный ID с учётом регистра.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend нет | да | да | да

<string> должна быть уникальной во всей конфигурации haproxy среди объектов всех типов. Формат не задан, чтобы пользователь мог выбрать собственные правила именования. Единственное ограничение — длина не более 127 символов. Допустимы все буквенно-цифровые значения, а также символы ‘.’, ‘:’, ‘-’ и ‘_’. См. также “shm-stats-file”.

hash-balance-factor <factor>

hash-balance-factor <factor>

Задаёт коэффициент балансировки для консистентного хеширования с ограниченной нагрузкой

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | нет | да

Аргументы:

<factor> — ограничение максимального числа одновременных запросов, отправляемых серверу, в
         процентах от среднего числа одновременных запросов по всем активным серверам.

Параметр “hash-balance-factor” для сервера с “hash-type consistent” включает алгоритм, который не позволяет одному серверу получить слишком много запросов одновременно, даже если в некоторые корзины хеша попадает значительно больше запросов, чем в другие. Значение <factor> 0 (по умолчанию) отключает эту возможность. В остальных случаях <factor> задаётся в процентах и должен быть больше 100. Например, при <factor> 150 нагрузка ни одного сервера не может превышать среднюю более чем в 1.5 раза. Веса серверов, если они используются, учитываются.

Если первоначально выбранный сервер не подходит, алгоритм выбирает другой на основе хеша запроса, пока не найдёт сервер со свободной ёмкостью. Более высокий <factor> допускает больший дисбаланс между серверами, а более низкий <factor> требует в среднем проверять больше серверов, что влияет на производительность. Разумные значения находятся в диапазоне от 125 до 200.

Эта настройка также используется алгоритмом “balance random”, который внутри опирается на механизм консистентного хеширования.

См. также: “balance” и “hash-type”.

hash-preserve-affinity { always | maxconn | maxqueue }

hash-preserve-affinity { always | maxconn | maxqueue }

Задаёт способ назначения потоков серверам при балансировке по хешу, когда серверы полностью загружены или их очередь заполнена.

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Можно указать следующие значения:

- "always"  : стратегия по умолчанию. Поток назначается серверу
               на основе хеширования независимо от того, полностью ли
               загружен этот сервер.

- "maxconn" : пропускаются полностью загруженные серверы, у которых
               задан "maxconn". Другой сервер выбирается при обходе
               хеш-кольца. Это не влияет на серверы без "maxconn".
               Если все серверы полностью загружены, запрос ставится
               в очередь последнего сервера в хеш-кольце перед
               первоначально выбранным сервером.

- "maxqueue": пропускаются серверы с заданным "maxconn", ненулевым
               "maxqueue" (ограниченным размером очереди) и полностью
               заполненной очередью. Другой сервер выбирается при
               обходе хеш-кольца. Это не влияет на серверы, у которых
               отсутствует хотя бы один из параметров "maxconn"
               и "maxqueue".

См. также: “maxconn”, “maxqueue”, “hash-balance-factor”

hash-type <method> <function> <modifier>

hash-type <method> <function> <modifier>

Задаёт способ сопоставления хешей с серверами

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<method> — способ выбора сервера по хешу, вычисленному функцией <function>:

  map-based   Хеш-таблица представляет собой статический массив всех работающих серверов.
              Распределение хешей будет очень равномерным и будет учитывать веса, но останется
              статическим: изменения веса работающего сервера игнорируются. Поэтому плавный
              старт не поддерживается. Сервер выбирается по позиции в массиве, и при изменении
              числа серверов меняется большинство соответствий. Когда сервер становится
              доступным или недоступным либо добавляется в группу, большинство соединений
              перераспределяется между другими серверами. Это может быть неудобно, например, для
              кешей.

  consistent  Хеш-таблица представляет собой дерево со множеством вхождений каждого сервера. В
              дереве ищется ключ хеша и выбирается ближайший сервер. Этот хеш динамический: веса
              работающих серверов можно изменять, поэтому он совместим с плавным стартом. Его
              преимущество в том, что при изменении доступности сервера перемещаются только его
              соответствия. При добавлении сервера в группу перераспределяется лишь небольшая
              часть соответствий, что идеально подходит для кешей. Однако из-за принципа работы
              распределение никогда не будет очень равномерным; иногда для его улучшения
              приходится менять вес сервера или его ID. Для одинакового распределения на
              нескольких балансировщиках важно, чтобы ID всех серверов в точности
              совпадали. Примечание: если хеш-функция не указана, консистентное хеширование
              использует sdbm и avalanche.

<function> — используемая хеш-функция:

   sdbm   Эта функция первоначально создана для библиотеки баз данных sdbm — реализации ndbm,
          находящейся в общественном достоянии. Она хорошо перемешивает биты, обеспечивая лучшее
          распределение ключей и меньшее число разбиений. Это также хорошая универсальная
          хеш-функция с равномерным распределением, кроме случаев, когда суммарный вес серверов
          кратен 64; тогда может помочь модификатор avalanche.

   djb2   Эту функцию много лет назад впервые предложил Dan Bernstein в comp.lang.c. Исследования
          показали, что при некоторых нагрузках она даёт более равномерное распределение, чем
          sdbm. Обычно она хорошо работает с текстовыми входными данными, но без модификатора
          avalanche может давать крайне плохие результаты, если входные данные содержат только
          числа или суммарный вес серверов кратен 33.

   wt6    Эта функция разработана для HAProxy при прежних испытаниях других функций. Она не
          столь равномерна, как остальные, но значительно меньше зависит от входных данных или
          числа серверов. Она может служить альтернативой sdbm+avalanche или djb2+avalanche при
          консистентном хешировании либо хешировании числовых данных, например исходного адреса
          IP или идентификатора посетителя в параметре URL.

   crc32  Это наиболее распространённая реализация CRC32, используемая в Ethernet, gzip,
          PNG и т. д. Она медленнее остальных, но может давать более равномерное
          распределение или менее предсказуемые результаты, особенно на строках.

   none   Ключ не хешируется, а сам используется как хеш. Это удобно, если ключ нужно хешировать
          вручную соответствующим преобразователем и передать haproxy готовый результат.
          Операция преобразует ключ в строку, если он ещё не является строкой, и разбирает её
          как целое число, значение которого используется в качестве ключа. Некоторые типы
          входных ключей здесь могут быть неприменимы, например адреса IP.

<modifier> — необязательный метод, применяемый после хеширования ключа:

   avalanche   Эта директива указывает, что результат описанной выше хеш-функции не следует
               использовать напрямую: сначала необходимо применить полный 4-байтовый
               лавинный хеш. Этот шаг перемешивает биты предыдущего хеша, устраняя нежелательные
               эффекты, когда входные данные содержат ограниченный набор значений или число
               серверов кратно одному из компонентов хеша (64 для SDBM, 33 для
               DJB2). avalanche обычно делает результат менее предсказуемым, но распределение
               становится менее равномерным, чем с исходной функцией. Для некоторых нагрузок
               могут потребоваться испытания. Этот хеш — один из многих, предложенных Bob
               Jenkins.

Тип хеша по умолчанию — “map-based”; он рекомендуется для большинства случаев. Функция по умолчанию — “sdbm”. Функцию следует выбирать с учётом диапазона хешируемых значений.

См. также: “balance”, “hash-balance-factor”, “hash-preserve-affinity”, “server”

http-after-response <action> <options...> [ { if | unless } <condition> ]

http-after-response <action> <options...> [ { if | unless } <condition> ]

Контроль доступа для всех ответов уровня 7: от серверов, апплетов/служб и внутренних ответов.

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да(!) | да | да | да

Директива http-after-response задаёт набор правил обработки на уровне 7. В секциях frontend, listen и backend правила проверяются в порядке объявления. Поскольку они применяются к ответам, сначала выполняются правила бэкенда, затем фронтенда. За любым правилом можно указать необязательное условие на основе ACL; тогда правило проверяется только при истинном значении условия.

В отличие от правил http-response, эти правила применяются ко всем ответам: от серверов и сформированным самим HAProxy. Они проверяются в конце анализа ответа, до этапа пересылки данных.

Условие проверяется непосредственно перед выполнением действия, а действие выполняется ровно один раз. Поэтому действие может изменять элемент, проверяемый условием, без каких-либо проблем. Несколько действий могут зависеть от одного условия: первое действие, изменяющее результат его проверки, неявно отключает остальные. Это используется, например, при попытках присвоить пустой переменной значение из разных источников. Число директив “http-after-response” в экземпляре не ограничено.

Первое ключевое слово после “http-after-response” в синтаксисе — действие правила; за ним может следовать различное число аргументов действия. Поддерживаемые действия и их синтаксис перечислены в разделе 4.3 «Действия» (нужны действия с отметкой “HTTP Aft”).

Эта директива доступна только в именованных секциях defaults, а в анонимных недоступна. Правила секции defaults проверяются до правил связанной с ней секции прокси. Во избежание неоднозначности одну и ту же секцию defaults нельзя использовать одновременно для прокси с возможностями фронтенда и прокси с возможностями бэкенда. Поэтому секция listen не может использовать секцию defaults с такими правилами.

Примечание: ошибки на ранних этапах разбора запроса обрабатываются мультиплексором на более низком уровне, до анализа http. Поэтому к таким ошибкам набор правил http-after-response не применяется.

Пример:

http-after-response set-header Strict-Transport-Security "max-age=31536000"
http-after-response set-header Cache-Control "no-store,no-cache,private"
http-after-response set-header Pragma "no-cache"

http-check comment <string>

http-check comment <string>

Задаёт комментарий для следующего правила http-check, который попадает в журнал при неудаче этого правила.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<string>  — комментарий, добавляемый в журнал, если следующее правило http-check завершилось
          неудачей.

Работает только для правил connect, send и expect. Позволяет делать сообщения об ошибках понятнее.

См. также: “option httpchk”, “http-check connect”, “http-check send” и “http-check expect”.

http-check connect [default] [port <expr>] [addr <ip>] [send-proxy]

http-check connect [default] [port <expr>] [addr <ip>] [send-proxy]
                   [via-socks4] [ssl] [sni <sni>] [alpn <alpn>] [linger]
                   [proto <name>] [comment <msg>]

Открывает новое соединение для проверки работоспособности HTTP

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

comment <msg>  задаёт сообщение, которое выводится, если проверка правила завершается
        неудачей.

default      Использует параметры по умолчанию из строки server для проверок работоспособности.
             Параметры сервера применяются, только если не переопределены.

port <expr>  Если не задан, используется порт проверки или сервера. Указывает HAProxy, куда
             устанавливать соединение. <port> должен быть целым числом допустимого порта
             TCP от 1 до 65535 или выражением извлечения образца.

addr <ip>    Задаёт адрес IP для проверки работоспособности.

send-proxy   Отправляет строку протокола PROXY

via-socks4   Включает исходящие проверки работоспособности через вышестоящий прокси socks4.

ssl          Открывает зашифрованное соединение

sni <sni>    Задаёт SNI для проверок работоспособности по SSL.

alpn <alpn>  Задаёт протоколы, объявляемые через ALPN. Список содержит имена протоколов,
             разделённые запятыми, например "h2,http/1.1". Если не задан, используется ALPN
             сервера.

proto <name> Принудительно задаёт протокол мультиплексора для этого соединения. Это должен быть
             протокол мультиплексора HTTP, допустимый на стороне бэкенда. Список доступных
             протоколов выводится командой haproxy -vv.

linger       Закрывает соединение корректно вместо отправки единственного RST.

Как и для проверок tcp-check, можно настроить соединение для проверки работоспособности HTTP. Эту директиву также следует использовать для описания сценария с несколькими обменами запросами и ответами, возможно на разных портах или с разными серверами.

Если порт TCP не задан ни в строке server, ни директивой server port, первым шагом последовательности http-check необходимо указать порт через “http-check connect”.

В наборе правил http-check требуется ‘connect’, причём набор обязательно должен начинаться правилом ‘connect’. Это позволяет убедиться, что администратор понимает свои действия.

Хотя набор правил должен начинаться с connect, перед ним всё же могут стоять правила set-var, unset-var или comment.

Примеры:

# check HTTP and HTTPs services on a server.
# first open port 80 thanks to server line port directive, then
# tcp-check opens port 443, ciphered and run a request on it:
option httpchk

http-check connect
http-check send meth GET uri / ver HTTP/1.1 hdr host haproxy.1wt.eu
http-check expect status 200-399
http-check connect port 443 ssl sni haproxy.1wt.eu
http-check send meth GET uri / ver HTTP/1.1 hdr host haproxy.1wt.eu
http-check expect status 200-399

server www 10.0.0.1 check port 80

См. также: “option httpchk”, “http-check send”, “http-check expect”

http-check disable-on-404

http-check disable-on-404

Включает режим обслуживания при ответе HTTP/404 на проверки работоспособности

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы: отсутствуют

При этом параметре сервер, возвращающий код HTTP 404, исключается из дальнейшей балансировки нагрузки, но продолжает получать соединения с привязкой сеанса. Это очень удобный способ плавно завершать обслуживание серверов для веб-администраторов. Если в этом режиме обнаруживается отказ сервера, формируется только уведомление notice вместо alert. При возобновлении ответов 2xx или 3xx сервер немедленно возвращается в группу. На странице статистики сервер в этом режиме имеет состояние “NOLB”. Параметр работает только совместно с “httpchk”. При сочетании с “http-check expect” он имеет приоритет, поэтому ответы 404 по-прежнему считаются мягкой остановкой. Уже остановленный сервер остаётся остановленным, даже если отвечает 404. Параметр проверяется только для работающих серверов.

См. также: “option httpchk” и “http-check expect”.

http-check expect [min-recv <int>] [comment <msg>]

http-check expect [min-recv <int>] [comment <msg>]
                  [ok-status <st>] [error-status <st>] [tout-status <st>]
                  [on-success <fmt>] [on-error <fmt>] [status-code <expr>]
                  [!] <match> <pattern>

Позволяет проверкам работоспособности HTTP учитывать содержимое ответа или определённые коды состояния

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

comment <msg>  задаёт сообщение, которое выводится, если проверка правила завершается
        неудачей.

min-recv  Необязательный параметр, задающий минимальный объём данных для проверки текущего
          правила expect. Если получено меньше байтов, проверка ждёт новых данных. Это позволяет
          устранить неоднозначность некоторых правил сопоставления или не выполнять затратное
          сопоставление с регулярным выражением на заведомо неполном содержимом. Для точной
          строки используется меньшее из длины строки и этого параметра. Параметр игнорируется
          при значении -1. Если правило expect не совпало, проверка ждёт новых данных. При
          значении 0 результат проверки всегда окончательный.

ok-status <st>     Необязательный параметр, задающий состояние проверки, если правило expect
                   успешно выполнено и является последним в наборе правил tcp-check.
                   Поддерживаются "L7OK", "L7OKC", "L6OK" и "L4OK":
                     - L7OK : проверка пройдена на уровне 7
                     - L7OKC: проверка условно пройдена на уровне 7; сервер
                       переводится в состояние NOLB.
                     - L6OK : проверка пройдена на уровне 6
                     - L4OK : проверка пройдена на уровне 4 По умолчанию
                       используется "L7OK".

error-status <st>  Необязательный параметр, задающий состояние проверки при ошибке выполнения
                     правила expect. Поддерживаются "L7OKC", "L7RSP", "L7STS", "L6RSP" и
                     "L4CON":
                     - L7OKC: проверка условно пройдена на уровне 7; сервер
                       переводится в состояние NOLB.
                     - L7RSP: некорректный ответ уровня 7 — ошибка протокола
                     - L7STS: ошибка ответа уровня 7, например HTTP 5xx
                     - L6RSP: некорректный ответ уровня 6 — ошибка протокола
                     - L4CON: проблема соединения уровней 1-4 По умолчанию
                       используется "L7RSP".

tout-status <st>   Необязательный параметр, задающий состояние проверки при тайм-ауте выполнения
                   правила expect. Поддерживаются "L7TOUT", "L6TOUT" и "L4TOUT":
                     - L7TOUT: тайм-аут уровня 7 (HTTP/SMTP)
                     - L6TOUT: тайм-аут уровня 6 (SSL)
                     - L4TOUT: тайм-аут уровней 1-4 По умолчанию используется
                       "L7TOUT".

on-success <fmt>   Необязательный параметр настройки информационного сообщения в журнале, если
                   правило expect успешно выполнено и является последним в наборе правил
                   tcp-check. <fmt> — строка пользовательского формата журнала (см. раздел
                   8.2.6).

on-error <fmt>     Необязательный параметр настройки информационного сообщения в журнале при
                   ошибке выполнения правила expect. <fmt> — строка пользовательского формата
                   журнала (см. раздел 8.2.6).

status-code <expr> Необязательный параметр, задающий код состояния проверки, записываемый в журнал
                   при успехе или ошибке. <expr> — стандартное выражение HAProxy, состоящее из
                   извлечения образца и следующих за ним преобразователей.

<match>   — ключевое слово, задающее способ поиска определённого шаблона в ответе. Допустимы
          "status", "rstatus", "hdr", "fhdr", "string" и "rstring". Перед ключевым словом можно
          поставить восклицательный знак ("!"), инвертирующий результат сопоставления. Между
          ним и ключевым словом допускаются пробелы. Подробнее о поддерживаемых ключевых словах
          см. ниже.

<pattern> — это шаблон для поиска. Он может быть строкой, регулярным выражением или более сложным
          шаблоном с несколькими аргументами. Если строковый шаблон содержит пробелы, они должны
          быть экранированы с помощью обычного обратного слеша ('\').

По умолчанию “option httpchk” считает коды состояния 2xx и 3xx допустимыми, а остальные недопустимыми. “http-check expect” определяет, что считать допустимым и недопустимым. В бэкенде поддерживается только одна директива “http-check”. Если сервер не отвечает или истекает тайм-аут, проверка, очевидно, завершается неудачей. Доступные способы сопоставления:

status <codes>:  Проверяет коды состояния, полученные при разборе строки <codes>. Она должна
                  содержать список кодов состояния или диапазонов кодов, разделённых запятыми.
                  Ответ проверки работоспособности считается допустимым, если его код состояния
                  совпадает с любым кодом или входит в любой диапазон списка. При "!" перед
                  ключевым словом "status" совпадение кода делает ответ недопустимым.

rstatus <regex>: Проверяет код состояния HTTP по регулярному выражению. Ответ проверки
                  работоспособности считается допустимым, если его код состояния соответствует
                  выражению. При "!" перед ключевым словом "rstatus" совпадение кода делает
                  ответ недопустимым. Обычно это используется для проверки нескольких кодов.

hdr  { name | name-lf } [ -m <meth> ] <name>
     [ { value | value-lf } [ -m <meth> ] <value>:
                  Проверяет указанный шаблон заголовка в заголовках ответа HTTP. Шаблон имени
                  обязателен, а шаблон значения необязателен. Если значение не задано,
                  проверяется только наличие заголовка. <meth> — метод сопоставления имени или
                  значения заголовка. Поддерживаются "str" (точное совпадение), "beg"
                  (совпадение префикса), "end" (совпадение суффикса), "sub" (совпадение
                  подстроки) и "reg" (регулярное выражение). По умолчанию используется точное
                  совпадение. При параметре "name-lf" <name> вычисляется как строка
                  пользовательского формата журнала (см. раздел 8.2.6). При параметре "value-lf"
                  <value> вычисляется как строка log-format. Эти параметры нельзя использовать с
                  методом сопоставления по регулярному выражению. Значение заголовка
                  рассматривается как список, разделённый запятыми. Имена заголовков
                  сопоставляются без учёта регистра.

fhdr { name | name-lf } [ -m <meth> ] <name>
     [ { value | value-lf } [ -m <meth> ] <value>:
                  Проверяет указанный шаблон полного заголовка в заголовках ответа HTTP.
                  Работает в точности как "hdr", но проверяет значение заголовка целиком, не
                  считая запятые разделителями.

string <string>: Проверяет точное совпадение строки в теле ответа HTTP. Ответ проверки
                  работоспособности считается допустимым, если его тело содержит эту строку в
                  точности. При "!" перед ключевым словом "string" наличие строки в теле
                  делает ответ недопустимым. Это позволяет искать обязательное слово в конце
                  динамической страницы либо обнаруживать сбой по определённой ошибке на
                  странице проверки, например трассировке стека.

rstring <regex>: Проверяет регулярное выражение в теле ответа HTTP. Ответ проверки
                  работоспособности считается допустимым, если его тело соответствует выражению.
                  При "!" перед ключевым словом "rstring" совпадение делает ответ
                  недопустимым. Это позволяет искать обязательное слово в конце динамической
                  страницы либо обнаруживать сбой по определённой ошибке на странице проверки,
                  например трассировке стека.

string-lf <fmt>: Проверяет совпадение строки пользовательского формата журнала (см. раздел
                  8.2.6) в теле ответа HTTP. Ответ проверки работоспособности считается
                  допустимым, если его тело содержит строку, полученную при вычислении <fmt>
                  по правилам log-format. При "!" перед ключевым словом наличие строки в теле
                  делает ответ недопустимым.

Размер ответов ограничивается глобальным параметром “tune.bufsize”, по умолчанию 16384 байта. Поэтому в слишком большом ответе при “string” или “rstring” может отсутствовать обязательный шаблон. Если большой ответ совершенно необходим, максимальный размер по умолчанию можно изменить глобальной переменной. Однако разбор очень больших ответов может расходовать лишние циклы CPU, особенно с регулярными выражениями; всегда лучше направлять проверки на меньшие ресурсы.

В наборе правил http-check последнее правило expect может быть неявным. Если после последнего “http-check send” правило expect не указано, неявно задаётся правило expect для кодов состояния 2xx или 3xx. Оно задаётся даже при полном отсутствии правил “http-check”, если установлена только “option httpchk”.

Наконец, если “http-check expect” комбинируется с “http-check disable-on-404”, то последнее имеет приоритет при ответе сервера с кодом 404.

Примеры:

# only accept status 200 as valid
http-check expect status 200,201,300-310

# be sure a sessid coookie is set
http-check expect hdr name "set-cookie" value -m beg "sessid="

# consider SQL errors as errors
http-check expect ! string SQL\ Error

# consider status 5xx only as errors
http-check expect ! rstatus ^5

# check that we have a correct hexadecimal tag before /html
http-check expect rstring <!--tag:[0-9a-f]*--></html>

См. также: “option httpchk”, “http-check connect”, “http-check disable-on-404” и “http-check send”.

http-check send [meth <method>] [{ uri <uri> | uri-lf <fmt> }>] [ver <version>]

http-check send [meth <method>] [{ uri <uri> | uri-lf <fmt> }>] [ver <version>]
                [hdr <name> <fmt>]* [{ body <string> | body-lf <fmt> }]
                [comment <msg>]

Позволяет добавить список заголовков и/или тело в запрос, отправляемый при проверках работоспособности HTTP.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

comment <msg>  задаёт сообщение, которое выводится, если проверка правила завершается
        неудачей.

meth <method>  — необязательный метод HTTP для запросов. Если не задан, используется "OPTIONS":
               обычно он требует мало обработки на сервере и легко исключается из журналов.
               Можно использовать любой метод, хотя изобретать нестандартные не рекомендуется.

uri <uri>      Необязательный параметр, задающий URI запросов HTTP строкой <uri>. По
               умолчанию используется "/", доступный почти на любом сервере; можно задать
               любой другой URI. Строки запроса разрешены.

uri-lf <fmt>   Необязательный параметр, задающий URI запросов HTTP с помощью
               пользовательского формата журнала <fmt> (см. раздел 8.2.6). По умолчанию
               используется "/", доступный почти на любом сервере; можно задать любой другой
               URI. Строки запроса разрешены.

ver <version>  — необязательная строка версии HTTP. По умолчанию используется "HTTP/1.0", но
               некоторые серверы могут некорректно работать с HTTP 1.0, поэтому переход
               на HTTP/1.1 иногда помогает. Поле Host обязательно в HTTP/1.1; для его добавления
               следует использовать аргумент "hdr".

hdr <name> <fmt>  Добавляет поле заголовка HTTP с именем <name> и значением <fmt>,
                  заданным по правилам пользовательского формата журнала из раздела 8.2.6.

body <string>  Добавляет тело <string> в запрос, отправляемый при проверках работоспособности
               HTTP. Если тело задано, заголовок "Content-Length" добавляется в запрос автоматически.

body-lf <fmt>  Добавляет в запрос проверок работоспособности HTTP тело, заданное
               пользовательским форматом журнала <fmt> (см. раздел 8.2.6). Если тело задано,
               заголовок "Content-Length" добавляется в запрос автоматически.

В дополнение к строке запроса, заданной директивой “option httpchk”, эта директива является правильным способом добавить заголовки и необязательное тело в запрос проверки работоспособности HTTP. При заданном теле соответствующий заголовок “Content-Length” добавляется автоматически. Поэтому этот заголовок и заголовок “Transfer-encoding” не следует включать в запрос, заданный через “http-check send”: если они там присутствуют, они игнорируются. Старый приём добавления заголовков после строки версии в строке “option httpchk” теперь устарел.

Кроме того, “http-check send” не поддерживает постоянные соединения HTTP. Заголовок “Connection: close” добавляется автоматически, если заголовок Connection ещё не настроен записью hdr.

Заголовок Host и компонент authority запроса, если оба заданы, автоматически синхронизируются. Это означает, что при отправке запроса HTTP добавление Host в запрос соответственно обновляет компонент authority. Поэтому значение заголовка Host может перезаписать настроенный компонент authority запроса.

Кроме того, сейчас заголовок Host не добавляется автоматически в запросы HTTP/1.1 и выше. Его следует добавлять явно.

См. также: “option httpchk”, “http-check send-state” и “http-check expect”.

http-check send-state

http-check send-state

Включает отправку заголовка состояния при проверках работоспособности HTTP

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы: отсутствуют

При включённом параметре HAProxy всегда отправляет специальный заголовок “X-Haproxy-Server-State” со списком параметров, показывающих каждому серверу, каким его видит HAProxy. Например, это удобно при работе с сервером без доступа к HAProxy, когда оператору нужно знать, считает ли HAProxy сервер работающим или является ли он последним в группе.

Заголовок состоит из полей, разделённых точками с запятой. Первое поле — слово (“UP”, “DOWN”, “NOLB”), за которым может следовать число успешных проверок относительно общего числа, требуемого до перехода, как в интерфейсе статистики. Следующие поля имеют вид “<variable>=<value>” и в произвольном порядке указывают некоторые доступные в интерфейсе статистики значения: - переменная “address” содержит адрес сервера бэкенда и соответствует полю <address> в объявлении сервера. Для сокетов домена unix используется “unix”.

- Переменная "port" содержит порт сервера бэкенда и соответствует полю `<port>` в объявлении сервера. Для сокетов домена unix используется "unix".

- Переменная "name" содержит имя бэкенда, косую черту ("/"), затем имя сервера. Это удобно при проверках одного сервера в нескольких бэкендах.

- Переменная "node" содержит имя узла HAProxy, заданное глобальной переменной "node", либо имя хоста системы, если переменная не задана.

- Переменная "weight" содержит вес сервера, косую черту ("/") и общий вес группы с учётом только пригодных к работе серверов. Это помогает понять, доступны ли другие серверы для обработки нагрузки при отказе этого сервера.

- Переменная "scur" содержит текущее число одновременных соединений на сервере, косую черту ("/"), затем общее число соединений на всех серверах того же бэкенда.

- Переменная "qcur" содержит текущее число запросов в очереди сервера.

Пример заголовка, полученного прикладным сервером:

>>>  X-Haproxy-Server-State: UP 2/3; name=bck/srv2; node=lb1; weight=1/2; \
       scur=13/22; qcur=0

См. также: “option httpchk”, “http-check disable-on-404” и “http-check send”.

http-check set-var(<var-name>[,<cond>...]) <expr>

http-check set-var(<var-name>[,<cond>...]) <expr>
http-check set-var-fmt(<var-name>[,<cond>...]) <fmt>

Эта операция устанавливает содержимое переменной. Переменная объявляется непосредственно при использовании.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<var-name>    — имя переменной. Можно использовать только области видимости "proc", "sess" и
             "check". Подробности см. в разделе 2.8 о переменных.

 <cond>      Набор условий, которые должны быть истинны одновременно, чтобы переменная была
             задана (например, "ifnotempty", "ifgt" и т. д.). Полный список условий приведён в
             описании преобразователя set-var.

 <expr>      Выражение извлечения образца, за которым могут следовать преобразователи.

 <fmt>       Значение, заданное пользовательским форматом журнала (см. «Пользовательский
             формат журнала» в разделе 8.2.6).

Примеры:

http-check set-var(check.port) int(1234)
http-check set-var-fmt(check.port) "name=%H"

http-check unset-var(<var-name>)

http-check unset-var(<var-name>)

Освобождает ссылку на переменную в пределах её области видимости.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<var-name>    — имя переменной. Можно использовать только области видимости "proc", "sess" и
             "check". Подробности см. в разделе 2.8 о переменных.

Примеры:

http-check unset-var(check.port)

http-error status <code> [content-type <type>]

http-error status <code> [content-type <type>]
           [ { default-errorfiles | errorfile <file> | errorfiles <name> |
           file `<file>` | lf-file `<file>` | string `<str>` | lf-string `<fmt>` } ]
       [ hdr `<name>` `<fmt>` ]*

Определяет пользовательское сообщение об ошибке, которое будет использоваться вместо ошибок, генерируемых HAProxy.

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

status <code>         — это HTTP код состояния. Он должен быть указан. В настоящее время
                     HAProxy способен генерировать коды 200, 400, 401, 403,
                     404, 405, 407, 408, 410, 413, 414, 425,
                     429, 431, 500, 501, 502, 503 и 504.

content-type <type>  — тип содержимого ответа, например "text/plain". При настроенном errorfile или
                     пустом теле этот параметр игнорируется и его следует опустить. В остальных
                     случаях его необходимо задать.

default-errorfiles    сбрасывает ранее определённое сообщение об ошибке для текущего прокси для кода
                     состояния <code>. Если используется в бэкенде, используется сообщение об
                     ошибке из фронтенда, если оно определено. Если используется в фронтенде,
                     используется сообщение об ошибке по умолчанию.

errorfile <file>      указывает на файл, содержащий полный HTTP ответ. Рекомендуется
                     придерживаться общепринятой практики добавления ".http" к имени файла,
                     чтобы люди не путали ответ с HTML-страницами ошибок, и использовать
                     абсолютные пути, поскольку файлы читаются до выполнения chroot.

errorfiles <name>    Задаёт секцию http-errors, из которой импортируется сообщение об ошибке с
                     кодом состояния <code>. Если такое сообщение не найдено, рассматриваются
                     сообщения об ошибках самого прокси.

file <file>           указывает на файл, который следует использовать в качестве тела ответа.
                     Если файл не пуст, его content-type должен быть указан в качестве аргумента для
                     "content-type", в противном случае любой аргумент "content-type" игнорируется. <file>
                     рассматривается как необработанная строка.

string <str>          указывает на необработанную строку, которую следует использовать в
                     качестве тела ответа. content-type всегда должен быть указан в качестве
                     аргумента для "content-type".

lf-file <file>        указывает на файл, который следует использовать в качестве тела ответа.
                     Если файл не пуст, его content-type должен быть указан в качестве аргумента для
                     "content-type", в противном случае любой аргумент "content-type" игнорируется. <file>
                     интерпретируется как пользовательский формат журнала (см. раздел 8.2.6).

lf-string <str>      задаёт строку log-format для тела ответа. content-type обязательно задаётся
                     аргументом "content-type".

hdr <name> <fmt>     Добавляет в ответ поле заголовка HTTP с именем <name> и значением
                     <fmt>, заданным по правилам пользовательского формата журнала (см. раздел
                     8.2.6). При использовании errorfile этот параметр игнорируется.

Эту директиву можно использовать вместо “errorfile” для задания пользовательского сообщения об ошибке. Как и “errorfile”, она применяется к ошибкам, обнаруженным и возвращаемым HAProxy. Если задан errorfile, он разбирается при запуске HAProxy и должен соответствовать стандартам HTTP. Созданный ответ не должен превышать настроенный размер буфера (BUFFSIZE); иначе возвращается внутренняя ошибка. Наконец, если планируется переписывать эти ошибки правилами http-after-response, следует оставить доступным зарезервированное пространство буфера (см. “tune.maxrewrite”).

Файлы читаются одновременно с конфигурацией и сохраняются в памяти. По этой причине ошибки продолжают возвращаться даже при chroot, и изменения файла не учитываются во время работы процесса.

Примечание: ошибки 400/408/500, возникающие на ранней стадии разбора запроса, обрабатываются мультиплексором на более низком уровне. Пользовательское форматирование там не поддерживается, поэтому поддерживаются только статические сообщения об ошибках, заданные директивой “errorfile”. Однако ограничение действует лишь во время разбора заголовков запроса или между двумя транзакциями.

См. также: “errorfile”, “errorfiles”, “errorloc”, “errorloc302”, “errorloc303” и раздел 12.4 о http-errors.

http-request <action> [options...] [ { if | unless } <condition> ]

http-request <action> [options...] [ { if | unless } <condition> ]

Управление доступом для запросов уровня 7

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да(!) | да | да | да

Директива http-request определяет набор правил обработки уровня 7. В секции frontend, listen или backend правила проверяются в порядке объявления. После любого правила может следовать необязательное условие на основе ACL; тогда правило проверяется лишь при истинном результате условия.

Условие проверяется непосредственно перед выполнением действия, а действие выполняется ровно один раз. Поэтому действие может без проблем менять элемент, проверяемый условием. Несколько действий также могут зависеть от одного условия: первого действия, меняющего результат его проверки, достаточно для неявного отключения остальных действий. Например, так пустой переменной пытаются присвоить значение из разных источников. Число директив “http-request” на экземпляр не ограничено.

Первое ключевое слово после “http-request” в синтаксисе — действие правила. За ним может следовать разное число аргументов этого действия. Поддерживаемые действия и их синтаксис перечислены в разделе 4.3 «Действия» (см. действия с отметкой “HTTP Req”).

Эта директива доступна только в именованных секциях defaults, а в анонимных недоступна. Правила секции defaults проверяются до правил связанной с ней секции прокси. Во избежание неоднозначности одну и ту же секцию defaults нельзя использовать одновременно для прокси с возможностями фронтенда и прокси с возможностями бэкенда. Поэтому секция listen не может использовать секцию defaults с такими правилами.

Пример:

acl nagios src 192.168.129.3
acl local_net src 192.168.0.0/16
acl auth_ok http_auth(L1)

http-request allow if nagios
http-request allow if local_net auth_ok
http-request auth realm Gimme if local_net auth_ok
http-request deny

Пример:

acl key req.hdr(X-Add-Acl-Key) -m found
acl add path /addacl
acl del path /delacl

acl myhost hdr(Host) -f myhost.lst

http-request add-acl(myhost.lst) %[req.hdr(X-Add-Acl-Key)] if key add
http-request del-acl(myhost.lst) %[req.hdr(X-Add-Acl-Key)] if key del

Пример:

acl value  req.hdr(X-Value) -m found
acl setmap path /setmap
acl delmap path /delmap

use_backend bk_appli if { hdr(Host),map_str(map.lst) -m found }

http-request set-map(map.lst) %[src] %[req.hdr(X-Value)] if setmap value
http-request del-map(map.lst) %[src]                     if delmap

См. также: “stats http-request”, раздел 12.2 о списках пользователей и раздел 7 об использовании ACL.

http-response <action> <options...> [ { if | unless } <condition> ]

http-response <action> <options...> [ { if | unless } <condition> ]

Управление доступом для ответов уровня 7

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да(!) | да | да | да

Директива http-response определяет набор правил обработки уровня 7. В секции frontend, listen или backend правила проверяются в порядке объявления. Поскольку они применяются к ответам, сначала выполняются правила бэкенда, затем правила фронтенда. После любого правила может следовать необязательное условие на основе ACL; тогда правило проверяется лишь при истинном результате условия.

Условие проверяется непосредственно перед выполнением действия, а действие выполняется ровно один раз. Поэтому действие может без проблем менять элемент, проверяемый условием. Несколько действий также могут зависеть от одного условия: первого действия, меняющего результат его проверки, достаточно для неявного отключения остальных действий. Например, так пустой переменной пытаются присвоить значение из разных источников. Число директив “http-response” на экземпляр не ограничено.

Первое ключевое слово после “http-response” в синтаксисе — действие правила. За ним может следовать разное число аргументов этого действия. Поддерживаемые действия и их синтаксис перечислены в разделе 4.3 «Действия» (см. действия с отметкой “HTTP Res”).

Эта директива доступна только в именованных секциях defaults, а в анонимных недоступна. Правила секции defaults проверяются до правил связанной с ней секции прокси. Во избежание неоднозначности одну и ту же секцию defaults нельзя использовать одновременно для прокси с возможностями фронтенда и прокси с возможностями бэкенда. Поэтому секция listen не может использовать секцию defaults с такими правилами.

Пример:

acl key_acl res.hdr(X-Acl-Key) -m found

acl myhost hdr(Host) -f myhost.lst

http-response add-acl(myhost.lst) %[res.hdr(X-Acl-Key)] if key_acl
http-response del-acl(myhost.lst) %[res.hdr(X-Acl-Key)] if key_acl

Пример:

acl value  res.hdr(X-Value) -m found

use_backend bk_appli if { hdr(Host),map_str(map.lst) -m found }

http-response set-map(map.lst) %[src] %[res.hdr(X-Value)] if value
http-response del-map(map.lst) %[src]                     if ! value

См. также: “http-request”, раздел 12.2 о списках пользователей и раздел 7 об использовании ACL.

http-reuse { never | safe | aggressive | always }

http-reuse { never | safe | aggressive | always }

Определяет, как простаивающие соединения HTTP могут совместно использоваться запросами

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Чтобы не создавать новые соединения с серверами бэкенда для каждого запроса HTTP, HAProxy пытается сохранять использованные соединения открытыми во время простоя. Эти соединения относятся к определённому серверу и хранятся в списке, называемом пулом, где группируются по набору общих ключевых свойств. Последующие запросы HTTP ищут в соответствующем пуле совместимое соединение с идентичными свойствами и повторно используют его вместо создания нового.

Максимальное число простаивающих соединений, сохраняемых на сервере, задаётся серверным ключевым словом “pool-max-conn”. Неиспользуемые соединения периодически удаляются с интервалом “pool-purge-delay”.

Для определения, пригодно ли простаивающее соединение для повторного использования при данном запросе, используются следующие свойства соединения:

  • адреса источника и назначения
  • протокол proxy
  • параметры сокета TOS и mark
  • имя соединения, определяемое результатом вычисления выражения “pool-conn-name”, если оно задано; иначе — выражением “sni”, которое по умолчанию равно “req.hdr(host),field(1,:)”, то есть использует поле заголовка “Host” входящего запроса без двоеточия и номера порта.

Иногда из-за дополнительных ограничений поиск или повторное использование соединения не выполняется. Это определяется стратегией повторного использования, заданной аргументом ключевого слова:

- "never" : Простаивающие соединения никогда не используются совместно разными сеансами. Режим можно принудительно включить, чтобы отменить другую стратегию, унаследованную из секции defaults, или для устранения неполадок. Например, старое некорректное приложение может считать, что запросы в одном соединении идут от одного клиента; если исправить приложение нельзя, может быть желательно отключить совместное использование соединений в одном бэкенде. Пример — старый HAProxy со вставкой cookie в режиме туннеля, не проверяющий запросы после первого.

- "safe"  : Стратегия по умолчанию и рекомендуемая. Первый запрос сеанса всегда отправляется по собственному соединению; только последующие запросы могут направляться по другим существующим соединениям. Это позволяет браузеру молча повторить запрос, если сервер закроет соединение во время его отправки. Поскольку поведение в точности эквивалентно обычным постоянным соединениям, побочных эффектов быть не должно. Соединения с протоколами, подверженными блокировке начала очереди (бэкенд с h2 или fcgi), обрабатываются особо. При обработке хотя бы одного потока используемое соединение резервируется для потоков того же сеанса. Когда обрабатываемых потоков не остаётся, оно освобождается и может использоваться повторно.

- "aggressive": Режим может быть полезен в окружениях веб-служб, где не все серверы обязательно известны и желательно передавать большинство первых запросов по существующим соединениям. Первые запросы тогда передаются только по соединениям, уже повторно использованным хотя бы один раз: это доказывает правильную поддержку повторного использования сервером. Режим следует применять лишь при уверенности, что клиент иногда может повторить неудачный запрос и выгода от агрессивного повторного использования существенно превышает недостатки редких неудач соединения.

- "always": Режим рекомендуется только при уверенности, что на пути к серверу существующие соединения никогда не разрываются вскоре после освобождения. Первый запрос сеанса может отправляться по существующему соединению. При бэкенде из группы кешей это может заметно повысить производительность по сравнению с "safe": поведение таких компонентов обычно стабильно, а совместное использование соединений им полезно. В этом режиме рекомендуется сохранять низкий тайм-аут "http-keep-alive", чтобы неработающие соединения не оставались доступными для использования. В большинстве случаев прирост производительности будет таким же, как у "aggressive", но с большими рисками. Режим следует использовать только при улучшении ситуации по сравнению с "aggressive".

Также следует учитывать, что соединения с некоторыми сомнительными схемами аутентификации, зависящими от соединения, например NTLM, по возможности помечаются как частные и никогда не используются совместно. Однако это не так при использовании протокола с мультиплексированием и уровня режима повторного использования выше стратегии по умолчанию “safe”: в этом случае ничто не мешает соединению уже использоваться совместно.

Решение о том, оставить ли простаивающее соединение открытым или закрыть его после обработки, также определяется параметрами “tune.pool-low-fd-ratio” (по умолчанию: 20%) и “tune.pool-high-fd-ratio” (по умолчанию: 25%). Они задают долю от общего числа файловых дескрипторов, занятых простаивающими соединениями, при превышении которой HAProxy соответственно перестаёт оставлять соединения открытыми после ответа и начинает активно закрывать простаивающие соединения. В некоторых конфигурациях с очень высокой долей простаивающих соединений — из-за слишком низкого глобального “maxconn” либо большого объёма трафика HTTP/2 или HTTP/3 на фронтенде (мало соединений) при соединениях HTTP/1 на бэкенде — частота повторного использования может снижаться, поскольку открытыми сохраняются слишком немногие соединения. В таком случае может быть полезно изменить эти пороги либо просто увеличить глобальное значение “maxconn”.

В редких случаях, когда имя узла используется для различения исходящих соединений TLS, например в прямом прокси, и большинство запросов обращается к разным узлам, частота повторного использования будет очень низкой. Автоматическое вытеснение редко используемых соединений сработает раньше, чем их успеют использовать повторно, поскольку механизм непрерывно измеряет среднее число соединений, необходимое для обслуживания без исчерпания ресурсов. В таких ситуациях значение “pool-low-conn”, близкое к ожидаемому среднему числу простаивающих соединений, может помочь сохранить больше соединений: оно побуждает потоки создавать собственные, вместо того чтобы пытаться брать соединения других потоков и тем самым сокращать пул доступных соединений.

Если локально размещённый сервер использует один сертификат с несколькими именами узлов или шаблонами имён с подстановочными знаками и обслуживает несколько сайтов, может быть эффективнее указать “no-sni-auto” в строке “server”, чтобы не резервировать соединение для одного имени Host. Это значительно повысит частоту повторного использования. Однако некоторые серверы могут выполнять чрезмерные проверки соответствия Host и SNI и вследствие этого отклонять последующие запросы, поэтому параметр требует предварительной проверки. Поведение по умолчанию (“sni-auto”) обеспечивает безопасность и с такими серверами.

При явном включении групп потоков важно понимать, что простаивающие соединения могут использоваться только потоками одной группы. Поэтому неравномерная нагрузка между группами может потребовать больше простаивающих соединений и снизить частоту повторного использования. В этом случае можно применить то же решение: увеличить глобальный “maxconn” либо доли пула.

См. также: “option http-keep-alive”, “pool-conn-name”, “pool-max-conn”, “pool-purge-delay”, “server maxconn”, “sni”, “thread-groups”, “tune.pool-high-fd-ratio”, “tune.pool-low-fd-ratio”

http-send-name-header [<header>]

http-send-name-header [<header>]

Добавляет имя сервера в запрос. Использует строку заголовка, заданную <header>

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<header>  Строка заголовка для передачи имени сервера

Директива “http-send-name-header” устанавливает в поле заголовка с именем <header> имя целевого сервера непосредственно перед отправкой запроса в сеть. Все существующие вхождения этого заголовка удаляются. При повторных попытках и перераспределениях поле заголовка обновляется и всегда отражает сервер, с которым предпринимается попытка соединения. Поскольку заголовок изменяется очень поздно при установлении соединения, это может неожиданно повлиять на уже изменённые заголовки. Например, использование заголовков транспортного уровня, таких как connection, content-length, transfer-encoding и т. п., скорее всего приведёт к отправке серверу некорректных запросов. Поэтому запрещены следующие имена заголовков: host, content-length, transfer-encoding и connection.

См. также: “server”

id <value>

id <value>

Задаёт постоянный ID прокси.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend нет | да | да | да

Аргументы: отсутствуют

Задаёт постоянный ID прокси. ID должен быть уникальным и положительным. Если он не задан, автоматически назначается неиспользованный ID. По историческим причинам значение 1 не используется, если не задано явно. Поэтому наименьшее автоматически назначаемое значение — 2. Сейчас этот ID возвращается только в статистике.

ignore-persist { if | unless } <condition>

ignore-persist { if | unless } <condition>

Объявляет условие игнорирования привязки сеанса

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend нет | нет | да | да

По умолчанию при включённой привязке сеанса по cookie все запросы с этой cookie безусловно сохраняют привязку, если целевой сервер работает и доступен.

Директива “ignore-persist” позволяет объявить различные условия на основе ACL, при выполнении которых запрос игнорирует привязку сеанса. Иногда это полезно для балансировки запросов статических файлов, которым часто не требуется привязка сеанса. Также это позволяет полностью отключить привязку для определённого User-Agent, например для некоторых поисковых роботов.

Привязка сеанса игнорируется, когда выполняется условие “if” либо когда не выполняется условие “unless”.

Пример:

acl url_static  path_beg         /static /images /img /css
acl url_static  path_end         .gif .png .jpg .css .js
ignore-persist  if url_static

См. также: “force-persist”, “cookie” и раздел 7 об использовании ACL.

load-server-state-from-file { global | local | none }

load-server-state-from-file { global | local | none }

Позволяет перезагружать HAProxy без прерывания обслуживания

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Эта директива указывает HAProxy файл, в котором сохранено состояние серверов предыдущего работавшего процесса. При запуске, до начала обработки трафика, новый процесс может применить прежнее состояние к серверам так, словно перезагрузки не было. Директива “load-server-state-from-file” указывает HAProxy, какой файл использовать. Сейчас предусмотрены только 2 аргумента: запретить загрузку состояния либо загрузить его из файла со всеми бэкендами и серверами. Файл состояния можно создать, выполнив команду “show servers state” через сокет статистики и перенаправив вывод.

Формат файла имеет версию и строго определён. Для его понимания следует обратиться к описанию команды “show servers state” в главе 9.3 руководства по управлению.

Аргументы:

global     загружает содержимое файла, указанного глобальной директивой "server-state-file".

local      загружает содержимое файла, указанного директивой "server-state-file-name", если она задана. Иначе в
           качестве имени файла используется имя бэкенда.

none       не загружает состояние для этого бэкенда

Примечания: - адрес IP сервера по умолчанию сохраняется при перезагрузках, но порядок можно изменить параметром сервера “init-addr”. Это означает, что изменение адреса IP через CLI во время работы сохранится, а изменение локального средства разрешения имён, например /etc/hosts, может не иметь эффекта при использовании файла состояния.

- вес сервера переносится из предыдущего работавшего процесса, если он
  не изменился между прежним и новым файлами конфигурации.

Пример: минимальная конфигурация

  global
   stats socket /tmp/socket
   server-state-file /tmp/server_state

  defaults
   load-server-state-from-file global

  backend bk
   server s1 127.0.0.1:22 check weight 11
   server s2 127.0.0.1:22 check weight 12

Затем можно выполнить:

socat /tmp/socket - <<< "show servers state" > /tmp/server_state

Содержимое файла /tmp/server_state будет примерно таким:

1
# <field names skipped for the doc example>
1 bk 1 s1 127.0.0.1 2 0 11 11 4 6 3 4 6 0 0
1 bk 2 s2 127.0.0.1 2 0 12 12 4 6 3 4 6 0 0

Пример: минимальная конфигурация

global
 stats socket /tmp/socket
 server-state-base /etc/haproxy/states

defaults
 load-server-state-from-file local

backend bk
 server s1 127.0.0.1:22 check weight 11
 server s2 127.0.0.1:22 check weight 12

Затем можно выполнить:

socat /tmp/socket - <<< "show servers state bk" > /etc/haproxy/states/bk

Содержимое файла /etc/haproxy/states/bk будет примерно таким:

1
# <field names skipped for the doc example>
1 bk 1 s1 127.0.0.1 2 0 11 11 4 6 3 4 6 0 0
1 bk 2 s2 127.0.0.1 2 0 12 12 4 6 3 4 6 0 0

См. также: “server-state-file”, “server-state-file-name” и “show servers state”

log global

log global
log <target> [len <length>] [format <format>] [sample <ranges>:<sample_size>]
    [profile <prof>] <facility> [<level> [<minlevel>]]
no log

Включает ведение журнала событий и трафика для отдельного экземпляра.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Префикс:

no         следует использовать, когда необходимо очистить список средств журналирования,
           например чтобы не наследовать список по умолчанию. Этот префикс не допускает
           аргументов.

Аргументы:

global     следует использовать, когда параметры журналирования экземпляра совпадают с
           глобальными. Это наиболее распространённый вариант. "global" заменяет все аргументы
           log аргументами записей log из секции "global". Для экземпляра разрешена только одна
           директива "log global"; эта форма не принимает других параметров.

<target>   указывает, куда отправлять журналы. Формат совпадает с форматом журналов секции
           "global"; допустимы следующие варианты:

           - Адрес IPv4, за которым могут следовать двоеточие (':') и порт UDP.
             Если порт не указан, по умолчанию используется 514 — стандартный порт syslog.

           - Адрес IPv6, за которым следует двоеточие (':') и может следовать порт
             UDP. Если порт не указан, по умолчанию используется 514 — стандартный порт
             syslog.

           - Путь в файловой системе к сокету домена UNIX. Следует учитывать chroot —
             путь должен быть доступен внутри chroot — и uid/gid: запись по этому пути должна
             быть разрешена соответствующим пользователю и группе.

           - Номер файлового дескриптора в форме "fd@<number>", который может указывать на канал,
             терминал или сокет. В этом случае журналирование не буферизуется и для каждой
             записи выполняется один вызов writev(). Это несколько затратно, но допустимо для
             большинства нагрузок. Отправляемые таким образом сообщения не обрезаются, но могут
             быть отброшены; при этом увеличивается счётчик DroppedLogs. Вызов writev() атомарен
             даже для каналов, если размер сообщения не превышает PIPE_BUF, для которого POSIX
             рекомендует минимум 512 и который в большинстве современных операционных систем
             составляет 4096 байт. Более крупное сообщение может перемежаться с сообщениями
             других процессов. В исключительных случаях для отладки файловый дескриптор также
             можно направить в файл, но это существенно замедлит HAProxy, поскольку
             неблокирующие вызовы будут игнорироваться. Кроме того, очистить или ротировать этот
             файл без перезапуска процесса будет невозможно. Настроенный формат syslog
             сохраняется, поэтому вывод пригоден для сервера syslog по TCP. См. также
             форматы "short" и "raw" ниже.

           - "stdout" / "stderr" — псевдонимы соответственно "fd@1" и "fd@2", см. выше.

           - Кольцевой буфер в форме "ring@<name>" — размещённый в памяти кольцевой буфер,
             доступный через CLI командой "show events". Эта команда также выводит существующие
             кольцевые буферы и их размеры. Такие буферы теряются при перезагрузке конфигурации
             или перезапуске, но как дополнительный механизм они могут облегчить диагностику,
             обеспечивая немедленный доступ к журналам. О кольцевых буферах см. раздел 12.5.

           - Бэкенд журналирования в форме "backend@<name>". Сообщения журнала передаются
             соответствующему бэкенду журналирования, который отправляет их нужному серверу
             согласно настройкам балансировки нагрузки бэкенда. Бэкенд журналирования — секция
             backend с заданным "mode log"; подробнее см. "mode".

           - Явный префикс потокового адреса, например "tcp@", "tcp6@", "tcp4@" или
             "uxst@", создаёт неявный кольцевой буфер с сервером пересылки потока по заданному
             адресу.

           В параметре адреса можно ссылаться на переменные окружения; о них см. раздел 2.3.

<length>   необязательная максимальная длина строки. Более длинные строки журнала обрезаются
           перед отправкой. Это нужно, поскольку серверы syslog по-разному обрабатывают длину
           строк журнала. Все серверы поддерживают значение по умолчанию 1024, но некоторые
           просто отбрасывают более длинные строки, а другие записывают их. Если сервер
           поддерживает длинные строки, этот параметр можно задать так, чтобы избежать их
           обрезания. Если же сервер отбрасывает длинные строки, предпочтительнее обрезать их
           перед отправкой. Допустимые значения — от 80 до 65535 включительно. Значение
           по умолчанию 1024 обычно подходит для всех стандартных применений. В некоторых
           случаях длинных захваченных данных или журналов в формате JSON могут потребоваться
           большие значения. Если URI запросов обрезаются, также может потребоваться
           увеличить "tune.http.logurilen".

<ranges>   список диапазонов через запятую, определяющий, какие записи журнала включать в
           образец. Используется для распределения нагрузки от журналов, отправляемых серверу
           журналирования. Границы диапазонов не могут быть нулевыми; нумерация начинается с
           1; размер либо период образца в числе записей журнала обязательно задаётся
           параметром <sample_size>.

<sample_size> Размер образца в числе записей журнала, учитываемых при распределении нагрузки от
           журналирования. Используется для распределения нагрузки от журналов, отправляемых
           серверу syslog. Этот размер должен быть больше либо равен наибольшей верхней границе
           диапазонов. См. также параметр <ranges>.

<format> формат журнала, используемый при формировании сообщений syslog. Возможны следующие
         варианты:

  local     аналог формата сообщений syslog rfc3164, но без поля имени узла. Используется по
            умолчанию. Примечание: параметр "log-send-hostname" меняет формат по умолчанию на rfc3164.

  rfc3164   формат сообщений syslog RFC3164. (https://tools.ietf.org/html/rfc3164)

  rfc5424   формат сообщений syslog RFC5424. (https://tools.ietf.org/html/rfc5424)

  priority  сообщение, содержащее только уровень вместе с категорией syslog в угловых скобках,
            например '<63>', и следующий за ними текст. PID, дата, время, имя процесса и
            имя системы опускаются. Предназначено для локального сервера журналирования.

  short     сообщение, содержащее только уровень в угловых скобках, например '<3>', и
            следующий за ним текст. PID, дата, время, имя процесса и имя системы опускаются.
            Предназначено для локального сервера журналирования. Формат совместим с данными,
            принимаемыми средством журналирования systemd.

  timed     сообщение, содержащее только уровень в угловых скобках, например '<3>', за которым
            следуют дата ISO и текст. PID, имя процесса и имя системы опускаются.
            Предназначено для локального сервера журналирования.

  iso       сообщение, содержащее только дату ISO и следующий за ней текст. PID, имя
            процесса и имя системы опускаются. Предназначено для локального сервера
            журналирования.

  raw       сообщение, содержащее только текст. Уровень, PID, дата, время, имя процесса и
            имя системы опускаются. Предназначено для контейнеров или разработки, где важность
            сообщения зависит только от используемого файлового дескриптора (stdout/stderr).

<prof>     имя необязательной секции "log-profile", которая учитывается при формировании журнала для
           переопределения некоторых параметров журналирования. Подробнее см. "8.3.5. Профили
           журналирования".

<facility> должна быть одной из 24 стандартных категорий syslog:

               kern   user   mail   daemon auth   syslog lpr    news
               uucp   cron   auth2  ftp    ntp    audit  alert  cron2
               local0 local1 local2 local3 local4 local5 local6 local7

           Для форматов "short" и "raw" категория игнорируется, но всё равно требуется как
           позиционное поле. В этом случае рекомендуется "daemon", чтобы явно показать, что
           значение предназначено только для локального использования.

<level>    необязательный параметр для фильтрации исходящих сообщений. По умолчанию отправляются
           все сообщения. Если уровень задан, отправляются только сообщения с важностью не ниже
           этого уровня. Можно также задать необязательный минимальный уровень. Тогда сообщения,
           сформированные с более высоким уровнем важности, ограничиваются этим уровнем. Это
           позволяет избежать отправки сообщений "emerg" на все терминалы в некоторых
           конфигурациях syslog по умолчанию. Известны восемь уровней:

             emerg  alert  crit   err    warning notice info  debug

Важно помнить, что именно фронтенд решает, какие данные соединения журналировать. При переключении по содержимому записи журнала бэкенда игнорируются. Соединения журналируются на уровне “info”.

Однако объявление журналирования в бэкенде определяет, как и куда записываются изменения состояния серверов. Уровень “notice” используется для перехода сервера в рабочее состояние, “warning” — для сигналов завершения и окончательного прекращения работы сервиса, “alert” — при переходе сервера в нерабочее состояние.

Примечание: согласно RFC3164, перед отправкой сообщения обрезаются до 1024 байт.

Пример:

log global
log stdout format short daemon          # send log to systemd
log stdout format raw daemon            # send everything to stdout
log stderr format raw daemon notice     # send important events to stderr
log 127.0.0.1:514 local0 notice         # only send important events
log tcp@127.0.0.1:514 local0 notice notice  # same but limit output
                                            # level and send in tcp
log "${LOCAL_SYSLOG}:514" local0 notice   # send to local server

log-format <fmt>

log-format <fmt>

Задаёт пользовательскую строку формата журнала для записей о трафике

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Эта директива задаёт строку формата журнала для всех записей о трафике, проходящем через фронтенд, в котором указана эта строка. Если директива используется в секции defaults, тот же формат применяют все последующие фронтенды. Подробное описание пользовательской строки формата журнала приведено в разделе 8.2.6 .

Также можно задать отдельный log-format только для ошибок соединения; см. параметр “error-log-format”.

Директива “log-format” переопределяет предыдущие директивы “option tcplog”, “log-format”, “option httplog” и “option httpslog”.

log-format-sd <fmt>

log-format-sd <fmt>

Задаёт пользовательскую строку формата журнала для формирования structured-data RFC5424

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Эта директива задаёт строку формата журнала structured-data RFC5424 для всех записей о трафике, проходящем через фронтенд, в котором указана эта строка. Если директива используется в секции defaults, тот же формат применяют все последующие фронтенды. Подробное описание строки формата журнала приведено в разделе 8.2.6 .

Подробнее о части structured-data RFC5424 см. https://tools.ietf.org/html/rfc5424#section-6.3 .

Примечание: эта строка формата журнала применяется только к средствам журналирования, для которых задан формат “rfc5424”.

Пример:

log-format-sd [exampleSDID@1234\ bytes=\"%B\"\ status=\"%ST\"]

log-steps <steps>

log-steps <steps>

Задаёт этапы обработки транзакции, на которых следует формировать записи журнала.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Во время обработки транзакций tcp/http HAProxy может формировать записи журнала на разных этапах: accept, connect, request, response, close.

По умолчанию HAProxy формирует одну запись журнала на транзакцию, как только могут быть определены все элементы выражения logformat. На практике это обычно происходит в конце транзакции: после завершения ответа для HTTP либо соединения для TCP, если не используется “option logasap”.

Директива “log-steps” позволяет уточнить моменты формирования записей журнала и даже создавать несколько записей для одной транзакции. Специальное значение ‘all’ включает все доступные источники записей, позволяя отслеживать транзакцию от accept до close. Можно также выборочно задать отдельные источники по именам через запятую, определяя, когда формировать записи.

Распространённые источники записей журнала: accept, connect, request, response, close.

Пример:

frontend myfront
    option httplog
    log-steps accept,close         #only log accept and close for the txn

Источники записей, указанные как “этапы журналирования”, например accept и close, можно использовать без изменений в log-profiles после директивы ‘on’. Сочетание “log-steps” и log-profiles особенно удобно для точного управления записями, автоматически формируемыми HAProxy при обработке транзакций.

Этот параметр относится только к фронтендам и игнорируется в бэкендах.

См. также: “log-profile”

log-tag <string>

log-tag <string>

Задаёт метку для всех исходящих записей журнала

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Устанавливает в поле метки заголовка syslog эту строку. По умолчанию используется log-tag, заданный в секции global, либо, если он не задан, имя программы при запуске из командной строки — обычно “HAProxy”. Иногда это помогает различать несколько процессов на одном узле либо экземпляры разных заказчиков внутри одного процесса. В бэкенде записи о переходах серверов в рабочее или нерабочее состояние используют эту метку. Например, удобно задать log-tag для обслуживаемого заказчика в секции defaults, затем разместить все его фронтенды и бэкенды, а для следующего заказчика начать новую секцию defaults. См. также глобальную директиву “log-tag”.

max-keep-alive-queue <value>

max-keep-alive-queue <value>

Задаёт максимальную длину очереди сервера для сохранения соединений keep-alive

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

HTTP keep-alive по возможности старается повторно использовать одно и то же соединение с сервером, но иногда это мешает работе: например, когда у одного сервера много соединений, а остальные простаивают. Это особенно характерно для серверов статического содержимого.

Этот параметр задаёт порог числа соединений в очереди, при достижении которого HAProxy перестаёт пытаться повторно использовать тот же сервер и предпочитает найти другой. Значение по умолчанию -1 означает отсутствие ограничения. Ноль означает, что запросы keep-alive никогда не ставятся в очередь. Для близко расположенных серверов с низкой задержкой, нечувствительных к разрыву keep-alive, рекомендуется низкое значение: например, для локального сервера статического содержимого — 10 или меньше. Для удалённых серверов с высокой задержкой могут потребоваться более высокие значения, компенсирующие задержку и/или затраты на выбор другого сервера.

Это не влияет на ответы, для которых после ответа 401 сохраняется привязка к тому же серверу. Они всё равно направляются на тот же сервер, даже если должны быть поставлены в очередь.

См. также: “option http-server-close”, “option prefer-last-server”, параметр сервера “maxconn” и привязку сеанса по cookie.

max-session-srv-conns <nb>

max-session-srv-conns <nb>

Задаёт максимальное число исходящих соединений, которые могут оставаться простаивающими для данного клиентского сеанса. Значение по умолчанию — 5; оно точно равно MAX_SRV_LIST, определяемому при сборке.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

maxconn <conns>

maxconn <conns>

Задаёт максимальное число одновременных соединений на фронтенде

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы:

<conns>   максимальное число одновременных соединений, которые фронтенд принимает для
          обслуживания. Лишние соединения ставятся системой в очередь прослушивающего сокета и
          обслуживаются после закрытия одного из соединений.

Если система поддерживает это, на крупных сайтах может быть полезно существенно увеличить этот предел, чтобы HAProxy управлял очередями соединений и не оставлял попытки соединения клиентов без ответа. Значение не следует устанавливать выше глобального maxconn. Нужно также учитывать, что соединение содержит два буфера размером tune.bufsize каждый — по умолчанию 16kB — и другие данные; в итоге каждое установленное соединение потребляет около 33 kB RAM. Поэтому система среднего уровня с 1GB RAM при правильной настройке может выдерживать около 20000-25000 одновременных соединений.

Также при больших значениях <conns> серверы могут быть не рассчитаны на такую нагрузку, поэтому обычно разумно задать для них приемлемые ограничения числа соединений.

Если это значение равно нулю, как по умолчанию, используется глобальное значение “maxconn”.

См. также: “server”, “maxconn” секции global, “fullconn”

mode { tcp|http|log|spop }

mode { tcp|http|log|spop }

Задаёт режим работы или протокол экземпляра. Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да Аргументы:

tcp       экземпляр работает в чистом режиме TCP. Между клиентами и серверами
          устанавливается полнодуплексное соединение без анализа уровня 7. Это режим по
          умолчанию. Его следует использовать для SSL, SSH, SMTP и т. д.

http      экземпляр работает в режиме HTTP. Запрос клиента подробно анализируется до
          соединения с любым сервером. Все запросы, не соответствующие RFC, отклоняются.
          Возможны фильтрация, обработка и переключение на уровне 7. Именно в этом режиме
          HAProxy приносит основную пользу.

haterm    фронтенд работает в режиме проверки производительности HTTP haterm. Бэкенды его не
          поддерживают. Подробнее см. doc/haterm.txt.

log       В секции backend превращает бэкенд в бэкенд журналов. Его можно использовать как
          назначение для любой директивы "log" через синтаксис "backend@<name>". Сообщения журналов
          распределяются между серверами бэкенда по настройкам балансировки нагрузки, задаваемым
          ключевым словом "balance". Бэкенды журналов поддерживают серверы UDP: перед адресом
          сервера ставится префикс "udp@". Общие возможности бэкендов и серверов
          поддерживаются, но возможности, специфичные для TCP или HTTP, — нет.

spop      В секции backend превращает бэкенд в бэкенд spop. Режим обязателен, если бэкенд
          содержит серверы SPOA. Однако при режиме tcp он автоматически преобразуется в spop,
          если такие серверы обнаружены.

При переключении содержимого фронтенд и бэкенд обязательно должны работать в одном режиме (обычно HTTP); иначе конфигурация будет отклонена.

Пример:

defaults http_instances
    mode http

monitor fail { if | unless } <condition>

monitor fail { if | unless } <condition>

Добавляет условие сообщения об отказе в ответ на запрос мониторинга HTTP.

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend нет | да | да | нет

Аргументы:

if <cond>     Запрос мониторинга завершится неудачей, если условие выполнено, и успехом в
              остальных случаях. Условие следует задать как комбинированную проверку, которая
              обязательно вызывает отказ, если выполнены все условия. Например, малое число
              серверов одновременно в бэкенде и его резерве.

unless <cond> Запрос мониторинга завершится успехом только при выполненном условии, а иначе —
              неудачей. Условие может проверять наличие минимального числа активных серверов в
              списке бэкендов.

Эта директива добавляет условие, которое может заставить ответ на запрос мониторинга сообщить об отказе. По умолчанию при запросе внешним компонентом URI для мониторинга возвращается ответ 200. При выполнении одного из условий выше HAProxy возвращает 503 вместо 200. Это удобно для сообщения об отказе площадки внешнему компоненту, который может строить объявления маршрутов между площадками по доступности, сообщаемой HAProxy. В таком случае используется ACL с критерием “nbsrv”. “monitor fail” работает только в режиме HTTP. При необходимости оба сообщения состояния можно изменить с помощью “errorfile” или “errorloc”.

Пример:

frontend www
   mode http
   acl site_dead nbsrv(dynamic) lt 2
   acl site_dead nbsrv(static)  lt 2
   monitor-uri   /site_alive
   monitor fail  if site_dead

См. также: “monitor-uri”, “errorfile”, “errorloc”

monitor-uri <uri>

monitor-uri <uri>

Перехватывает URI, используемый запросами мониторинга внешних компонентов

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы:

<uri>     — точный URI для перехвата, чтобы вернуть состояние работоспособности HAProxy
          вместо пересылки запроса.

При получении во фронтенде запроса HTTP к <uri> HAProxy не пересылает и не журналирует его, а возвращает “HTTP/1.0 200 OK” либо “HTTP/1.0 503 Service unavailable” в зависимости от условий отказа “monitor fail”. Обычно этого достаточно, чтобы внешняя проверка HTTP определила, что служба UP и работает, без пересылки запроса серверу бэкенда. Метод HTTP, версия и все заголовки игнорируются, но сам запрос должен быть корректен хотя бы на уровне HTTP. Ключевое слово можно использовать только во фронтенде в режиме HTTP.

Запросы мониторинга обрабатываются очень рано: сразу после разбора запроса, ещё до любых “http-request”. До них применяются только наборы правил tcp-request. Журналировать эти запросы тоже нельзя, что соответствует их назначению. Для мониторинга можно настроить лишь один URI; при нескольких директивах “monitor-uri” последний определяет используемый URI. Такие запросы служат только для сообщения о работоспособности HAProxy вышестоящему компоненту. Однако можно добавить любое число условий с “monitor fail” и ACL, подстраивая результат под любую проверку (чаще всего число доступных серверов бэкенда).

Примечание: если <uri> начинается с косой черты (’/’), сопоставление выполняется с путём запроса вместо URI запроса. Это обходной путь, позволяющий запросам HTTP/2 совпадать с monitor-uri: в HTTP/2 клиентам рекомендуется отправлять только абсолютные URI.

Пример:

# Use /haproxy_test to report HAProxy's status
frontend www
    mode http
    monitor-uri /haproxy_test

См. также: “monitor fail”

option abortonclose

option abortonclose
no option abortonclose

Включает или отключает досрочное прерывание ещё не начатой обработки при закрытии соединения клиентом

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы: отсутствуют

TCP соединения можно закрывать независимо в каждом направлении; соединение, закрытое лишь в одном направлении, часто называют «полузакрытым». Изначально, когда в экосистеме HTTP преобладал «режим закрытия», при котором на соединение приходились только один запрос и один ответ перед закрытием, скриптовые клиенты довольно часто отправляли запрос, закрывали отправляющую сторону, ждали ответа, получали уведомление о закрытии и завершали работу. Но с появлением постоянных соединений (keep-alive) и более развитых протоколов эта практика практически исчезла. Теперь клиент закрывает соединение до получения ответа главным образом тогда, когда пользователь хочет прервать передачу или когда истекает тайм-аут и соединение закрывается.

Эти две ситуации (полузакрытое соединение и прерывание) неразличимы на стороне сервера (здесь — слушателя HAProxy). Это проблема: сохранение соединения и продолжение обработки запроса после прерывания клиентом может потреблять много ресурсов, особенно если закрытие вызвано нажатием кнопки «перезагрузить». Тогда новые запросы ставятся в очередь, а предыдущие не прерываются. И наоборот, безусловное прерывание при таком полузакрытии нарушило бы работу ряда TCP приложений и даже некоторых HTTP приложений во внутренних сетях, взаимодействующих с устаревшими агентами.

Параметр “abortonclose” позволяет выбрать нужное поведение: - во фронтенде он предотвращает обработку TLS рукопожатий, ожидающих на полузакрытом соединении. Это может произойти, если пользователь нажмёт «перезагрузить» во время HTTPS запроса под высокой нагрузкой, например при переключении VRRP между активным и резервным узлами HAProxy: все клиенты одновременно переподключаются к новому узлу, и всем нужно выполнить дорогостоящее полное TLS рукопожатие. Если оно занимает больше нескольких секунд, некоторые пользователи, вероятно, откажутся ждать, и тратить такты CPU на их рукопожатия бессмысленно. С учётом затрат CPU на TLS рукопожатия рекомендуется оставлять этот параметр включённым на фронтендах, доступных из интернета. Это поведение по умолчанию для входящих TLS соединений.

- в бэкенде он вызывает попытку прервать запрос при полузакрытии соединения,
  если запрос ещё не отправлен серверу (то есть ожидает в очереди или при
  попытке подключения). Если сервер уже обслуживает запрос, соединение с ним
  в свою очередь переводится в полузакрытое состояние, чтобы передать серверу
  ту же ситуацию; сервер затем решает, как действовать. Это поведение по
  умолчанию для бэкендов в режиме HTTP.

Рекомендуется включать этот параметр на доступных из интернета конечных точках TLS и HTTP сервисах и отключать его для чисто TCP сервисов, а также для устаревших сред, не доступных извне. По умолчанию он включён в HTTP бэкендах; его можно принудительно отключить, добавив перед ним ключевое слово “no” в самой секции backend или в секции “defaults”, из которой она наследует настройки. Он также включён по умолчанию для TLS слушателей и может быть принудительно отключён директивой “no option abortonclose” во фронтенде или в секции “defaults”, из которой он наследует настройки.

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

См. также: “timeout queue” и параметры сервера “maxconn” и “maxqueue”

option accept-invalid-http-request (deprecated)

option accept-invalid-http-request     (deprecated)
no option accept-invalid-http-request  (deprecated)

Включить или отключить ослабление правил разбора HTTP запросов

Ключевое слово “accept-invalid-http-request” устарело; вместо него используйте “option accept-unsafe-violations-in-http-request”.

option accept-invalid-http-response (deprecated)

option accept-invalid-http-response     (deprecated)
no option accept-invalid-http-response  (deprecated)

Включить или отключить ослабление правил разбора HTTP ответов

Ключевое слово “accept-invalid-http-response” устарело; вместо него используйте “option accept-unsafe-violations-in-http-response”.

option accept-unsafe-violations-in-http-request

option accept-unsafe-violations-in-http-request
no option accept-unsafe-violations-in-http-request

Включить или отключить ослабление правил разбора HTTP запросов

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы: отсутствуют

По умолчанию HAProxy соблюдает различные HTTP RFC при разборе сообщений. Это означает, что разбор достаточно строг и для некорректных сообщений клиенту возвращается ошибка. Это желательное поведение: такие сообщения в основном используются для атак, эксплуатирующих слабые места серверов и обходящих фильтрацию безопасности. Иногда браузер с ошибками по какой-либо причине (конфигурация, реализация…) не соблюдает эти RCF, и проблему не исправляют сразу. Тогда можно ослабить парсер HAProxy и принять некоторые некорректные запросы, задав этот параметр. По историческим причинам большинство правил относится к разбору H1. Более новые версии HTTP обычно аккуратнее проработаны, и приложения точнее соблюдают эти протоколы.

При включении этого параметра действуют следующие правила:

* Только в H1 недопустимые символы, включая символ NULL, в имени заголовка
  не приводят к отклонению сообщения; однако сам заголовок отбрасывается.

* Только в H1 символ NULL в значении заголовка принимается;

* Только в H1 символы с кодом выше 127 в URI принимаются. Список символов,
  допустимых в URI, строго определён RFC3986; символы 0-31, 32 (пробел),
  34 ('"'), 60 ('<'), 62 ('>'), 92 ('&#92;'), 94 ('^'), 96 ('`'),
  123 ('{'), 124 ('|'), 125 ('}'), 127 (удаление) и всё выше обычно запрещены.
  В H1 все символы из диапазона (0..32), а также 127 всегда блокируются. Все символы с кодом
  выше 127 (не включая его) также блокируются, кроме случая, когда этот
  параметр включён. Остальные символы (33..126) вообще не проверяются.

* В H1 и H2 URL, содержащие ссылки на фрагменты ('#' после пути),
  принимаются;

* Только в H1 компонент authority для запросов CONNECT не проверяется;

* Только в H1 компонент authority и значение заголовка Host не проверяются.

* Только в H1 проверки версии HTTP ослабляются. Разрешается пропускать
  запросы HTTP/0.9 GET (без указания версии), другие имена протоколов
  (например, RTSP), а также несколько цифр как в старшей, так и в
  младшей части номера версии.

* Только в H1 принимаются запросы WebSocket (RFC6455) без корректного поля
  заголовка "Sec-Websocket-Key".

Никогда не следует включать этот параметр по умолчанию: он скрывает ошибки приложений и создаёт бреши в безопасности. Его следует применять только после подтверждения проблемы.

При включении этого параметра некорректные, но принятые H1 запросы перехватываются для последующего анализа командой “show errors” через UNIX сокет статистики. Это также помогает подтвердить, что проблема устранена.

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

См. также: “option accept-unsafe-violations-in-http-response” и “show errors” в сокете статистики.

option accept-unsafe-violations-in-http-response

option accept-unsafe-violations-in-http-response
no option accept-unsafe-violations-in-http-response

Включить или отключить ослабление правил разбора HTTP ответов

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы: отсутствуют

Как и “option accept-unsafe-violations-in-http-request”, этот параметр можно использовать для ослабления правил разбора HTTP ответов. Его следует включать только для доверенных устаревших серверов, чтобы принимать некоторые некорректные ответы. По историческим причинам большинство правил относится к разбору H1. Более новые версии HTTP обычно аккуратнее проработаны, и приложения точнее соблюдают эти протоколы.

При включении этого параметра действуют следующие правила:

* Только в H1 коды состояния длиннее 3 цифр, значение которых помещается
  в 16 бит, не отклоняются.

* Только в H1 недопустимые символы, включая символ NULL, в имени заголовка
  не приводят к отклонению сообщения; однако сам заголовок отбрасывается.

* Только в H1 символ NULL в значении заголовка принимается;

* Только в H1 допускаются пустые значения заголовка Transfer-Encoding
  или несколько вхождений значения "chunked";

* Только в H1 компонент authority и значение заголовка Host не проверяются.

* Только в H1 проверки версии HTTP становятся менее строгими. Допускаются
  другие имена протоколов (например, RTSP) и несколько цифр как в старшей,
  так и в младшей части номера версии.

* Только в H1 допускаются ответы WebSocket (RFC6455), в которых отсутствует
  корректное поле заголовка "Sec-Websocket-Accept".

Никогда не следует включать этот параметр по умолчанию: он скрывает ошибки приложений и создаёт бреши в безопасности. Его следует применять только после подтверждения проблемы.

Когда эта опция включена, некорректные имена заголовков по-прежнему допускаются в ответах, но весь ответ сохраняется для последующего анализа с помощью запроса “show errors” через UNIX-сокет статистики. Это также помогает убедиться, что проблема устранена.

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

См. также: “option accept-unsafe-violations-in-http-request” и “show errors” через сокет статистики.

option allbackups

option allbackups
no option allbackups

Использовать все резервные серверы одновременно либо только первый из них

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы: отсутствуют

По умолчанию первый работоспособный резервный сервер получает весь трафик, когда все основные серверы недоступны. Иногда предпочтительно использовать несколько резервных серверов одновременно, поскольку одного недостаточно. Когда включена “option allbackups”, при недоступности всех основных серверов нагрузка распределяется между всеми резервными серверами. Используется тот же алгоритм балансировки с учётом весов серверов. Таким образом, резервные серверы больше не имеют приоритета друг перед другом.

Эта опция чаще всего используется со статическими группами серверов, предназначенными для возврата страницы с извинениями (“sorry”), когда приложение полностью недоступно.

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

option checkcache

option checkcache
no option checkcache

Анализировать все ответы серверов и блокировать ответы с cookie, которые могут попасть в кэш

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы: отсутствуют

Некоторые высокоуровневые фреймворки повсеместно устанавливают cookie приложения и не всегда дают разработчику достаточно возможностей управлять кэшированием ответов. Если с объектом, допускающим кэширование, возвращается cookie сеанса, возникает высокий риск смешения или кражи сеансов пользователей, проходящих через одни и те же кэши. В некоторых ситуациях лучше заблокировать ответ, чем допустить утечку конфиденциальных сведений о сеансе.

Опция “checkcache” включает глубокую проверку всех ответов серверов на строгое соответствие спецификации HTTP в части кэширования. Она тщательно проверяет заголовки “Cache-control”, “Pragma” и “Set-cookie” в ответе сервера, чтобы выявить риск кэширования cookie прокси на стороне клиента. Когда эта опция включена, клиенту могут быть переданы только следующие ответы: - все ответы без заголовка “Set-Cookie”; - все ответы с кодом, отличным от 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501, при условии, что сервер не установил поле заголовка “Cache-control: public”; - все ответы на запросы с методом, отличным от GET, HEAD, OPTIONS, TRACE, при условии, что сервер не установил поле заголовка ‘Cache-Control: public’; - ответы с заголовком ‘Pragma: no-cache’ - ответы с заголовком ‘Cache-control: private’ - ответы с заголовком ‘Cache-control: no-store’ - ответы с заголовком ‘Cache-control: max-age=0’ - ответы с заголовком ‘Cache-control: s-maxage=0’ - ответы с заголовком ‘Cache-control: no-cache’ - ответы с заголовком ‘Cache-control: no-cache=“set-cookie”’ - ответы с заголовком ‘Cache-control: no-cache=“set-cookie,’ (допускающим другие поля после set-cookie) - ответы, не содержащие ни сведений о свежести (“Cache-control” с “max-age” либо “s-maxage” или заголовка “Expires”), ни валидатора (заголовка “ETag” или “Last-Modified”), поскольку соответствующий спецификации кэш не сохраняет такой ответ.

Если ответ не соответствует этим требованиям, он блокируется так же, как правилом “http-response deny”, с ответом “HTTP 502 bad gateway”. Состояние сеанса отображается как “PH–”, что означает блокировку ответа прокси во время обработки заголовков. Кроме того, в журнал записывается оповещение, чтобы администраторы знали о необходимости исправления.

Из-за существенного влияния на приложение перед вводом в эксплуатацию следует тщательно протестировать его с включённой опцией. Также полезно всегда включать её при тестировании, даже если она не используется в рабочей среде: она сообщает о потенциально опасном поведении приложения.

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

option clitcpka

option clitcpka
no option clitcpka

Включает или отключает отправку пакетов TCP для поддержания соединения на стороне клиента

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы: отсутствуют

Если между клиентом и сервером находится межсетевой экран или другой компонент, учитывающий состояние сеанса, а протокол предполагает очень долгие сеансы с длительными периодами простоя (например, удалённые рабочие столы), один из промежуточных компонентов может решить, что слишком долго простаивавший сеанс истёк.

Включение поддержания соединений TCP на уровне сокета заставляет систему регулярно отправлять пакеты на другой конец соединения, сохраняя его активным. Интервал между проверочными пакетами задаётся только системой и зависит от операционной системы и её настроек.

Важно понимать, что пакеты поддержания соединения не отправляются и не принимаются на уровне приложения: их видят только сетевые стеки. Поэтому даже если одна сторона прокси уже использует такие пакеты для сохранения соединения, они не пересылаются на другую сторону прокси.

Это никак не связано с постоянными соединениями HTTP.

Параметр “clitcpka” включает отправку проверочных пакетов TCP для поддержания соединения на клиентской стороне. Это должно помочь, если наблюдается истечение времени жизни сеансов между HAProxy и клиентом.

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

См. также: “option srvtcpka”, “option tcpka”

option contstats

option contstats

Включить непрерывное обновление статистики трафика

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы: отсутствуют

По умолчанию счётчики, используемые для расчёта статистики, увеличиваются только при завершении потока. Это достаточно хорошо работает при обслуживании небольших объектов, но для больших объектов (например, крупных изображений или архивов) либо потоковой передачи аудио и видео график, построенный по счётчикам HAProxy, напоминает ежа. Если включить эту опцию, счётчики будут регулярно увеличиваться во время передачи потока, обычно каждые 5 секунд, чего зачастую достаточно для получения ровных графиков. Пересчёт напрямую затрагивает часто выполняемый участок кода, поэтому по умолчанию он не включён: при очень большом числе сеансов он может вызывать множество пробуждений и небольшое снижение производительности.

option disable-h2-upgrade

option disable-h2-upgrade
no option disable-h2-upgrade

Включить или выключить неявное переключение клиентского соединения HTTP/1.x на HTTP/2.

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы: отсутствуют

По умолчанию HAProxy может неявно переключить клиентское соединение HTTP/1.x на HTTP/2, если первый запрос, полученный по данному HTTP-соединению, совпадает с преамбулой соединения HTTP/2 (то есть строкой “PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n”). Это позволяет поддерживать клиентов HTTP/1.x и HTTP/2 в соединениях без SSL. Для отключения неявного переключения необходимо использовать эту опцию. Учтите, что такое переключение поддерживается только для HTTP-прокси; это ограничение распространяется и на опцию. Кроме того, можно принудительно использовать HTTP/2 в незашифрованных соединениях, указав “proto h2” в строке bind. Эта опция применяется ко всем строкам bind. Чтобы отключить неявное переключение на HTTP/2 для конкретной строки bind, можно использовать “proto h1”.

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

option dontlog-normal

option dontlog-normal
no option dontlog-normal

Включить или выключить запись в журнал обычных успешных соединений

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы: отсутствуют

Существуют крупные сайты, обрабатывающие несколько тысяч соединений в секунду, для которых ведение журнала создаёт серьёзные трудности. Некоторые даже вынуждены выключать журналы и теряют возможность диагностировать проблемы в рабочей среде. Эта опция гарантирует, что обычные соединения, в которых не было ошибок, тайм-аутов, повторных попыток или перенаправления на другой сервер, не попадут в журнал. Тем самым место на диске остаётся для аномалий. В режиме HTTP проверяется код состояния ответа, и ответы с кодами 5xx всё равно записываются в журнал.

Настоятельно не рекомендуется использовать эту опцию: чаще всего ключ к решению сложных проблем содержится в обычных записях журнала, которые в данном случае отсутствуют. Если требуется разделить журналы, см. опцию “log-separate-errors”.

См. также: “log”, “dontlognull”, “log-separate-errors” и раздел 8 о ведении журнала.

option dontlognull

option dontlognull
no option dontlognull

Включить или выключить запись в журнал пустых соединений

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы: отсутствуют

В некоторых средах отдельные компоненты регулярно подключаются к различным системам, чтобы убедиться, что те работают. Такие подключения могут исходить как от другого балансировщика, так и от систем мониторинга. По умолчанию даже простая проверка или сканирование порта создаёт запись в журнале. Если эти соединения слишком сильно засоряют журналы, можно включить опцию “dontlognull”: соединение, по которому не было передано данных, не будет записываться в журнал. Обычно этому условию соответствуют такие проверки. Учтите, что ошибки по-прежнему возвращаются клиенту и учитываются в статистике. Если это нежелательно, можно использовать опцию option http-ignore-probes.

Как правило, в неконтролируемых средах (например, в интернете) рекомендуется не использовать эту опцию, иначе сканирование и другие вредоносные действия не будут записываться в журнал.

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

См. также: “log”, “http-ignore-probes”, “monitor-uri” и раздел 8 о ведении журнала.

option external-check

option external-check

Использовать внешние процессы для проверок работоспособности серверов

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Работоспособность сервера можно проверять с помощью внешней команды. Для этого запускается исполняемый файл, заданный директивой “external-check command”.

Требуется включить глобальную директиву “external-check”.

См. также: “external-check”, “external-check command”, “external-check path”

option forwarded [ proto ]

option forwarded [ proto ]
                 [ host | host-expr <host_expr> ]
                 [ by | by-expr <by_expr> ] [ by_port | by_port-expr <by_port_expr>]
                 [ for | for-expr <for_expr> ] [ for_port | for_port-expr <for_port_expr>]
no option forwarded

Включить добавление заголовка forwarded по rfc 7239 в запросы, отправляемые серверам

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<host_expr>     необязательный аргумент, задающий пользовательское выражение образца, результат
                которого используется как значение параметра 'host'

<by_expr>       необязательный аргумент, задающий пользовательское выражение образца, результат
                которого используется как значение "nodename" параметра 'by'

<for_expr>      необязательный аргумент, задающий пользовательское выражение образца, результат
                которого используется как значение "nodename" параметра 'for'

<by_port_expr>  необязательный аргумент, задающий пользовательское выражение образца, результат
                которого используется как значение "nodeport" параметра 'by'

<for_port_expr> необязательный аргумент, задающий пользовательское выражение образца, результат которого
                используется как значение "nodeport" параметра 'for'

Поскольку HAProxy работает в режиме обратного прокси, серверы теряют часть контекста запроса (его происхождение: IP-адрес клиента, используемый протокол и т. д.).

Распространённый способ обойти это ограничение — использовать известный заголовок x-forward-for и другие заголовки x-forward-*, чтобы передать часть контекста серверам и приложениям за прокси. Хотя этот подход работает и широко применяется, IETF официально его не поддерживает, и он может стать причиной проблем совместимости и безопасности.

Для решения этой проблемы IETF описал новое расширение HTTP: заголовок forwarded (RFC7239). Дополнительные сведения: https://www.rfc-editor.org/rfc/rfc7239.html

Один этот заголовок позволяет передать множество сведений и, главное, решает проблему цепочек прокси. (RFC допускает, чтобы несколько последовательно расположенных прокси добавляли собственные значения в уже существующий заголовок.)

Эту опцию можно указать в секциях defaults, listen или backend, но в секциях frontend она игнорируется.

Директива option forwarded без аргументов использует неявное поведение по умолчанию: включает параметр proto и добавляет исходный IP-адрес клиента.

Эквивалентная явная конфигурация, заданная вручную:

option forwarded proto for

Ключевое слово ‘by’ включает параметр ‘by’ (“nodename”) в заголовке forwarded и позволяет добавить сведения о прокси, через который проходит запрос. Значением ‘by’ будет IP-адрес прокси (адрес назначения). Если он недоступен (например, для UNIX-слушателя), ‘by’ получит значение “unknown”.

Ключевое слово ‘by-expr’ включает параметр ‘by’ (“nodename”) в заголовке forwarded и позволяет добавить сведения о прокси, через который проходит запрос. Значением ‘by’ будет результат выражения образца <by_expr>, если он корректен; иначе устанавливается “unknown”.

Ключевое слово ‘for’ включает параметр ‘for’ (“nodename”) в заголовке forwarded и позволяет добавить сведения о клиенте, от которого поступил запрос. Значением ‘for’ будет IP-адрес клиента (адрес источника). Если он недоступен (например, для UNIX-слушателя), ‘for’ получит значение “unknown”.

Ключевое слово ‘for-expr’ включает параметр ‘for’ (“nodename”) в заголовке forwarded и позволяет добавить сведения о клиенте, от которого поступил запрос. Значением ‘for’ будет результат выражения образца <for_expr>, если он корректен; иначе устанавливается “unknown”.

Ключевое слово ‘by_port’ добавляет сведения “nodeport” к параметру ‘by’. Для ‘by_port’ необходимо задать ‘by’ или ‘by-expr’, иначе оно игнорируется. Если порт прокси (порт назначения) доступен, “nodeport” получает его значение; в противном случае он игнорируется.

Ключевое слово ‘by_port-expr’ добавляет сведения “nodeport” к параметру ‘by’. Для ‘by_port-expr’ необходимо задать ‘by’ или ‘by-expr’, иначе оно игнорируется. Значением “nodeport” будет результат выражения образца <by_port_expr>, если он корректен; иначе он игнорируется.

Ключевое слово ‘for_port’ добавляет сведения “nodeport” к параметру ‘for’. Для ‘for_port’ необходимо задать ‘for’ или ‘for-expr’, иначе оно игнорируется. Если порт клиента (порт источника) доступен, “nodeport” получает его значение; в противном случае он игнорируется.

Ключевое слово ‘for_port-expr’ добавляет сведения “nodeport” к параметру ‘for’. Для ‘for_port-expr’ необходимо задать ‘for’ или ‘for-expr’, иначе оно игнорируется. Значением “nodeport” будет результат выражения образца <for_port_expr>, если он корректен; иначе он игнорируется.

Примеры:

# Those servers want the ip address and protocol of the client request
# Resulting header would look like this:
#   forwarded: proto=http;for=127.0.0.1
backend www_default
    mode http
    option forwarded
    #equivalent to: option forwarded proto for

# Those servers want the requested host and hashed client ip address
# as well as client source port (you should use seed for xxh32 if ensuring
# ip privacy is a concern)
# Resulting header would look like this:
#   forwarded: host="haproxy.org";for="_000000007F2F367E:60138"
backend www_host
    mode http
    option forwarded host for-expr src,xxh32,hex for_port

# Those servers want custom data in host, for and by parameters
# Resulting header would look like this:
#   forwarded: host="host.com";by=_haproxy;for="[::1]:10"
backend www_custom
    mode http
    option forwarded host-expr str(host.com) by-expr str(_haproxy) for for_port-expr int(10)

# Those servers want random 'for' obfuscated identifiers for request
# tracing purposes while protecting sensitive IP information
# Resulting header would look like this:
#   forwarded: for=_000000002B1F4D63
backend www_for_hide
    mode http
    option forwarded for-expr rand,hex

См. также: “option forwardfor”, “option originalto”

option forwardfor [ except <network> ] [ header <name> ] [ if-none ]

option forwardfor [ except <network> ] [ header <name> ] [ if-none ]

Включить добавление заголовка X-Forwarded-For в запросы, отправляемые серверам

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

<network> необязательный аргумент, выключающий эту опцию для источников, соответствующих <network>
<name>    необязательный аргумент, задающий другое имя заголовка "X-Forwarded-For".

Поскольку HAProxy работает в режиме обратного прокси, серверы видят его IP-адрес как адрес клиента. Это иногда неудобно, если в журналах сервера должен быть указан IP-адрес клиента. Чтобы решить эту проблему, HAProxy может добавлять известный HTTP-заголовок “X-Forwarded-For” ко всем запросам, отправляемым серверу. Значение этого заголовка содержит IP-адрес клиента. Поскольку заголовок всегда добавляется в конец существующего списка заголовков, сервер необходимо настроить на использование только последнего вхождения этого заголовка. Способ включения поддержки данного стандартного заголовка описан в руководстве сервера. Учтите, что необходимо использовать только последнее вхождение: клиент вполне может уже передать собственный такой заголовок.

Ключевое слово “header” позволяет задать другое имя заголовка вместо стандартного “X-Forwarded-For”. Это полезно, если заголовок “X-Forwarded-For” уже поступает от другого приложения (например, stunnel) и его требуется сохранить. Также это полезно, если сервер бэкенда не использует “X-Forwarded-For” и требует другой заголовок (например, серверы Zeus требуют “X-Cluster-Client-IP”).

Иногда один экземпляр HAProxy обслуживает как прямой доступ клиентов, так и доступ через обратный прокси (например, если обратный SSL-прокси расшифровывает HTTPS-трафик). Можно отключить добавление заголовка для известного адреса или сети источника, указав ключевое слово “except”, а затем адрес сети. В этом случае заголовок не добавляется для IP-адресов источника, входящих в эту сеть. Чаще всего это применяется для частных сетей или 127.0.0.1. Поддерживаются как IPv4, так и IPv6.

Другой вариант — ключевое слово “if-none”: заголовок добавляется, только если он ещё отсутствует. Его следует использовать исключительно в полностью доверенной среде, поскольку контроль конечного пользователя над заголовками, поступающими в HAProxy, может привести к проблеме безопасности.

Эту опцию можно указать во фронтенде или бэкенде. Если она используется хотя бы в одном из них, заголовок добавляется. Если подчинённый аргумент header задан и во фронтенде, и в бэкенде, значение бэкенда имеет приоритет. Что касается аргумента “if-none”, если хотя бы один из них его не задаёт, он требует обязательного добавления заголовка, и это требование имеет приоритет.

Пример:

# Public HTTP address also used by stunnel on the same machine
frontend www
    mode http
    option forwardfor except 127.0.0.1  # stunnel already adds the header

# Those servers want the IP Address in X-Client
backend www
    mode http
    option forwardfor header X-Client

См. также: “option httpclose”, “option http-server-close”, “option http-keep-alive”

option h1-case-adjust-bogus-client

option h1-case-adjust-bogus-client
no option h1-case-adjust-bogus-client

Включить или выключить изменение регистра заголовков HTTP/1, отправляемых некорректно работающим клиентам

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы: отсутствуют

Стандартный регистр имён заголовков отсутствует: согласно RFC7230, регистр для них не имеет значения. Поэтому приложения должны обрабатывать их без учёта регистра. Однако некоторые некорректно работающие приложения нарушают стандарты и ошибочно полагаются на регистр, чаще всего используемый браузерами. Проблема становится критической в HTTP/2: все имена заголовков должны передаваться в нижнем регистре, и HAProxy следует тому же правилу. Все имена заголовков отправляются клиентам и серверам в нижнем регистре независимо от версии HTTP.

Когда HAProxy получает ответ HTTP/1, имена его заголовков преобразуются в нижний регистр; дальнейшая обработка и отправка клиентам выполняются в этом виде. Если известно, что клиент нарушает стандарты HTTP и не может обработать ответ HAProxy, можно преобразовать имена заголовков из нижнего регистра в другой формат при формировании ответа и его отправке клиенту. Для этого нужно включить эту опцию и задать список преобразуемых заголовков глобальными директивами “h1-case-adjust” или “h1-case-adjust-file”. Это обязательно должно быть лишь временным обходным решением на период исправления клиента: клиенты, которым требуются такие меры, могут быть уязвимы к атакам с контрабандой содержимого (content smuggling), и их обязательно нужно исправить.

Учтите, что эта опция не влияет на клиентов, соблюдающих стандарты.

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

См. также: “option h1-case-adjust-bogus-server”, “h1-case-adjust”, “h1-case-adjust-file”.

option h1-case-adjust-bogus-server

option h1-case-adjust-bogus-server
no option h1-case-adjust-bogus-server

Включить или выключить изменение регистра заголовков HTTP/1, отправляемых некорректно работающим серверам

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы: отсутствуют

Стандартный регистр имён заголовков отсутствует: согласно RFC7230, регистр для них не имеет значения. Поэтому приложения должны обрабатывать их без учёта регистра. Однако некоторые некорректно работающие приложения нарушают стандарты и ошибочно полагаются на регистр, чаще всего используемый браузерами. Проблема становится критической в HTTP/2: все имена заголовков должны передаваться в нижнем регистре, и HAProxy следует тому же правилу. Все имена заголовков отправляются клиентам и серверам в нижнем регистре независимо от версии HTTP.

Когда HAProxy получает запрос HTTP/1, имена его заголовков преобразуются в нижний регистр; дальнейшая обработка и отправка серверам выполняются в этом виде. Если известно, что сервер нарушает стандарты HTTP и не может обработать запрос HAProxy, можно преобразовать имена заголовков из нижнего регистра в другой формат при формировании запроса и его отправке серверу. Для этого нужно включить эту опцию и задать список преобразуемых заголовков глобальными директивами “h1-case-adjust” или “h1-case-adjust-file”. Это обязательно должно быть лишь временным обходным решением на период исправления сервера: серверы, которым требуются такие меры, могут быть уязвимы к атакам с контрабандой содержимого (content smuggling), и их обязательно нужно исправить.

Учтите, что эта опция не влияет на серверы, соблюдающие стандарты.

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

См. также: “option h1-case-adjust-bogus-client”, “h1-case-adjust”, “h1-case-adjust-file”.

option http-buffer-request

option http-buffer-request
no option http-buffer-request

Включить или выключить ожидание всего тела HTTP-запроса перед продолжением обработки

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы: отсутствуют

Иногда перед принятием решения желательно дождаться тела HTTP-запроса. Например, так работает “balance url_param”. Первый вариант применения — буферизация запросов медленных клиентов перед подключением к серверу. Другой вариант — выбор маршрута по содержимому тела запроса. Эта опция, указанная во фронтенде или бэкенде, заставляет обработку HTTP ждать, пока не будет получено всё тело либо не заполнится буфер запроса. У некоторых приложений, использующих HTTP нестандартным образом и ожидающих передачу данных между фронтендом и бэкендом без буферизации, это может вызвать нежелательные побочные эффекты. Поэтому эту опцию однозначно не следует включать по умолчанию.

См. также: “option http-no-delay”, “timeout http-request”, “http-request wait-for-body”

option http-drop-request-trailers

option http-drop-request-trailers
no option http-drop-request-trailers

Удалять завершающие поля HTTP (trailers) из запроса при его отправке серверу

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | нет | да

Аргументы: отсутствуют

Когда эта опция включена, все завершающие поля HTTP, обнаруженные в запросе, удаляются перед его отправкой серверу.

В RFC9110#section-6.5.1 указано, что завершающие поля можно объединять с полями заголовков. Это следует делать намеренно, но для некоторых приложений такое поведение может оказаться проблемой, особенно если злоумышленники скрывают конфиденциальные поля заголовков в завершающей части запроса, а посредники объединяют их с заголовками без специальных проверок. В этом случае в бэкенде можно включить эту опцию, чтобы удалять все завершающие поля из запросов перед их отправкой серверу.

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

См. также: “option http-drop-response-trailers”

option http-drop-response-trailers

option http-drop-response-trailers
no option http-drop-response-trailers

Удаляет завершающие поля HTTP из ответа при отправке клиенту

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы: отсутствуют

Параметр похож на “option http-drop-request-trailers”, но для удаления завершающих полей из ответов перед отправкой клиентам необходимо использовать именно его.

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

См. также: “option http-drop-request-trailers”

option http-ignore-probes

option http-ignore-probes
no option http-ignore-probes

Включает или отключает журналирование пустых соединений и тайм-аутов запросов

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы: отсутствуют

Недавно некоторые браузеры начали реализовывать возможность “pre-connect”: они заранее соединяются с недавно посещёнными сайтами на случай, если пользователь захочет зайти туда снова. В результате с сайтами устанавливается много соединений, заканчивающихся 408 Request Timeout, если тайм-аут наступает первым, либо 400 Bad Request, если браузер первым решает закрыть соединение. Они засоряют журнал и увеличивают счётчики ошибок. “option dontlognull” уже существовал, но здесь его недостаточно. Вместо этого параметр делает следующее: - не отправляет клиенту сообщения 400/408, если по соединению ничего не получено до его закрытия; - не создаёт в этом случае записей журнала; - не увеличивает никакие счётчики ошибок

Таким образом, пустое соединение молча игнорируется. Лучше не использовать параметр без очевидной необходимости: он скроет реальные проблемы. Самая частая причина отсутствия запроса и появления 408 — несогласованность MTU между клиентом и промежуточным компонентом, например VPN, блокирующим слишком большие пакеты. Обычно такие проблемы проявляются в запросах POST и GET с большими cookie. Журналы часто являются единственным способом их обнаружить.

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

См. также: “log”, “dontlognull”, “errorfile” и раздел 8 о журналировании.

option http-keep-alive

option http-keep-alive
no option http-keep-alive

Включает или отключает постоянные соединения HTTP между клиентом и сервером для соединений HTTP/1.x

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы: отсутствуют

По умолчанию HAProxy использует режим постоянных соединений HTTP/1.x: в каждом соединении обрабатывает запросы и ответы, оставляя соединение простаивать с обеих сторон. Режим можно изменить параметрами, например “option http-server-close” или “option httpclose”. Этот параметр возвращает режим постоянных соединений, что удобно, когда в секции defaults задан другой режим.

“option http-keep-alive” включает режим постоянных соединений HTTP на стороне клиента и сервера. Он обеспечивает наименьшую задержку на стороне клиента (в медленной сети) и самое быстрое повторное использование сеансов на стороне сервера ценой сохранения простаивающих соединений с серверами. Для малых объектов с этим параметром обычно можно достичь примерно вдвое большей интенсивности запросов, чем с “http-server-close”. Он может быть полезен главным образом в двух случаях:

- Сервер не соблюдает HTTP и аутентифицирует соединение вместо запросов (например, аутентификация NTLM).

- Стоимость установления соединения с сервером значительна по сравнению со стоимостью получения с него соответствующего объекта.

Последний случай возможен, когда сервер — быстрый статический сервер кеша.

Сейчас журналы не показывают, пришли ли запросы из одного сеанса. Указанное в журналах время приёма соответствует окончанию предыдущего запроса, а время запроса — ожиданию нового. Время запроса в постоянном соединении по-прежнему ограничено “timeout http-keep-alive” либо “timeout http-request”, если первый не задан.

Этот параметр отключает и заменяет любые ранее заданные “option httpclose” или “option http-server-close”.

См. также: “option httpclose”, “option http-server-close”, “option prefer-last-server” и “option http-pretend-keepalive”.

option http-no-delay

option http-no-delay
no option http-no-delay

Предписать системе отдавать приоритет малой задержке интерактивного обмена перед производительностью HTTP

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы: отсутствуют

В HTTP каждая полезная нагрузка однонаправленная и не предполагает интерактивности. Ожидается, что любой агент в некоторой мере ставит данные в очередь с разумно малой задержкой. Некоторые очень редкие приложения обмена между серверами злоупотребляют HTTP, ожидая высокой интерактивности на этапе полезной нагрузки с множеством чередующихся фрагментов данных в обе стороны в одном запросе. Спецификация HTTP совершенно не поддерживает это, и через большинство прокси или серверов это не работает. Через HAProxy такие приложения работают, но испытывают большие задержки из-за сетевых оптимизаций, повышающих производительность: системе предписывается ждать достаточного объёма данных для отправки лишь полных пакетов. Типичные задержки — около 200 ms на полный цикл обмена. Это происходит только при ненормальном использовании. Обычные сценарии, например запросы CONNECT и WebSockets, не затрагиваются.

При наличии “option http-no-delay” во фронтенде или бэкенде соединения все такие оптимизации отключаются для максимально быстрого обмена. Работоспособность при этом не гарантируется: нарушение может возникнуть в другом месте. Но если приложение работает через HAProxy, оно будет работать максимально быстро. Этот параметр никогда не следует использовать по умолчанию и вообще не следует применять, пока не обнаружено такое ошибочное приложение. Его использование увеличивает расход пропускной способности и CPU, что может значительно снизить производительность в средах с высокой задержкой.

См. также: “option http-buffer-request”

option http-pretend-keepalive

option http-pretend-keepalive
no option http-pretend-keepalive

Определить, будет ли HAProxy объявлять постоянное соединение HTTP/1.x с сервером

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы: отсутствуют

При “option http-server-close” или “option httpclose” HAProxy добавляет заголовок “Connection: close” в запрос HTTP/1.x, пересылаемый серверу. К сожалению, некоторые серверы при этом автоматически отказываются от кодирования по частям для ответов неизвестной длины, хотя эти вещи совершенно не связаны. В результате клиент или кэш может получить неполный ответ, не заметив этого, и считать его полным.

При “option http-pretend-keepalive” HAProxy даёт серверу понять, что соединение будет сохраняться открытым. Тогда сервер не переходит к описанному выше ошибочному поведению. Получив весь ответ, HAProxy закрывает соединение с сервером, как при “option httpclose”. Поэтому клиент получает нормальный ответ, а соединение на стороне сервера корректно закрывается.

Не рекомендуется включать этот параметр по умолчанию: большинство серверов эффективнее сами закрывают соединение после последнего пакета и немного раньше освобождают буферы. Дополнительный сетевой пакет также может немного снизить общую пиковую производительность. Однако при включённом параметре у HAProxy немного меньше работы. Если узкое место всей архитектуры — HAProxy, его включение может сэкономить несколько циклов CPU.

Параметр можно задавать в секциях backend и listen. Во фронтенде он игнорируется, и при запуске выдаётся предупреждение. Параметр относится к бэкенду, поэтому задавать его на фронтенде практически незачем.

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

См. также: “option httpclose”, “option http-server-close” и “option http-keep-alive”

option http-restrict-req-hdr-names { preserve | delete | reject }

option http-restrict-req-hdr-names { preserve | delete | reject }

Задать политику HAProxy для имён заголовков запросов HTTP с символами вне набора “[a-zA-Z0-9-]”

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

preserve  отключить фильтрацию. Режим по умолчанию для прокси HTTP без настроенного
          приложения FastCGI.

delete    удалить заголовки запросов с именем, содержащим символ вне набора "[a-zA-Z0-9-]". Режим по
          умолчанию для бэкендов HTTP с настроенным приложением FastCGI.

reject    отклонить запрос ответом 403-Forbidden, если он содержит имя заголовка с символом
          вне набора "[a-zA-Z0-9-]".

Этот параметр позволяет ограничить имена заголовков запросов буквами, цифрами и дефисом ([A-Za-z0-9-]). Это может быть обязательно для взаимодействия с серверами, не соблюдающими HTTP и не обрабатывающими некоторые символы в именах заголовков. Также это может быть обязательно для приложений FastCGI: все символы имён заголовков, кроме букв и цифр, заменяются подчёркиванием (’_’). Поэтому легко смешать имена заголовков и обойти некоторые правила. Например, заголовки “X-Forwarded-For” и “X_Forwarded-For” оба преобразуются в “HTTP_X_FORWARDED_FOR” в FastCGI.

Обратите внимание: параметр вычисляется для каждого прокси после правил http-request.

option http-server-close

option http-server-close
no option http-server-close

Включить или отключить закрытие соединений HTTP/1.x на стороне сервера

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы: отсутствуют

По умолчанию HAProxy использует режим постоянных соединений HTTP/1.x: в каждом соединении обрабатывает запросы и ответы, затем оставляет соединение простаивать с обеих сторон. Изменить режим можно параметрами вроде “option http-server-close” или “option httpclose”. Параметр “option http-server-close” включает закрытие соединения HTTP на стороне сервера, сохраняя поддержку постоянных соединений HTTP и конвейерной передачи на стороне клиента. Это обеспечивает минимальную задержку клиента в медленной сети и самое быстрое повторное использование сеансов на стороне сервера для экономии его ресурсов, как и “option httpclose”. Кроме того, серверы без поддержки постоянных соединений могут обслуживаться в этом режиме для клиентов, если соблюдают требования RFC7230. Некоторые серверы не всегда соблюдают их при “Connection: close” в запросе; тогда постоянные соединения вообще не используются. Обойти проблему позволяет “option http-pretend-keepalive”.

Сейчас журналы не показывают, пришли ли запросы из одного сеанса. Указанное в журналах время приёма соответствует окончанию предыдущего запроса, а время запроса — ожиданию нового. Время запроса в постоянном соединении по-прежнему ограничено “timeout http-keep-alive” либо “timeout http-request”, если первый не задан.

Параметр можно задать во фронтенде и в бэкенде. Он включён, если включён хотя бы во фронтенде или бэкенде данного соединения. Отключает и заменяет любые ранее заданные “option httpclose” или “option http-keep-alive”. Сочетание с другими параметрами при разных настройках фронтенда и бэкенда см. в разделе 4 («Прокси»).

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

См. также: “option httpclose”, “option http-pretend-keepalive” и “option http-keep-alive”.

option http-use-proxy-header

option http-use-proxy-header
no option http-use-proxy-header

Использовать нестандартный заголовок Proxy-Connection вместо Connection

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы: отсутствуют

Хотя RFC7230 явно требует от агентов HTTP/1.1 использовать заголовок Connection для указания намерения сохранять или закрывать соединения, браузеры и прокси игнорируют его для проксируемых соединений, используя вместо него недокументированный нестандартный Proxy-Connection. При установке балансировщика между браузерами и такими прокси возникает различие между тем, как HAProxy понимает обмен, и тем, о чём договорились клиент и прокси.

При задании параметра во фронтенде HAProxy может автоматически переключаться на нестандартный заголовок, если видит проксируемые запросы. Здесь так называется запрос, URI которого не начинается ни с ‘/’, ни с ‘*’. Это несовместимо с режимом туннеля HTTP. Параметр можно задавать только во фронтенде, и он влияет на запрос в течение всего времени его существования.

Кроме того, при заданном параметре запрос, требующий аутентификации, автоматически переключается на заголовки аутентификации прокси, если сам является проксируемым. Это позволяет проверять или требовать аутентификацию перед существующим прокси.

Обычно этот параметр никогда не следует использовать, кроме как перед прокси.

См. также: “option httpclose” и “option http-server-close”.

option httpchk

option httpchk
option httpchk <uri>
option httpchk <method> <uri>
option httpchk <method> <uri> <version>
option httpchk <method> <uri> <version> <host>

Включить протокол HTTP для проверок работоспособности серверов

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<method>  необязательный метод HTTP запросов. Если не задан, используется "OPTIONS": обычно он
          требует мало обработки сервером, и его легко отфильтровать из журналов. Можно
          использовать любой метод, но придумывать нестандартные не рекомендуется.

<uri>     URI запросов HTTP. По умолчанию — " / ", доступный по умолчанию почти на
          любом сервере, но можно задать другой URI. Строки параметров разрешены.

<version> необязательная строка версии HTTP. По умолчанию — "HTTP/1.0", но некоторые серверы
          неверно работают с HTTP 1.0, и переход на HTTP/1.1 иногда помогает. Поле Host
          обязательно в HTTP/1.1.

<host>    необязательное значение заголовка HTTP Host. По умолчанию не задано. Это строка
          log-format.

По умолчанию проверки работоспособности сервера лишь пытаются установить соединение TCP. При “option httpchk” после установления TCP отправляется полный запрос HTTP. Ответы 2xx и 3xx считаются допустимыми, а все остальные, включая отсутствие ответа, означают отказ сервера.

В сочетании с директивами “http-check” можно настроить отправляемый запрос HTTP проверки работоспособности или правила сопоставления ответа. Можно также настроить последовательность send/expect, как с директивой “tcp-check” для проверок TCP.

По умолчанию для открытия соединений проверок работоспособности HTTP используется конфигурация сервера. Но параметры сервера можно переопределить правилами “http-check connect”.

Параметр “httpchk” не обязательно требует бэкенд HTTP и работает также с обычными бэкендами TCP. Это особенно полезно для проверки простых сценариев на отдельных портах через демон inetd. Но внутри всегда используется мультиплексор HTX, поэтому форматирование запроса и разбор ответа строгие.

Примеры:

# Relay HTTPS traffic to Apache instance and check service availability
# using HTTP request "OPTIONS * HTTP/1.1" on port 80.
backend https_relay
    mode tcp
    option httpchk OPTIONS * HTTP/1.1
    http-check send hdr Host www
    server apache1 192.168.1.1:443 check port 80

См. также: “option ssl-hello-chk”, “option smtpchk”, “option mysql-check”, “option pgsql-check”, “http-check”, а также параметры сервера “check”, “port” и “inter”.

option httpclose

option httpclose
no option httpclose

Включить или отключить закрытие соединений HTTP/1.x

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы: отсутствуют

По умолчанию HAProxy использует режим постоянных соединений HTTP/1.x: в каждом соединении обрабатывает запросы и ответы, затем оставляет соединение простаивать с обеих сторон. Изменить режим можно параметрами вроде “option http-server-close” или “option httpclose”.

При “option httpclose” HAProxy закрывает соединение клиента или сервера в зависимости от места настройки. Фронтенд отвечает за клиентские соединения, бэкенд — за серверные. На слушателе параметр применяется к обеим сторонам. В каждом направлении проверяется наличие заголовка “Connection: close”, и при его отсутствии он добавляется.

Параметр можно сочетать с “option http-pretend-keepalive”: тогда заголовок запроса “Connection: close” не отправляется, но соединение всё равно закрывается после получения всего ответа.

Отключает и заменяет любые ранее заданные “option http-server-close” или “option http-keep-alive”.

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

См. также: “option http-server-close”.

option httplog [ clf ]

option httplog [ clf ]

Включить запись запроса HTTP, состояния потока и таймеров в журнал

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы:

clf       аргумент "clf" задаёт формат вывода CLF вместо формата HTTP HAProxy по
          умолчанию. Полезно, если журналы HAProxy нужно передавать конкретному анализатору,
          который поддерживает только CLF и не допускает расширения.

По умолчанию формат журнала содержит мало данных: только адреса источника и назначения и имя экземпляра. При “option httplog” каждая строка получает гораздо более подробный формат: среди прочего запрос HTTP, таймеры соединения, состояние потока, числа соединений, захваченные заголовки и cookie, имена фронтенда, бэкенда и сервера и, конечно, адрес источника и порты.

Указание только “option httplog” автоматически сбрасывает режим ‘clf’, если он был задан по умолчанию.

“option httplog” переопределяет любую ранее заданную директиву “log-format”.

См. также раздел 8 о ведении журнала.

option httpslog

option httpslog

Включить запись запроса HTTPS, состояния потока и таймеров в журнал

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

По умолчанию формат журнала содержит мало данных: только адреса источника и назначения и имя экземпляра. При “option httpslog” каждая строка получает гораздо более подробный формат: среди прочего запрос HTTP, таймеры соединения, состояние потока, числа соединений, захваченные заголовки и cookie, имена фронтенда, бэкенда и сервера, состояния проверки сертификата SSL и рукопожатия SSL и, конечно, адрес источника и порты.

“option httpslog” переопределяет любую ранее заданную директиву “log-format”.

См. также раздел 8 о ведении журнала.

option idle-close-on-response

option idle-close-on-response
no option idle-close-on-response

Не закрывать простаивающие соединения фронтенда во время мягкой остановки

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы: отсутствуют

По умолчанию простаивающие соединения закрываются при мягкой остановке. В некоторых средах клиент прокси может заранее подготовить простаивающие соединения для последующей отправки запросов. Без корректного повтора при ошибках записи это может вызвать ошибки при перезагрузке haproxy. Хотя правильной реализации следует повторять попытку при ошибках соединения или записи, параметр введён для обратной совместимости с haproxy до версии 2.4. До v2.4 haproxy ожидал последнего запроса и ответа, чтобы добавить заголовок “connection: close” перед закрытием и сообщить клиенту, что соединение больше нельзя использовать повторно.

На практике такое поведение наблюдалось в AWS с ALB перед haproxy. В результате ALB отправлял 502 при перезагрузках haproxy.

Следует учитывать, что параметр может увеличить число старых процессов, если соединения слишком долго простаивают. При частых перезагрузках может потребоваться соответствующая настройка клиентских тайм-аутов и/или “hard-stop-after”.

См. также: “timeout client”, “timeout client-fin”, “timeout http-request”, “hard-stop-after”

option independent-streams

option independent-streams
no option independent-streams

Включить или отключить независимую обработку тайм-аутов обоих направлений

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы: отсутствуют

По умолчанию при отправке данных через сокет обновляются и тайм-аут записи, и тайм-аут чтения этого сокета: считается, что на нём есть активность, а других способов понять, следует ли ожидать данные, нет.

Хотя такое поведение подходит почти всем приложениям, иногда желательно отключить его и обновлять тайм-аут чтения только при входящих данных. Это касается потоков с большими тайм-аутами и малым объёмом обмена, например сеанса telnet. Если сервер внезапно исчезает, исходящие данные накапливаются в системных буферах сокета, оба тайм-аута правильно обновляются, а узнать, что сервер не получает данные, невозможно, поэтому тайм-аут не наступает. Но если протокол всегда возвращает отправленные данные, одного тайм-аута чтения достаточно для обнаружения проблемы. В более многословных протоколах такой проблемы нет, поскольку данные не задерживаются надолго в буферах сокета.

Во фронтенде параметр отключает обновление тайм-аута чтения при отправке данных клиенту. Вероятно, этот случай редко полезен. В бэкенде отключает обновление тайм-аута чтения при отправке серверу. Обычно это нарушает передачу больших запросов HTTP POST по медленным каналам, поэтому использовать следует осторожно.

См. также: “timeout client”, “timeout server” и “timeout tunnel”

option ldap-check

option ldap-check

Использовать проверки работоспособности LDAPv3 для серверов

Можно использовать в следующих контекстах: tcp

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы: отсутствуют

Можно проверять правильную работу сервера с LDAPv3 вместо простого приёма соединения TCP. При включённом параметре серверу отправляется сообщение анонимной простой операции bind LDAPv3, а ответ анализируется на наличие сообщения ответа bind LDAPv3.

Сервер считается работоспособным только при значении success в resultCode ответа LDAP (http://tools.ietf.org/html/rfc4511#section-4.1.9 ).

Запись запросов bind в журнал зависит от сервера; способ настройки см. в его документации.

Пример:

option ldap-check

См. также: “option httpchk”

option log-health-checks

option log-health-checks
no option log-health-checks

Включить или отключить запись изменений состояния проверок работоспособности в журнал

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы: отсутствуют

По умолчанию неудачные проверки работоспособности журналируются при состоянии сервера UP, а успешные — при DOWN, поэтому объём дополнительной информации ограничен.

При включённом параметре журналируются любые изменения состояния проверки или работоспособности сервера. Это позволяет узнать, что перед аварией сервер иногда не проходил проверки, либо точно определить, когда он перестал возвращать допустимый статус HTTP, затем когда порт начал отклонять соединения и когда сервер совсем перестал отвечать.

Обратите внимание: изменения состояния, не вызванные проверками работоспособности, например включение или отключение через CLI, намеренно не журналируются этим параметром.

См. также: “option httpchk”, “option ldap-check”, “option mysql-check”, “option pgsql-check”, “option redis-check”, “option smtpchk”, “option tcp-check”, “log” и раздел 8 о ведении журнала.

option log-separate-errors

option log-separate-errors
no option log-separate-errors

Изменить уровень журнала для не вполне успешных соединений

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы: отсутствуют

Иногда искать ошибки в журналах трудно. Этот параметр повышает уровень записей HAProxy с потенциально полезной информацией: ошибками, тайм-аутами, повторными попытками, повторным распределением запросов или кодами HTTP 5xx. Уровень меняется с “info” на “err”, позволяя большинству демонов syslog записывать их отдельно в другой файл. Не следует удалять их из исходного файла: иначе теряется порядок событий, содержащий очень важные сведения.

С этим параметром крупные сайты с несколькими тысячами соединений в секунду могут записывать обычный трафик в буфер с ротацией, архивируя только меньшие журналы ошибок.

См. также: “log”, “dontlognull”, “dontlog-normal” и раздел 8 о ведении журнала.

option logasap

option logasap
no option logasap

Включить или отключить раннюю запись в журнал.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы: отсутствуют

По умолчанию записи журнала создаются, когда все псевдонимы формата журнала и функции извлечения образцов в определении строки log-format возвращают значение либо когда поток завершается. Это позволяет встроенным строкам log-format учитывать время передачи или число байт в сообщениях журнала.

При долгих соединениях, например передаче больших файлов или RDP, запрос или соединение может появиться в журнале нескоро. С “option logasap” сообщение создаётся сразу после установления серверного соединения в режиме tcp либо после отправки сервером полных заголовков в режиме http. Журналу будет недоставать общего числа байт: оно покажет лишь данные, переданные до создания сообщения, а общее время не учтёт оставшееся время существования соединения или передачи. Для HTTP полезно захватывать заголовок ответа Content-Length, чтобы журнал хотя бы показывал ожидаемое число передаваемых байт.

Примеры:

listen http_proxy 0.0.0.0:80
    mode http
    option httplog
    option logasap
    log 192.168.2.200 local3
    >>> Feb  6 12:14:14 localhost \
          haproxy[14389]: 10.0.1.2:33317 [06/Feb/2009:12:14:14.655] http-in \
          static/srv1 9/10/7/14/+30 200 +243 - - ---- 3/1/1/1/0 1/0 \
          "GET /image.iso HTTP/1.0"

См. также: “option httplog”, “capture response header” и раздел 8 о ведении журнала.

option mysql-check [ user <username> [ { post-41 | pre-41 | post-80 } ] ]

option mysql-check [ user <username> [ { post-41 | pre-41 | post-80 } ] ]

Использовать проверки работоспособности MySQL для серверов

Можно использовать в следующих контекстах: tcp

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<username> имя пользователя для соединения с сервером MySQL.
post-41    отправлять проверки, совместимые с клиентами v4.1 и новее (по умолчанию)
pre-41     отправлять проверки, совместимые с клиентами до v4.1
post-80    отправлять проверки, совместимые с клиентами v8.0 и новее, с установленным
           флагом CLIENT_PLUGIN_AUTH и модулем аутентификации mysql_native_password. Использовать при соединении с
           серверами MySQL 8.0+, если пользователь проверки создан с аутентификацией
           mysql_native_password. Пример:
             CREATE USER 'haproxy'@'%' IDENTIFIED WITH mysql_native_password BY '';

При заданном имени пользователя проверка отправляет два пакета MySQL: Client Authentication и QUIT, чтобы корректно закрыть сеанс MySQL. Затем разбирается пакет MySQL Handshake Initialization и/или Error. Это простая, но полезная проверка, не создающая на сервере ошибок или прерванных соединений. Однако нужен незаблокированный авторизованный пользователь без пароля. Для создания простого пользователя MySQL с ограниченными правами и необязательными ограничениями ресурсов:

CREATE USER '<username>'@'<ip_of_haproxy|network_of_haproxy/netmask>'
/*!50701 WITH MAX_QUERIES_PER_HOUR 1 MAX_UPDATES_PER_HOUR 0 */
/*M!100201 MAX_STATEMENT_TIME 0.0001 */;

Без имени пользователя, что устарело и не рекомендуется, проверка лишь разбирает пакет Mysql Handshake Initialization или Error, ничего не отправляя. Сообщалось, что это может вызвать блокировку при слишком частых проверках и/или недостаточном трафике. Следует проверить значение MySQL “max_connect_errors”: если после прерванного соединения новое успешно устанавливается за меньшее число попыток, чем MySQL “max_connect_errors”, счётчик ошибок узла сбрасывается в ноль. Если сервер HAProxy заблокирован, разблокировать его можно только оператором “FLUSH HOSTS”.

Следует помнить, что наличие или согласованность базы данных не проверяется. Для этого можно использовать внешнюю проверку, например через xinetd.

Проверка требует MySQL >=3.22; для более ранних версий следует использовать проверку TCP.

Принимающему серверу MySQL часто нужно видеть IP-адрес клиента, в частности для проверки прав по IP и ведения журнала соединений. По возможности разумно подставлять IP-адрес клиента при соединении с сервером через аргумент “usesrc” ключевого слова “source”. Для этого требуется сборка с поддержкой прозрачного прокси и маршрутизация сервером MySQL трафика клиента через машину HAProxy.

См. также: “option httpchk”

option nolinger

option nolinger
no option nolinger

Включить или отключить немедленную очистку ресурсов сеанса после закрытия

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы: отсутствуют

Если клиент или сервер некорректно обрывает соединение, например физически отключается, срабатывают тайм-ауты и сеанс закрывается. Но в системе он некоторое время остаётся в FIN_WAIT1, занимая ресурсы и, возможно, ограничивая установление новых соединений.

В таком случае можно включить “option nolinger”, который заставляет систему немедленно удалять ожидающие данные сокета при закрытии. Отправляется TCP RST, ожидающие данные обрезаются, а сеанс сразу удаляется из системных таблиц. Клиент обычно видит усечённые ответы, если закрытие происходит с последним блоком данных, например при перенаправлении или ответе об ошибке. На стороне сервера это может сразу освободить исходные порты при пересылке клиентского прерывания в туннелях. В обоих случаях отправляется сброс TCP; поскольку сеанс сразу уничтожается, повторной передачи не будет. В сети с потерями это может усугубить проблемы, особенно если на стороне с потерями есть межсетевой экран: он может увидеть и обработать сброс, удалив свой сеанс, а затем блокировать любой дальнейший трафик этого сеанса, включая повторные передачи с другой стороны. Если другая сторона не получила сброс, она больше никогда не получит RST, а межсетевой экран может записывать в журнал множество заблокированных пакетов.

По всем этим причинам настоятельно рекомендуется НЕ использовать параметр, кроме случаев крайней необходимости как последнего средства. Обычно тайм-ауты “client-fin” или “server-fin” дают сходный результат с более надёжным поведением. В Linux также можно использовать “tcp-ut” в настройках bind или server.

Параметр можно использовать во фронтендах и бэкендах в зависимости от нужной стороны: на фронтенде для клиентов, на бэкенде для серверов. Хотя он технически поддерживается в секциях “defaults”, там его действительно нельзя использовать: он может случайно распространиться на секции, где его применять нельзя, и вызвать проблемы.

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

См. также: “timeout client-fin”, “timeout server-fin”, ключевые слова “tcp-ut” для bind или server.

option originalto [ except <network> ] [ header <name> ]

option originalto [ except <network> ] [ header <name> ]

Включить добавление заголовка X-Original-To в запросы к серверам

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

<network> необязательный аргумент для отключения параметра для источников, соответствующих <network>
<name>    необязательный аргумент для другого имени заголовка "X-Original-To".

Поскольку HAProxy может работать прозрачно, любой запрос клиента может перенаправляться на прокси, а HAProxy может пересылать его в сложную среду SQUID, теряя узел назначения из SO_ORIGINAL_DST. Это мешает правилам доступа на основе адресов назначения. Для решения HAProxy может добавлять новый заголовок HTTP “X-Original-To” во все запросы серверу. Его значение представляет исходный IP-адрес назначения. Использование заголовка должно быть настроено так, чтобы всегда учитывалось только последнее вхождение. Обратите внимание: должно использоваться только последнее вхождение, поскольку клиент вполне может уже передать такой заголовок.

Ключевое слово “header” позволяет задать другое имя вместо “X-Original-To” по умолчанию. Это может быть полезно, если уже есть заголовок “X-Original-To” другого приложения, который нужно сохранить, либо если сервер бэкенда не использует “X-Original-To” и требует другой заголовок.

Иногда один экземпляр HAProxy обслуживает прямой доступ клиентов и доступ через обратный прокси, например SSL-прокси для расшифровки HTTPS. Добавление заголовка можно отключить для известного адреса или сети назначения, задав “except” и адрес сети. Тогда для любого IP назначения, соответствующего сети, заголовок не добавляется. Чаще всего используются частные сети или 127.0.0.1. Поддерживаются IPv4 и IPv6.

Параметр можно задать во фронтенде или бэкенде. Если его использует хотя бы один из них, заголовок добавляется. Если оба задают вложенный аргумент header, значение бэкенда имеет приоритет над значением фронтенда.

Примеры:

# Original Destination address
frontend www
    mode http
    option originalto except 127.0.0.1

# Those servers want the IP Address in X-Client-Dst
backend www
    mode http
    option originalto header X-Client-Dst

См. также: “option httpclose”, “option http-server-close”.

option persist

option persist
no option persist

Включить или отключить принудительное сохранение привязки к неработающим серверам

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы: отсутствуют

Если запрос HTTP приходит в бэкенд с cookie, указывающим на неработающий сервер, по умолчанию он перераспределяется другому серверу. При крайней необходимости “option persist” позволяет сначала принудительно отправить его неработающему серверу. Частый случай — чрезвычайная нагрузка и постоянные переключения состояния серверов. Тогда пользователи всё равно направляются серверу, на котором открыли сеанс, в надежде на корректное обслуживание. Рекомендуется вместе использовать “option redispatch”: если соединиться совсем невозможно и сервер окончательно не работает, клиент в итоге перенаправляется другому работоспособному серверу.

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

См. также: “option redispatch”, “retries”, “force-persist”

option pgsql-check user <username>

option pgsql-check user <username>

Использовать проверки работоспособности PostgreSQL для серверов

Можно использовать в следующих контекстах: tcp

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<username> имя пользователя для соединения с сервером PostgreSQL.

Проверка отправляет PostgreSQL StartupMessage и ждёт запрос Authentication либо сообщение ErrorResponse. Это простая, но полезная проверка, не создающая на сервере ошибок или прерванных соединений. Она идентична “mysql-check”.

См. также: “option httpchk”

option prefer-last-server

option prefer-last-server
no option prefer-last-server

Позволить нескольким балансируемым запросам оставаться на одном сервере

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы: отсутствуют

Если используемый алгоритм балансировки недетерминированный и предыдущий запрос отправлен серверу, соединение с которым ещё сохраняется у HAProxy, иногда желательно по возможности направлять последующие запросы того же сеанса этому серверу. Это отличается от привязки сеанса: задаётся лишь предпочтение, которое HAProxy пытается соблюсти без каких-либо гарантий. Основное применение — постоянные соединения с серверами. HAProxy пытается повторно использовать то же соединение с сервером вместо перераспределения другому серверу с закрытием соединения. Это разумно для серверов статических файлов и мало полезно вместе с алгоритмами хеширования. При недетерминированном алгоритме HAProxy уже автоматически пытается сохранять привязку к серверу с ответом 401 или прокси с 407, требующим аутентификации. Это обязательно для работы с некорректным механизмом запроса аутентификации NTLM и значительно помогает при устранении неполадок ошибочных приложений. Параметр option prefer-last-server тоже может быть полезен в таких средах, чтобы не перераспределять трафик после каждого иного ответа.

Полезно уточнить, какие алгоритмы считаются детерминированными. Они всегда выбирают один сервер для заданных данных клиента, если набор доступных серверов не изменился. Обычно для выбора используются хеширование или поиск по входящим запросам, но не всегда: “static-rr” тоже можно считать детерминированным, поскольку выбор основан на статическом весе сервера и предсказуем. Алгоритм “sticky” обеспечивает детерминированную маршрутизацию для возвращающихся клиентов.

Недетерминированные алгоритмы выбирают сервер по динамическому состоянию серверов или простому циклическому обходу, поэтому два последовательных запроса не обязательно попадут на один сервер. Именно для них предназначен option prefer-last-server. Примеры — roundrobin и leastconn.

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

См. также: “option http-keep-alive”

option redispatch

option redispatch
option redispatch <interval>
no option redispatch

Включить или отключить перераспределение сеансов при неудачном соединении

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<interval> необязательное целое число, определяющее частоту перераспределения при повторных
           попытках соединения. Положительное P означает перераспределение при каждой P-й
           попытке; отрицательное N — на N-й попытке при отсчёте от последней. Например,
           значение по умолчанию -1 сохраняет прежнее перераспределение при последней
           попытке; положительное 1 — при каждой попытке, положительное 3 — при
           каждой третьей. Значение 0 отключает перераспределение.

В режиме HTTP, если сервер из cookie не работает, клиенты могут окончательно остаться привязанными к нему, например при “option persist” или “force-persist”, поскольку не могут сбросить cookie и больше не получат доступ к службе.

Параметр “option redispatch” позволяет прокси нарушить привязку на основе cookie или консистентного хеширования и перераспределить клиентов работоспособному серверу.

Активные серверы выбираются из подмножества доступных. Активные серверы, которые не отказали и не находятся в режиме обслуживания, то есть серверы без проверок работоспособности либо проверенные как “up”, выбираются в следующем порядке:

1. Любой активный нерезервный сервер, если он есть, либо,

2. Если "allbackups" не задан, первый резервный сервер в списке, либо

3. Если "allbackups" задан, любой резервный сервер.

При повторной попытке HAProxy старается выбрать другой сервер вместо предыдущего. Новый сервер выбирается из текущего списка серверов.

Однако если между повторными попытками список обновится, соединения иногда могут быть перенаправлены на резервный сервер. Например, многочисленные попытки могут длиться дольше, чем требуется для обнаружения отказа сервера, удаления его из списка и перехода к списку резервных серверов.

Это также позволяет при нескольких неудачах установления соединения повторить попытку на другом сервере. Разумеется, для этого “retries” должен иметь ненулевое значение.

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

См. также: “option persist”, “force-persist”, “retries”

option redis-check

option redis-check

Использует проверки работоспособности redis для проверки серверов

Можно использовать в следующих контекстах: tcp

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы: отсутствуют

Можно проверить, правильно ли сервер работает по протоколу REDIS, вместо простой проверки принятия соединения TCP. При включённом параметре серверу отправляется команда redis PING, затем ответ анализируется на наличие сообщения “+PONG”.

Пример:

option redis-check

См. также: “option httpchk”, “option tcp-check”, “tcp-check expect”

option smtpchk

option smtpchk
option smtpchk <hello> <domain>

Использует проверки работоспособности SMTP для проверки серверов

Можно использовать в следующих контекстах: tcp

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<hello>   — необязательный аргумент, задающий команду "hello". Это либо "HELO" (для SMTP),
          либо "EHLO" (для ESMTP). Все остальные значения преобразуются в команду по
          умолчанию ("HELO").

<domain>  — доменное имя, представляемое серверу. Его можно задать только при указанной команде
          hello; в этом случае оно обязательно. По умолчанию используется "localhost".

При “option smtpchk” проверки работоспособности состоят из установления соединения TCP и последующей команды SMTP. По умолчанию это “HELO localhost”. Анализируется код возврата сервера: допустимыми считаются только коды, начинающиеся с “2”. Все остальные ответы, включая отсутствие ответа, считаются ошибкой и означают неработающий сервер.

Эта проверка предназначена для серверов или ретрансляторов SMTP. В зависимости от запроса некоторые серверы могут не журналировать каждую попытку соединения; можно поэкспериментировать для улучшения поведения. Часто проще воспользоваться telnet на порту 25, чем менять конфигурацию.

Входящему серверу SMTP чаще всего нужен адрес IP клиента для разных целей, включая фильтрацию спама, защиту от подмены и журналирование. Когда это возможно, при соединении с сервером часто целесообразно подставлять адрес IP клиента с помощью аргумента “usesrc” ключевого слова “source”. Для этого поддержка прозрачного прокси должна быть включена при сборке.

Пример:

option smtpchk HELO mydomain.org

См. также: “option httpchk”, “source”

option socket-stats
no option socket-stats

Включает или отключает сбор и предоставление отдельной статистики для каждого сокета.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы: отсутствуют

option splice-auto

option splice-auto
no option splice-auto

Включает или отключает автоматическое ускорение сокетов ядром в обоих направлениях

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы: отсутствуют

При включении параметра во фронтенде или бэкенде HAProxy автоматически оценивает целесообразность использовать механизм TCP splicing ядра для пересылки данных между клиентом и сервером в каждом направлении. Эвристики HAProxy оценивают, может ли этот механизм повысить производительность. Оба направления обрабатываются независимо. Эвристики не слишком агрессивны, чтобы ограничить чрезмерное использование splicing. Его поддержка должна быть включена при сборке; глобальный параметр “nosplice” позволяет отключить её глобально. Поскольку splice использует каналы, требуется достаточное число свободных каналов.

Важное примечание: TCP splicing на уровне ядра — возможность только Linux, впервые появившаяся в ядре 2.6.25. Она ускоряет передачу данных между сокетами без копирования в пространство пользователя, заметно повышая производительность и экономя циклы CPU. Во многих ранних реализациях есть ошибки, приводящие к повреждению данных и/или низкой эффективности. Поэтому возможность по умолчанию выключена и использовать её следует крайне осторожно. Проверить корректность реализации невозможно, но 2.6.29 — первая версия с правильно работающей реализацией. При сомнениях splicing можно отключить глобально ключевым словом “nosplice”.

Пример:

option splice-auto

Если параметр включён в секции “defaults”, в отдельном экземпляре его можно отключить, добавив перед ним ключевое слово “no”.

См. также: “option splice-request”, “option splice-response” и глобальные параметры “nosplice” и “maxpipes”

option splice-request

option splice-request
no option splice-request

Включает или отключает автоматическое ускорение сокетов ядром для запросов

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы: отсутствуют

При включении параметра во фронтенде или бэкенде HAProxy по возможности использует механизм TCP splicing ядра для пересылки данных от клиента к серверу. Если свободных каналов не осталось, он может по-прежнему использовать схему recv/send. Поддержка splicing должна быть включена при сборке; глобальный параметр “nosplice” позволяет отключить её глобально. Поскольку splice использует каналы, требуется достаточное число свободных каналов.

Важное примечание: ограничения применения см. в “option splice-auto”.

Пример:

option splice-request

Если параметр включён в секции “defaults”, в отдельном экземпляре его можно отключить, добавив перед ним ключевое слово “no”.

См. также: “option splice-auto”, “option splice-response” и глобальные параметры “nosplice” и “maxpipes”

option splice-response

option splice-response
no option splice-response

Включает или отключает автоматическое ускорение сокетов ядром для ответов

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы: отсутствуют

При включении параметра во фронтенде или бэкенде HAProxy по возможности использует механизм TCP splicing ядра для пересылки данных от сервера к клиенту. Если свободных каналов не осталось, он может по-прежнему использовать схему recv/send. Поддержка splicing должна быть включена при сборке; глобальный параметр “nosplice” позволяет отключить её глобально. Поскольку splice использует каналы, требуется достаточное число свободных каналов.

Важное примечание: ограничения применения см. в “option splice-auto”.

Пример:

option splice-response

Если параметр включён в секции “defaults”, в отдельном экземпляре его можно отключить, добавив перед ним ключевое слово “no”.

См. также: “option splice-auto”, “option splice-request” и глобальные параметры “nosplice” и “maxpipes”

option spop-check

option spop-check

Использует проверки работоспособности SPOP для проверки серверов

Можно использовать в следующих контекстах: tcp

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы: отсутствуют

Можно проверить, правильно ли сервер работает по протоколу SPOP, вместо простой проверки принятия соединения TCP. При включённом параметре между HAProxy и сервером выполняется рукопожатие HELLO, затем ответ анализируется, чтобы убедиться в отсутствии сообщения об ошибке.

Пример:

option spop-check

См. также: “option httpchk”

option srvtcpka

option srvtcpka
no option srvtcpka

Включает или отключает отправку пакетов TCP для поддержания соединения на стороне сервера

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы: отсутствуют

Если между клиентом и сервером находится межсетевой экран или другой компонент, учитывающий состояние сеанса, а протокол предполагает очень долгие сеансы с длительными периодами простоя (например, удалённые рабочие столы), один из промежуточных компонентов может решить, что слишком долго простаивавший сеанс истёк.

Включение поддержания соединений TCP на уровне сокета заставляет систему регулярно отправлять пакеты на другой конец соединения, сохраняя его активным. Интервал между проверочными пакетами задаётся только системой и зависит от операционной системы и её настроек.

Важно понимать, что пакеты поддержания соединения не отправляются и не принимаются на уровне приложения: их видят только сетевые стеки. Поэтому даже если одна сторона прокси уже использует такие пакеты для сохранения соединения, они не пересылаются на другую сторону прокси.

Это никак не связано с постоянными соединениями HTTP.

Параметр “srvtcpka” включает отправку проверочных пакетов TCP для поддержания соединения на серверной стороне. Это должно помочь, когда наблюдается истечение сеансов между HAProxy и сервером.

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

См. также: “option clitcpka”, “option tcpka”

option ssl-hello-chk

option ssl-hello-chk

Использует проверки работоспособности с сообщением client hello SSLv3 для проверки серверов

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы: отсутствуют

При передаче некоторых протоколов на основе SSL через HAProxy в режиме TCP можно проверить, правильно ли сервер работает с SSL, вместо простой проверки принятия соединения TCP. При “option ssl-hello-chk” после установления соединения серверу отправляются чистые сообщения client hello SSLv3, затем ответ анализируется на наличие сообщения server hello SSL. Сервер считается пригодным только при наличии этого сообщения server hello в ответе.

Все проверенные до сих пор серверы правильно отвечают на сообщения client hello SSLv3. Большинство проверенных серверов даже не журналируют запросы, содержащие только сообщения hello, что удобно.

Проверка работает даже при сборке HAProxy без поддержки SSL, поскольку сама формирует сообщение SSL. Если поддержка SSL доступна, лучше использовать собственные проверки работоспособности SSL вместо этой.

См. также: “option httpchk”, “check-ssl”

option tcp-check

option tcp-check

Выполняет проверки работоспособности последовательностями tcp-check send/expect

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Этот способ проверки работоспособности предназначен для сочетания со списками команд “tcp-check”, чтобы поддерживать последовательности проверок типа send/expect.

Проверки TCP сейчас поддерживают 4 режима работы: - без директивы “tcp-check” проверка состоит только из попытки соединения; это по-прежнему режим по умолчанию.

- Указаны только "tcp-check send" или "tcp-check send-binary": при открытии соединения отправляется строка. В некоторых протоколах это позволяет, например, отправить "QUIT", чтобы сервер не журналировал ошибку соединения при каждой проверке работоспособности. Результат проверки по-прежнему основан только на возможности открыть соединение.

- Указан только "tcp-check expect": проверяется приветствие сервера. Соединение открывается, и HAProxy ждёт содержимого от сервера, которое должно удовлетворять правилам. Результат проверки основан на совпадении содержимого с правилами. Подходит для POP, IMAP, SMTP, FTP, SSH, TELNET.

- Указаны и "tcp-check send", и "tcp-check expect": проверяется протокол с обменом приветствиями. HAProxy отправляет сообщение, сервер отвечает, затем ответ анализируется. Результат проверки основан на совпадении содержимого ответа с правилами. Часто подходит для протоколов, требующих привязки или модели запрос/ответ. Примеры — LDAP, MySQL, Redis и SSL, хотя для каждого уже есть специальные проверки с более глубоким пониманием соответствующего протокола. В этом режиме можно отправлять много запросов и анализировать много ответов.

Пятый режим позволяет вставлять комментарии на разных шагах сценария.

В каждое создаваемое правило tcp-check можно добавить директиву “comment” со строкой. Эта строка выводится в журнал и stderr в режиме отладки, что помогает делать сообщения об ошибках понятными пользователю. Разумеется, “comment” необязателен.

Во время проверки работоспособности доступна область видимости переменных для хранения образцов данных с помощью операции “tcp-check set-var”. Освобождать эти переменные можно через “tcp-check unset-var”.

Примеры:

# perform a POP check (analyze only server's banner)
option tcp-check
tcp-check expect string +OK\ POP3\ ready comment POP\ protocol

# perform an IMAP check (analyze only server's banner)
option tcp-check
tcp-check expect string *\ OK\ IMAP4\ ready comment IMAP\ protocol

# look for the redis master server after ensuring it speaks well
# redis protocol, then it exits properly.
# (send a command then analyze the response 3 times)
option tcp-check
tcp-check comment PING\ phase
tcp-check send PING\r\n
tcp-check expect string +PONG
tcp-check comment role\ check
tcp-check send info\ replication\r\n
tcp-check expect string role:master
tcp-check comment QUIT\ phase
tcp-check send QUIT\r\n
tcp-check expect string +OK

Сформировать запрос HTTP, затем проанализировать ответ
(отправить много заголовков перед анализом)
option tcp-check
tcp-check comment forge\ and\ send\ HTTP\ request
tcp-check send HEAD\ /\ HTTP/1.1\r\n
tcp-check send Host:\ www.mydomain.com\r\n
tcp-check send User-Agent:\ HAProxy\ tcpcheck\r\n
tcp-check send \r\n
tcp-check expect rstring HTTP/1\..\ (2..|3..) comment check\ HTTP\ response

См. также: “tcp-check connect”, “tcp-check expect” и “tcp-check send”.

option tcp-smart-accept

option tcp-smart-accept
no option tcp-smart-accept

Включает или отключает экономию одного пакета ACK при принятии соединения

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы: отсутствуют

Когда приходит запрос на соединение HTTP, система подтверждает его от имени HAProxy. Затем клиент сразу отправляет запрос, который система также подтверждает, уведомляя HAProxy о новом соединении. HAProxy читает запрос и отвечает. Таким образом, система отправляет один лишний пакет ACK TCP: запрос мог бы быть подтверждён ответом HAProxy.

Поэтому в режиме HTTP HAProxy автоматически просит систему не отправлять этот бесполезный ACK на поддерживающих это платформах (сейчас по крайней мере Linux). Это не должно создавать проблем: если ответ задерживается дольше ожидаемого, система всё равно отправит ACK через 40 ms.

При сложной отладке сети может быть желательно отключить эту оптимизацию: задержанные ACK усложняют поиск мест задержки пакетов. Чтобы вернуться к обычному поведению, можно указать “no option tcp-smart-accept”.

Можно также принудительно включить её для прокси, работающих не с HTTP, просто указав “option tcp-smart-accept”. Например, это может быть полезно для некоторых служб, таких как SMTP, где сервер начинает обмен первым.

Рекомендуется не включать этот параметр принудительно в секции defaults. При сомнениях можно вернуть автоматическое значение, добавив перед ним ключевое слово “default”, либо отключить его ключевым словом “no”.

См. также: “option tcp-smart-connect”

option tcp-smart-connect

option tcp-smart-connect
no option tcp-smart-connect

Включает или отключает экономию одного пакета ACK при установлении соединения

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы: отсутствуют

В некоторых системах (по крайней мере Linux) HAProxy может попросить ядро не отправлять сразу пустой ACK при запросе на соединение, а непосредственно отправить буферизованный запрос. Это экономит один сетевой пакет и повышает производительность. Может быть полезно и некоторым серверам: они сразу получают запрос вместе с входящим соединением.

Возможность включается при заданном “option tcp-smart-connect” в бэкенде. По умолчанию она выключена, поскольку усложняет отладку сети.

Её имеет смысл включать только для протоколов, где клиент начинает обмен первым, например HTTP. В остальных случаях при отсутствии данных для отправки вместо ACK отправляется обычный ACK.

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

См. также: “option tcp-smart-accept”

option tcpka

option tcpka

Включает или отключает отправку пакетов TCP для поддержания соединения с обеих сторон

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы: отсутствуют

Если между клиентом и сервером находится межсетевой экран или другой компонент, учитывающий состояние сеанса, а протокол предполагает очень долгие сеансы с длительными периодами простоя (например, удалённые рабочие столы), один из промежуточных компонентов может решить, что слишком долго простаивавший сеанс истёк.

Включение поддержания соединений TCP на уровне сокета заставляет систему регулярно отправлять пакеты на другой конец соединения, сохраняя его активным. Интервал между проверочными пакетами задаётся только системой и зависит от операционной системы и её настроек.

Важно понимать, что пакеты поддержания соединения не отправляются и не принимаются на уровне приложения: их видят только сетевые стеки. Поэтому даже если одна сторона прокси уже использует такие пакеты для сохранения соединения, они не пересылаются на другую сторону прокси.

Это никак не связано с постоянными соединениями HTTP.

Параметр “tcpka” включает отправку проверочных пакетов TCP для поддержания соединения на клиентской и серверной сторонах. Это имеет смысл только в секциях “defaults” или “listen”. Во фронтенде такие пакеты получает только клиентская сторона, в бэкенде — только серверная. Поэтому при разделении конфигурации на фронтенды и бэкенды настоятельно рекомендуется явно использовать “option clitcpka” и “option srvtcpka”.

См. также: “option clitcpka”, “option srvtcpka”

option tcplog [clf]

option tcplog [clf]

Включает подробное журналирование соединений TCP с состоянием потока и таймерами

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы:

clf       При добавлении аргумента "clf" вывод имеет формат CLF вместо формата TCP
          HAProxy по умолчанию. Это удобно, если журналы HAProxy нужно передавать специальному
          нерасширяемому анализатору, поддерживающему только CLF. Поскольку ожидается формат
          HTTP, некоторые значения заданы заранее: запрос http отображается как TCP, а
          код ответа — как 000.

По умолчанию формат журнала очень беден: он содержит только исходный адрес, адрес назначения и имя экземпляра. “option tcplog” делает каждую строку гораздо богаче: она включает, помимо прочего, таймеры соединения, состояние потока, число соединений, имена фронтенда, бэкенда и сервера, а также, конечно, исходный адрес и порты. Параметр полезен для чистых прокси TCP, чтобы определить, кто — клиент или сервер — разрывает соединение либо достигает тайм-аута. Для обычных прокси HTTP лучше использовать ещё более полный “option httplog”.

“option tcplog” переопределяет любую предыдущую директиву “log-format”.

См. также: “option httplog” и раздел 8 о журналировании.

option transparent (deprecated)

option transparent        (deprecated)
no option transparent     (deprecated)

Включает прозрачное проксирование на стороне клиента

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы: отсутствуют

Параметр появился для предоставления привязки сеанса уровня 7 балансировщикам нагрузки уровня 3. Идея — использовать способность операционной системы (OS) перенаправлять входящее соединение к удалённому адресу в локальный процесс (здесь HAProxy) и сообщать ему первоначально запрошенный адрес. При включённом параметре сеансы без cookie пересылаются на исходный адрес IP назначения входящего запроса (который, как ожидается, соответствует адресу другого оборудования), а запросы с cookie по-прежнему пересылаются подходящему серверу.

Вопреки распространённому мнению, этот параметр НЕ заставляет HAProxy представлять серверу адрес IP клиента при установлении соединения.

Начиная с 3.3 параметр устарел из-за ряда внутренних технических ограничений. Его использование вызывает предупреждение; при действительной необходимости его можно убрать глобальным ключевым словом “expose-deprecated-directives”.

Правильный подход — объявить сервер с адресом 0.0.0.0: он обеспечит соединение с ожидаемым адресом назначения. Сервер также правильно обрабатывает простаивающие соединения с целевыми серверами.

Пример:

# option transparent  ## before 3.3
server transparent 0.0.0.0

См. также: аргумент “usesrc” ключевого слова “source” и параметр “transparent” ключевого слова “bind”.

option use-small-buffers [ queue | l7-retries | check ]*

Включает поддержку малых буферов для указанных категорий.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Параметр позволяет включить поддержку малых буферов в разных местах для экономии памяти. По умолчанию, без параметров, малые буферы используются везде, где это возможно. Иначе их применение можно ограничить следующими местами:

  • queue: При включении малые буферы хранят запросы, если те достаточно малы, пока соединение находится в очереди.
  • l7-retries: При включении малые буферы сохраняют запросы при включённых повторных попытках L7.
  • check: При включении малые буферы используются для запросов проверок работоспособности.

При включённой возможности малые буферы используются лишь там, где это возможно. Если данные слишком велики, автоматически используется обычный буфер. Размер малых буферов настраивается глобальным параметром “tune.bufsize.small”.

Если параметр включён в секции “defaults”, для отдельного экземпляра его можно отключить, добавив перед ним ключевое слово “no”.

См. также: tune.bufsize.small

persist rdp-cookie

persist rdp-cookie
persist rdp-cookie(<name>)

Включает привязку сеанса на основе cookie RDP

Можно использовать в следующих контекстах: tcp

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<name>    — необязательное имя проверяемого cookie RDP. Если опущено, используется имя по
          умолчанию "msts". Сейчас нет обоснованной причины менять это имя.

Эта директива включает привязку сеанса на основе cookie RDP. Cookie RDP содержит всю информацию, необходимую для поиска сервера в списке известных серверов. Поэтому при включённом параметре в бэкенде запрос анализируется; найденный cookie RDP декодируется. Если он соответствует известному серверу, который по-прежнему находится в состоянии UP (или включён “option persist”), соединение пересылается этому серверу.

Это имеет смысл только в бэкенде TCP, но для работы фронтенд должен ждать достаточно долго, чтобы cookie RDP присутствовал в буфере запроса. Такое же требование действует для метода балансировки “rdp-cookie”. Поэтому настоятельно рекомендуется поместить все директивы в одну секцию “listen”.

Также важно понимать, что терминальный сервер отправит cookie RDP только при настройке «режима перенаправления по токену», то есть при отключённом параметре «перенаправление по адресу IP».

Пример:

listen tse-farm
    bind :3389
    # wait up to 5s for an RDP cookie in the request
    tcp-request inspect-delay 5s
    tcp-request content accept if RDP_COOKIE
    # apply RDP cookie persistence
    persist rdp-cookie
    # if server is unknown, let's balance on the same cookie.
    # alternatively, "balance leastconn" may be useful too.
    balance rdp-cookie
    server srv1 1.1.1.1:3389
    server srv2 1.1.1.2:3389

См. также: “balance rdp-cookie”, “tcp-request” и ACL “req.rdp_cookie”.

quic-initial <action> [ { if | unless } <condition> ]

quic-initial <action> [ { if | unless } <condition> ]

Выполняет действие над входящим пакетом QUIC Initial. В отличие от “tcp-request connection”, оно выполняется до создания любого элемента соединения, а также до начала и завершения рукопожатия SSL. Это эффективнее при отклонении попыток соединения.

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да(!) | да | да | нет

Аргументы:

<action>    задаёт действие, выполняемое при соблюдении условия. См. ниже.

<condition> — стандартное условие на основе ACL только уровня 4 (см. раздел 7).
            Однако правила QUIC initial выполняются слишком рано даже для некоторых методов
            извлечения образцов уровня 4. Несмотря на отсутствие предупреждений
            конфигурации, возможны неопределённые результаты во время работы, хотя аварийного
            завершения не будет. Сейчас поддерживаются только внутренние образцы и "src*" и
            "dst*" уровня 4.

Действие выполняется в начале разбора пакета QUIC. Поэтому поддерживается лишь минимальный список действий: - accept - dgram-drop - reject - send-retry

rate-limit sessions <rate>

rate-limit sessions <rate>

Ограничивает число новых сеансов, принимаемых фронтендом за секунду

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы:

<rate>    Параметр <rate> — целое число, задающее максимальное число новых сеансов,
          принимаемых фронтендом за секунду.

Когда фронтенд достигает указанного числа новых сеансов в секунду, он перестаёт принимать новые соединения, пока частота снова не опустится ниже предела. В это время ожидающие сеансы остаются в очереди сокета backlog (в системных буферах), и HAProxy даже не знает об их ожидании. При очень низком пределе для сильно нагруженной службы может быть целесообразно увеличить очередь сокета ключевым словом “backlog”.

Возможность особенно эффективна против атак на основе соединений или злоупотребления службой на уязвимых серверах. Частота сеансов измеряется каждую миллисекунду, поэтому точность чрезвычайно высока. Ограничение также применяется немедленно: для обнаружения порога задержка вообще не нужна.

Пример: ограничить частоту соединений SMTP максимум 10 в секунду.

listen smtp
    mode tcp
    bind :25
    rate-limit sessions 10
    server smtp1 127.0.0.1:1025

Примечание: при достижении максимальной частоты состояние фронтенда не меняется, но при включённом “socket-stats” его сокеты отображаются в статистике как “WAITING”.

См. также: ключевое слово “backlog” и критерий ACL “fe_sess_rate”.

redirect location <loc> [code <code>] <option> [{if | unless} <condition>]

redirect location <loc> [code <code>] <option> [{if | unless} <condition>]
redirect prefix   <pfx> [code <code>] <option> [{if | unless} <condition>]
redirect scheme   <sch> [code <code>] <option> [{if | unless} <condition>]

Возвращает перенаправление HTTP при выполнении/невыполнении условия

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend нет | да | да | да

При выполнении/невыполнении условия запрос HTTP приводит к ответу с перенаправлением. Если условие не задано, перенаправление применяется безусловно.

Аргументы:

<loc>     При "redirect location" точное значение <loc> помещается в заголовок HTTP "Location". В
          правиле "http-request" значение <loc> следует правилам пользовательского формата журнала и
          может включать динамические значения (см. «Пользовательский формат журнала» в разделе
          8.2.6).

<pfx>     При "redirect prefix" заголовок "Location" строится соединением <pfx> и полного пути URI,
          включая строку запроса, если не указан "drop-query" (см. ниже). Особый случай: при <pfx>,
          точно равном "/", перед исходным URI ничего не вставляется. Это позволяет
          перенаправить на тот же URL, например для вставки cookie. В правиле "http-request"
          значение <pfx> следует правилам пользовательского формата журнала и может включать
          динамические значения (см. «Пользовательский формат журнала» в разделе 8.2.6).

<sch>     При "redirect scheme" заголовок "Location" строится соединением <sch>, "://", первого
          вхождения заголовка "Host", затем пути URI со строкой запроса, если не указан
          "drop-query" (см. ниже). Если путь не найден либо равен "*", используется "/". Если
          заголовок "Host" не найден, возвращается пустой компонент хоста, который большинство
          современных браузеров понимает как перенаправление на тот же хост. Директива чаще
          всего перенаправляет HTTP на HTTPS. В правиле "http-request" значение <sch> следует
          правилам пользовательского формата журнала и может включать динамические значения (см.
          «Пользовательский формат журнала» в разделе 8.2.6).

<code>    Необязательный код определяет нужный тип перенаправления HTTP. Поддерживаются
          только 301, 302, 303, 307 и 308; если код не задан, по умолчанию
          используется 302. Код 301 означает «перемещён навсегда», и браузер может
          кешировать Location. Код 302 означает «перемещён временно»: браузеру не следует
          кешировать перенаправление. Код 303 эквивалентен 302, но браузер запрашивает
          адрес методом GET. Код 307 подобен 302, однако явно требует повторного
          использования того же метода. Аналогично 308 заменяет 301, если необходимо
          использовать тот же метод.

<option>  Несколько параметров позволяют настроить ожидаемое поведение перенаправления:

  - "drop-query" При использовании ключевого слова в перенаправлении на основе префикса адрес
    задаётся без строки запроса. Это удобно, например, для направления пользователей на
    незащищённую страницу. На перенаправления типа location параметр не влияет.

  - "append-slash" Ключевое слово можно использовать вместе с "drop-query", чтобы направлять
    пользователей с URL без завершающего '/' на тот же URL с '/'. Это помогает
    поисковым системам видеть только один URL. Для этого предпочтителен код возврата
    301.

  - "ignore-empty" Ключевое слово действует только при получении адреса из выражения формата
    журнала, то есть при использовании в http-request или http-response. Если результат выражения пуст,
    правило следует молча пропустить. Основное применение — массовые перенаправления известных
    путей с помощью простой карты.

  - "set-cookie NAME[=value]" В ответ добавляется заголовок "Set-Cookie" с NAME и необязательным "=value".
    Иногда это указывает, что пользователь уже был замечен, например для защиты от некоторых
    типов DoS. Другие параметры cookie не добавляются, поэтому это cookie сеанса. Для браузера
    одно имя cookie без знака равенства отличается от cookie со знаком равенства.

  - "set-cookie-fmt <fmt>" Эквивалентен предыдущему параметру, но заголовок "Set-Cookie" заполняется
    результатом вычисления строки log-format <fmt>. Следует соблюдать формат "NAME[=value]": при разборе
    конфигурации специальные проверки не выполняются.

  - "clear-cookie NAME[=]" Добавляется заголовок "Set-Cookie" с NAME и необязательным "=", но с
    атрибутом "Max-Age", равным нулю. Это велит браузеру удалить cookie и удобно, например, на
    страницах выхода. Очистка cookie "NAME" не удаляет cookie, заданный как "NAME=value". Для этого
    необходимо очистить "NAME=", поскольку браузер различает эти варианты.

  - "keep-query" При использовании ключевого слова в перенаправлении на основе location строка
    запроса исходного URI, если она есть, добавляется к адресу. Если её нет, ничего не
    добавляется. Если адрес уже содержит строку запроса, исходная добавляется через разделитель
    '&'.

Пример: перевести только URL входа на HTTPS.

acl clear      dst_port  80
acl secure     dst_port  8080
acl login_page url_beg   /login
acl logout     url_beg   /logout
acl uid_given  url_reg   /login?userid=[^&]+
acl cookie_set hdr_sub(cookie) SEEN=1

redirect prefix   https://mysite.com set-cookie SEEN=1 if !cookie_set
redirect prefix   https://mysite.com           if login_page !secure
redirect prefix   http://mysite.com drop-query if login_page !uid_given
redirect location http://mysite.com/           if !login_page secure
redirect location / clear-cookie USERID=       if logout

Пример: перенаправлять запросы статей без завершающего ‘/’.

acl missing_slash path_reg ^/article/[^/]*$
redirect code 301 prefix / drop-query append-slash if missing_slash

Пример: перенаправлять весь трафик HTTP на HTTPS, когда HAProxy обрабатывает SSL.

redirect scheme https if !{ ssl_fc }

Пример: добавлять префикс ‘www.’ перед всеми хостами, у которых его нет.

http-request redirect code 301 location      \
  http://www.%[hdr(host)]%[capture.req.uri]  \
  unless { hdr_beg(host) -i www }

Пример: постоянно перенаправлять только старые URL на новые.

http-request redirect code 301 location               \
  %[path,map_str(old-blog-articles.map)] ignore-empty

Об использовании ACL см. раздел 7 .

retries <value>

retries <value>

Задаёт число повторных попыток обращения к серверу после неудачи

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<value>   — число повторных попыток выполнения запроса или установления соединения с сервером
          после неудачи.

По умолчанию повторяются только попытки установить новое соединение. Однако с директивой “retry-on” повторную попытку могут вызывать и другие условия, например пустой ответ или нежелательный код состояния. Каждое из них учитывается как одна попытка; когда общее число попыток достигает заданного здесь значения, возвращается ошибка.

Чтобы не устанавливать соединение повторно немедленно с перезапускающимся сервером, перед повторной попыткой обращения к тому же серверу вводится задержка min(“timeout connect”, одна секунда).

При “option redispatch” некоторые повторные попытки могут выполняться на другом сервере, даже если cookie указывает на иной сервер. По умолчанию это только последняя повторная попытка, если “option redispatch” не передан аргумент.

См. также: “option redispatch”

retry-on [space-delimited list of keywords]

retry-on [space-delimited list of keywords]

Задаёт условия автоматического повторения неудачного запроса. Настройка действует только при “mode”, равном http; иначе молча игнорируется.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

 <keywords>  Список ключевых слов или кодов состояния HTTP, разделённых пробелами. Каждый
             элемент обозначает тип неудачи, при которой следует попытаться повторить запрос.
             Перед изменением настройки следует прочитать примечания внизу. Поддерживаются
             следующие ключевые слова:

   none              Никогда не повторять

   conn-failure      Повторять при неудаче установления соединения или согласования SSL,
                     если запрос не удалось отправить. Это значение по умолчанию.

   empty-response    Повторять, если соединение с сервером закрылось после отправки части
                     запроса, а от сервера ничего не получено. Это может быть вызвано тайм-аутом
                     запроса на сервере, плохим состоянием сети, отказом или перезапуском
                     сервера во время обработки запроса.

   junk-response     Повторять, если полученное от сервера не похоже на полный ответ HTTP,
                     включая неполные заголовки ответа или содержимое, не относящееся к HTTP.
                     Обычно повторять при таких событиях нецелесообразно: причиной может быть
                     ошибка конфигурации (неверный порт сервера) либо вредоносный для сервера
                     запрос, например атака с переполнением буфера.

   response-timeout  Истёк тайм-аут сервера при ожидании ответа на запрос. Причиной может быть
                     плохое состояние сети, повторное использование простаивающего соединения,
                     истёкшего на промежуточном участке, либо чрезвычайно затратная обработка
                     запроса. Обычно повторять при таких событиях запросы к серверам с тяжёлой
                     обработкой баз данных, например полными сканированиями, нецелесообразно:
                     это может усилить атаки отказа в обслуживании.

   0rtt-rejected     Повторять запросы, отправленные в ранних данных и отклонённые сервером.
                     Обычно повторение таких запросов считается безопасным.

   <status>          Любой код состояния HTTP из "401" (Unauthorized), "403" (Forbidden),
   "404" (Not Found), "408" (Request Timeout), "421" (Misdirected Request), "425" (Too
   Early), "429" (Too Many Requests), "500" (Server Error), "501" (Not Implemented),
   "502" (Bad Gateway), "503" (Service Unavailable), "504" (Gateway Timeout).

   all-retryable-errors
                     Повторять запрос при любой ошибке, допускающей повторение. Сейчас включает
                     "conn-failure", "empty-response", "junk-response", "response-timeout", "0rtt-rejected", "500", "502", "503" и
                     "504".

Эта директива заменяет предыдущие настройки новыми; они не накапливаются.

Любое значение, кроме “none” и “conn-failure”, требует выделить буфер и скопировать туда весь запрос, что влияет на память и производительность. Запросы, не помещающиеся в один буфер, никогда не повторяются (см. глобальный tune.bufsize).

Необходимо убедиться, что приложение защищено от повторного выполнения, например уникальными IDs транзакций, передаваемыми в запросах, либо что повторение того же запроса не имеет последствий. Иначе любое значение retry-on, кроме “conn-failure” и “none”, очень опасно. Серверы статических файлов и кеши обычно считаются безопасными для любых повторных попыток. Код состояния может помочь быстро уйти от сервера с ненормальным поведением, например нехваткой памяти или проблемами файловой системы. В таком случае может быть целесообразно немедленно перераспределить соединение на другой сервер (см. “option redispatch”). Наконец, большинство неудач вызвано самими запросами: повторение запроса, нарушающего работу сервера, часто ещё больше ухудшает состояние этого сервера, а при перераспределении — всей службы.

Если нет точного понимания того, как приложение обрабатывает повторяемые запросы, эту директиву не следует использовать.

Значение по умолчанию — “conn-failure”.

Пример:

retry-on 503 504

См. также: “retries”, “option redispatch”, “tune.bufsize”

server <name> <address>[:[port]] [param*]

server <name> <address>[:[port]] [param*]

Объявляет сервер в бэкенде

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend нет | нет | да | да

Аргументы:

<name>    — внутреннее имя сервера, отображаемое в журналах и уведомлениях. При "http-send-name-header" оно
          добавляется в заголовок запроса, отправляемого серверу. Имя должно быть уникальным в
          секции backend.

<address> — адрес IPv4 или IPv6 сервера. Можно также указать разрешаемое имя хоста; оно
          разрешается при запуске. Адрес "0.0.0.0" или "*" имеет особый смысл: соединение
          пересылается на тот же адрес IP, что и клиентское соединение. Это удобно в
          архитектурах прозрачного прокси, где соединение клиента перехватывается и HAProxy
          должен переслать его на исходный адрес назначения. Это примерно соответствует "transparent",
          но при использовании сервера можно ограничить число одновременных соединений и вести
          статистику. Перед адресом можно указать необязательный префикс семейства,
          принудительно задающий его независимо от формата адреса. Это удобно, например, для
          пути сокета unix без косой черты ('/'). Сейчас поддерживаются:
                - 'ipv4@'  -> адрес всегда IPv4
                - 'ipv6@'  -> адрес всегда IPv6
                - 'unix@'  -> адрес — путь локального сокета unix
                - 'abns@'  -> адрес в абстрактном пространстве имён (только Linux)
                - 'abnsz@'  -> адрес в абстрактном пространстве имён (только Linux), но явно
                  завершается нулём. Поэтому дополнение sun_path с помощью \0 не
                  используется. Это удобно для взаимодействия с программами, не реализующими
                  используемые haproxy правила именования abns по умолчанию.
                - 'sockpair@' -> адрес — FD подключённого сокета unix или пары socketpair.
                  При соединении бэкенд создаёт пару соединённых сокетов и передаёт один из них
                  через FD. Часть bind использует полученный сокет как FD клиента.
                  Следует использовать осторожно.
                - 'quic4@' [ ЭКСПЕРИМЕНТАЛЬНО] -> адрес разрешается как IPv4, используется
                  протокол UDP. QUIC на стороне бэкенда считается экспериментальным
                  главным образом потому, что препятствует удалению сервера во время работы.
                  Требуется глобальное ключевое слово "expose-experimental-directives".
                - 'quic6@' [ ЭКСПЕРИМЕНТАЛЬНО] -> адрес разрешается как IPv6, используется
                  протокол UDP. Аналогично помечено как экспериментальное.
                - 'rhttp@' [ ЭКСПЕРИМЕНТАЛЬНО ] -> собственное семейство адресов пассивного
                  сервера в контексте обратного HTTP. Эта экспериментальная возможность
                  требует "expose-experimental-directives" в строке перед этим сервером.
          В параметре адреса можно ссылаться на переменные окружения; см. раздел 2.3.
          Настройка "init-addr" позволяет изменить способ разрешения адресов IP при запуске.

<port>    — необязательное указание порта. Если задан, все соединения направляются на этот
          порт; иначе используется порт, к которому подключился клиент. Перед портом можно
          поставить "+" или "-": тогда порт сервера вычисляется прибавлением указанного
          значения к порту клиента.

<param*>  — список параметров сервера. Ключевое слово "server" принимает множество параметров; ему
          посвящён целый раздел. Подробнее см. раздел 5.

Примеры:

server first  10.1.1.1:1080 cookie first  check inter 1000
server second 10.1.1.2:1080 cookie second check inter 1000
server transp ipv4@
server backup "${SRV_BACKUP}:1080" backup
server www1_dc1 "${LAN_DC1}.101:80"
server www1_dc2 "${LAN_DC2}.101:80"

Примечание: для сокетов “abns” HAProxy в абстрактном пространстве имён Linux длина адреса равна полной длине sun_path. Некоторые другие программы, например socat, по умолчанию используют только длину строки. Чтобы определение абстрактного сокета в socat было совместимо с сокетами HAProxy, к нему нужно добавить параметр “,unix-tightsocklen=0”; другой вариант — использовать семейство сокетов “abnsz” HAProxy.

См. также: “default-server”, “http-send-name-header” и раздел 5 о параметрах серверов

server-state-file-name [ { use-backend-name | <file> } ]

server-state-file-name [ { use-backend-name | <file> } ]

Задаёт файл состояния серверов, который читается, загружается и применяется к серверам этого бэкенда.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend нет | нет | да | да

Действует только при “load-server-state-from-file”, равном “local”. Если <file> отсутствует, указан “use-backend-name” либо директива не задана, используется имя бэкенда. <file>, начинающийся с ‘/’, считается абсолютным путём; иначе <file> присоединяется к глобальной директиве “server-state-base”.

Пример: приведённая ниже минимальная конфигурация заставит HAProxy искать файл состояния серверов ‘/etc/haproxy/states/bk’:

global
  server-state-file-base /etc/haproxy/states

backend bk
  load-server-state-from-file

См. также: “server-state-base”, “load-server-state-from-file” и “show servers state”

server-template <prefix> <num | range> <fqdn>[:<port>] [params*]

server-template <prefix> <num | range> <fqdn>[:<port>] [params*]

Задаёт шаблон инициализации серверов с общими параметрами. Имена серверов строятся из <prefix> и <num | range>.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend нет | нет | да | да

Аргументы:

<prefix>  Префикс создаваемых имён серверов.

<num | range> Если задан <num>, шаблон инициализирует <num> серверов с числовыми суффиксами имён
          от 1 до <num>. Можно также задать диапазон <num_low>-<num_high>, чтобы использовать
          суффиксы имён от <num_low> до <num_high>.

<fqdn>    FQDN всех серверов, инициализируемых шаблоном.

<port>    Имеет тот же смысл, что и аргумент <port> у "server" (см. ключевое слово "server").

<params*> Остальные параметры сервера из числа поддерживаемых ключевым словом "server".

Примеры:

# Initializes 3 servers with srv1, srv2 and srv3 as names,
# google.com as FQDN, and health-check enabled.
server-template srv 1-3 google.com:80 check

# or
server-template srv 3 google.com:80 check

# would be equivalent to:
server srv1 google.com:80 check
server srv2 google.com:80 check
server srv3 google.com:80 check

source <addr>[:<port>] [usesrc { <addr2>[:<port2>] | client | clientip } ]

source <addr>[:<port>] [usesrc { <addr2>[:<port2>] | client | clientip } ]
source <addr>[:<port>] [usesrc { <addr2>[:<port2>] | hdr_ip(<hdr>[,<occ>]) } ]
source <addr>[:<port>] [interface <name>]

Задаёт исходный адрес для исходящих соединений

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<addr>    — адрес IPv4, к которому HAProxy привязывается перед соединением с сервером. Он также
          используется как исходный адрес проверок работоспособности.

          Значение по умолчанию 0.0.0.0 позволяет системе выбрать наиболее подходящий адрес для
          достижения назначения. Перед адресом можно задать необязательный префикс семейства,
          принудительно выбирающий его независимо от формата адреса. Это удобно, например, для
          пути сокета unix без косой черты ('/'). Сейчас поддерживаются:
            - 'ipv4@' -> адрес всегда IPv4
            - 'ipv6@' -> адрес всегда IPv6
            - 'unix@' -> адрес — путь локального сокета unix
            - 'abns@' -> адрес в абстрактном пространстве имён (только Linux)
            - 'abnsz@'  -> адрес в абстрактном пространстве имён с завершающим нулём (только
              Linux)

          В параметре адреса можно ссылаться на переменные окружения; подробнее см. раздел
          2.3 о переменных окружения.

<port>    — необязательный порт. Обычно он не нужен, но может пригодиться в особых условиях.
          Значение по умолчанию ноль позволяет системе выбрать свободный порт. Бэкенд не
          поддерживает диапазоны портов: для принудительного задания диапазонов их необходимо
          указать в каждой строке "server".

<addr2>   — адрес IP, представляемый серверу при пересылке соединений в режиме полностью
          прозрачного прокси. Сейчас это поддерживается только некоторыми ядрами Linux с
          дополнительными исправлениями. При заданном адресе подключающиеся к серверу клиенты
          представляются этим адресом, а проверки работоспособности по-прежнему используют
          <addr>.

<port2>   — необязательный порт, представляемый серверу при пересылке соединений в режиме
          полностью прозрачного прокси (см. <addr2> выше). Значение по умолчанию ноль позволяет
          системе выбрать свободный порт.

<hdr>     — имя заголовка HTTP, из которого извлекается IP для привязки. Это имя
          заголовка со списком, разделённым запятыми и допускающим несколько адресов IP. По
          умолчанию используется последнее вхождение. Предназначено для X-Forwarded-For и автоматической
          привязки к адресу IP клиента, видимому предыдущему прокси, обычно Stunnel. Выбор
          другого вхождения относительно последнего описан ниже в <occ>. Если заголовок или
          вхождение не найдено, привязка не выполняется и используется адрес IP прокси по
          умолчанию. Как и у любого заголовка HTTP, его имя не зависит от регистра.

<occ>     — номер используемого значения в заголовке с несколькими значениями. Вместе с
          "hdr_ip(<hdr>)" задаёт вхождение для исходного адреса IP. Положительные значения
          отсчитываются от первого вхождения: 1 — первое. Отрицательные отсчитываются от
          последнего: -1 — последнее. Это удобно, когда X-Forwarded-For задаётся на входе
          инфраструктуры и должен использоваться через несколько уровней прокси. Если значение
          не задано, подразумевается -1. Ноль отключает возможность.

<name>    — необязательное имя интерфейса, к которому привязывается исходящий трафик. На
          поддерживающих эту возможность системах (сейчас только Linux) весь трафик к серверу
          можно привязать к этому интерфейсу, даже если по таблицам маршрутизации система
          выбрала бы другой. Использовать следует крайне осторожно. Этот параметр требует
          привилегий root.

Ключевое слово “source” полезно в сложных окружениях, где соединяться с серверами разрешено только с определённого адреса. Например, оно может понадобиться, когда через общедоступный шлюз необходимо использовать частный адрес и известно, что система не может сама определить подходящий исходный адрес.

Расширение, доступное в некоторых ядрах Linux с дополнительными исправлениями, можно использовать через необязательное ключевое слово “usesrc”. Оно позволяет соединяться с серверами с адресом IP, не принадлежащим самой системе. Это называется «режимом полностью прозрачного прокси». Для работы этого режима серверы назначения должны направлять ответный трафик к этому адресу через машину с HAProxy; на ней обычно необходимо включить пересылку IP.

В режиме «полностью прозрачного прокси» можно принудительно представлять серверам определённый адрес IP. На практике это используется редко. Чаще HAProxy поручают представлять адрес IP клиента. Для этого есть два способа:

- Представлять адрес IP и порт клиента. Это наиболее прозрачный режим, но при включённом отслеживании соединений IP на машине он может создавать проблемы: одно соединение может наблюдаться дважды с разными состояниями. Однако у этого решения есть большое преимущество: система не ограничена 64k исходящих пар «адрес + порт», поскольку можно использовать все диапазоны клиентов.

- Представлять только адрес IP клиента и выбирать свободный порт. Решение по-прежнему достаточно изящно, но чуть менее прозрачно: журналы нижестоящих межсетевых экранов не будут соответствовать журналам вышестоящих. Недостаток — число одновременных соединений ограничено обычными 64k портов. Однако поскольку порты до и после прокси различаются, повторное использование той же сессии не нарушает локальное отслеживание соединений IP на машине.

Этот параметр задаёт исходный адрес по умолчанию для всех серверов бэкенда. Его можно также указать в секции “defaults”. Для более точного задания исходного адреса на уровне сервера служит серверный параметр “source”. Подробнее см. раздел 5 .

Для работы “usesrc” нужны привилегии root либо, на поддерживающих это системах, специальное право “cap_net_raw”. См. также глобальную директиву “setcap”.

Примеры:

backend private
    # Connect to the servers using our 192.168.1.200 source address
    source 192.168.1.200

backend transparent_ssl1
    # Connect to the SSL farm from the client's source address
    source 192.168.1.200 usesrc clientip

backend transparent_ssl2
    # Connect to the SSL farm from the client's source address and port
    # not recommended if IP conntrack is present on the local machine.
    source 192.168.1.200 usesrc client

backend transparent_ssl3
    # Connect to the SSL farm from the client's source address. It
    # is more conntrack-friendly.
    source 192.168.1.200 usesrc clientip

backend transparent_smtp
    # Connect to the SMTP farm from the client's source address/port
    # with Tproxy version 4.
    source 0.0.0.0 usesrc clientip

backend transparent_http
    # Connect to the servers using the client's IP as seen by previous
    # proxy.
    source 0.0.0.0 usesrc hdr_ip(x-forwarded-for,-1)

См. также: параметр сервера “source” в разделе 5 , патчи Tproxy для ядра Linux на www.balabit.com , ключевое слово “bind”.

srvtcpka-cnt <count>

srvtcpka-cnt <count>

Задаёт максимальное число проверочных пакетов для поддержания соединения, которые TCP должен отправить до разрыва соединения на стороне сервера.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<count>   — максимальное число проверочных пакетов для поддержания соединения.

Это ключевое слово соответствует параметру сокета TCP_KEEPCNT. Если оно не указано, используется общесистемный параметр TCP (tcp_keepalive_probes). Доступность этой настройки зависит от операционной системы. Известно, что она работает в Linux.

См. также: “option srvtcpka”, “srvtcpka-idle”, “srvtcpka-intvl”.

srvtcpka-idle <timeout>

srvtcpka-idle <timeout>

Задаёт время простоя соединения, после которого TCP начинает отправлять проверочные пакеты для поддержания соединения, если отправка пакетов TCP для поддержания соединения на стороне сервера включена.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<timeout> — время простоя соединения до начала отправки проверочных пакетов TCP для
          поддержания соединения. По умолчанию задаётся в секундах, но можно использовать любую
          другую единицу, добавив её обозначение после числа, как описано в начале документа.

Это ключевое слово соответствует параметру сокета TCP_KEEPIDLE. Если оно не указано, используется общесистемный параметр TCP (tcp_keepalive_time). Доступность этой настройки зависит от операционной системы. Известно, что она работает в Linux.

См. также: “option srvtcpka”, “srvtcpka-cnt”, “srvtcpka-intvl”.

srvtcpka-intvl <timeout>

srvtcpka-intvl <timeout>

Задаёт интервал между отдельными проверочными пакетами для поддержания соединения на стороне сервера.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<timeout> — интервал между отдельными проверочными пакетами для поддержания соединения. По
          умолчанию задаётся в секундах, но можно использовать любую другую единицу, добавив её
          обозначение после числа, как описано в начале документа.

Это ключевое слово соответствует параметру сокета TCP_KEEPINTVL. Если оно не указано, используется общесистемный параметр TCP (tcp_keepalive_intvl). Доступность этой настройки зависит от операционной системы. Известно, что она работает в Linux.

См. также: “option srvtcpka”, “srvtcpka-cnt”, “srvtcpka-idle”.

stats admin { if | unless } <cond>

stats admin { if | unless } <cond>

Включает административный уровень статистики при выполнении/невыполнении условия

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend нет | да | да | да

Эта директива включает административный уровень статистики при выполнении/невыполнении условия.

Административный уровень позволяет включать и отключать серверы через веб-интерфейс. По соображениям безопасности страница статистики по умолчанию доступна только для чтения. Если в секции заданы директивы “stats scope”, изменения состояния будут принимать только указанные ими прокси; доступ к остальным будет запрещён.

Сейчас размер запроса POST ограничен размером буфера за вычетом зарезервированного пространства. Поэтому при слишком длинном списке серверов запрос не будет обработан. Рекомендуется менять лишь несколько серверов за один раз.

Эти административные запросы POST уязвимы для атак CSRF. Риск частично снижается проверкой совпадения Origin (или Referer, если Origin отсутствует) с заголовком Host, но этого недостаточно для полного предотвращения атаки. Полностью защититься от таких атак невозможно. Рекомендуется не предоставлять этот интерфейс в публичный доступ и ограничивать круг тех, кто может им пользоваться.

Пример:

# statistics admin level only for localhost
backend stats_localhost
    stats enable
    stats admin if LOCALHOST

Пример:

# statistics admin level always enabled because of the authentication
backend stats_auth
    stats enable
    stats auth  admin:AdMiN123
    stats admin if TRUE

Пример:

# statistics admin level depends on the authenticated user
userlist stats-auth
    group admin    users admin
    user  admin    insecure-password 'AdMiN123'
    group readonly users haproxy
    user  haproxy  insecure-password 'haproxy'

backend stats_auth
    stats enable
    acl AUTH       http_auth(stats-auth)
    acl AUTH_ADMIN http_auth_group(stats-auth) admin
    stats http-request auth unless AUTH
    stats admin if AUTH_ADMIN

См. также: “stats enable”, “stats auth”, “stats http-request”, “stats scope”, раздел 12.2 о списках пользователей и раздел 7 об использовании ACL.

ssl-f-use [<sslbindconf> ...]*

ssl-f-use [<sslbindconf> ...]*

Назначает сертификат текущему фронтенду.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend нет | да | да | нет

Аргументы:

<sslbindconf> поддерживает следующие ключевые слова строки bind (см. раздел 5.1. Параметры bind):

- allow-0rtt
- alpn
- ca-file
- ca-verify-file
- ciphers
- ciphersuites
- client-sigalgs
- crl-file
- curves
- ecdhe
- ktls
- no-alpn
- no-ca-names
- npn
- sigalgs
- ssl-min-ver
- ssl-max-ver
- verify

sslbindconf также поддерживает следующие ключевые слова директивы crt-store load (см. раздел
12.7.1. Параметры загрузки):

- crt
- key
- ocsp
- issuer
- sctl
- ocsp-update

Назначает сертификат <crtname> автоматически созданному crt-list с именем фронтенда и префиксом @ (например, ‘@frontend1’).

Этот неявный crt-list назначается всем строкам bind с “ssl” в текущем фронтенде.

Команды crt-list, выполняемые через сокет статистики, действуют на этот crt-list, поэтому в нём можно заменять, удалять и добавлять сертификаты и параметры SSL.

Пример:

frontend https
    bind :443 ssl
    bind quic4@:443 ssl
    ssl-f-use crt foobar.pem.rsa sigalgs "RSA-PSS+SHA256"
    ssl-f-use crt test.foobar.pem
    ssl-f-use crt test2.foobar.crt key test2.foobar.key ocsp test2.foobar.ocsp ocsp-update on

См. также: “crt-list” и “crt”.

stats auth <user>:<passwd>

stats auth <user>:<passwd>

Включает статистику с аутентификацией и предоставляет доступ учётной записи

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

<user>    — имя пользователя, которому предоставляется доступ

<passwd>  — пароль этого пользователя в открытом виде

Эта директива включает статистику с настройками по умолчанию и разрешает доступ только объявленным пользователям. Её можно повторить столько раз, сколько необходимо, чтобы добавить нужное число пользователей. При попытке доступа к статистике без действительной учётной записи возвращается ответ “401 Forbidden”, чтобы браузер запросил действительное имя пользователя и пароль. Область аутентификации, возвращаемая браузеру, настраивается через “stats realm”.

Поскольку используется базовая аутентификация HTTP (Basic Authentication), пароли передаются по сети в открытом виде. Поэтому было решено и в конфигурационном файле использовать открытые пароли: это напоминает пользователям, что здесь не следует использовать конфиденциальные пароли или пароли от других учётных записей.

Можно также ограничить набор прокси, отображаемых в отчёте, с помощью “stats scope”.

Хотя одной этой директивы достаточно для включения статистики, рекомендуется задать все остальные настройки, чтобы не полагаться на неочевидные параметры по умолчанию.

Пример:

# public access (limited to this backend only)
backend public_www
    server srv1 192.168.0.1:80
    stats enable
    stats hide-version
    stats scope   .
    stats uri     /admin?stats
    stats realm   HAProxy\ Statistics
    stats auth    admin1:AdMiN123
    stats auth    admin2:AdMiN321

# internal monitoring access (unlimited)
backend private_monitoring
    stats enable
    stats uri     /admin?stats
    stats refresh 5s

См. также: “stats enable”, “stats realm”, “stats scope”, “stats uri”

stats enable

stats enable

Включает статистику с настройками по умолчанию

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы: отсутствуют

Эта директива включает статистику с настройками по умолчанию, заданными при сборке. Если не указано иное, используются: - stats uri : /haproxy?stats - stats realm: “HAProxy Statistics” - stats auth : без аутентификации - stats scope: без ограничений

Хотя одной этой директивы достаточно для включения статистики, рекомендуется задать все остальные настройки, чтобы не полагаться на неочевидные параметры по умолчанию.

Пример:

# public access (limited to this backend only)
backend public_www
    server srv1 192.168.0.1:80
    stats enable
    stats hide-version
    stats scope   .
    stats uri     /admin?stats
    stats realm   HAProxy\ Statistics
    stats auth    admin1:AdMiN123
    stats auth    admin2:AdMiN321

# internal monitoring access (unlimited)
backend private_monitoring
    stats enable
    stats uri     /admin?stats
    stats refresh 5s

См. также: “stats auth”, “stats realm”, “stats uri”

stats hide-version

stats hide-version

Включает статистику и скрывает версию HAProxy

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы: отсутствуют

На странице статистики вместе со статистическими данными может отображаться полезная информация о состоянии, в том числе версия HAProxy. Однако сообщать точную версию любому посетителю обычно считается опасным: это может помочь подобрать атаки на известные уязвимости. Директива “stats hide-version” убирает версию из отчёта статистики. Это рекомендуется для публичных сайтов и сайтов со слабым логином/паролем и является настройкой по умолчанию.

Хотя одной этой директивы достаточно для включения статистики, рекомендуется задать все остальные настройки, чтобы не полагаться на неочевидные параметры по умолчанию.

Пример:

# public access (limited to this backend only)
backend public_www
    server srv1 192.168.0.1:80
    stats enable
    stats hide-version
    stats scope   .
    stats uri     /admin?stats
    stats realm   HAProxy\ Statistics
    stats auth    admin1:AdMiN123
    stats auth    admin2:AdMiN321

# internal monitoring access (unlimited)
backend private_monitoring
    stats enable
    stats uri     /admin?stats
    stats refresh 5s

См. также: “stats auth”, “stats enable”, “stats realm”, “stats uri”, “stats show-version”

stats http-request { allow | deny | auth [realm <realm>] }

stats http-request { allow | deny | auth [realm <realm>] }
             [ { if | unless } <condition> ]

Управление доступом к статистике

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend нет | нет | да | да

Как и “http-request”, этот набор параметров позволяет точно управлять доступом к статистике. После каждого параметра могут идти if/unless и acl. Первый параметр с совпавшим условием (или без условия) определяет окончательное действие. При “deny” возвращается ошибка 403; при “allow” выполняется обычная обработка; при “auth” возвращается код ошибки 401/407, чтобы клиент запросил имя пользователя и пароль.

Число директив http-request на экземпляр не имеет фиксированного ограничения.

См. также: “http-request”, раздел 12.2 о списках пользователей и раздел 7 об использовании ACL.

stats realm <realm>

stats realm <realm>

Включает статистику и задаёт область аутентификации

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

<realm>   — имя области базовой аутентификации HTTP (Basic Authentication), сообщаемое
          браузеру. Браузер отображает его во всплывающем окне, предлагающем пользователю ввести
          действительные имя пользователя и пароль.

Область читается как одно слово, поэтому все пробелы в ней следует экранировать обратной косой чертой (’\’).

Эта директива полезна только в сочетании со “stats auth”, поскольку относится исключительно к аутентификации.

Хотя одной этой директивы достаточно для включения статистики, рекомендуется задать все остальные настройки, чтобы не полагаться на неочевидные параметры по умолчанию.

Пример:

# public access (limited to this backend only)
backend public_www
    server srv1 192.168.0.1:80
    stats enable
    stats hide-version
    stats scope   .
    stats uri     /admin?stats
    stats realm   HAProxy\ Statistics
    stats auth    admin1:AdMiN123
    stats auth    admin2:AdMiN321

# internal monitoring access (unlimited)
backend private_monitoring
    stats enable
    stats uri     /admin?stats
    stats refresh 5s

См. также: “stats auth”, “stats enable”, “stats uri”

stats refresh <delay>

stats refresh <delay>

Включить статистику с автоматическим обновлением

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

<delay>   — рекомендуемая задержка обновления, задаваемая в секундах и возвращаемая браузеру,
          который просматривает страницу отчёта. Хотя браузер вправе применять любую задержку,
          обычно он соблюдает её и обновляет страницу через указанное количество секунд.
          Интервал обновления можно задать в любой другой единице времени, отличной от
          используемой по умолчанию, добавив её суффикс к значению, как описано в начале этого
          документа.

Эта директива полезна для экранов мониторинга, на которых постоянно открыта страница с данными об активности балансировщика нагрузки. Если она задана, HTML страница отчёта будет содержать ссылку “refresh”/“stop refresh”, позволяющую пользователю включать или отключать автоматическое обновление страницы.

Хотя одной этой директивы достаточно для включения статистики, рекомендуется задать все остальные настройки, чтобы не полагаться на неочевидные параметры по умолчанию.

Пример:

# public access (limited to this backend only)
backend public_www
    server srv1 192.168.0.1:80
    stats enable
    stats hide-version
    stats scope   .
    stats uri     /admin?stats
    stats realm   HAProxy\ Statistics
    stats auth    admin1:AdMiN123
    stats auth    admin2:AdMiN321

# internal monitoring access (unlimited)
backend private_monitoring
    stats enable
    stats uri     /admin?stats
    stats refresh 5s

См. также: “stats auth”, “stats enable”, “stats realm”, “stats uri”

stats scope { <name> | "." }

stats scope { <name> | "." }

Включить статистику и ограничить область доступа

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

<name>    — имя секции listen, frontend или backend, включаемой в отчёт. Специальное имя
          "." (одна точка) обозначает секцию, в которой находится эта директива.

Если эта директива задана, в отчёте будут показаны только секции, перечисленные с её помощью. Все остальные будут скрыты, а попытки изменить их состояние в режиме администрирования будут отклонены. Если в отчёт нужно включить несколько секций, эту директиву можно повторять столько раз, сколько требуется. Имена проверяются простым сравнением строк; существование секции с указанным именем никогда не проверяется.

Хотя одной этой директивы достаточно для включения статистики, рекомендуется задать все остальные настройки, чтобы не полагаться на неочевидные параметры по умолчанию.

Пример:

# public access (limited to this backend only)
backend public_www
    server srv1 192.168.0.1:80
    stats enable
    stats hide-version
    stats scope   .
    stats uri     /admin?stats
    stats realm   HAProxy\ Statistics
    stats auth    admin1:AdMiN123
    stats auth    admin2:AdMiN321

# internal monitoring access (unlimited)
backend private_monitoring
    stats enable
    stats uri     /admin?stats
    stats refresh 5s

См. также: “stats auth”, “stats enable”, “stats realm”, “stats uri” и “stats admin”

stats show-desc [ <desc> ]

stats show-desc [ <desc> ]

Включить отображение описания на странице статистики.

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

`<desc>`    — необязательное описание для отображения. Если оно не задано, автоматически
          используется описание из секции global.

Эта директива полезна для пользователей, предлагающих своим клиентам общие сервисы, где узел или описание следует задавать разными для каждого клиента.

Хотя одной этой директивы достаточно для включения отчёта статистики, рекомендуется задать и все остальные настройки, чтобы не полагаться на неочевидные параметры по умолчанию. По умолчанию описание не отображается.

Пример:

# internal monitoring access (unlimited)
backend private_monitoring
    stats enable
    stats show-desc Master node for Europe, Asia, Africa
    stats uri       /admin?stats
    stats refresh   5s

См. также: “show-node”, “stats enable”, “stats uri” и “description” в секции global.

stats show-legends

stats show-legends

Включить отображение дополнительной информации на странице статистики

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы: отсутствуют

Включить отображение дополнительной информации на странице статистики: - cap: возможности (прокси) - mode: один из режимов tcp, http или health (прокси) - id: SNMP ID (прокси, сокет, сервер) - IP (сокет, сервер) - cookie (бэкенд, сервер)

Хотя одной этой директивы достаточно для включения отчёта статистики, рекомендуется задать и все остальные настройки, чтобы не полагаться на неочевидные параметры по умолчанию. По умолчанию эта информация не отображается.

См. также: “stats enable”, “stats uri”.

stats show-modules

stats show-modules

Включить отображение дополнительного модуля статистики на странице статистики

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы: отсутствуют

В конце строки добавляются новые столбцы, в которых дополнительные значения статистики представлены во всплывающей подсказке.

Хотя одной этой директивы достаточно для включения отчёта статистики, рекомендуется задать и все остальные настройки, чтобы не полагаться на неочевидные параметры по умолчанию. По умолчанию эта информация не отображается.

См. также: “stats enable”, “stats uri”.

stats show-node [ <name> ]

stats show-node [ <name> ]

Включить отображение имени узла на странице статистики.

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

<name>    — необязательное имя для отображения. Если оно не задано, автоматически используется
          имя узла из секции global.

Эта директива полезна для пользователей, предлагающих своим клиентам общие сервисы, где узел или описание могут различаться на странице статистики для каждого клиента. По умолчанию имя узла не отображается.

Хотя одной этой директивы достаточно для включения статистики, рекомендуется задать все остальные настройки, чтобы не полагаться на неочевидные параметры по умолчанию.

Пример:

# internal monitoring access (unlimited)
backend private_monitoring
    stats enable
    stats show-node Europe-1
    stats uri       /admin?stats
    stats refresh   5s

См. также: “show-desc”, “stats enable”, “stats uri” и “node” в секции global.

stats show-version

stats show-version

Включить статистику и отображение версии HAProxy

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы: отсутствуют

Страница статистики может отображать вместе со статистикой полезные сведения о состоянии, в том числе версию HAProxy. Однако обычно считается опасным сообщать точную версию всем: это может помочь проводить целевые атаки на известные уязвимости. Поэтому по умолчанию она не отображается. “stats show-version” включает отображение этих сведений. Это не рекомендуется для публичных сайтов или любых сайтов со слабыми учётными данными (именем пользователя и паролем).

См. также: “stats auth”, “stats enable”, “stats realm”, “stats uri”, “stats hide-version”

stats uri <prefix>

stats uri <prefix>

Включить статистику и задать префикс URI для доступа к ней

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

<prefix>  — префикс любого URI, перенаправляемого к статистике. Этот префикс может содержать
          знак вопроса ('?'), обозначающий часть строки запроса.

URI статистики перехватывается в ретранслируемом трафике, поэтому выглядит как страница обычного приложения. Настоятельно рекомендуется убедиться, что выбранный URI никогда не встретится в приложении, иначе обратиться к нему в приложении будет невозможно.

URI по умолчанию, встроенный в HAProxy, — “/haproxy?stats”, но его можно изменить при сборке, поэтому лучше всегда явно задавать его здесь. Обычно полезно включать в URI знак вопроса, чтобы промежуточные прокси воздерживались от кэширования результатов. Кроме того, поскольку любая строка с этим префиксом будет принята как запрос статистики, знак вопроса помогает гарантировать, что никакой корректный URI не начнётся с тех же слов.

Иногда очень удобно использовать “/” как префикс URI и поместить эту директиву в отдельный экземпляр “listen”. Так легко выделить адрес или порт исключительно для статистики.

Хотя одной этой директивы достаточно для включения статистики, рекомендуется задать все остальные настройки, чтобы не полагаться на неочевидные параметры по умолчанию.

Пример:

# public access (limited to this backend only)
backend public_www
    server srv1 192.168.0.1:80
    stats enable
    stats hide-version
    stats scope   .
    stats uri     /admin?stats
    stats realm   HAProxy\ Statistics
    stats auth    admin1:AdMiN123
    stats auth    admin2:AdMiN321

# internal monitoring access (unlimited)
backend private_monitoring
    stats enable
    stats uri     /admin?stats
    stats refresh 5s

См. также: “stats auth”, “stats enable”, “stats realm”

stick match <pattern> [table <table>] [{if | unless} <cond>]

stick match <pattern> [table <table>] [{if | unless} <cond>]

Задать условие сопоставления шаблона запроса для привязки пользователя к серверу

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend нет | нет | да | да

Аргументы:

<pattern>  — правило выражения образца, описанное в разделе 7.3. Оно задаёт, какие элементы
           входящего запроса или соединения будут анализироваться в поисках совпадающей записи в
           таблице привязок. Это правило обязательно.

<table>    — необязательное имя таблицы привязок. Если оно не задано, используется таблица того
           же бэкенда. Таблица привязок объявляется директивой "stick-table".

<cond>     — необязательное условие сопоставления. Оно позволяет сопоставлять по определённому
           критерию только при соблюдении (или несоблюдении) других условий. Например, можно
           сопоставлять по исходному IP адресу, кроме случая, когда запрос проходит через
           известный прокси: тогда сопоставление выполнялось бы по заголовку с этим IP
           адресом.

Некоторые протоколы или приложения требуют сложных правил привязки и не всегда могут полагаться только на cookie или хэширование. Директива “stick match” описывает правило извлечения критерия привязки из входящего запроса или соединения. Полный список возможных шаблонов и правил преобразования см. в разделе 7 .

Таблицу нужно объявить директивой “stick-table”. Её тип должен быть совместим с шаблоном. По умолчанию используется таблица в том же бэкенде. Можно совместно использовать таблицу с другими бэкендами, сославшись на неё ключевым словом “table”. При ссылке на другую таблицу используются ID серверов в этих бэкендах. По умолчанию ID всех серверов в каждом бэкенде начинаются с 1, поэтому достаточно порядка серверов. Но при сомнениях настоятельно рекомендуется явно задать ID серверов с помощью их настройки “id”.

Условия применения директивы “stick match” можно ограничить с помощью “if” или “unless”, за которыми следует условие. Об условиях на основе ACL см. раздел 7 .

Количество директив “stick match” не ограничено. Первая применимая директива, для которой найдено совпадение, направит запрос на тот же сервер, что использовался для запроса, создавшего запись. Таким образом, несколько сопоставлений можно использовать как запасные варианты.

Правила stick проверяются после cookie привязки, поэтому не влияют на привязку, если cookie уже использовался для выбора сервера. Так очень легко вставлять cookie и сопоставлять IP адреса, сохраняя привязку между HTTP и HTTPS.

Пример:

# forward SMTP users to the same server they just used for POP in the
# last 30 minutes
backend pop
    mode tcp
    balance roundrobin
    stick store-request src
    stick-table type ip size 200k expire 30m
    server s1 192.168.1.1:110
    server s2 192.168.1.1:110

backend smtp
    mode tcp
    balance roundrobin
    stick match src table pop
    server s1 192.168.1.1:25
    server s2 192.168.1.1:25

См. также: “stick-table”, “stick on”, раздел 11 о таблицах привязок и раздел 7 об ACL и извлечении образцов.

stick on <pattern> [table <table>] [{if | unless} <condition>]

stick on <pattern> [table <table>] [{if | unless} <condition>]

Задать шаблон запроса для связывания пользователя с сервером

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend нет | нет | да | да

Примечание: эта форма в точности эквивалентна “stick match”, за которой следует “stick store-request”, обе с одинаковыми аргументами. Подробности см. в описании обоих ключевых слов. Эта форма предоставлена лишь для удобства написания конфигураций, которые проще сопровождать.

Примеры:

# The following form ...
stick on src table pop if !localhost

# ...is strictly equivalent to this one:
stick match src table pop if !localhost
stick store-request src table pop if !localhost


# Use cookie persistence for HTTP, and stick on source address for HTTPS as
# well as HTTP without cookie. Share the same table between both accesses.
backend http
    mode http
    balance roundrobin
    stick on src table https
    cookie SRV insert indirect nocache
    server s1 192.168.1.1:80 cookie s1
    server s2 192.168.1.1:80 cookie s2

backend https
    mode tcp
    balance roundrobin
    stick-table type ip size 200k expire 30m
    stick on src
    server s1 192.168.1.1:443
    server s2 192.168.1.1:443

См. также: “stick match”, “stick store-request” и раздел 11 о таблицах привязок.

stick store-request <pattern> [table <table>] [{if | unless} <condition>]

stick store-request <pattern> [table <table>] [{if | unless} <condition>]

Задать шаблон запроса для создания записи в таблице привязок

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend нет | нет | да | да

Аргументы:

<pattern>  — правило выражения образца, описанное в разделе 7.3. Оно задаёт, какие элементы
           входящего запроса или соединения будут анализироваться, извлекаться и сохраняться в
           таблице после выбора сервера.

<table>    — необязательное имя таблицы привязок. Если оно не задано, используется таблица того
           же бэкенда. Таблица привязок объявляется директивой "stick-table".

<cond>     — необязательное условие сохранения. Оно позволяет сохранять определённые критерии
           только при соблюдении (или несоблюдении) некоторых условий. Например, можно сохранять
           исходный IP адрес, кроме случая, когда запрос проходит через известный прокси:
           тогда сохранялась бы преобразованная форма заголовка с этим IP адресом.

Некоторые протоколы или приложения требуют сложных правил привязки и не всегда могут полагаться только на cookie или хэширование. Директива “stick store-request” описывает правило, определяющее, что и когда извлекать из запроса для сохранения в таблице привязок, чтобы следующие запросы могли сопоставляться с записью с помощью “stick match”. Очевидно, извлечённая часть должна иметь смысл и допускать совпадение в последующем запросе. Например, сохранение IP адреса клиента часто имеет смысл. Сохранение ID из параметра URL тоже имеет смысл. Сохранение исходного порта почти никогда не имеет смысла, поскольку совпадения будут случайными. Полный список возможных шаблонов и правил преобразования см. в разделе 7 .

Таблицу нужно объявить директивой “stick-table”. Её тип должен быть совместим с шаблоном. По умолчанию используется таблица в том же бэкенде. Можно совместно использовать таблицу с другими бэкендами, сославшись на неё ключевым словом “table”. При ссылке на другую таблицу используются ID серверов в этих бэкендах. По умолчанию ID всех серверов в каждом бэкенде начинаются с 1, поэтому достаточно порядка серверов. Но при сомнениях настоятельно рекомендуется явно задать ID серверов с помощью их настройки “id”.

Условия применения директивы “stick store-request” можно ограничить с помощью “if” или “unless”, за которыми следует условие. Это условие проверяется при разборе запроса, поэтому можно использовать любые критерии. Об условиях на основе ACL см. раздел 7 .

Количество директив “stick store-request” не ограничено, но действует предел 8 одновременных сохранений на запрос или ответ. Это позволяет сохранить до 8 критериев, извлечённых из запроса или ответа, независимо от количества правил. Сохраняются только первые 8 совпавших критериев. Так можно заполнять несколько таблиц одновременно, чтобы увеличить вероятность распознавания пользователя при другом протоколе или способе доступа. Можно использовать несколько правил store-request с одной таблицей, располагая их в порядке убывания предпочтения, чтобы найти наиболее подходящий критерий. Для данной таблицы сохраняется только первый извлечённый критерий. Все последующие правила store-request, ссылающиеся на ту же таблицу, пропускаются, и их ACL не проверяются.

Правила “store-request” проверяются после установления соединения с сервером, чтобы таблица содержала настоящий сервер, обработавший запрос.

Пример:

# forward SMTP users to the same server they just used for POP in the
# last 30 minutes
backend pop
    mode tcp
    balance roundrobin
    stick store-request src
    stick-table type ip size 200k expire 30m
    server s1 192.168.1.1:110
    server s2 192.168.1.1:110

backend smtp
    mode tcp
    balance roundrobin
    stick match src table pop
    server s1 192.168.1.1:25
    server s2 192.168.1.1:25

См. также: “stick-table”, “stick on”, раздел 11 о таблицах привязок и раздел 7 об ACL и извлечении образцов.

stick store-response <pattern> [table <table>] [{if | unless} <condition>]

stick store-response <pattern> [table <table>] [{if | unless} <condition>]

Задать шаблон ответа для создания записи в таблице привязок

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend нет | нет | да | да

Аргументы:

<pattern>  — правило выражения образца, описанное в разделе 7.3. Оно задаёт, какие элементы
           ответа или соединения будут анализироваться, извлекаться и сохраняться в таблице
           после выбора сервера.

<table>    — необязательное имя таблицы привязок. Если оно не задано, используется таблица того
           же бэкенда. Таблица привязок объявляется директивой "stick-table".

<cond>     — необязательное условие сохранения. Оно позволяет сохранять определённые критерии
           только при соблюдении (или несоблюдении) некоторых условий. Например, можно сохранять
           ID сеанса SSL только тогда, когда ответ является SSL server hello.

Некоторые протоколы или приложения требуют сложных правил привязки и не всегда могут полагаться только на cookie или хэширование. Директива “stick store-response” описывает правило, определяющее, что и когда извлекать из ответа для сохранения в таблице привязок, чтобы следующие запросы могли сопоставляться с записью с помощью “stick match”. Очевидно, извлечённая часть должна иметь смысл и допускать совпадение в последующем запросе. Сохранение ID из заголовка ответа имеет смысл. Полный список возможных шаблонов и правил преобразования см. в разделе 7 .

Таблицу нужно объявить директивой “stick-table”. Её тип должен быть совместим с шаблоном. По умолчанию используется таблица в том же бэкенде. Можно совместно использовать таблицу с другими бэкендами, сославшись на неё ключевым словом “table”. При ссылке на другую таблицу используются ID серверов в этих бэкендах. По умолчанию ID всех серверов в каждом бэкенде начинаются с 1, поэтому достаточно порядка серверов. Но при сомнениях настоятельно рекомендуется явно задать ID серверов с помощью их настройки “id”.

Условия применения директивы “stick store-response” можно ограничить с помощью “if” или “unless”, за которыми следует условие. Это условие проверяется при разборе ответа, поэтому можно использовать любые критерии. Об условиях на основе ACL см. раздел 7 .

Количество директив “stick store-response” не ограничено, но действует предел 8 одновременных сохранений на запрос или ответ. Это позволяет сохранить до 8 критериев, извлечённых из запроса или ответа, независимо от количества правил. Сохраняются только первые 8 совпавших критериев. Так можно заполнять несколько таблиц одновременно, чтобы увеличить вероятность распознавания пользователя при другом протоколе или способе доступа. Можно использовать несколько правил store-response с одной таблицей, располагая их в порядке убывания предпочтения, чтобы найти наиболее подходящий критерий. Для данной таблицы сохраняется только первый извлечённый критерий. Все последующие правила store-response, ссылающиеся на ту же таблицу, пропускаются, и их ACL не проверяются. Однако даже если правило store-request ссылается на таблицу, правило store-response тоже может использовать эту таблицу. Это означает, что каждая таблица может одновременно изучить ровно один элемент из запроса и один элемент из ответа.

Таблица будет содержать настоящий сервер, обработавший запрос.

Пример:

# Learn SSL session ID from both request and response and create affinity.
backend https
    mode tcp
    balance roundrobin
    # maximum SSL session ID length is 32 bytes.
    stick-table type binary len 32 size 30k expire 30m

    acl clienthello req.ssl_hello_type 1
    acl serverhello res.ssl_hello_type 2

    # use tcp content accepts to detects ssl client and server hello.
    tcp-request inspect-delay 5s
    tcp-request content accept if clienthello

    # no timeout on response inspect delay by default.
    tcp-response content accept if serverhello

    # SSL session ID (SSLID) may be present on a client or server hello.
    # Its length is coded on 1 byte at offset 43 and its value starts
    # at offset 44.

    # Match and learn on request if client hello.
    stick on req.payload_lv(43,1) if clienthello

    # Learn on response if server hello.
    stick store-response resp.payload_lv(43,1) if serverhello

    server s1 192.168.1.1:443
    server s2 192.168.1.1:443

См. также: “stick-table”, “stick on”, раздел 11 о таблицах привязок и раздел 7 об ACL и извлечении шаблонов.

stick-table type <type> size <size> [expire <expire>] [args...]

stick-table type <type> size <size> [expire <expire>] [args...]

Настроить таблицу привязок для текущей секции

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend нет | да | да | да

Используется для объявления и настройки stick-table. Полное описание и список поддерживаемых аргументов см. в разделе 11.1 . Обязательны только тип и размер.

tcp-check comment <string>

tcp-check comment <string>

Задаёт комментарий для следующего правила tcp-check, который выводится в журнале при его неудаче.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<string>  — текст комментария, добавляемый в журнал при неудаче следующего правила tcp-check.

Работает только для правил connect, send и expect. Позволяет делать сообщения об ошибках понятнее.

См. также: “option tcp-check”, “tcp-check connect”, “tcp-check send” и “tcp-check expect”.

tcp-check connect [default] [port <expr>] [addr <ip>] [send-proxy] [via-socks4]

tcp-check connect [default] [port <expr>] [addr <ip>] [send-proxy] [via-socks4]
                  [ssl] [sni <sni>] [alpn <alpn>] [linger]
                  [proto <name>] [comment <msg>]

Открывает новое соединение

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

comment <msg>  задаёт сообщение, которое выводится, если проверка правила завершается
        неудачей.

default      Использует параметры по умолчанию из строки server для проверок работоспособности.
             Параметры сервера применяются, только если не переопределены.

port <expr>  Если не задан, используется порт проверки или сервера. Указывает HAProxy, куда
             устанавливать соединение. <port> должен быть целым числом допустимого порта
             TCP от 1 до 65535 или выражением извлечения образца.

addr <ip>    Задаёт адрес IP для проверки работоспособности.

send-proxy   Отправляет строку протокола PROXY

via-socks4   Включает исходящие проверки работоспособности через вышестоящий прокси socks4.

ssl          Открывает зашифрованное соединение

sni <sni>    Задаёт SNI для проверок работоспособности по SSL.

alpn <alpn>  задаёт протоколы, объявляемые через ALPN. Список состоит из имён протоколов,
             разделённых запятыми, например: "http/1.1,http/1.0" (без кавычек). Если не задан, используется
             ALPN сервера.

proto <name> принудительно задаёт протокол мультиплексора для этого соединения. Это должен быть
             протокол мультиплексора TCP, пригодный для использования на стороне бэкенда.
             Список доступных протоколов выводится в haproxy -vv.

linger       Закрывает соединение корректно вместо отправки единственного RST.

Если приложение использует более одного TCP порта или HAProxy балансирует нагрузку между многими сервисами в одном бэкенде, имеет смысл отдельно проверять все сервисы, прежде чем считать сервер работоспособным.

Если TCP порт не настроен ни в строке server, ни директивой server port, первым шагом последовательности должен быть ’tcp-check connect port <port>’.

В наборе правил tcp-check требуется ‘connect’; также обязательно начинать набор правил с правила ‘connect’. Цель — обеспечить осознанность действий администратора.

Хотя набор правил должен начинаться с connect, перед ним всё же могут стоять правила set-var, unset-var или comment.

Примеры:

# check HTTP and HTTPs services on a server.
# first open port 80 thanks to server line port directive, then
# tcp-check opens port 443, ciphered and run a request on it:
option tcp-check
tcp-check connect
tcp-check send GET\ /\ HTTP/1.0\r\n
tcp-check send Host:\ haproxy.1wt.eu\r\n
tcp-check send \r\n
tcp-check expect rstring (2..|3..)
tcp-check connect port 443 ssl
tcp-check send GET\ /\ HTTP/1.0\r\n
tcp-check send Host:\ haproxy.1wt.eu\r\n
tcp-check send \r\n
tcp-check expect rstring (2..|3..)
server www 10.0.0.1 check port 80

# check both POP and IMAP from a single server:
option tcp-check
tcp-check connect port 110 linger
tcp-check expect string +OK\ POP3\ ready
tcp-check connect port 143
tcp-check expect string *\ OK\ IMAP4\ ready
server mail 10.0.0.1 check

См. также: “option tcp-check”, “tcp-check send”, “tcp-check expect”

tcp-check expect [min-recv <int>] [comment <msg>]

tcp-check expect [min-recv <int>] [comment <msg>]
                 [ok-status <st>] [error-status <st>] [tout-status <st>]
                 [on-success <fmt>] [on-error <fmt>] [status-code <expr>]
                 [!] <match> <pattern>

Указать данные для сбора и анализа при общей проверке работоспособности

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

comment <msg>  задаёт сообщение, которое выводится, если проверка правила завершается
        неудачей.

min-recv  необязателен и позволяет задать минимальное количество данных, необходимое для проверки
          текущего правила expect. Если количество полученных байтов меньше этого предела,
          проверка будет ждать дополнительных данных. Этот параметр можно использовать для
          устранения неоднозначности некоторых правил сопоставления или для предотвращения
          дорогостоящих проверок регулярных выражений на содержимом, которое заведомо ещё
          неполно. Если используется точная строка (string или binary), берётся минимум из длины
          строки и значения этого параметра. Параметр игнорируется, если задан равным -1.
          Если правило expect не совпадает, проверка будет ждать дополнительных данных. При
          значении 0 результат проверки всегда окончательный.

ok-status <st>     необязателен и позволяет задать статус проверки, если правило expect успешно
                     проверено и является последним правилом в наборе tcp-check. Поддерживаются
                     "L7OK", "L7OKC", "L6OK" и "L4OK":
                     - L7OK : проверка пройдена на уровне 7
                     - L7OKC: проверка условно пройдена на уровне 7, перевести
                       сервер в состояние NOLB.
                     - L6OK : проверка пройдена на уровне 6
                     - L4OK : проверка пройдена на уровне 4
                    По умолчанию используется "L7OK".

error-status <st>  Необязательный параметр, задающий состояние проверки при ошибке выполнения
                     правила expect. Поддерживаются "L7OKC", "L7RSP", "L7STS", "L6RSP" и
                     "L4CON":
                     - L7OKC: проверка условно пройдена на уровне 7; сервер
                       переводится в состояние NOLB.
                     - L7RSP: некорректный ответ уровня 7 — ошибка протокола
                     - L7STS: ошибка ответа уровня 7, например HTTP 5xx
                     - L6RSP: некорректный ответ уровня 6 — ошибка протокола
                     - L4CON: проблема соединения уровней 1-4 По умолчанию
                       используется "L7RSP".

tout-status <st>   Необязательный параметр, задающий состояние проверки при тайм-ауте выполнения
                   правила expect. Поддерживаются "L7TOUT", "L6TOUT" и "L4TOUT":
                     - L7TOUT: тайм-аут уровня 7 (HTTP/SMTP)
                     - L6TOUT: тайм-аут уровня 6 (SSL)
                     - L4TOUT: тайм-аут уровней 1-4 По умолчанию используется
                       "L7TOUT".

on-success <fmt>   необязателен и позволяет настроить информационное сообщение, выводимое в
                   журнал, если правило expect успешно проверено и является последним правилом в
                   наборе tcp-check. <fmt> — пользовательский формат журнала (см. раздел
                   8.2.6).

on-error <fmt>     необязателен и позволяет настроить информационное сообщение, выводимое в
                   журнал, если при проверке правила expect произошла ошибка. <fmt> —
                   пользовательский формат журнала (см. раздел 8.2.6).

status-code <expr> Необязательный параметр, задающий код состояния проверки, записываемый в журнал
                   при успехе или ошибке. <expr> — стандартное выражение HAProxy, состоящее из
                   извлечения образца и следующих за ним преобразователей.

<match>   — ключевое слово, задающее способ поиска определённого шаблона в ответе. Возможные
          значения: "string", "rstring", "binary" или "rbinary". Перед ключевым словом может стоять
          восклицательный знак ("!"), инвертирующий результат сопоставления. Между
          восклицательным знаком и ключевым словом разрешены пробелы. Подробнее о поддерживаемых
          ключевых словах см. ниже.

<pattern> — искомый шаблон. Это может быть строка или регулярное выражение. Если шаблон содержит
          пробелы, их нужно экранировать обычной обратной косой чертой ('\'). Если задано
          сопоставление binary, шаблон нужно передать как последовательность чётного количества
          шестнадцатеричных цифр. Каждая пара цифр представляет байт. Шестнадцатеричные цифры
          могут быть в верхнем или нижнем регистре.

Доступные виды сопоставления намеренно похожи на соответствующие варианты http-check:

string <string>: проверяет точное совпадение строки в буфере ответа. Ответ проверки
                  работоспособности считается корректным, если буфер ответа содержит эту точную
                  строку. Если перед ключевым словом "string" стоит "!", ответ считается
                  некорректным, если его тело содержит эту строку. Это можно использовать для
                  поиска обязательного шаблона в ответе протокола или для обнаружения сбоя при
                  появлении определённой ошибки в баннере протокола.

rstring <regex>: проверяет регулярное выражение на буфере ответа. Ответ проверки
                  работоспособности считается корректным, если буфер ответа соответствует этому
                  выражению. Если перед ключевым словом "rstring" стоит "!", ответ считается
                  некорректным, если его тело соответствует выражению.

string-lf <fmt>: проверяет совпадение пользовательского формата журнала в буфере ответа. Ответ
                  проверки работоспособности считается корректным, если буфер ответа содержит
                  строку, полученную при вычислении <fmt>, который следует правилам
                  пользовательского формата журнала, описанным в разделе 8.2.6. Если перед
                  ключевым словом стоит "!", ответ считается некорректным, если буфер
                  содержит эту строку.

binary <hexstring>: проверяет точное совпадение строки в её шестнадцатеричной форме в буфере ответа.
                     Ответ проверки работоспособности считается корректным, если буфер ответа
                     содержит эту точную шестнадцатеричную строку. Цель — сопоставление данных в
                     двоичных протоколах.

rbinary <regex>: проверяет регулярное выражение на буфере ответа, как "rstring". Однако буфер
                  ответа преобразуется в шестнадцатеричную форму, включая NUL байты. Это
                  позволяет всем механизмам регулярных выражений сопоставлять любое двоичное
                  содержимое. Шестнадцатеричное преобразование занимает вдвое больше места, чем
                  исходный ответ. Поэтому ожидаемый шаблон следует рассчитывать на данные
                  размером не более половины буфера ответа.

binary-lf <hexfmt>: проверяет совпадение пользовательского формата журнала в его
                     шестнадцатеричной форме в буфере ответа. Ответ проверки работоспособности
                     считается корректным, если буфер ответа содержит шестнадцатеричную строку,
                     полученную при вычислении <fmt>, который следует правилам
                     пользовательского формата журнала (см. раздел 8.2.6). Если перед ключевым
                     словом стоит "!", ответ считается некорректным, если буфер содержит эту
                     шестнадцатеричную строку. Перед сопоставлением с буфером ответа
                     шестнадцатеричная строка преобразуется в двоичную.

Ответы ограничены размером, заданным глобальным параметром “tune.bufsize”, по умолчанию 16384 байта. Поэтому слишком большие ответы могут не содержать обязательный шаблон при использовании “string”, “rstring” или binary. Если большой ответ совершенно необходим, можно изменить максимальный размер по умолчанию, задав глобальную переменную. Однако следует помнить, что разбор очень больших ответов может расходовать такты CPU впустую, особенно при использовании регулярных выражений; всегда лучше направлять проверки на меньшие ресурсы. Кроме того, в текущем состоянии проверка не найдёт ни строку, ни регулярное выражение после нулевого символа в ответе. Аналогично невозможно задать сопоставление с нулевым символом.

Примеры:

# perform a POP check
option tcp-check
tcp-check expect string +OK\ POP3\ ready

# perform an IMAP check
option tcp-check
tcp-check expect string *\ OK\ IMAP4\ ready

# look for the redis master server
option tcp-check
tcp-check send PING\r\n
tcp-check expect string +PONG
tcp-check send info\ replication\r\n
tcp-check expect string role:master
tcp-check send QUIT\r\n
tcp-check expect string +OK

См. также: “option tcp-check”, “tcp-check connect”, “tcp-check send”, “tcp-check send-binary”, “http-check expect”, tune.bufsize

tcp-check send <data> [comment <msg>]

tcp-check send <data> [comment <msg>]
tcp-check send-lf <fmt> [comment <msg>]

Указать строку или пользовательский формат журнала, отправляемые как запрос при общей проверке работоспособности

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

comment <msg>  задаёт сообщение, которое выводится, если проверка правила завершается
        неудачей.

<data>         — строка, отправляемая в ходе сеанса общей проверки работоспособности.

<fmt>          — пользовательский формат журнала, отправляемый после вычисления в ходе сеанса
               общей проверки работоспособности (см. раздел 8.2.6).

Примеры:

# look for the redis master server
option tcp-check
tcp-check send info\ replication\r\n
tcp-check expect string role:master

См. также: “option tcp-check”, “tcp-check connect”, “tcp-check expect”, “tcp-check send-binary”, tune.bufsize

tcp-check send-binary <hexstring> [comment <msg>]

tcp-check send-binary <hexstring> [comment <msg>]
tcp-check send-binary-lf <hexfmt> [comment <msg>]

Указать строку шестнадцатеричных цифр или пользовательский формат журнала с шестнадцатеричными цифрами, отправляемые как двоичный запрос при проверке работоспособности на уровне TCP

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

comment <msg>  задаёт сообщение, которое выводится, если проверка правила завершается
        неудачей.

<hexstring>    — шестнадцатеричная строка, отправляемая после преобразования в двоичную форму в ходе
               сеанса общей проверки работоспособности.

<hexfmt>       — шестнадцатеричный пользовательский формат журнала, отправляемый после вычисления
               и преобразования в двоичную форму в ходе сеанса общей проверки работоспособности
               (см. раздел 8.2.6).

Примеры:

# redis check in binary
option tcp-check
tcp-check send-binary 50494e470d0a # PING\r\n
tcp-check expect binary 2b504F4e47 # +PONG

См. также: “option tcp-check”, “tcp-check connect”, “tcp-check expect”, “tcp-check send”, tune.bufsize

tcp-check set-var(<var-name>[,<cond>...]) <expr>

tcp-check set-var(<var-name>[,<cond>...]) <expr>
tcp-check set-var-fmt(<var-name>[,<cond>...]) <fmt>

Эта операция устанавливает содержимое переменной. Переменная объявляется непосредственно при использовании.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<var-name>    — имя переменной. Можно использовать только области видимости "proc", "sess" и
             "check". Подробности см. в разделе 2.8 о переменных.

 <cond>      Набор условий, которые должны быть истинны одновременно, чтобы переменная была
             задана (например, "ifnotempty", "ifgt" и т. д.). Полный список условий приведён в
             описании преобразователя set-var.

 <expr>      Выражение извлечения образца, за которым могут следовать преобразователи.

 <fmt>       Значение, заданное по правилам пользовательского формата журнала (см.
             «Пользовательский формат журнала» в разделе 8.2.6).

Примеры:

tcp-check set-var(check.port) int(1234)
tcp-check set-var-fmt(check.name) "%H"

tcp-check unset-var(<var-name>)

tcp-check unset-var(<var-name>)

Освобождает ссылку на переменную в пределах её области видимости.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<var-name>    — имя переменной. Можно использовать только области видимости "proc", "sess" и
             "check". Подробности см. в разделе 2.8 о переменных.

Примеры:

tcp-check unset-var(check.port)

tcp-request connection <action> <options...> [ { if | unless } <condition> ]

tcp-request connection <action> <options...> [ { if | unless } <condition> ]

Выполнить действие над входящим соединением в зависимости от условия уровня 4

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да(!) | да | да | нет

Аргументы:

<action>    задаёт действие, выполняемое при соблюдении условия. См. ниже.

<condition> — стандартное условие на основе ACL только уровня 4 (см. раздел 7).

Сразу после принятия нового входящего соединения можно проверить условия, чтобы решить, нужно ли принять или отбросить это соединение либо отслеживать его счётчики. Эти условия не могут использовать содержимое данных: чтение из соединения ещё не выполнялось, и буферы ещё не выделены. Это позволяет выборочно и очень быстро принимать или отбрасывать соединения от разных источников с очень небольшими накладными расходами. Если для принятия решения нужно проверить содержимое, необходимо использовать директивы “tcp-request content”.

Правила “tcp-request connection” проверяются строго в порядке их объявления. Если ни одно правило не совпало или правил нет, действие по умолчанию — принять входящее соединение. Особого ограничения на количество добавляемых правил нет. За любым правилом может следовать необязательное условие на основе ACL; в этом случае правило проверяется только тогда, когда условие истинно.

Условие проверяется непосредственно перед выполнением действия, а действие выполняется ровно один раз. Поэтому нет проблемы, если действие изменяет элемент, проверяемый в условии. Это также означает, что несколько действий могут зависеть от одного условия, и тогда первого действия, изменяющего результат проверки условия, достаточно для неявного отключения остальных действий. Например, это используется при попытке присвоить значение пустой переменной из разных источников.

Первое ключевое слово после “tcp-request connection” в синтаксисе задаёт действие правила; за ним может следовать различное количество аргументов этого действия. Поддерживаемые действия и их синтаксис перечислены в разделе 4.3 «Действия» (ищите действия с отметкой в столбце “TCP RqCon”).

Эта директива доступна только в именованных секциях defaults, а в анонимных недоступна. Правила секции defaults проверяются до правил связанной с ней секции прокси. Во избежание неоднозначности одну и ту же секцию defaults нельзя использовать одновременно для прокси с возможностями фронтенда и прокси с возможностями бэкенда. Поэтому секция listen не может использовать секцию defaults с такими правилами.

Условие “if/unless” необязательно. Если условие для действия не задано, оно просто выполняется безусловно. Это может быть полезно для действий “track-sc*”, а также для смены действия по умолчанию на отклонение.

Пример: принимать все соединения от узлов из белого списка, отклонять слишком часто поступающие соединения, не учитывая их, и отслеживать принятые соединения. В результате частота соединений от источников, злоупотребляющих подключениями, ограничивается.

    tcp-request connection accept if { src -f /etc/haproxy/whitelist.lst }
    tcp-request connection reject if { src_conn_rate gt 10 }
    tcp-request connection track-sc0 src

Пример: принимать все соединения от узлов из белого списка, учитывать все остальные соединения и отклонять слишком часто поступающие. В результате нарушители остаются заблокированными, пока не снизят частоту.

    tcp-request connection accept if { src -f /etc/haproxy/whitelist.lst }
    tcp-request connection track-sc0 src
    tcp-request connection reject if { sc0_conn_rate gt 10 }

Пример: включить протокол PROXY для трафика от всех известных прокси.

    tcp-request connection expect-proxy layer4 if { src -f proxies.lst }

Об использовании ACL см. раздел 7 .

См. также: “tcp-request session”, “tcp-request content”, “stick-table”

tcp-request content <action> [{if | unless} <condition>]

tcp-request content <action> [{if | unless} <condition>]

Выполнить действие над новым сеансом в зависимости от условия уровней 4–7

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да(!) | да | да | да

Аргументы:

<action>    задаёт действие, выполняемое при соблюдении условия. См. ниже.

<condition> — стандартное условие на основе ACL уровней 4–7 (см. раздел 7).

Содержимое запроса можно анализировать на раннем этапе обработки запроса, называемом «проверка содержимого TCP». На этом этапе правила на основе ACL проверяются при каждом обновлении содержимого запроса, пока не совпадёт правило “accept”, “reject” или “switch-mode” либо не истечёт задержка проверки TCP запроса без совпадения какого-либо правила.

Первое отличие этих правил от правил “tcp-request connection” состоит в том, что правила “tcp-request content” могут использовать содержимое для принятия решения. Чаще всего эти решения связаны с распознаванием протокола или проверкой его корректности. Второе отличие — правила на основе содержимого можно использовать и во фронтенде, и в бэкенде. При постоянном соединении HTTP с клиентом все правила tcp-request content проверяются заново. Поэтому HAProxy хранит сведения о том, какие счётчики привязки были назначены правилом “tcp-request connection”, а какие — правилом “tcp-request content”, и сбрасывает все связанные с содержимым счётчики после обработки HTTP запроса. Это позволяет назначить их снова при повторной проверке правил для следующего запроса. Это особенно важно, когда правило отслеживает некоторую информацию L7 или зависит от ACL на основе L7, поскольку отслеживание может меняться между запросами.

Правила, основанные на содержимом, проверяются строго в порядке их объявления. Если ни одно правило не совпало или правил нет, действие по умолчанию — принять содержимое. Особого ограничения на количество добавляемых правил нет.

Хотя это и не обязательно, рекомендуется использовать track-sc0 в правилах “tcp-request connection”, track-sc1 в правилах “tcp-request content” во фронтенде и track-sc2 в правилах “tcp-request content” в бэкенде: так конфигурацию легче читать и диагностировать. Но это лишь рекомендация, и все счётчики можно использовать где угодно.

Первое ключевое слово после “tcp-request content” в синтаксисе задаёт действие правила; за ним может следовать различное количество аргументов этого действия. Поддерживаемые действия и их синтаксис перечислены в разделе 4.3 «Действия» (ищите действия с отметкой в столбце “TCP RqCnt”).

Эта директива доступна только в именованных секциях defaults, а в анонимных недоступна. Правила секции defaults проверяются до правил связанной с ней секции прокси. Во избежание неоднозначности одну и ту же секцию defaults нельзя использовать одновременно для прокси с возможностями фронтенда и прокси с возможностями бэкенда. Поэтому секция listen не может использовать секцию defaults с такими правилами.

Условие “if/unless” необязательно. Если условие для действия не задано, оно просто выполняется безусловно. Это может быть полезно для действий “track-sc*”, а также для смены действия по умолчанию на отклонение.

Также рекомендуется использовать правило “tcp-request session” для отслеживания информации, которая не зависит от содержимого уровня 7, особенно для фронтендов HTTP. Некоторые операции обработки HTTP выполняются на уровне сеанса и могут привести к раннему отклонению запросов. В этом случае отслеживание на уровне содержимого может нарушиться. При запуске выдаётся предупреждение, чтобы по возможности предотвратить такое ненадёжное использование.

С помощью правил “tcp-request content” в TCP прокси вполне можно проверять содержимое уровня 7: HTTP-специфичные проверки ACL умеют предварительно разбирать содержимое буфера перед извлечением нужных данных. Если содержимое буфера не разбирается как корректное HTTP сообщение, ACL не совпадает. Здесь используется тот же парсер, что и при любой другой обработке HTTP, поэтому риска различий в разборе нет. Во фронтенде HTTP или бэкенде HTTP гарантируется, что при первой проверке правила HTTP содержимое уже будет доступно: разбор HTTP выполняется на ранних этапах обработки соединения, на уровне сеанса. Однако для таких прокси гораздо естественнее и рекомендуется использовать правила “http-request”.

Отслеживать информацию уровня 7 также можно, если она доступна в момент обработки правила. Если отслеживаемые данные ещё недоступны, механизм обработки правил умеет ждать до истечения задержки проверки.

Пример:

tcp-request content use-service lua.deny if { src -f /etc/haproxy/blacklist.lst }

Пример:

tcp-request content set-var(sess.my_var) src
tcp-request content set-var-fmt(sess.from) %[src]:%[src_port]
tcp-request content unset-var(sess.my_var2)

Пример:

# Accept HTTP requests containing a Host header saying "example.com"
# and reject everything else. (Only works for HTTP/1 connections)
acl is_host_com hdr(Host) -i example.com
tcp-request inspect-delay 30s
tcp-request content accept if is_host_com
tcp-request content reject

# Accept HTTP requests containing a Host header saying "example.com"
# and reject everything else. (works for HTTP/1 and HTTP/2 connections)
acl is_host_com hdr(Host) -i example.com
tcp-request inspect-delay 5s
tcp-request content switch-mode http if HTTP
tcp-request content reject   # non-HTTP traffic is implicit here
...
http-request reject unless is_host_com

Пример:

# reject SMTP connection if client speaks first
tcp-request inspect-delay 30s
acl content_present req.len gt 0
tcp-request content reject if content_present

# Forward HTTPS connection only if client speaks
tcp-request inspect-delay 30s
acl content_present req.len gt 0
tcp-request content accept if content_present
tcp-request content reject

Пример:

# Track the last IP(stick-table type string) from X-Forwarded-For
tcp-request inspect-delay 10s
tcp-request content track-sc0 hdr(x-forwarded-for,-1)
# Or track the last IP(stick-table type ip|ipv6) from X-Forwarded-For
tcp-request content track-sc0 req.hdr_ip(x-forwarded-for,-1)

Пример:

# track request counts per "base" (concatenation of Host+URL)
tcp-request inspect-delay 10s
tcp-request content track-sc0 base table req-rate

Пример: отслеживать счётчики отдельно для фронтенда и бэкенда, блокировать нарушителей во фронтенде, когда бэкенд обнаруживает злоупотребление (и устанавливает gpc0).

    frontend http
        # Use General Purpose Counter 0 in SC0 as a global abuse counter
        # protecting all our sites
        stick-table type ip size 1m expire 5m store gpc0
        tcp-request connection track-sc0 src
        tcp-request connection reject if { sc0_get_gpc0 gt 0 }
        ...
        use_backend http_dynamic if { path_end .php }

    backend http_dynamic
        # if a source makes too fast requests to this dynamic site (tracked
        # by SC1), block it globally in the frontend.
        stick-table type ip size 1m expire 5m store http_req_rate(10s)
        acl click_too_fast sc1_http_req_rate gt 10
        acl mark_as_abuser sc0_inc_gpc0(http) gt 0
        tcp-request content track-sc1 src
        tcp-request content reject if click_too_fast mark_as_abuser

Об использовании ACL см. раздел 7 .

См. также: “tcp-request connection”, “tcp-request session”, “tcp-request inspect-delay” и “http-request”.

tcp-request inspect-delay <timeout>

tcp-request inspect-delay <timeout>

Установить максимально допустимое время ожидания данных при проверке содержимого

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да(!) | да | да | да

Аргументы:

<timeout> — значение тайм-аута, по умолчанию в миллисекундах; можно использовать любую другую
          единицу, добавив её суффикс к числу, как описано в начале этого документа.

Те, кто использует HAProxy главным образом для ретрансляции TCP, часто обеспокоены риском передачи серверу любого протокола без анализа. Чтобы анализировать содержимое запроса, нужно сначала задержать данные, а затем проанализировать их. Эта директива просто включает задержку данных на время не более указанного.

Проверка содержимого TCP выполняется на очень раннем этапе, когда соединение поступает во фронтенд, а затем на очень раннем этапе его передачи в бэкенд. Это означает, что соединение может сначала испытать задержку во фронтенде, а затем вторую задержку в бэкенде, если в обоих есть правила tcp-request.

При проверке содержимого HAProxy проверяет все правила для каждого нового поступившего фрагмента, учитывая, что данные неполны. Если до истечения указанной задержки ни одно правило не совпало, по её истечении выполняется последняя проверка: на этот раз содержимое считается окончательным. Если задержка не задана, HAProxy вообще не будет ждать и сразу вынесет решение по имеющейся информации. Очевидно, это вряд ли будет полезно и может даже привести к гонкам, поэтому такие настройки не рекомендуются.

Задержка проверки сокращается при ошибке соединения, его закрытии или заполнении буфера запроса.

Как только правило совпадает, запрос освобождается и продолжает обрабатываться обычным образом. Если тайм-аут истёк и ни одно правило не совпало, политика по умолчанию — пропустить запрос без изменений.

Для большинства протоколов достаточно установить несколько секунд: большинство клиентов отправляют весь запрос сразу после подключения. Добавьте 3 или более секунд для учёта повторных передач TCP; этого достаточно. Для некоторых протоколов имеет смысл задавать большие значения, например чтобы клиент никогда не начинал обмен раньше сервера (например, SMTP) или чтобы дождаться данных от клиента до передачи данных серверу (например, SSL). Тайм-аут клиента должен быть не меньше задержки проверки, иначе он истечёт первым. Если клиент закрывает соединение или буфер заполнен, задержка немедленно истекает, поскольку содержимое уже не сможет измениться.

Эта директива доступна только в именованных секциях defaults, но не в анонимных. Прокси наследуют это значение из своей секции defaults.

См. также: “tcp-request content accept”, “tcp-request content reject”, “timeout client”.

tcp-request session <action> [{if | unless} <condition>]

tcp-request session <action> [{if | unless} <condition>]

Выполнить действие над прошедшим проверку сеансом в зависимости от условия уровня 5

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да(!) | да | да | нет

Аргументы:

<action>    задаёт действие, выполняемое при соблюдении условия. См. ниже.

<condition> — стандартное условие на основе ACL только уровня 5 (см. раздел 7).

После проверки сеанса (то есть после завершения всех рукопожатий) можно проверить условия, чтобы решить, нужно ли принять или отбросить этот сеанс либо отслеживать его счётчики. Эти условия не могут использовать содержимое данных, поскольку буферы ещё не выделены и на этом этапе обработка не может ждать. Основное применение — скопировать некоторую раннюю информацию в переменные (переменные доступны в сеансе) или отслеживать сведения, полученные после рукопожатия, например элементы уровня SSL (SNI, шифры, CN сертификата клиента) или информацию из заголовка протокола PROXY (например, отслеживать переданный таким способом адрес источника). Таким образом, извлечённую информацию можно скопировать в переменную или отслеживать правилами “track-sc”. Разумеется, можно также решать, принимать или отклонять сеанс, как и в других наборах правил. Большинство операций, выполняемых здесь, можно выполнить и в правилах “tcp-request content”, но в HTTP эти правила проверяются для каждого нового запроса, что не всегда допустимо. Например, правило может увеличивать счётчик при каждой проверке. Можно также определить страну по геолокации исходного IP адреса, записать её в переменную уровня сеанса, а затем переписать исходный адрес из HTTP заголовка для всех запросов. Если для принятия решения нужно проверить содержимое, необходимо использовать директивы “tcp-request content”.

Правила “tcp-request session” проверяются строго в порядке их объявления. Если ни одно правило не совпало или правил нет, действие по умолчанию — принять входящий сеанс. Особого ограничения на количество добавляемых правил нет.

Первое ключевое слово после “tcp-request session” в синтаксисе задаёт действие правила; за ним может следовать различное количество аргументов этого действия. Поддерживаемые действия и их синтаксис перечислены в разделе 4.3 «Действия» (ищите действия с отметкой в столбце “TCP RqSes”).

Эта директива доступна только в именованных секциях defaults, а в анонимных недоступна. Правила секции defaults проверяются до правил связанной с ней секции прокси. Во избежание неоднозначности одну и ту же секцию defaults нельзя использовать одновременно для прокси с возможностями фронтенда и прокси с возможностями бэкенда. Поэтому секция listen не может использовать секцию defaults с такими правилами.

Условие “if/unless” необязательно. Если условие для действия не задано, оно просто выполняется безусловно. Это может быть полезно для действий “track-sc*”, а также для смены действия по умолчанию на отклонение.

Пример: по умолчанию отслеживать первоначальный адрес источника, а для соединений от локальных прокси — адрес, указанный в заголовке протокола PROXY. Первое правило уровня соединения включает для них приём протокола PROXY; второе правило отслеживает тот адрес, который мы решили сохранить после необязательного декодирования.

    tcp-request connection expect-proxy layer4 if { src -f proxies.lst }
    tcp-request session track-sc0 src

Пример: принимать все сеансы от узлов из белого списка, отклонять слишком часто поступающие сеансы, не учитывая их, и отслеживать принятые сеансы. В результате частота сеансов от источников, злоупотребляющих подключениями, ограничивается.

    tcp-request session accept if { src -f /etc/haproxy/whitelist.lst }
    tcp-request session reject if { src_sess_rate gt 10 }
    tcp-request session track-sc0 src

Пример: принимать все сеансы от узлов из белого списка, учитывать все остальные сеансы и отклонять слишком часто поступающие. В результате нарушители остаются заблокированными, пока не снизят частоту.

    tcp-request session accept if { src -f /etc/haproxy/whitelist.lst }
    tcp-request session track-sc0 src
    tcp-request session reject if { sc0_sess_rate gt 10 }

Об использовании ACL см. раздел 7 .

См. также: “tcp-request connection”, “tcp-request content”, “stick-table”

tcp-response content <action> [{if | unless} <condition>]

tcp-response content <action> [{if | unless} <condition>]

Выполнить действие над ответом в сеансе в зависимости от условия уровней 4–7

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да(!) | нет | да | да

Аргументы:

<action>    задаёт действие, выполняемое при соблюдении условия. См. ниже.

<condition> — стандартное условие на основе ACL уровней 4–7 (см. раздел 7).

Содержимое ответа можно анализировать на раннем этапе обработки ответа, называемом «проверка содержимого TCP». На этом этапе правила на основе ACL проверяются при каждом обновлении содержимого ответа, пока не совпадёт окончательное правило либо не истечёт заданная задержка проверки TCP ответа без совпадения какого-либо правила.

Чаще всего эти решения связаны с распознаванием протокола или проверкой его корректности.

Правила, основанные на содержимом, проверяются строго в порядке их объявления. Если ни одно правило не совпало или правил нет, действие по умолчанию — принять содержимое. Особого ограничения на количество добавляемых правил нет.

Первое ключевое слово после “tcp-response content” в синтаксисе задаёт действие правила; за ним может следовать различное количество аргументов этого действия. Поддерживаемые действия и их синтаксис перечислены в разделе 4.3 «Действия» (ищите действия с отметкой в столбце “TCP RsCnt”).

Эта директива доступна только в именованных секциях defaults, а в анонимных недоступна. Правила секции defaults проверяются до правил связанной с ней секции прокси. Во избежание неоднозначности одну и ту же секцию defaults нельзя использовать одновременно для прокси с возможностями фронтенда и прокси с возможностями бэкенда. Поэтому секция listen не может использовать секцию defaults с такими правилами.

Условие “if/unless” необязательно. Если условие для действия не задано, оно просто выполняется безусловно. Это может быть полезно для смены действия по умолчанию на отклонение.

Поддерживаются несколько типов действий:

С помощью правил “tcp-response content” вполне можно проверять содержимое уровня 7, но тогда важно убедиться, что весь ответ помещён в буфер, иначе совпадений по содержимому не будет. Лучше всего для этого определять протокол HTTP в течение периода проверки.

Об использовании ACL см. раздел 7 .

См. также: “tcp-request content”, “tcp-response inspect-delay”

tcp-response inspect-delay <timeout>

tcp-response inspect-delay <timeout>

Установить максимально допустимое время ожидания ответа при проверке содержимого

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да(!) | нет | да | да

Аргументы:

<timeout> — значение тайм-аута, по умолчанию в миллисекундах; можно использовать любую другую
          единицу, добавив её суффикс к числу, как описано в начале этого документа.

Эта директива доступна только в именованных секциях defaults, но не в анонимных. Прокси наследуют это значение из своей секции defaults.

См. также: “tcp-response content”, “tcp-request inspect-delay”.

timeout check <timeout>

timeout check <timeout>

Установить дополнительный тайм-аут проверки, применяемый только после установления соединения.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<timeout> — значение тайм-аута, по умолчанию в миллисекундах; можно использовать любую другую
          единицу, добавив её суффикс к числу, как описано в начале этого документа.

Если он задан, HAProxy использует min(“timeout connect”, “inter”) как тайм-аут подключения для проверки, а “timeout check” — как дополнительный тайм-аут чтения. “min” используется, чтобы очень большой “timeout connect” (например, у тех, кому он понадобился из-за очереди или ловушки соединений (tarpit)) не замедлял проверки. (Учтите также, что обоснованных причин для таких больших тайм-аутов подключения нет: чтобы избежать их, всегда можно использовать “timeout queue” и “timeout tarpit”.)

Если “timeout check” не задан, HAProxy использует “inter” как тайм-аут всей проверки (подключение + чтение), точно так же, как во всех версиях <1.3.15.

В большинстве случаев запрос проверки гораздо проще и обрабатывается быстрее обычных запросов, а пользователи могут хотеть исключить медленно отвечающие серверы, поэтому этот тайм-аут следует делать меньше “timeout server”.

Этот параметр относится к бэкенду, но его можно задать один раз для всех в секциях “defaults”. Это один из самых простых способов не забыть о нём.

См. также: “timeout connect”, “timeout queue”, “timeout server”, “timeout tarpit”.

timeout client <timeout>

timeout client <timeout>

Установить максимальное время бездействия на стороне клиента.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы:

<timeout> — значение тайм-аута, по умолчанию в миллисекундах; можно использовать любую другую
          единицу, добавив её суффикс к числу, как описано в начале этого документа.

Тайм-аут бездействия применяется, когда от клиента ожидается подтверждение или отправка данных. В режиме HTTP его особенно важно учитывать на первом этапе, когда клиент отправляет запрос, и во время ответа, когда клиент читает данные, отправленные сервером. При этом для первого этапа предпочтительнее задать “timeout http-request”, чтобы лучше защитить HAProxy от атак типа Slowloris. Значение по умолчанию задаётся в миллисекундах, но можно использовать любую другую единицу, добавив её суффикс к числу, как описано в начале этого документа. В режиме TCP (и в меньшей степени в режиме HTTP) настоятельно рекомендуется сохранять тайм-аут клиента равным тайм-ауту сервера, чтобы избежать сложных для диагностики ситуаций. Полезно учитывать потерю одного или нескольких TCP пакетов, задавая тайм-ауты чуть больше значений, кратных 3 секундам (например, 4 или 5 секунд). Если долгоживущие потоки смешаны с короткоживущими (например, WebSocket и HTTP), имеет смысл рассмотреть “timeout tunnel”, который переопределяет “timeout client” и “timeout server” для туннелей, а также “timeout client-fin” для полузакрытых соединений.

Этот параметр относится к фронтенду, но его можно задать один раз для всех в секциях “defaults”. Это один из самых простых способов не забыть о нём. Если тайм-аут не задан, он считается бесконечным, что не рекомендуется. Такая настройка принимается и работает, но при запуске выдаётся предупреждение: если системные тайм-ауты тоже не настроены, в системе могут накапливаться просроченные сеансы.

См. также: “timeout server”, “timeout tunnel”, “timeout http-request”.

timeout client-fin <timeout>

timeout client-fin <timeout>

Установить тайм-аут бездействия на стороне клиента для полузакрытых соединений.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы:

<timeout> — значение тайм-аута, по умолчанию в миллисекундах; можно использовать любую другую
          единицу, добавив её суффикс к числу, как описано в начале этого документа.

Тайм-аут бездействия применяется, когда от клиента ожидается подтверждение или отправка данных, а одно направление уже закрыто. Этот тайм-аут отличается от “timeout client” тем, что применяется только к соединениям, закрытым в одном направлении. Это особенно полезно, чтобы соединения не оставались слишком долго в состоянии FIN_WAIT, когда клиенты завершают соединение некорректно. Эта проблема особенно распространена для длительных соединений, таких как RDP или WebSocket. Этот тайм-аут может переопределять “timeout tunnel”, когда соединение закрывается в одном направлении. Он применяется к бездействующим HTTP/2 соединениям после отправки кадра GOAWAY, который часто означает ожидание скорого завершения соединения.

Этот параметр относится к фронтенду, но его можно задать один раз для всех в секциях “defaults”. По умолчанию он не задан, поэтому полузакрытые соединения используют другие тайм-ауты (timeout.client или timeout.tunnel).

См. также: “timeout client”, “timeout server-fin” и “timeout tunnel”.

timeout client-hs <timeout>

timeout client-hs <timeout>

Установить максимальное время ожидания завершения TLS рукопожатия клиента. Применимо как к TCP, так и к QUIC соединениям.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы:

<timeout> — значение тайм-аута, по умолчанию в миллисекундах; можно использовать любую другую
          единицу, добавив её суффикс к числу, как описано в начале этого документа.

Если этот тайм-аут рукопожатия не задан, вместо него используется тайм-аут клиента.

timeout connect <timeout>

timeout connect <timeout>

Установить максимальное время ожидания успешного завершения попытки подключения к серверу.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<timeout> — значение тайм-аута, по умолчанию в миллисекундах; можно использовать любую другую
          единицу, добавив её суффикс к числу, как описано в начале этого документа.

Если сервер находится в той же LAN, что и HAProxy, соединение должно устанавливаться немедленно (менее чем за несколько миллисекунд). В любом случае полезно учитывать потерю одного или нескольких TCP пакетов, задавая тайм-ауты чуть больше значений, кратных 3 секундам (например, 4 или 5 секунд). По умолчанию тайм-аут подключения также задаёт такое же значение тайм-аутам очереди и tarpit, если они не указаны.

Этот параметр относится к бэкенду, но его можно задать один раз для всех в секциях “defaults”. Это один из самых простых способов не забыть о нём. Если тайм-аут не задан, он считается бесконечным, что не рекомендуется. Такая настройка принимается и работает, но при запуске выдаётся предупреждение: если системные тайм-ауты тоже не настроены, в системе могут накапливаться неудавшиеся сеансы.

См. также: “timeout check”, “timeout queue”, “timeout server”, “timeout tarpit”.

timeout http-keep-alive <timeout>

timeout http-keep-alive <timeout>

Установить максимально допустимое время ожидания появления нового HTTP запроса

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

<timeout> — значение тайм-аута, по умолчанию в миллисекундах; можно использовать любую другую
          единицу, добавив её суффикс к числу, как описано в начале этого документа.

По умолчанию время ожидания нового запроса при постоянном соединении задаётся параметром “timeout http-request”. Однако это не всегда удобно: некоторые пользователи хотят очень короткие тайм-ауты постоянных соединений, чтобы быстрее освобождать соединения, а другие предпочитают более длительные, сохраняя короткий тайм-аут после начала поступления запроса.

Тайм-аут “http-keep-alive” удовлетворяет этим потребностям. Он определяет, сколько ждать начала поступления нового HTTP запроса после отправки ответа. Как только получен первый байт запроса, для ожидания всего запроса используется тайм-аут “http-request”. Пустые строки перед новым запросом не обновляют тайм-аут и не считаются новым запросом.

Между этими двумя тайм-аутами есть ещё одно различие: при истечении timeout http-keep-alive ошибка не возвращается, соединение просто закрывается. Если тайм-аут соединения истекает в “http-request” во время ожидания завершения запроса, перед закрытием соединения клиенту возвращается ошибка HTTP 408, если во фронтенде не задана “option http-ignore-probes”.

Обычно “timeout http-keep-alive” лучше всего использовать для предотвращения слишком долгого удержания клиентами открытого, но бездействующего соединения на сайтах с большим количеством коротких соединений. Для HTTP/1.1 этого можно добиться, задав значение от нескольких десятков до сотен миллисекунд. Тогда соединение закроется после запроса страницы клиентом, и его не придётся держать открытым в ожидании дальнейшей активности клиента. В этом случае новая активность браузера вызовет новое рукопожатие на уровне TCP и/или SSL. Типичный пример — HTTP сайты, которые лишь перенаправляют на HTTPS страницу. Такие соединения лучше не оставлять бездействующими надолго: они не будут использоваться повторно, разве что для получения значка сайта.

Другой случай прямо противоположен: некоторые сайты хотят разрешить клиентам долго повторно использовать бездействующие соединения (например, от 30 секунд до одной минуты), но не хотят столько же ждать первого запроса, чтобы избежать очень дешёвого способа атаки. В этом случае тайм-аут http-keep-alive задаётся большим, а http-request остаётся маленьким (несколько секунд).

При очень маленьком значении дополнительные запросы, не передаваемые конвейерно, скорее всего будут обрабатываться через другое соединение — если только они действительно не передаются конвейерно, что в HTTP/1.1 бывает очень редко (запросы отправляются подряд, без ожидания ответа). Большинство реализаций HTTP/1.1 отправляют запрос, ждут ответа, затем отправляют следующий. Небольшое значение здесь для HTTP/1.1 может помочь снизить потребление памяти и сокетов на сайтах с сотнями тысяч клиентов ценой увеличения вычислительных затрат на рукопожатия.

При работе с HTTP/2 следует особенно осторожно задавать небольшие значения. HTTP/2 мультиплексирует запросы в одном соединении, чтобы сократить накладные расходы на повторное подключение на уровнях TCP и/или SSL. Протокол также использует управляющие кадры, которые плохо переносят раннее закрытие TCP соединения. В очень редких случаях это может привести к обрезанным ответам, когда данные уничтожаются в пути после выхода из HAProxy (который тогда даже не может записать ошибку в журнал). В качестве начального малого значения для HTTP/2 соединений предлагается около 4 секунд. Это не позволит большинству современных реализаций постоянных соединений бессмысленно удерживать устаревшие соединения открытыми и одновременно позволит последующим запросам использовать соединение повторно. Однако значение следует корректировать по необходимости: это лишь отправная точка.

Если этот параметр не задан, применяется тайм-аут “http-request”; если не заданы оба, на нижнем уровне по-прежнему применяется “timeout client”. Чтобы он действовал, его следует задать во фронтенде, кроме случая, когда фронтенд работает в режиме TCP: тогда используется тайм-аут бэкенда HTTP.

См. также: “timeout http-request”, “timeout client”.

timeout http-request <timeout>

timeout http-request <timeout>

Установить максимально допустимое время ожидания полного HTTP запроса

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

<timeout> — значение тайм-аута, по умолчанию в миллисекундах; можно использовать любую другую
          единицу, добавив её суффикс к числу, как описано в начале этого документа.

Для защиты от DoS может потребоваться сократить максимально допустимое время получения полного HTTP запроса, не меняя тайм-аут клиента. Это помогает защититься от установленных соединений, по которым ничего не отправляется. Тайм-аут клиента плохо защищает от такого злоупотребления: это тайм-аут бездействия, и если атакующий время от времени отправляет один символ, он не сработает. При тайм-ауте HTTP запроса скорость отправки клиентом не имеет значения: запрос будет прерван, если не завершится вовремя. Когда тайм-аут истекает, клиенту отправляется ответ HTTP 408 с уведомлением о проблеме, а соединение закрывается. В журнале будет указан код завершения “cR”. У некоторых современных браузеров возникают проблемы с этим стандартным, хорошо документированным поведением, поэтому может потребоваться скрыть код 408 с помощью “option http-ignore-probes” или “errorfile 408 /dev/null”. Подробнее см. объяснение кода завершения “cR” в разделе 8.5 .

По умолчанию этот тайм-аут применяется только к заголовкам запроса, а не к данным. После получения пустой строки он больше не используется. В сочетании с “option http-buffer-request” этот тайм-аут применяется также к телу запроса. На постоянных соединениях он снова используется для ожидания второго запроса, если “timeout http-keep-alive” не задан.

Обычно достаточно задать несколько секунд, поскольку большинство клиентов отправляют весь запрос сразу после подключения. Добавьте 3 или более секунд для учёта повторных передач TCP; этого достаточно. Очень маленькие значения (например, 50 ms) обычно работают в локальных сетях, пока нет потерь пакетов. Это не позволит отправлять HTTP запросы вручную с помощью telnet.

Если этот параметр не задан, тайм-аут клиента по-прежнему применяется между фрагментами входящего запроса. Чтобы он действовал, его следует задать во фронтенде, кроме случая, когда фронтенд работает в режиме TCP: тогда используется тайм-аут бэкенда HTTP.

См. также: “errorfile”, “http-ignore-probes”, “timeout http-keep-alive” и “timeout client”, “option http-buffer-request”.

timeout queue <timeout>

timeout queue <timeout>

Установить максимальное время ожидания в очереди освобождения места для соединения

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<timeout> — значение тайм-аута, по умолчанию в миллисекундах; можно использовать любую другую
          единицу, добавив её суффикс к числу, как описано в начале этого документа.

При достижении maxconn сервера соединения остаются ожидать в очереди, отдельной для сервера или общей для бэкенда. Чтобы ожидание не было бесконечным, к запросам в очереди применяется тайм-аут. Если он истёк, считается, что запрос почти наверняка не будет обслужен, поэтому его отбрасывают, а клиенту возвращают ошибку 503.

Директива “timeout queue” позволяет задать максимальное время ожидания запроса в очереди. Если она не указана, используется то же значение, что и для тайм-аута подключения к бэкенду (“timeout connect”), для обратной совместимости со старыми версиями, в которых параметра “timeout queue” не было.

См. также: “timeout connect”.

timeout server <timeout>

timeout server <timeout>

Установить максимальное время бездействия на стороне сервера.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<timeout> — значение тайм-аута, по умолчанию в миллисекундах; можно использовать любую другую
          единицу, добавив её суффикс к числу, как описано в начале этого документа.

Тайм-аут бездействия применяется, когда от сервера ожидается подтверждение или отправка данных. В режиме HTTP этот тайм-аут особенно важно учитывать на первом этапе ответа сервера, когда он должен отправить заголовки: он непосредственно отражает время обработки запроса сервером. Чтобы определить подходящее значение, часто полезно начать со времени ответа, которое считается неприемлемым, затем изучить распределение времени ответа в журналах и соответствующим образом скорректировать значение.

Значение по умолчанию задаётся в миллисекундах, но можно использовать любую другую единицу, добавив её суффикс к числу, как описано в начале этого документа. В режиме TCP (и в меньшей степени в режиме HTTP) настоятельно рекомендуется сохранять тайм-аут клиента равным тайм-ауту сервера, чтобы избежать сложных для диагностики ситуаций. Независимо от ожидаемого времени ответа сервера полезно учитывать потерю как минимум одного или нескольких TCP пакетов, задавая тайм-ауты чуть больше значений, кратных 3 секундам (например, не менее 4 или 5 секунд). Если долгоживущие потоки смешаны с короткоживущими (например, WebSocket и HTTP), имеет смысл рассмотреть “timeout tunnel”, который переопределяет “timeout client” и “timeout server” для туннелей.

Этот параметр относится к бэкенду, но его можно задать один раз для всех в секциях “defaults”. Это один из самых простых способов не забыть о нём. Если тайм-аут не задан, он считается бесконечным, что не рекомендуется. Такая настройка принимается и работает, но при запуске выдаётся предупреждение: если системные тайм-ауты тоже не настроены, в системе могут накапливаться просроченные сеансы.

См. также: “timeout client” и “timeout tunnel”.

timeout server-fin <timeout>

timeout server-fin <timeout>

Установить тайм-аут бездействия на стороне сервера для полузакрытых соединений.

Можно использовать в следующих контекстах: tcp, http, log

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<timeout> — значение тайм-аута, по умолчанию в миллисекундах; можно использовать любую другую
          единицу, добавив её суффикс к числу, как описано в начале этого документа.

Тайм-аут бездействия применяется, когда от сервера ожидается подтверждение или отправка данных, а одно направление уже закрыто. Этот тайм-аут отличается от “timeout server” тем, что применяется только к соединениям, закрытым в одном направлении. Это особенно полезно, чтобы соединения не оставались слишком долго в состоянии FIN_WAIT, когда удалённый сервер завершает соединение некорректно. Эта проблема особенно распространена для длительных соединений, таких как RDP или WebSocket. Этот тайм-аут может переопределять “timeout tunnel”, когда соединение закрывается в одном направлении. Эта настройка предусмотрена для полноты, но в большинстве ситуаций она не нужна.

Этот параметр относится к бэкенду, но его можно задать один раз для всех в секциях “defaults”. По умолчанию он не задан, поэтому полузакрытые соединения используют другие тайм-ауты (timeout.server или timeout.tunnel).

См. также: “timeout client-fin”, “timeout server” и “timeout tunnel”.

timeout tarpit <timeout>

timeout tarpit <timeout>

Задаёт длительность удержания соединений в ловушке соединений (tarpit)

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

<timeout> — длительность нахождения в ловушке соединений (tarpit), по умолчанию в миллисекундах.
          Можно использовать любую другую единицу, добавив её после числа, как описано в начале
          документа.

Соединение, помещённое в ловушку через “http-request tarpit”, некоторое время сохраняется открытым без активности, затем закрывается. “timeout tarpit” задаёт длительность сохранения его открытым.

Значение по умолчанию указывается в миллисекундах, но после числа можно добавить другую единицу, как описано в начале документа. Если значение не задано, для совместимости со старыми версиями без “timeout tarpit” используется тайм-аут соединения бэкенда (“timeout connect”).

См. также: “timeout connect”.

timeout tunnel <timeout>

timeout tunnel <timeout>

Задаёт максимальное время бездействия на клиентской и серверной сторонах туннелей.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы:

<timeout> — значение тайм-аута, по умолчанию в миллисекундах; можно использовать любую другую
          единицу, добавив её суффикс к числу, как описано в начале этого документа.

Тайм-аут туннеля применяется при установленном двунаправленном соединении клиента с сервером, которое неактивно в обоих направлениях. После превращения соединения в туннель он заменяет клиентский и серверный тайм-ауты. В TCP он применяется, как только к обоим соединениям перестают быть подключены анализаторы (например, приняты правила содержимого tcp). В HTTP он применяется при переходе соединения к другому протоколу (например, WebSocket или пересылке запроса CONNECT прокси) либо после первого ответа, когда не задан параметр постоянных соединений/закрытия.

Поскольку тайм-аут обычно применяется к долгоживущим соединениям, как правило, целесообразно также задать “timeout client-fin”. Он обрабатывает случаи, когда клиент внезапно исчезает из сети и не подтверждает закрытие либо посылает сообщение о закрытии и перестаёт подтверждать ожидающие данные. Это возможно в сетях с потерями пакетов и межсетевыми экранами; признак — большое число сеансов в состоянии FIN_WAIT.

Значение по умолчанию указывается в миллисекундах, но после числа можно добавить другую единицу, как описано в начале документа. Независимо от ожидаемого обычного простоя полезно предусмотреть потерю одного или нескольких пакетов TCP, задавая тайм-ауты чуть больше значений, кратных 3 секундам (например, минимум 4 или 5 секунд).

Этот параметр относится к бэкенду, но его можно задать один раз для всех в секциях “defaults”. Это один из самых простых способов не забыть о нём.

Пример:

defaults http
    option http-server-close
    timeout connect 5s
    timeout client 30s
    timeout client-fin 30s
    timeout server 30s
    timeout tunnel  1h    # timeout to use with WebSocket and CONNECT

См. также: “timeout client”, “timeout client-fin”, “timeout server”.

transparent (deprecated)

transparent (deprecated)

Включает прозрачное проксирование на стороне клиента

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | нет | да | да

Аргументы: отсутствуют

Это ключевое слово появилось для предоставления привязки сеанса уровня 7 балансировщикам нагрузки уровня 3. Идея — использовать способность операционной системы (OS) перенаправлять входящее соединение к удалённому адресу в локальный процесс (здесь HAProxy) и сообщать ему первоначально запрошенный адрес. При включённом параметре сеансы без cookie пересылаются на исходный адрес IP назначения входящего запроса (который, как ожидается, соответствует адресу другого оборудования), а запросы с cookie по-прежнему пересылаются подходящему серверу.

Ключевое слово “transparent” устарело; вместо него следует использовать “option transparent”.

Вопреки распространённому мнению, этот параметр НЕ заставляет HAProxy представлять серверу адрес IP клиента при установлении соединения.

См. также: “option transparent”

unique-id-format <fmt>

unique-id-format <fmt>

Создаёт уникальный ID для каждого запроса.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | да

Аргументы:

<fmt>   — строка пользовательского формата журнала (см. раздел 8.2.6).

Это ключевое слово создаёт ID для каждого запроса по пользовательскому формату журнала. Уникальный ID помогает отслеживать запрос через множество компонентов сложной инфраструктуры. Созданный ID можно также журналировать через псевдоним %ID в строке пользовательского формата журнала.

Формат следует составлять из элементов, гарантированно уникальных при совместном использовании. Например, при нескольких экземплярах HAProxy может быть важно включить имя узла. Часто нужно журналировать исходный адрес и адрес назначения входящего соединения, а также порты. Поскольку в одном соединении может быть несколько запросов, счётчик запросов может помочь их различать. Аналогично отметка времени может защитить от переполнения счётчика. Журналирование ID процесса предотвращает коллизии после перезапуска службы.

Для многих полей рекомендуется шестнадцатеричная запись: она компактнее и экономит место в журналах.

Для обычных соединений уникальный ID создаётся по формату, настроенному во фронтенде. Для проверок работоспособности используется формат бэкенда при использовании извлечения “unique-id” в наборе правил tcp-check или http-check.

Пример:

unique-id-format %{+X}o\ %ci:%cp_%fi:%fp_%Ts_%rt:%pid

сформирует:

       7F000001:8296_7F00001E:1F90_4F7B0A69_0003:790A

См. также: “unique-id-header”

unique-id-header <name>

unique-id-header <name>

Добавляет заголовок с уникальным ID в запрос HTTP.

Можно использовать в следующих контекстах: http

Можно использовать в секциях: defaults | frontend | listen | backend да | да | да | нет

Аргументы:

<name>   — имя заголовка.

Добавляет в запрос HTTP, отправляемый серверу, заголовок unique-id на основе unique-id-format. Без unique-id-format этот параметр не работает.

Пример:

    unique-id-format %{+X}o\ %ci:%cp_%fi:%fp_%Ts_%rt:%pid
    unique-id-header X-Unique-ID

    сформирует:

       X-Unique-ID: 7F000001:8296_7F00001E:1F90_4F7B0A69_0003:790A

См. также: "unique-id-format"

use_backend <backend> [{if | unless} <condition>]

use_backend <backend> [{if | unless} <condition>]

Переключает на определённый бэкенд, если условие на основе ACL выполнено или не выполнено.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend нет | да | да | нет

Аргументы:

<backend>   — имя существующей секции backend или "listen" либо пользовательский формат журнала,
            дающий имя бэкенда (см. «Пользовательский формат журнала» в разделе 8.2.6).

<condition> — условие, составленное из ACL, как описано в разделе 7. Если оно не задано,
            правило применяется безусловно.

При переключении по содержимому соединения поступают на фронтенд, а затем распределяются по бэкендам в зависимости от ряда условий. Соответствие условий и бэкендов задаётся ключевым словом “use_backend”. Обычно оно используется при обработке HTTP, но применимо и к чистому TCP: без анализа содержимого, с ACL без состояния (например, для проверки исходного адреса), либо вместе с правилом “tcp-request”, позволяющим дождаться данных.

Число правил “use_backend” не ограничено. Они проверяются в порядке объявления; первое совпавшее правило назначает бэкенд, даже если он считается неработоспособным. Однако совпавшее правило, указывающее на отключённый или неопубликованный бэкенд, игнорируется, и проверка правил продолжается.

В первой форме бэкенд используется при выполнении условия, во второй — при его невыполнении. Если ни одно условие не выполнено, используется бэкенд из “default_backend”, если он не отключён и не снят с публикации. Если бэкенда по умолчанию нет, в секции “listen” используются серверы той же секции, а во фронтенде сервер не выбирается и возвращается ответ 503 о недоступности сервиса.

Можно переключаться с фронтенда TCP на бэкенд HTTP. Если фронтенд уже проверил, что используется HTTP, обработка на бэкенде начинается сразу; иначе бэкенд ждёт поступления полного запроса HTTP. Это полезно, когда фронтенд должен распознавать несколько протоколов на одном порту, в том числе HTTP.

Если <backend> — обычное имя, оно разрешается при разборе конфигурации, и отсутствие указанного бэкенда вызывает ошибку. Если же <backend> задан пользовательским форматом журнала, проверить его при разборе конфигурации нельзя: имя бэкенда разрешается динамически во время работы. Если полученное имя не соответствует ни одному допустимому бэкенду, остальные правила не проверяются и применяется директива default_backend. При динамических именах настоятельно рекомендуется использовать префикс, не используемый другими бэкендами, чтобы запрос не мог принудительно выбрать неразрешённый бэкенд.

Правила “use_backend” с явно заданным именем также позволяют определить связи между фронтендами и бэкендами для расчёта параметра “fullconn” бэкенда. Для динамических имён это невозможно.

См. также: “default_backend”, “tcp-request”, “fullconn”, “log-format” и раздел 7 об ACL.

use-fcgi-app <name>

use-fcgi-app <name>

Определяет приложение FastCGI для бэкенда.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend нет | нет | да | да

Аргументы:

<name>    — имя используемого приложения FastCGI.

Подробнее о настройке приложения FastCGI см. раздел 10.1 .

use-server <server> if <condition>

use-server <server> if <condition>
use-server <server> unless <condition>

Использует только указанный сервер, если условие на основе ACL выполнено или не выполнено.

Можно использовать в следующих контекстах: tcp, http

Можно использовать в секциях: defaults | frontend | listen | backend нет | нет | да | да

Аргументы:

<server>    — имя существующего сервера в той же секции backend либо строка пользовательского
            формата журнала, дающая имя сервера (см. раздел 8.2.6).

<condition> — условие, составленное из ACL, как описано в разделе 7.

По умолчанию соединения, поступающие на бэкенд, распределяются между доступными серверами согласно настроенному алгоритму, если только не используется механизм привязки, например cookie, обнаруженный в запросе.

Иногда требуется направить определённый запрос на конкретный сервер, не объявляя для него отдельный бэкенд. Это позволяют правила “use-server”. Они проверяются после правил “redirect”, перед обработкой cookie и имеют приоритет над cookie. Число правил “use-server” не ограничено. Правила проверяются в порядке объявления; первое совпавшее правило назначает сервер.

Если правило указывает на неработоспособный сервер, а “option persist” не используется и ни одно правило force-persist не сработало, это правило игнорируется. Проверка последующих правил продолжается до первого совпадения.

В первой форме сервер используется при выполнении условия, во второй — при его невыполнении. Если ни одно условие не выполнено, обработка продолжается и сервер назначается другими механизмами привязки.

Даже при совпадении правила обработка cookie продолжается, но уже не назначает сервер. Это позволяет удалять префикс у cookie с префиксами.

Директива “use-server” работает в режимах HTTP и TCP, что позволяет использовать её при анализе содержимого. Например, при протоколах с неявным TLS сервер в группе можно выбрать по полю TLS SNI (см. также “req.ssl_sni”). Если вес этих серверов равен нулю, для остального трафика они использоваться не будут.

Пример:

# intercept incoming TLS requests based on the SNI field
use-server www if { req.ssl_sni -i www.example.com }
server     www 192.168.0.1:443 weight 0
use-server mail if { req.ssl_sni -i mail.example.com }
server     mail 192.168.0.1:465 weight 0
use-server imap if { req.ssl_sni -i imap.example.com }
server     imap 192.168.0.1:993 weight 0
# all the rest is forwarded to this server
server  default 192.168.0.2:443 check

Если <server> — обычное имя, оно проверяется по серверам, указанным в конфигурации; отсутствие сервера вызывает ошибку. Для пользовательского формата журнала при разборе конфигурации проверка не выполняется. Если во время работы не удалось получить допустимое имя сервера, но ACL в условии правила use-server вернул true, остальные правила use-server не применяются и используется балансировка нагрузки.

См. также: “use_backend”, раздел 5 о серверах и раздел 7 об ACL.

4.3. Матрица ключевых слов действий

На разных этапах обработки запроса или ответа проверяется несколько наборов правил. Действие каждого правила может выполняться при соблюдении необязательного условия.

По умолчанию доступно множество действий: изменение содержимого, разрешение или блокировка обработки, изменение внутреннего состояния и т. д. Новые действия можно определять на Lua; их имена всегда начинаются с “lua.”.

Раньше некоторые действия были доступны только в определённых наборах правил. Теперь многие из них применимы к разным наборам. В таблице этого раздела для каждого поддерживаемого действия отмечены сокращённые названия наборов правил, в которых его можно использовать:

  • QUIC Ini: действие допустимо в правилах “quic-initial”
  • TCP RqCon: действие допустимо в правилах “tcp-request connection”
  • TCP RqSes: действие допустимо в правилах “tcp-request session”
  • TCP RqCnt: действие допустимо в правилах “tcp-request content”
  • TCP RsCnt: действие допустимо в правилах “tcp-response content”
  • HTTP Req: действие допустимо в правилах “http-request”
  • HTTP Res: действие допустимо в правилах “http-response”
  • HTTP Aft: действие допустимо в правилах “http-after-response”

Те же сокращения используются ниже в справочном разделе 4.4 .

 ключевое слово         QUIC: Ini   TCP: RqCon RqSes RqCnt RsCnt   HTTP: Req Res Aft
----------------------+-----------+-----------+-----+-----+------+----------+---+----
accept                         X           X     X     X     X            -   -   -
add-acl                        -           -     -     -     -            X   X   -
add-header                     -           -     -     -     -            X   X   X
add-headers-bin                -           -     -     -     -            X   X   X
allow                          -           -     -     -     -            X   X   X
attach-srv                     -           -     X     -     -            -   -   -
auth                           -           -     -     -     -            X   -   -
cache-store                    -           -     -     -     -            -   X   -
cache-use                      -           -     -     -     -            X   -   -
capture                        -           -     -     X     -            X   X   X
close                          -           -     -     -     X            -   -   -
del-acl                        -           -     -     -     -            X   X   -
del-header                     -           -     -     -     -            X   X   X
del-headers-bin                -           -     -     -     -            X   X   X
del-map                        -           -     -     -     -            X   X   X
deny                           -           -     -     -     -            X   X   -
dgram-drop                     X           -     -     -     -            -   -   -
disable-l7-retry               -           -     -     -     -            X   -   -
do-log                         X           X     X     X     X            X   X   X
do-resolve                     -           -     -     X     -            X   -   -
early-hint                     -           -     -     -     -            X   -   -
expect-netscaler-cip           -           X     -     -     -            -   -   -
expect-proxy layer4            -           X     -     -     -            -   -   -
normalize-uri                  -           -     -     -     -            X   -   -
pause                          -           -     -     -     -            X   X   -
redirect                       -           -     -     -     -            X   X   -
reject                         X           X     X     X     X            X   -   -
replace-header                 -           -     -     -     -            X   X   X
replace-path                   -           -     -     -     -            X   -   -
replace-pathq                  -           -     -     -     -            X   -   -
replace-uri                    -           -     -     -     -            X   -   -
replace-value                  -           -     -     -     -            X   X   X
return                         -           -     -     -     -            X   X   -
sc-add-gpc                     -           X     X     X     X            X   X   X
--keyword---------------QUIC--Ini---TCP--RqCon-RqSes-RqCnt-RsCnt---HTTP--Req-Res-Aft-sc-inc-gpc                     -           X     X     X     X            X   X   X
sc-inc-gpc0                    -           X     X     X     X            X   X   X
sc-inc-gpc1                    -           X     X     X     X            X   X   X
sc-set-gpt                     -           X     X     X     X            X   X   X
sc-set-gpt0                    -           X     X     X     X            X   X   X
send-retry                     X           -     -     -     -            -   -   -
send-spoe-group                -           -     -     X     X            X   X   -
set-bandwidth-limit            -           -     -     X     X            X   X   -
set-bc-mark                    -           -     -     X     -            X   -   -
set-bc-tos                     -           -     -     X     -            X   -   -
set-dst                        -           X     X     X     -            X   -   -
set-dst-port                   -           X     X     X     -            X   -   -
set-fc-mark                    -           X     X     X     X            X   X   -
set-fc-tos                     -           X     X     X     X            X   X   -
set-header                     -           -     -     -     -            X   X   X
set-headers-bin                -           -     -     -     -            X   X   X
set-log-level                  -           -     -     X     X            X   X   X
set-map                        -           -     -     -     -            X   X   X
set-mark (устарело)            -           X     X     X     X            X   X   -
set-method                     -           -     -     -     -            X   -   -
set-nice                       -           -     -     X     X            X   X   -
set-path                       -           -     -     -     -            X   -   -
set-pathq                      -           -     -     -     -            X   -   -
set-priority-class             -           -     -     X     -            X   -   -
set-priority-offset            -           -     -     X     -            X   -   -
--keyword---------------QUIC--Ini---TCP--RqCon-RqSes-RqCnt-RsCnt---HTTP--Req-Res-Aft-set-query                      -           -     -     -     -            X   -   -
set-retries                    -           -     -     X     -            X   -   -
set-src                        -           X     X     X     -            X   -   -
set-src-port                   -           X     X     X     -            X   -   -
set-status                     -           -     -     -     -            -   X   X
set-timeout                    -           -     -     -     -            X   X   -
set-tos (устарело)             -           X     X     X     X            X   X   -
set-uri                        -           -     -     -     -            X   -   -
set-var                        -           X     X     X     X            X   X   X
set-var-fmt                    -           X     X     X     X            X   X   X
silent-drop                    -           X     X     X     X            X   X   -
strict-mode                    -           -     -     -     -            X   X   X
switch-mode                    -           -     -     X     -            -   -   -
tarpit                         -           -     -     -     -            X   -   -
track-sc0                      -           X     X     X     -            X   X   -
track-sc1                      -           X     X     X     -            X   X   -
track-sc2                      -           X     X     X     -            X   X   -
unset-var                      -           X     X     X     X            X   X   X
use-service                    -           -     -     X     -            X   -   -
wait-for-body                  -           -     -     -     -            X   X   -
wait-for-handshake             -           -     -     -     -            X   -   -
--keyword---------------QUIC--Ini---TCP--RqCon-RqSes-RqCnt-RsCnt---HTTP--Req-Res-Aft-

4.4. Алфавитный справочник действий

В этом разделе подробно описаны все действия и их применение. Обозначения наборов правил те же, что в разделе 4.3 выше.

accept

accept

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft X | X | X | X | X | - | - | -

Прекращает проверку правил и пропускает запрос или ответ. Это завершающее действие: остальные правила того же набора в текущей секции не проверяются. Оно не отличается от “allow”, но для совместимости с прежними версиями в правилах TCP и QUIC используется “accept”, а в правилах HTTP — “allow”. См. также действие “allow” ниже.

add-acl(<file-name>) <key fmt>

add-acl(<file-name>) <key fmt>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | -

Добавляет новую запись в ACL. ACL должен быть загружен из файла, пусть даже пустого. Имя файла обновляемого ACL указывается в круглых скобках. Действие принимает один аргумент: <key fmt>, задающий содержимое новой записи по правилам пользовательского формата журнала из раздела 8.2.6 . Перед вставкой выполняется поиск в ACL, чтобы не создавать повторяющиеся значения. Это эквивалент команды “add acl” сокета статистики, который может вызываться запросом HTTP.

add-header <name> <fmt>

add-header <name> <fmt>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

Добавляет поле заголовка HTTP с именем <name> и значением <fmt>, заданным по правилам пользовательского формата журнала (см. раздел 8.2.6 ). Это особенно удобно для передачи серверу сведений о соединении, например сертификата SSL клиента, или для объединения нескольких заголовков в один. Правило не является завершающим: после него можно добавить другие подобные правила. Заголовок добавляется немедленно, поэтому следующее правило может использовать заголовок, полученный в результате предыдущего.

add-headers-bin <expr> [ prefix <str> ]

add-headers-bin <expr> [ prefix <str> ]

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

Вариант действия “add-header”, в котором имена и значения заголовков передаются двоичной строкой с кодированием varint. О формате varint см. функцию извлечения образца “req.hdrs_bin”. Это удобно для одновременного задания нескольких заголовков, имена которых заранее неизвестны. Эти заголовки не проверялись анализатором HTTP, поэтому могут привести к отправке некорректных сообщений, а в худшем случае — к атакам с подменой границ запросов (request smuggling). Число добавляемых заголовков также имеет значение: оно ограничено tune.http.maxhdr. При заданном необязательном префиксе из закодированной строки добавляются только заголовки, имена которых начинаются с <str>.

Пример:

# This would reset the Accept/UA/Host headers to their initial values
http-request set-var(txn.oldheaders) req.hdrs_bin
http-request del-header Accept
http-request del-header User-Agent
http-request del-header Host
http-request add-headers-bin var(txn.oldheaders)

allow

allow

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

Прекращает проверку правил и пропускает запрос. Это завершающее действие: остальные правила того же набора в текущей секции не проверяются. Оно не отличается от “accept”, но для совместимости с прежними версиями в правилах TCP используется “accept”, а в правилах HTTP — “allow”. См. также действие “accept” выше.

attach-srv <srv> [name <expr>] [ EXPERIMENTAL ]

attach-srv <srv> [name <expr>] [ EXPERIMENTAL ]

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | X | - | - | - | - | -

Перехватывает соединение после корректного установления HTTP/2. Направление соединения меняется на сторону бэкенда, и оно помещается в пул простаивающих соединений сервера <srv>. Действие допустимо только для серверов с адресом ‘rhttp@’.

Соединение помещается в пул простаивающих соединений сервера с именем, полученным при вычислении <expr>. С этим именем сопоставляются запросы, к которым применяется параметр “pool-conn-name” или “sni”. Подробнее см. “http-reuse”.

Reverse HTTP пока активно разрабатывается. Механизм конфигурации может измениться. Поэтому функция помечена как экспериментальная: перед этой директивой в отдельной строке необходимо указать “expose-experimental-directives”.

Также разрабатывается очень похожий, но независимый протокол. См. https://www.ietf.org/archive/id/draft-bt-httpbis-reverse-http-00.html .

auth [realm <realm>]

auth [realm <realm>]

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

Прекращает проверку правил и немедленно возвращает код ошибки HTTP 401 или 407, предлагая пользователю предоставить действительные имя и пароль. Остальные правила “http-request” не проверяются. Необязательный параметр “realm” задаёт область аутентификации, возвращаемую в ответе, — обычно это имя приложения.

Используется сообщение об ошибке соответствующего прокси. Его можно настроить директивой “errorfile” или “http-error”. В ответах 401 все вхождения заголовка WWW-Authenticate удаляются и заменяются одним новым заголовком с запросом базовой аутентификации для области “<realm>”. В ответах 407 то же происходит с заголовком Proxy-Authenticate. Если сообщение об ошибке должно оставаться неизменным, можно вместо этого использовать правило “http-request return”.

Пример:

acl auth_ok http_auth_group(L1) G1
http-request auth unless auth_ok

cache-store <name>

cache-store <name>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | - | X | -

Сохраняет http-response в кеше. Заголовки ответа сохраняются на этом этапе, поэтому другие действия http-response могут изменять их до или после сохранения ответа. Это действие отвечает за настройку фильтра сохранения в кеше.

О настройке кеша см. раздел 6.2 .

cache-use <name>

cache-use <name>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

Пытается выдать закешированный объект из кеша <name>. Эта директива обязательна и для сохранения в кеше, поскольку вычисляет хеш кеша. Если условие должно применяться и к сохранению, и к выдаче, его целесообразно поместить после этой директивы.

О настройке кеша см. раздел 6.2 .

capture <sample> [ len <length> | id <id> ]

capture <sample> [ len <length> | id <id> ]

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | - | X | X | X

Захватывает результат выражения образца <sample> из буфера запроса или ответа и преобразует его в строку длиной не более <len> символов. Строка сохраняется в следующем слоте “capture” для запроса или ответа, поэтому может оказаться рядом с захваченными заголовками HTTP. Затем она автоматически появляется в журналах; её также можно получить функциями извлечения образцов и поместить в заголовки или использовать иначе. Длину следует ограничивать, поскольку такой объём памяти выделяется для каждого захвата на всё время жизни потока. Длину можно задавать только в правилах “http-request”. Такой слот существует только в секции, где он объявлен. Поэтому если правило размещено в секции “listen”, которая также используется как бэкенд другого фронтенда, оно игнорируется для потоков, поступивших от этого фронтенда. Подробнее см. раздел 7.3 («Извлечение образцов»), “capture request header” и “capture response header”.

Если вместо “len” указано ключевое слово “id”, действие пытается сохранить захваченную строку в ранее объявленном слоте захвата. Это удобно для захвата на бэкендах. Идентификатор слота может быть объявлен предшествующей директивой “http-request capture” или ключевым словом “declare capture”.

При использовании этого действия на бэкенде необходимо убедиться, что соответствующие фронтенды имеют требуемые слоты захвата, иначе правило будет игнорироваться во время работы. Обнаружить это при разборе конфигурации невозможно: HAProxy может динамически разрешать имя бэкенда во время работы.

close

close

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | X | - | - | -

Немедленно закрывает соединение с сервером. Остальные правила “tcp-response content” не проверяются. Основное назначение — принудительно завершить соединение между клиентом и сервером после обмена данными, когда протокол приложения предполагает сначала дождаться длительных тайм-аутов. Это позволяет устранить простаивающие соединения, которые при некоторых протоколах занимают значительные ресурсы сервера.

del-acl(<file-name>) <key fmt>

del-acl(<file-name>) <key fmt>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | -

Удаляет запись из ACL. ACL должен быть загружен из файла, пусть даже пустого. Имя файла обновляемого ACL указывается в круглых скобках. Действие принимает один аргумент: <key fmt>, задающий содержимое удаляемой записи по правилам пользовательского формата журнала из раздела 8.2.6 . Это эквивалент команды “del acl” сокета статистики, который может вызываться запросом или ответом HTTP.

del-header <name> [ -m <meth> ]

del-header <name> [ -m <meth> ]

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

Удаляет все поля заголовка HTTP с именем, указанным в <name>. <meth> задаёт метод сопоставления имени заголовка. Поддерживаются “str” (точное совпадение), “beg” (совпадение префикса), “end” (совпадение суффикса), “sub” (совпадение подстроки) и “reg” (сопоставление с регулярным выражением). Если метод не указан, используется точное совпадение.

del-headers-bin <expr> [ -m <meth> ]

del-headers-bin <expr> [ -m <meth> ]

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

Удаляет все поля заголовка HTTP, имена которых заданы в <expr>. <expr> должно возвращать двоичную строку с кодированием varint, содержащую все имена удаляемых заголовков. Описание кодирования и примеры приведены в “add-headers-bin” и “set-headers-bin”. <meth> задаёт метод сопоставления для всех имён заголовков. Поддерживаются “str” (точное совпадение), “beg” (совпадение префикса), “end” (совпадение суффикса) и “sub” (совпадение подстроки). Метод “reg” (сопоставление с регулярным выражением) не поддерживается из-за непредсказуемой производительности во время работы. Если метод не указан, используется точное совпадение.

del-map(<map-name>) <key fmt>

del-map(<map-name>) <key fmt>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

Удаляет запись из MAP. <map-name> должно соответствовать формату имён карт отображения и ACL из раздела 2.7. Имя обновляемой MAP указывается в круглых скобках. Действие принимает один аргумент: <key fmt>, задающий содержимое удаляемой записи по правилам пользовательского формата журнала из раздела 8.2.6 . Оно принимает один аргумент: “имя файла”. Это эквивалент команды “del map” сокета статистики, который может вызываться запросом или ответом HTTP.

deny [ { status | deny_status } <code> ] [ content-type <type> ]

deny [ { status | deny_status } <code> ] [ content-type <type> ]
     [ { default-errorfiles | errorfile <file> | errorfiles <name> |
   file `<file>` | lf-file `<file>` | string `<str>` | lf-string `<fmt>` } ]
 [ hdr `<name>` `<fmt>` ]*

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | -

Прекращает обработку правил и немедленно отклоняет запрос или ответ. По умолчанию для запросов возвращается ошибка HTTP 403, а для ответов — 502, но возвращаемый ответ можно настроить с тем же синтаксисом, что и у действия “return”. Подробности см. ниже в описании “return”. Для совместимости, если аргументы не заданы либо указан только “deny_status”, подразумевается аргумент “default-errorfiles”. Таким образом, “deny [deny_status <status>]” — псевдоним “deny [status <status>] default-errorfiles”. Это завершающее действие: дальнейшие правила из того же набора для текущей секции не обрабатываются. Расширенный синтаксис также описан в действии “return”.

dgram-drop

dgram-drop

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft X | - | - | - | - | - | - | -

Без уведомления игнорирует получение начального пакета QUIC, который иначе привёл бы к созданию нового соединения QUIC и выполнению его рукопожатия SSL.

disable-l7-retry

disable-l7-retry

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

Отключает все попытки повторить запрос, если он завершился неудачей по любой причине, кроме ошибки соединения. Это может быть полезно, например, чтобы исключить повтор POST-запросов после неудачи.

do-log [profile <log_profile>]

do-log [profile <log_profile>]

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft X | X | X | X | X | X | X | X

Это действие вручную запускает формирование записи журнала на прокси. Учитываются параметры ведения журнала прокси, включая параметры форматирования, например “log-format”, но действие не влияет на записи, автоматически формируемые прокси при обработке транзакций.

С помощью “log-profile” можно точно описать, как следует формировать запись журнала в каждом из доступных контекстов, где применимо действие. Для этого служит ключевое слово ‘on’, за которым следует одно из значений: ‘quic-init’, ’tcp-req-conn’, ’tcp-req-sess’, ’tcp-req-cont’, ’tcp-res-cont’, ‘http-req’, ‘http-res’, ‘http-after-res’.

Они также корректно отображаются при использовании псевдонима формата журнала “%OG”.

Необязательный аргумент “profile” позволяет указать имя секции log-profile, которую следует использовать именно для этого действия do-log вместо секции, связанной с текущим средством записи журнала и применяемой по умолчанию.

Пример:

log-profile my-dft-prof
  on tcp-req-conn format "Connect: %ci"

log-profile my-local-prof
  on tcp-req-conn format "Local Connect: %ci"

frontend myfront
  log stdout format rfc5424 profile my-dft-prof local0
  log-format "log generated using proxy logformat, from '%OG'"
  acl local src 127.0.0.1
  # on connection use either log-profile from the logger (my-dft-prof) or
  # explicit my-local-prof if source ip is localhost
  tcp-request connection do-log if !local
  tcp-request connection do-log profile my-local-prof if local
  # on content use proxy logformat, since no override was specified
  # in my-dft-prof
  tcp-request content do-log

do-resolve(<var>,<resolvers>[,ipv4|ipv6]) <expr>

do-resolve(<var>,<resolvers>[,ipv4|ipv6]) <expr>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | - | X | - | -

Выполняет разрешение DNS для результата <expr> и сохраняет результат в переменной <var>. Используется секция резолверов DNS, указанная в <resolvers>. Необязательные аргументы ‘ipv4’ и ‘ipv6’ позволяют выбрать предпочтительное семейство адресов. См. также глобальное ключевое слово “dns-accept-family”, которое обеспечивает строгое использование определённого семейства.

Во время разрешения DNS клиентское соединение приостанавливается до завершения разрешения. Если найден IP-адрес, он сохраняется в <var>. При любой ошибке <var> не устанавливается. Это действие позволяет определять IP-адрес сервера во время выполнения на основании информации из запроса, например заголовка Host. Если действие используется для поиска IP-адреса сервера с последующим действием “set-dst”, IP-адрес сервера в бэкенде должен быть задан как 0.0.0.0. Действие do-resolve принимает параметр, содержащий только имя узла; любой порт необходимо удалить из строки.

Пример:

resolvers mydns
  nameserver local 127.0.0.53:53
  nameserver google 8.8.8.8:53
  timeout retry   1s
  hold valid 10s
  hold nx 3s
  hold other 3s
  hold obsolete 0s
  accepted_payload_size 8192

frontend fe
  bind 10.42.0.1:80
  http-request do-resolve(txn.myip,mydns,ipv4) hdr(Host),host_only
  http-request capture var(txn.myip) len 40

  # return 503 when the variable is not set,
  # which mean DNS resolution error
  use_backend b_503 unless { var(txn.myip) -m found }

  default_backend be

backend b_503
  # dummy backend used to return 503.
  # one can use the errorfile directive to send a nice
  # 503 error page to end users

backend be
  # rule to prevent HAProxy from reconnecting to services
  # on the local network (forged DNS name used to scan the network)
  http-request deny if { var(txn.myip) -m ip 127.0.0.0/8 10.0.0.0/8 }
  http-request set-dst var(txn.myip)
  server clear 0.0.0.0:0

ПРИМЕЧАНИЕ: Следует задать защитные правила, чтобы HAProxy не использовался для сканирования сети или, что ещё хуже, не обращался циклически к самому себе…

early-hint <name> <fmt>

early-hint <name> <fmt>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

Формирует ответ HTTP 103 Early Hints перед любым другим ответом. Добавляет к нему поле заголовка HTTP с именем <name> и значением <fmt>, которое следует правилам пользовательского формата журнала (см. пользовательский формат журнала в разделе 8.2.6 ). Это особенно полезно для передачи клиенту заголовков Link с целью предварительной загрузки ресурсов, необходимых для отображения документов HTML.

Дополнительную информацию см. в RFC 8297.

expect-netscaler-cip layer4

expect-netscaler-cip layer4

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | - | - | - | - | - | -

Настраивает клиентское соединение на получение заголовка протокола NetScaler Client IP insertion до чтения хотя бы одного байта из сокета. Это эквивалентно ключевому слову “accept-netscaler-cip” в строке “bind”, однако правило TCP позволяет принимать протокол PROXY только от определённых диапазонов IP-адресов с помощью ACL. Это удобно, когда трафик от общедоступных узлов проходит через несколько уровней балансировщиков нагрузки.

expect-proxy layer4

expect-proxy layer4

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | - | - | - | - | - | -

Настраивает клиентское соединение на получение заголовка протокола PROXY до чтения хотя бы одного байта из сокета. Это эквивалентно ключевому слову “accept-proxy” в строке “bind”, однако правило TCP позволяет принимать протокол PROXY только от определённых диапазонов IP-адресов с помощью ACL. Это удобно, когда трафик от общедоступных узлов проходит через несколько уровней балансировщиков нагрузки.

normalize-uri <normalizer>

normalize-uri <normalizer>
normalize-uri fragment-encode
normalize-uri fragment-strip
normalize-uri path-merge-slashes
normalize-uri path-strip-dot
normalize-uri path-strip-dotdot [ full ]
normalize-uri percent-decode-unreserved [ strict ]
normalize-uri percent-to-uppercase [ strict ]
normalize-uri query-sort-by-name

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

Выполняет нормализацию URI запроса.

Нормализация URI в HAProxy 2.4 пока доступна в качестве экспериментальной предварительной реализации. Поэтому для её использования сначала необходимо задать глобальную директиву ’expose-experimental-directives’. Следует быть готовым к тому, что поведение нормализаторов может измениться для устранения возможных проблем, что способно нарушить корректную обработку запросов в инфраструктуре.

Каждый нормализатор выполняет один вид нормализации, что позволяет точно выбрать уровень нормализации, подходящий для поддерживаемого бэкенда.

Например, нормализатор “path-strip-dotdot” может быть полезен для сервера статических файлов, который напрямую сопоставляет запрошенный URI с путём в локальной файловой системе. Однако он может нарушить маршрутизацию API, ожидающего определённое число сегментов в пути.

Некоторые нормализаторы могут приводить к небезопасным преобразованиям некорректных URI. Кроме того, нормализаторы, безопасные по отдельности, при неправильном сочетании тоже могут приводить к небезопасным преобразованиям.

Например, нормализатор “percent-decode-unreserved” может давать неожиданные результаты, если некорректный URI содержит символы процента без кодирования. Такой URI — “/%%36%36”: он декодируется в “/%66”, что, в свою очередь, эквивалентно “/f”. Параметр “strict” позволяет безопасно отклонять запросы к таким некорректным URI.

Доступны следующие нормализаторы:

  • fragment-encode: Кодирует “#” как “%23”.

    Следует предпочесть нормализатор “fragment-strip”, если только не известно, что некорректные клиенты неправильно кодируют ‘#’ в компоненте пути.

    Пример:

    • /#foo -> /%23foo
  • fragment-strip: Удаляет компонент “fragment” из URI.

    Согласно RFC 3986#3.5 компонент “fragment” URI не следует отправлять; пользовательскому агенту следует обрабатывать его после получения ресурса.

    Этот нормализатор следует применять первым, чтобы фрагмент не интерпретировался как часть компонента пути запроса.

    Пример:

    • /#foo -> /
  • path-strip-dot: Удаляет сегменты “/./” в компоненте “path” (RFC 3986#6.2.2.3).

    Сегменты с точками в процентном кодировании ("%2E”) не обнаруживаются. Если такое поведение нежелательно, сначала следует использовать нормализатор “percent-decode-unreserved”.

    Пример:

    • /. -> /
    • /./bar/ -> /bar/
    • /a/./a -> /a/a
    • /.well-known/ -> /.well-known/ (без изменений)
  • path-strip-dotdot: Нормализует сегменты “/../” в компоненте “path” (RFC 3986#6.2.2.3).

    Объединяет сегменты, пытающиеся обратиться к родительскому каталогу, с предшествующим им сегментом.

    Пустые сегменты не обрабатываются особым образом. Если такое поведение нежелательно, сначала следует использовать нормализатор “merge-slashes”.

    Сегменты с точками в процентном кодировании ("%2E") не обнаруживаются. Если такое поведение нежелательно, сначала следует использовать нормализатор “percent-decode-unreserved”.

    Пример:

    • /foo/../ -> /
    • /foo/../bar/ -> /bar/
    • /foo/bar/../ -> /foo/
    • /../bar/ -> /../bar/
    • /bar/../../ -> /../
    • /foo//../ -> /foo/
    • /foo/%2E%2E/ -> /foo/%2E%2E/

    Если указан параметр “full”, начальные “../” также удаляются:

    Пример:

    • /../bar/ -> /bar/
    • /bar/../../ -> /
  • path-merge-slashes: Объединяет соседние косые черты в компоненте “path” в одну косую черту.

    Пример:

    • // -> /
    • /foo//bar -> /foo/bar
  • percent-decode-unreserved: Декодирует незарезервированные символы в процентном кодировании в обычные символы (RFC 3986#6.2.2.2).

    Набор незарезервированных символов включает все буквы, все цифры, “-”, “.”, “_” и “~”.

    Пример:

    • /%61dmin -> /admin
    • /foo%3Fbar=baz -> /foo%3Fbar=baz (без изменений)
    • /%%36%36 -> /%66 (небезопасно)
    • /%ZZ -> /%ZZ

    Если указан параметр “strict”, при недопустимых последовательностях возвращается HTTP 400 Bad Request.

    Пример:

    • /%%36%36 -> HTTP 400
    • /%ZZ -> HTTP 400
  • percent-to-uppercase: Переводит буквы в процентно-кодированных последовательностях в верхний регистр (RFC 3986#6.2.2.1).

    Пример:

    • /%6f -> /%6F
    • /%zz -> /%zz

    Если указан параметр “strict”, при недопустимых последовательностях возвращается HTTP 400 Bad Request.

    Пример:

    • /%zz -> HTTP 400
  • query-sort-by-name: Сортирует параметры строки запроса по имени. Предполагается, что разделитель параметров — ‘&’. Короткие имена располагаются перед длинными, а параметры с одинаковыми именами сохраняют взаимный порядок.

    Пример:

    • /?c=3&a=1&b=2 -> /?a=1&b=2&c=3
    • /?aaa=3&a=1&aa=2 -> /?a=1&aa=2&aaa=3
    • /?a=3&b=4&a=1&b=5&a=2 -> /?a=3&a=1&a=2&b=4&b=5

pause { <timeout> | <expr> }

pause { <timeout> | <expr> }

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | -

Приостанавливает анализ сообщения на указанное число миллисекунд. Тайм-аут можно задать в миллисекундах или в любой другой единице, добавив её обозначение после числа, как описано в начале документа. Также можно задать выражение, которое должно вернуть число, интерпретируемое как тайм-аут в миллисекундах. Если вычисление выражения завершается неудачей или возвращает недопустимое значение, действие игнорируется, а обработка продолжается.

Это действие может использоваться для отладки. Оно также позволяет замедлять обслуживание некоторых клиентов по определённым критериям. Например, можно замедлять клиентов с чрезмерной интенсивностью запросов, отслеживая их правилом “track-sc”.

redirect <rule>

redirect <rule>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | -

Выполняет перенаправление HTTP по правилу перенаправления. Оно полностью соответствует директиве “redirect”, но вставляет правило, которое обрабатывается среди других правил “http-request” или “http-response” и использует пользовательский формат журнала. Для ответов разрешён только тип перенаправления “location”. Кроме того, при перенаправлении во время обработки ответа передача от сервера к HAProxy прерывается, поэтому клиенту нельзя переслать полезную нагрузку. В HTTP/1 это может привести к закрытию некоторых соединений. Это завершающее действие: дальнейшие правила из того же набора для текущей секции не обрабатываются. Синтаксис правила см. в описании ключевого слова “redirect”.

reject

reject

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft X | X | X | X | X | X | - | -

Прекращает обработку правил и немедленно закрывает соединение без отправки ответа. В правилах HTTP действует аналогично правилам “tcp-request content reject”. Может быть полезно для принудительного немедленного закрытия соединений HTTP/2.

В правилах “tcp-request connection” отклонённые соединения даже не становятся сеансами, поэтому в статистике они учитываются отдельно как «отклонённые соединения». Они не учитываются при ограничении интенсивности сеансов и не записываются в журнал. Эти правила следует использовать только для фильтрации чрезвычайно высокой интенсивности соединений, например при массовой DDoS-атаке. В таких экстремальных условиях запись каждого события в журнал привела бы к отказу системы и существенно снизила бы возможности фильтрации. Если ведение журнала необходимо, следует использовать правила “tcp-request content”, поскольку правила “tcp-request session” также не формируют записи журнала.

При использовании в правилах “tcp-response content” соединение с сервером закрывается, а передача ответа прерывается. Обычно это служит для предотвращения утечки конфиденциальной информации, как правило после проверки содержимого совместно с действием “wait-for-body”.

Это действие можно использовать и в правилах “quic-initial”. Только что открытое соединение QUIC немедленно закрывается без обработки рукопожатия SSL, а клиент уведомляется кодом ошибки CONNECTION_REFUSED.

replace-header <name> <match-regex> <replace-fmt>

replace-header <name> <match-regex> <replace-fmt>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

Сопоставляет значения всех вхождений поля заголовка <name> с <match-regex>. Сопоставление учитывает регистр. Совпавшие значения полностью заменяются на <replace-fmt>. В <replace-fmt> разрешены символы форматирования; они работают так же, как аргументы <fmt> в “http-request add-header”. Поддерживаются стандартные обратные ссылки: обратная косая черта (’\’), за которой следует число.

Это действие обрабатывает строки заголовков целиком независимо от количества содержащихся в них значений. Поэтому оно хорошо подходит для заголовков, чьи значения естественным образом содержат запятые, например If-Modified-Since или Set-Cookie. Для заголовков со списком значений, разделённых запятыми, например Accept или Cache-Control, следует использовать действие “replace-value”. См. также действие “replace-value”.

Пример:

http-request replace-header Cookie foo=([^;]*);(.*) foo=\1;ip=%bi;\2

# applied to:
Cookie: foo=foobar; expires=Tue, 14-Jun-2016 01:40:45 GMT;

# outputs:
Cookie: foo=foobar;ip=192.168.1.20; expires=Tue, 14-Jun-2016 01:40:45 GMT;

# assuming the backend IP is 192.168.1.20

http-request replace-header User-Agent curl foo

# applied to:
User-Agent: curl/7.47.0

# outputs:
User-Agent: foo

Пример:

http-response replace-header Set-Cookie (C=[^;]*);(.*) \1;ip=%bi;\2

# applied to:
Set-Cookie: C=1; expires=Tue, 14-Jun-2016 01:40:45 GMT

# outputs:
Set-Cookie: C=1;ip=192.168.1.20; expires=Tue, 14-Jun-2016 01:40:45 GMT

# assuming the backend IP is 192.168.1.20.

replace-path <match-regex> <replace-fmt>

replace-path <match-regex> <replace-fmt>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

Работает как “replace-header”, но обрабатывает компонент пути запроса вместо заголовка. Компонент пути начинается с первой ‘/’ после необязательных схемы и полномочного компонента и заканчивается перед вопросительным знаком. Таким образом, замена не изменяет схему, полномочный компонент и строку запроса.

Вычисление регулярных выражений может обходиться дороже, чем проверка некоторых ACL. Поэтому для редко выполняемых замен может быть полезно условие, позволяющее вообще не вычислять выражение, если условие не выполняется.

Пример:

# prefix /foo: turn /bar?q=1 into /foo/bar?q=1:
http-request replace-path (.*) /foo\1

# strip /foo: turn /foo/bar?q=1 into /bar?q=1
http-request replace-path /foo/(.*) /\1
# or more efficient if only some requests match:
http-request replace-path /foo/(.*) /\1 if { url_beg /foo/ }

replace-pathq <match-regex> <replace-fmt>

replace-pathq <match-regex> <replace-fmt>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

Работает так же, как “http-request replace-path”, но путь включает строку запроса, если она присутствует. Таким образом, заменяются и путь, и строка запроса.

Пример:

# suffix /foo: turn /bar?q=1 into /bar/foo?q=1:
http-request replace-pathq ([^?]*)(\?(.*))? \1/foo\2

replace-uri <match-regex> <replace-fmt>

replace-uri <match-regex> <replace-fmt>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

Работает как “replace-header”, но обрабатывает URI запроса вместо заголовка. URI может включать необязательные схему, полномочный компонент или строку запроса. Они считаются частью сопоставляемого значения.

Вычисление регулярных выражений может обходиться дороже, чем проверка некоторых ACL. Поэтому для редко выполняемых замен может быть полезно условие, позволяющее вообще не вычислять выражение, если условие не выполняется.

ВАЖНОЕ ПРИМЕЧАНИЕ: Исторически в HTTP/1.x подавляющее большинство запросов браузеров использует исходную форму URI, которая отличается от абсолютной формы отсутствием схемы и компонента authority в URI. Абсолютную форму в основном используют лишь запросы к прокси, запросы, составленные вручную, и некоторые запросы отдельных приложений. Поэтому в HTTP/1.x “replace-uri” обычно работает корректно с правилами, начинающимися с “/”. Однако в HTTP/2 клиентам рекомендуется отправлять только абсолютные URI, похожие на URI, используемые клиентами HTTP/1 при обращении к прокси. Такие частичные правила replace-uri могут не работать в HTTP/2, хотя работают в HTTP/1. Следует либо адаптировать правила для необязательного сопоставления схемы и компонента authority, либо использовать replace-path.

Пример:

# rewrite all "http" absolute requests to "https":
http-request replace-uri ^http://(.*) https://\1

# prefix /foo: turn /bar?q=1 into /foo/bar?q=1:
http-request replace-uri ([^/:]*://[^/]*)?(.*) \1/foo\2

replace-value <name> <match-regex> <replace-fmt>

replace-value <name> <match-regex> <replace-fmt>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

Работает как “replace-header”, но сопоставляет регулярное выражение с каждым значением поля заголовка <name>, разделённым запятыми, вместо заголовка целиком. Подходит для всех заголовков, допускающих несколько значений, например заголовка запроса Accept или заголовка Cache-Control в запросах и ответах.

Пример:

http-request replace-value X-Forwarded-For ^192\.168\.(.*)$ 172.16.\1

# applied to:
X-Forwarded-For: 192.168.10.1, 192.168.13.24, 10.0.0.37

# outputs:
X-Forwarded-For: 172.16.10.1, 172.16.13.24, 10.0.0.37

Пример:

http-after-response replace-value Cache-control ^public$ private

# applied to:
Cache-Control: max-age=3600, public

# outputs:
Cache-Control: max-age=3600, private

return [ status <code> ] [ content-type <type> ]

return [ status <code> ] [ content-type <type> ]
       [ { default-errorfiles | errorfile <file> | errorfiles <name> |
     file `<file>` | lf-file `<file>` | string `<str>` | lf-string `<fmt>` } ]
   [ hdr `<name>` `<fmt>` ]*

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | -

Прекращает обработку правил и немедленно возвращает ответ. По умолчанию ответ использует код состояния 200. Его можно изменить аргументом “status”. Тип содержимого ответа также можно задать аргументом “content-type”. Наконец, можно задать сам ответ: либо полный ответ HTTP с указанием используемого файла ошибки, либо полезную нагрузку ответа с указанием файла или строки. Ответ создаётся по следующим правилам:

  • Если не задан ни файл ошибки, ни полезная нагрузка, возвращается ответ-заглушка. Учитывается только аргумент “status”. Допустим любой код в диапазоне [200, 599]. Аргумент “content-type”, если он есть, игнорируется.

  • Если задан аргумент “default-errorfiles”, используются файлы ошибок прокси. Если задан аргумент “status”, он должен содержать один из кодов состояния, обрабатываемых HAProxy (200, 400, 403, 404, 405, 408, 410, 413, 414, 425, 429, 431, 500, 501, 502, 503 и 504). Аргумент “content-type”, если он есть, игнорируется.

  • Если аргументом “errorfile” задан конкретный файл ошибки, возвращается этот файл, содержащий полный ответ HTTP. Учитывается только аргумент “status”. Он должен содержать один из кодов состояния, обрабатываемых HAProxy (200, 400, 403, 404, 405, 408, 410, 413, 414, 425, 429, 431, 500, 501, 502, 503 и 504). Аргумент “content-type”, если он есть, игнорируется.

  • Если аргументом “errorfiles” задана секция http-errors, возвращается соответствующий файл из этой секции http-errors, содержащий полный ответ HTTP. Учитывается только аргумент “status”. Он должен содержать один из кодов состояния, обрабатываемых HAProxy (200, 400, 403, 404, 405, 408, 410, 413, 414, 425, 429, 431, 500, 501, 502, 503 и 504). Аргумент “content-type”, если он есть, игнорируется.

  • Если задан аргумент “file” или “lf-file”, содержимое файла используется как полезная нагрузка ответа. Если файл не пуст, тип его содержимого должен быть задан аргументом “content-type”. В противном случае любой аргумент “content-type” игнорируется. При аргументе “lf-file” содержимое файла вычисляется как пользовательский формат журнала (см. раздел 8.2.6 ). При аргументе “file” оно рассматривается как необработанное содержимое.

  • Если задан аргумент “string” или “lf-string”, указанная строка используется как полезная нагрузка ответа. Тип содержимого всегда должен быть задан аргументом “content-type”. При аргументе “lf-string” строка вычисляется как пользовательский формат журнала (см. раздел 8.2.6 ). При аргументе “string” она рассматривается как необработанная строка.

Если ответ не основан на файле ошибки, аргументы “hdr” позволяют добавить в него поля заголовков HTTP. В противном случае все аргументы “hdr” игнорируются. Для каждого заголовка имя задаётся в <name>, а значение — в <fmt> по правилам пользовательского формата журнала, описанным в разделе 8.2.6 .

Создаваемый ответ должен быть меньше буфера. Чтобы избежать предупреждений при загрузке файла ошибки или необработанного файла, также следует оставлять свободным пространство буфера, зарезервированное для перезаписи заголовков.

Это завершающее действие: дальнейшие правила из того же набора для текущей секции не обрабатываются.

Пример:

http-request return errorfile /etc/haproxy/errorfiles/200.http \
    if { path /ping }

http-request return content-type image/x-icon file /var/www/favicon.ico  \
    if { path /favicon.ico }

http-request return status 403 content-type text/plain    \
    lf-string "Access denied. IP %[src] is blacklisted."  \
    if { src -f /etc/haproxy/blacklist.lst }

sc-add-gpc(<idx>,<sc-id>) { <int> | <expr> }

sc-add-gpc(<idx>,<sc-id>) { <int> | <expr> }

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | X | X | X | X

Увеличивает счётчик общего назначения с индексом <idx> в массиве, связанном со счётчиком привязки, заданным в <sc-id>, на целое число <int> или результат вычисления выражения <expr> как целого числа. Целые числа и результаты выражений ограничены беззнаковыми 32-битными значениями. При ошибке действие завершается неудачей без уведомления, а обработка действий продолжается. <idx> — целое число от 0 до 99, а <sc-id> — целое число от 0 до 2. Действие также завершается неудачей без уведомления, если по этому индексу не хранится GPC. Запись таблицы обновляется, даже если значение равно нулю. ‘gpc_rate’ автоматически корректируется, отражая среднюю скорость роста значения gpc.

Это действие применимо только к типам данных ‘gpc’ и ‘gpc_rate’, представляющим массивы (data_types), но не к устаревшим типам данных (data_types) ‘gpc0’, ‘gpc1’, ‘gpc0_rate’ и ‘gpc1_rate’. Эквивалентной функции для устаревших типов данных нет, но если значение всегда равно 1, см. ‘sc-inc-gpc()’, ‘sc-inc-gpc0()’ и ‘sc-inc-gpc1()’. Уменьшать значение также нельзя; однако точные значения можно хранить в метке общего назначения, используя вместо этого ‘sc-set-gpt()’.

Главное назначение этого действия — подсчёт баллов или суммарных объёмов, например оценки опасности исходного IP-адреса, сообщённой сервером или WAF, суммарного количества отправленных на сервер байтов и т. п.

sc-inc-gpc(<idx>,<sc-id>)

sc-inc-gpc(<idx>,<sc-id>)

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | X | X | X | X

Увеличивает счётчик общего назначения с индексом <idx> в массиве, связанном со счётчиком привязки, заданным в <sc-id>. При ошибке действие завершается неудачей без уведомления, а обработка действий продолжается. <idx> — целое число от 0 до 99, а <sc-id> — целое число от 0 до 2. Действие также завершается неудачей без уведомления, если по этому индексу не хранится GPC. Применимо только к типам данных (data_types) в виде массивов ‘gpc’ и ‘gpc_rate’, но не к устаревшим типам данных (data_types) ‘gpc0’, ‘gpc1’, ‘gpc0_rate’ и ‘gpc1_rate’.

sc-inc-gpc0(<sc-id>)

sc-inc-gpc0(<sc-id>)
sc-inc-gpc1(<sc-id>)

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | X | X | X | X

Увеличивает счётчик GPC0 или GPC1 в соответствии со счётчиком привязки, заданным в <sc-id>. При ошибке действие завершается неудачей без уведомления, а обработка действий продолжается.

sc-set-gpt(<idx>,<sc-id>) { <int> | <expr> }

sc-set-gpt(<idx>,<sc-id>) { <int> | <expr> }

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | X | X | X | X

Устанавливает беззнаковую 32-битную метку GPT с индексом <idx> в массиве, связанном со счётчиком привязки, заданным в <sc-id>, в значение <int>/<expr>. Ожидаемый результат — логическое значение.

При ошибке действие завершается неудачей без уведомления, а обработка действий продолжается. <idx> — целое число от 0 до 99, а <sc-id> — целое число от 0 до 2. Действие также завершается неудачей без уведомления, если по этому индексу не хранится GPT.

Это действие применимо только к типу данных ‘gpt’, представляющему массив (data_type), но не к устаревшему типу ‘gpt0’.

sc-set-gpt0(<sc-id>) { <int> | <expr> }

sc-set-gpt0(<sc-id>) { <int> | <expr> }

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | X | X | X | X

Устанавливает беззнаковую 32-битную метку GPT0 в соответствии со счётчиком привязки, заданным в <sc-id>, и значением <int>/<expr>. Ожидаемый результат — логическое значение. При ошибке действие завершается неудачей без уведомления, а обработка действий продолжается. Это действие — псевдоним “sc-set-gpt(0,<sc-id>)”. См. также действие “sc-set-gpt”.

send-retry

send-retry

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft X | - | - | - | - | - | - | -

Принудительно отправляет пакет Retry в ответ на клиентский пакет Initial без токена. Это позволяет проверить адрес клиента до создания любых элементов соединения и начала рукопожатия.

send-spoe-group <engine-name> <group-name>

send-spoe-group <engine-name> <group-name>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | X | X | X | -

Это действие запускает отправку группы сообщений SPOE. Необходимо задать движок SPOE, используемый для отправки сообщений, и отправляемую группу SPOE. Движок SPOE должен ссылаться на существующий фильтр SPOE. Если в строке фильтра SPOE не задано имя движка, необходимо использовать имя агента SPOE.

Аргументы:

<engine-name>  Имя движка SPOE.

<group-name>   Имя группы SPOE, указанное в конфигурации движка.

set-bandwidth-limit <name> [limit {<expr> | <size>}] [period {<expr> | <time>}]

set-bandwidth-limit <name> [limit {<expr> | <size>}] [period {<expr> | <time>}]

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | X | X | X | -

Включает фильтр ограничения пропускной способности <name> в направлении загрузки на сервер или с сервера в зависимости от типа фильтра. Собственные предел и период можно задать тогда и только тогда, когда <name> ссылается на фильтр ограничения пропускной способности отдельного потока. При выполнении правило set-bandwidth-limit сначала сбрасывает все параметры фильтра к значениям по умолчанию и лишь затем включает его. Поэтому, если для одного фильтра выполняется несколько действий “set-bandwidth-limit”, учитывается только последнее. Для одного потока можно включить несколько фильтров ограничения пропускной способности.

Это действие нельзя использовать в секции defaults, поскольку в секциях defaults нельзя определять фильтры ограничения пропускной способности. Кроме того, ограничивается только передача полезной нагрузки HTTP. Заголовки HTTP не учитываются.

Аргументы:

<expr>  Стандартное выражение HAProxy, состоящее из извлечения образца и последующих
        преобразователей. Результат преобразуется в целое число и интерпретируется как размер в
        байтах для параметра "limit" и как длительность в миллисекундах для параметра "period".

<size>  Число в формате размера HAProxy, выраженное в байтах.

<time>  Число в формате времени HAProxy, выраженное в миллисекундах.

Пример:

http-request set-bandwidth-limit global-limit
http-request set-bandwidth-limit my-limit limit 1m period 10s

О настройке фильтра ограничения пропускной способности см. раздел 9.7 .

set-bc-mark { <mark> | <expr> }

set-bc-mark { <mark> | <expr> }

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | - | X | - | -

Устанавливает метку Netfilter/IPFW MARK для соединения с бэкендом, то есть для всех пакетов, отправляемых серверу, в значение <mark> или <expr> на платформах, которые это поддерживают. Это беззнаковое 32-битное значение может сопоставляться средствами netfilter/ipfw и таблицей маршрутизации либо использоваться при наблюдении за пакетами через DTrace. <mark> можно задавать в десятичном или шестнадцатеричном формате с префиксом “0x”. Вместо него можно использовать <expr> — стандартное выражение HAProxy, состоящее из извлечения образца и последующих преобразователей, которое должно возвращать целое число. Это действие может быть полезно для направления определённых пакетов по другому маршруту, например более дешёвому сетевому пути для массовых загрузок. Работает в ядрах Linux 2.6.32 и новее и требует административных привилегий, а также работает в FreeBSD и OpenBSD. Метка устанавливается на всё время существования соединения с бэкендом или сервером: от установления до закрытия.

set-bc-tos { <tos> | <expr> }

set-bc-tos { <tos> | <expr> }

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | - | X | - | -

Устанавливает значение поля TOS или DSCP для соединения с бэкендом, то есть для всех пакетов, отправляемых серверу, в значение <tos> или <expr> на платформах, которые это поддерживают. Это значение представляет все 8 бит поля IP TOS. В DSCP или TOS используются только 6 старших бит, а два младших всегда равны 0. Вместо него можно использовать <expr> — стандартное выражение HAProxy, состоящее из извлечения образца и последующих преобразователей, которое должно возвращать целое число. Действие позволяет влиять на маршрутизацию во внутренних маршрутизаторах на основании информации из запроса. Значение tos устанавливается на всё время существования соединения с бэкендом или сервером: от установления до закрытия.

Дополнительную информацию см. в RFC 2474, 2597, 3260 и 4594.

set-dst <expr>

set-dst <expr>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | - | X | - | -

Устанавливает IP-адрес назначения в значение указанного выражения. Полезно, если прокси перед HAProxy переписывает IP-адрес назначения, но передаёт правильный IP-адрес в заголовке HTTP, либо если необходимо скрыть IP-адрес для защиты конфиденциальности. Для соединения с новым адресом и портом следует использовать ‘0.0.0.0:0’ как адрес сервера в бэкенде.

Аргументы:

<expr>  Стандартное выражение HAProxy, состоящее из извлечения образца и последующих
        преобразователей.

Пример:

http-request set-dst hdr(x-dst)
http-request set-dst dst,ipmask(24)

По возможности set-dst сохраняет исходный порт назначения, если семейство адресов это позволяет; иначе порт назначения устанавливается в 0.

set-dst-port <expr>

set-dst-port <expr>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | - | X | - | -

Устанавливает порт назначения в значение указанного выражения. Для соединения с новым адресом и портом следует использовать ‘0.0.0.0:0’ как адрес сервера в бэкенде.

Аргументы:

<expr>  Стандартное выражение HAProxy, состоящее из извлечения образца и последующих
        преобразователей.

Пример:

http-request set-dst-port hdr(x-port)
http-request set-dst-port int(4000)

По возможности set-dst-port сохраняет исходный адрес назначения, если семейство адресов поддерживает порт; иначе перед перезаписью порта принудительно устанавливает адрес назначения в IPv4 “0.0.0.0”.

set-fc-mark { <mark> | <expr> }

set-fc-mark { <mark> | <expr> }

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | X | X | X | -

Устанавливает метку Netfilter/IPFW MARK для всех пакетов, отправляемых клиенту, в значение <mark> или <expr> на платформах, которые это поддерживают. Это беззнаковое 32-битное значение может сопоставляться средствами netfilter/ipfw и таблицей маршрутизации либо использоваться при наблюдении за пакетами через DTrace. <mark> можно задавать в десятичном или шестнадцатеричном формате с префиксом “0x”. Вместо него можно использовать <expr> — стандартное выражение HAProxy, состоящее из извлечения образца и последующих преобразователей, которое должно возвращать целое число. Это действие может быть полезно для направления определённых пакетов по другому маршруту, например более дешёвому сетевому пути для массовых загрузок. Работает в ядрах Linux 2.6.32 и новее и требует административных привилегий, а также работает в FreeBSD и OpenBSD.

set-fc-tos { <tos | <expr> }

set-fc-tos { <tos | <expr> }

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | X | X | X | -

Устанавливает значение поля TOS или DSCP в пакетах, отправляемых клиенту, в значение <tos> или <expr> на платформах, которые это поддерживают. Это значение представляет все 8 бит поля IP TOS. В DSCP или TOS используются только 6 старших бит, а два младших всегда равны 0. Вместо него можно использовать <expr> — стандартное выражение HAProxy, состоящее из извлечения образца и последующих преобразователей, которое должно возвращать целое число. Действие позволяет влиять на маршрутизацию в пограничных маршрутизаторах на основании информации из запроса.

Дополнительную информацию см. в RFC 2474, 2597, 3260 и 4594.

set-header <name> <fmt>

set-header <name> <fmt>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

Работает так же, как действие “add-header”, но сначала удаляет заголовок, если он существует. Полезно для передачи серверу информации безопасности в заголовке, которым не должны манипулировать внешние пользователи, либо для принудительной установки некоторых заголовков ответа, например “Server”, чтобы скрыть внешнюю информацию. Новое значение вычисляется до удаления, поэтому можно добавить значение к существующему заголовку.

Пример:

http-request set-header X-Haproxy-Current-Date %T
http-request set-header X-SSL                  %[ssl_fc]
http-request set-header X-SSL-Session_ID       %[ssl_fc_session_id,hex]
http-request set-header X-SSL-Client-Verify    %[ssl_c_verify]
http-request set-header X-SSL-Client-DN        %{+Q}[ssl_c_s_dn]
http-request set-header X-SSL-Client-CN        %{+Q}[ssl_c_s_dn(cn)]
http-request set-header X-SSL-Issuer           %{+Q}[ssl_c_i_dn]
http-request set-header X-SSL-Client-NotBefore %{+Q}[ssl_c_notbefore]
http-request set-header X-SSL-Client-NotAfter  %{+Q}[ssl_c_notafter]

set-headers-bin <expr> [ prefix <str> ]

set-headers-bin <expr> [ prefix <str> ]

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

Вариант действия “set-header”, в котором имена и значения заголовков передаются в двоичной строке с кодированием varint. Формат varint описан в извлечении образца “req.hdrs_bin”. Полезно для установки нескольких заголовков сразу, когда их имена заранее неизвестны. Эти заголовки не проверялись парсером HTTP, поэтому могут приводить к отправке некорректных сообщений, а в худших случаях — к атакам типа «контрабанда запросов». Количество вставляемых заголовков также важно: оно ограничено tune.http.maxhdr. Необязательный префикс позволяет устанавливать из кодированной строки только заголовки, начинающиеся с <str>.

Пример:

# This would reset the Accept/UA/Host headers to their initial values
http-request set-var(txn.oldheaders) req.hdrs_bin
http-request del-header Accept
http-request del-header User-Agent
http-request del-header Host
http-request set-headers-bin var(txn.oldheaders)

set-log-level <level>

set-log-level <level>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | X | X | X | X

Изменяет уровень журналирования текущего запроса при выполнении определённого условия. Допустимы 8 уровней syslog (см. ключевое слово “log”) и специальный уровень “silent”, отключающий ведение журнала для этого запроса. Это правило не является завершающим, поэтому действует последнее совпавшее правило. Оно может быть полезно для отключения проверок работоспособности, поступающих от другого оборудования.

set-map(<map-name>) <key fmt> <value fmt>

set-map(<map-name>) <key fmt> <value fmt>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

Добавляет новую запись в таблицу соответствий. <map-name> должен соответствовать формату имён таблиц соответствий и ACL, описанному в 2.7. Имя обновляемой MAP передаётся в круглых скобках. Принимает 2 аргумента: <key fmt>, по правилам пользовательского формата журнала из раздела 8.2.6 , для получения ключа таблицы, и <value fmt>, также по правилам пользовательского формата журнала, для получения содержимого новой записи. Перед вставкой выполняется поиск в таблице, чтобы избежать появления двух или более одинаковых значений. Эквивалентно команде “set map” через сокет статистики, но может запускаться запросом HTTP.

set-mark <mark> (deprecated)

set-mark <mark> (deprecated)

Псевдоним “set-fc-mark”, который следует использовать вместо него.

set-method <fmt>

set-method <fmt>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

Переписывает метод запроса результатом вычисления строки формата <fmt>. Обоснованных причин для этого должно быть очень мало, поскольку такое изменение скорее нарушит работу, чем исправит её.

set-nice <nice>

set-nice <nice>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | X | X | X | -

Устанавливает коэффициент “nice” обрабатываемого запроса или ответа. Он влияет только на соотношение с другими запросами, обрабатываемыми одновременно. Значение по умолчанию — 0, если оно не изменено параметром “nice” в строке “bind”. Допустимый диапазон — -1024..1024. Чем больше значение, тем «уступчивее» запрос; меньшие значения делают запрос важнее других. Это может ускорять некоторые запросы или снижать приоритет неважных запросов. Применение параметра без предварительных экспериментов может вызвать значительное замедление.

set-path <fmt>

set-path <fmt>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

Переписывает путь запроса результатом вычисления строки формата `<fmt>`. Строка запроса,
если она есть, остаётся неизменной. Схема и полномочный компонент перед путём, если они
есть, также остаются неизменными. Если у запроса нет пути ("*"), он заменяется строкой
формата. Это позволяет, например, добавить компонент каталога перед путём. См. также "http-request set-query"
и "http-request set-uri".

Пример:

# prepend the host name before the path
http-request set-path /%[hdr(host)]%[path]

set-pathq <fmt>

set-pathq <fmt>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

Работает так же, как “http-request set-path”, но также переписывает строку запроса. Позволяет удалить строку запроса вместе с вопросительным знаком, что невозможно с помощью “http-request set-query”.

set-priority-class <expr>

set-priority-class <expr>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | - | X | - | -

Устанавливает класс приоритета текущего запроса в очереди. Значение должно быть выражением извлечения образца, преобразуемым в целое число в диапазоне -2047..2047. Результаты за пределами диапазона ограничиваются его границами. Класс приоритета определяет порядок обработки запросов в очереди. Меньшие значения имеют более высокий приоритет.

set-priority-offset <expr>

set-priority-offset <expr>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | - | X | - | -

Устанавливает смещение временной метки приоритета текущего запроса в очереди. Значение должно быть выражением извлечения образца, преобразуемым в целое число в диапазоне -524287..524287. Результаты за пределами диапазона ограничиваются его границами. При постановке в очередь запросы сначала упорядочиваются по классу приоритета, затем по текущей временной метке, скорректированной на заданное смещение в миллисекундах. Меньшие значения имеют более высокий приоритет. Результирующая временная метка отслеживается с точностью, достаточной лишь для 524,287ms (8m44s287ms). Если запрос остаётся в очереди так долго, что скорректированная временная метка превышает это значение, он ошибочно определяется как имеющий наивысший приоритет. Поэтому важно задать “timeout queue” так, чтобы его значение в сочетании со смещением не превышало этот предел.

set-query <fmt>

set-query <fmt>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

Переписывает строку запроса после первого вопросительного знака ("?") результатом вычисления строки формата <fmt>. Часть перед вопросительным знаком остаётся неизменной. Если запрос не содержит вопросительного знака, а новое значение не пусто, в конце URI добавляется вопросительный знак, за которым следует новое значение. Если вопросительный знак уже был, он никогда не удаляется, даже при пустом значении. Это позволяет добавлять и удалять параметры строки запроса.

См. также “http-request set-query” и “http-request set-uri”.

Пример:

# replace "%3D" with "=" in the query string
http-request set-query %[query,regsub(%3D,=,g)]

set-retries <int> | <epxr>

set-retries <int> | <epxr>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | - | X | - | -

Переопределяет указанное значение “retries” только для текущего потока. Можно задать целое число в диапазоне [0, 100] либо выражение, которое должно вернуть целое число в диапазоне [0, 100].

Это действие имеет смысл только на стороне бэкенда, поэтому правило доступно лишь прокси с возможностями бэкенда. В секциях “defaults” оно также запрещено. Для слушателя действие проверяется в контексте фронтенда, поэтому значение retries сохраняется только тогда, когда поток не направляется в другой бэкенд, например правилом use-backend. Иначе заранее задаётся значение retries по умолчанию выбранного бэкенда.

Пример:

tcp-request content set-retries 3
http-request set-retries var(txn.retries)

set-src <expr>

set-src <expr>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | - | X | - | -

Задаёт исходный адрес IP равным значению указанного выражения. Это удобно, когда прокси перед HAProxy подменяет исходный IP, но передаёт правильный IP в заголовке HTTP, либо когда исходный IP требуется скрыть для защиты конфиденциальности. Все последующие вызовы извлечения “src” возвращают это значение (см. пример).

Аргументы:

<expr>  Стандартное выражение HAProxy, состоящее из извлечения образца и последующих
        преобразователей.

См. также “option forwardfor”.

Пример:

http-request set-src hdr(x-forwarded-for)
http-request set-src src,ipmask(24)

# After the masking this will track connections
# based on the IP address with the last byte zeroed out.
http-request track-sc0 src

По возможности set-src сохраняет исходный порт, если семейство адресов это допускает; иначе исходный порт устанавливается равным 0.

set-src-port <expr>

set-src-port <expr>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | - | X | - | -

Задаёт исходный порт равным значению указанного выражения.

Аргументы:

<expr>  Стандартное выражение HAProxy, состоящее из извлечения образца и последующих
        преобразователей.

Пример:

http-request set-src-port hdr(x-port)
http-request set-src-port int(4000)

По возможности set-src-port сохраняет исходный адрес, если семейство адресов поддерживает порт; иначе перед изменением порта принудительно задаёт исходный адрес IPv4 “0.0.0.0”.

set-status <status> [reason <str>]

set-status <status> [reason <str>]

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | - | X | X

Заменяет код состояния ответа значением <status>, которое должно быть целым числом от 100 до 999. Необязательный <str> задаёт собственный текст причины; иначе используется причина по умолчанию для указанного кода. Строка причины существует только в HTTP/1.x и игнорируется другими версиями протокола.

Пример:

# return "431 Request Header Fields Too Large"
http-response set-status 431
# return "503 Slow Down", custom reason
http-response set-status 503 reason "Slow Down".

set-timeout { client | connect | queue | server | tarpit | tunnel } { <timeout> | <expr> }

set-timeout { client | connect | queue | server | tarpit | tunnel } { <timeout> | <expr> }

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | -

Переопределяет указанный тайм-аут “client”, “connect”, “queue”, “server”, “tarpit” или “tunnel” только для текущего потока. Изменение одного тайм-аута не влияет на остальные, даже если они наследуются друг от друга при разборе конфигурации (см. последний пример). Тайм-аут можно задать в миллисекундах или другой единице, добавив её суффикс к числу, как описано в начале документа. Можно также указать выражение, которое должно возвращать число, трактуемое как тайм-аут в миллисекундах.

Тайм-ауты connect, queue, server и tunnel имеют смысл только на стороне бэкенда, поэтому это правило доступно лишь прокси с возможностями бэкенда. Аналогично тайм-аут client имеет смысл только на стороне фронтенда. Тайм-аут tarpit доступен на обеих сторонах. Для ожидаемого результата тайм-аут должен быть ненулевым. Для слушателя действие проверяется в контексте фронтенда, поэтому собственные тайм-ауты стороны бэкенда сохраняются только тогда, когда поток не направляется в другой бэкенд, например правилом use-backend. Иначе заранее задаются значения по умолчанию выбранного бэкенда.

Пример:

http-request set-timeout tunnel 5s
http-request set-timeout server req.hdr(host),map_int(host.lst)

Пример:

http-response set-timeout tunnel 5s
http-response set-timeout server res.hdr(X-Refresh-Seconds),mul(1000)

Пример:

defaults
  # This will set both tarpit and queue timeout to 5s as they are not
  # defined
  timeout connect 5s
  timeout client 30s
  timeout server 30s

listen foo
  # This will only change the connect timeout to 10s without affecting
  # queue or tarpit timeouts
  http-request set-timeout connect 10s

set-tos <tos> (deprecated)

set-tos <tos> (deprecated)

Это псевдоним “set-fc-tos” (следует использовать исходное действие).

set-uri <fmt>

set-uri <fmt>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

Изменяет URI запроса на результат вычисления строки формата <fmt>. Схема, компонент authority, путь и строка запроса заменяются одновременно. Это позволяет менять имена хостов перед прокси или выполнять сложные изменения URI, например переносить части между путём и строкой запроса. Абсолютный URI передаётся серверам HTTP/1.1 без изменений. Если такое поведение нежелательно, следует задавать хост, путь и/или строку запроса отдельно. См. также “http-request set-path” и “http-request set-query”.

set-var(<var-name>[,<cond>...]) <expr>

set-var(<var-name>[,<cond>...]) <expr>
set-var-fmt(<var-name>[,<cond>...]) <fmt>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | X | X | X | X

Задаёт содержимое переменной. Переменная объявляется непосредственно в этом правиле.

Аргументы:

<var-name>   Имя переменной. Задавать переменную родительского потока нельзя. Подробнее о
             переменных см. раздел 2.8.

 <cond>      Набор условий, которые должны быть истинны одновременно, чтобы переменная была
             задана (например, "ifnotempty", "ifgt" и т. д.). Полный список условий приведён в
             описании преобразователя set-var.

 <expr>      Стандартное выражение HAProxy, состоящее из извлечения образца и следующих за ним
             преобразователей.

 <fmt>       Значение, заданное по правилам пользовательского формата журнала (см.
             «Пользовательский формат журнала» в разделе 8.2.6).

В правилах HTTP допустимы все области видимости. В наборах правил без доступа к содержимому, например “tcp-request connection” и “tcp-request session”, допустимы только “proc” и “sess”.

Пример:

http-request set-var(req.my_var) req.fhdr(user-agent),lower
http-request set-var-fmt(txn.from) %[src]:%[src_port]

silent-drop [ rst-ttl <ttl> ]

silent-drop [ rst-ttl <ttl> ]

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | X | X | X | -

Прекращает проверку правил и резко удаляет соединение на стороне клиента способом, зависящим от системы и направленным на то, чтобы клиент не получил уведомления. Без аргумента rst-ttl с помощью TCP_REPAIR предпринимается попытка не отправлять клиенту пакеты FIN и RST. Если это не удаётся, главным образом из-за нехватки привилегий, отправляется пакет RST с TTL 1.

Клиент по-прежнему видит установленное соединение, хотя у HAProxy его уже нет, что экономит ресурсы. Однако оборудование с отслеживанием состояния между HAProxy и клиентом — межсетевые экраны, прокси и балансировщики нагрузки — также сохраняет установленное соединение в таблицах сеансов.

Необязательный rst-ttl меняет поведение: TCP_REPAIR не используется, а отправляется пакет RST с настраиваемым TTL. При разумном значении пакет проходит через локальную инфраструктуру, удаляя соединение из межсетевых экранов и других систем, но исчезает, не достигнув клиента. Последующие пакеты клиента отбрасываются уже входным оборудованием. Такие локальные RST защищают локальные ресурсы, но не ресурсы клиента. Это нельзя использовать без полного понимания последствий.

strict-mode { on | off }

strict-mode { on | off }

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | X

Включает или отключает строгий режим изменения для последующих правил. Не влияет на объявленные ранее правила и применим только к правилам изменения запросов. В строгом режиме любая неудача изменения вызывает внутреннюю ошибку; иначе такие ошибки молча игнорируются. Режим позволяет сделать некоторые изменения необязательными, а остальные — обязательными для продолжения обработки запроса.

По умолчанию строгий режим изменения включён. Его значение также сбрасывается после завершения проверки набора правил. Например, если изменить режим на фронтенде, при начале проверки правил бэкенда HAProxy восстанавливает режим по умолчанию.

switch-mode http [ proto <name> ]

switch-mode http [ proto <name> ]

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | - | - | - | -

Выполняет переход соединения к другому протоколу. Пока поддерживаются только переходы к HTTP. Протокол указывать необязательно. Действие доступно только прокси с возможностями фронтенда. Переход выполняется немедленно; следующие правила “tcp-request content” не проверяются. Этот способ следует предпочитать неявному переходу на основе режима бэкенда. Он позволяет задавать директивы HTTP во фронтенде без предупреждений; они проверяются условно, если переход к HTTP выполнен. Однако по-прежнему необходимо выбрать бэкенд HTTP. Направлять соединение HTTP — с переходом к протоколу или без него — на сервер TCP не поддерживается.

Подробнее о переходах к HTTP см. раздел 4 о прокси.

tarpit [ { status | deny_status } <code>] [content-type <type>]

tarpit [ { status | deny_status } <code>] [content-type <type>]
       [ { default-errorfiles | errorfile <file> | errorfiles <name> |
       file `<file>` | lf-file `<file>` | string `<str>` | lf-string `<fmt>` } ]
   [ hdr `<name>` `<fmt>` ]*

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

Прекращает проверку правил и немедленно блокирует запрос, не отвечая в течение “timeout tarpit” либо “timeout connect”, если первый не задан. После задержки, если клиент ещё подключён, возвращается ответ, чтобы клиент не заподозрил попадание в ловушку соединений (tarpit). В журнале указываются флаги “PT”. Правило tarpit замедляет роботов во время атаки, если они ограничены числом одновременных запросов. Оно может быть очень эффективно против примитивных роботов и значительно снижает нагрузку на межсетевые экраны по сравнению с “deny”. Но против «правильно» разработанных роботов оно может ухудшить ситуацию, заставляя HAProxy и входной межсетевой экран поддерживать огромное число одновременных соединений. По умолчанию возвращается ошибка HTTP 500. Ответ можно настроить тем же синтаксисом, что и правила “http-request return”; подробности см. в “http-request return”.

Для совместимости при отсутствии аргументов либо только при “deny_status” подразумевается аргумент “default-errorfiles”. Поэтому “http-request tarpit [deny_status <status>]” — псевдоним “http-request tarpit [status <status>] default-errorfiles”. Остальные правила “http-request” не проверяются. См. также “http-request return” и “http-request silent-drop”.

track-sc0 <key> [table <table>]

track-sc0 <key> [table <table>]
track-sc1 <key> [table <table>]
track-sc2 <key> [table <table>]

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | - | X | X | -

Включает отслеживание счётчиков привязки для текущего запроса. Эти правила не прекращают проверку и не меняют действие по умолчанию. Число счётчиков, одновременно отслеживаемых для одного соединения, задаётся глобальным “tune.stick-counters”. По умолчанию используется MAX_SESS_STKCTR, если он задан при сборке (выводится в haproxy -vv); его значение по умолчанию — 3, поэтому номер track-sc лежит между 0 и (tune.stick-counters-1). Первое выполненное правило “track-sc0” включает отслеживание счётчиков указанной таблицы как первого набора. Первое выполненное правило “track-sc1” включает отслеживание счётчиков указанной таблицы как второго набора. Первое выполненное правило “track-sc2” включает отслеживание счётчиков указанной таблицы как третьего набора. Рекомендуется использовать первый набор для счётчиков фронтенда, а второй для счётчиков бэкенда. Это лишь рекомендация: все наборы можно использовать везде.

Аргументы:

<key>   Обязательный параметр — правило с выражением извлечения образца, описанное в разделе
        7.3. Задаёт элементы входящего соединения, запроса или ответа, которые
        анализируются, извлекаются, объединяются и используются для выбора записи таблицы, чьи
        счётчики обновляются.

<table> Необязательная таблица вместо таблицы по умолчанию — stick-table, объявленной в текущем
        прокси. Все сопоставления ключа и обновления счётчиков выполняются в этой таблице до
        конца сеанса.

После выполнения правила “track-sc*” ключ ищется в таблице; если его нет, для него выделяется запись. Указатель на запись сохраняется на всё время жизни сеанса. Её счётчики обновляются как можно чаще: при каждом обновлении счётчиков сеанса и обязательно при его завершении. Счётчики обновляются только для событий после начала отслеживания. Исключение — счётчики соединений и запросов: они обновляются обязательно, чтобы отражать полезную информацию.

Если запись отслеживает счётчики одновременных соединений, одно соединение учитывается всё время отслеживания записи, и в этот период срок её действия не истекает. Отслеживание счётчиков также быстрее простой проверки ключей: для всех проверок ACL, использующих запись, выполняется только один поиск в таблице.

unset-var(<var-name>)

unset-var(<var-name>)

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | X | X | X | X | X | X | X

Удаляет переменную. Подробнее о <var-name> см. действие “set-var”.

Пример:

http-request unset-var(req.my_var)

use-service <service-name>

use-service <service-name>

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | - | X | - | -

Запускает настроенную службу TCP или HTTP, отвечающую на запрос, в зависимости от набора правил. Правило завершающее: остальные правила того же набора не проверяются.

Служба может отправить любой допустимый ответ либо немедленно закрыть соединение, не отвечая. Для служб HTTP допустимым является корректный ответ HTTP. Помимо встроенных служб, например экспортера Prometheus для HTTP, можно писать собственные службы TCP и HTTP на Lua.

Аргументы:

<service-name>  Обязательный параметр — вызываемая служба

Пример:

http-request use-service prometheus-exporter if { path /metrics }

wait-for-body time <time> [ at-least <bytes> ] [use-large-buffer]

wait-for-body time <time> [ at-least <bytes> ] [use-large-buffer]

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | X | -

Задерживает обработку запроса или ответа до выполнения одного из следующих условий:

  • Получено всё тело запроса; обработка продолжается обычным образом.
  • Получено <bytes> байтов, если указан аргумент “at-least”, а <bytes> не равен нулю; обработка продолжается обычным образом.
  • Буфер запроса заполнен; обработка продолжается обычным образом. Размер буфера задаётся параметром “tune.bufsize”.
  • Запрос ожидал больше <time> миллисекунд. В этом случае HAProxy отвечает клиенту ошибкой 408 “Request Timeout” и прекращает обработку запроса. Если раньше выполнено любое другое условие, этот тайм-аут не срабатывает, даже если получено ещё не всё тело.

Параметр “use-large-buffer” позволяет выделить большой буфер, если обычного недостаточно для тела сообщения. Для его использования должен быть задан глобальный параметр “tune.bufsize.large”.

Это действие можно использовать вместо “option http-buffer-request”.

Аргументы:

<time>    Обязательный параметр — максимальное время ожидания тела. Использует формат времени
          HAProxy и выражается в миллисекундах.

<bytes>   Необязательный параметр — минимальный объём полезной нагрузки, после получения
          которого ожидание прекращается. Использует формат размера HAProxy и выражается в
          байтах. Значение 0 (по умолчанию) означает отсутствие ограничения.

Пример:

http-request wait-for-body time 1s at-least 1k if METH_POST

См. также: “option http-buffer-request” и “tune.bufsize.large”

wait-for-handshake

wait-for-handshake

Применимо в: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | - | - | X | - | -

Задерживает обработку запроса до завершения согласования SSL. Это особенно удобно, чтобы откладывать обработку ранних данных, пока не подтверждена их корректность.

14 - 5. Параметры bind и server

Параметры слушателей, server, default-server и разрешения имён DNS

Ключевые слова “bind”, “server” и “default-server” поддерживают ряд настроек, зависящих от параметров сборки и системы, в которой собран HAProxy. Обычно каждая настройка состоит из одного слова, иногда со значением, и записывается в той же строке “bind” или “server”. Все эти параметры описаны в этом разделе.

5.1. Параметры bind

Ключевое слово “bind” поддерживает ряд настроек, которые передаются аргументами в той же строке. Их порядок не имеет значения, если они указаны после адреса привязки. Все параметры необязательны. Некоторые состоят из одного слова (логические параметры), другие требуют значения. В последнем случае значение должно следовать непосредственно за именем настройки.

Ниже перечислены поддерживаемые настройки.

accept-netscaler-cip <magic number>

accept-netscaler-cip <magic number>

Требует использования протокола NetScaler Client IP insertion для любого соединения, принятого любым сокетом TCP, объявленным в той же строке. Протокол NetScaler Client IP insertion задаёт адреса уровня 3/4 входящего соединения, которые используются везде, где требуется адрес, за единственным исключением правил “tcp-request connection”: они видят только реальный адрес соединения. В журналах отражаются адреса, указанные в протоколе, если только он не нарушен; при нарушении используется реальный адрес. Это ключевое слово совместно с поддержкой внешних компонентов может эффективно и надёжно заменять механизм X-Forwarded-For, который не всегда надёжен и даже не всегда применим. Для более точного определения клиентов, которым разрешено использовать протокол, см. также “tcp-request connection expect-netscaler-cip”.

accept-proxy

accept-proxy

Требует использования протокола PROXY для любого соединения, принятого любым сокетом, объявленным в той же строке. Версии 1 и 2 протокола PROXY поддерживаются и корректно определяются. Протокол PROXY задаёт адреса уровня 3/4 входящего соединения, которые используются везде, где требуется адрес, за единственным исключением правил “tcp-request connection”: они видят только реальный адрес соединения. В журналах отражаются адреса, указанные в протоколе, если только он не нарушен; при нарушении используется реальный адрес. Эта директива совместно с поддержкой внешних компонентов может эффективно и надёжно заменять механизм X-Forwarded-For, который не всегда надёжен и даже не всегда применим. Для более точного определения клиентов, которым разрешено использовать протокол, см. также “tcp-request connection expect-proxy”.

allow-0rtt

allow-0rtt

Разрешает приём ранних данных при использовании TLSv1.3. По соображениям безопасности эта возможность по умолчанию отключена. Она уязвима к атакам повторного воспроизведения, поэтому её следует разрешать только для запросов, которые безопасно повторять, то есть идемпотентных запросов. Для любого запроса, небезопасного при использовании ранних данных, можно применять действие “wait-for-handshake”. Для QUIC режим 0rtt поддерживается с QuicTLS, OpenSSL >= 3.5.2 и AWS-LC. Для TCP/TLS режим 0rtt поддерживается только с OpenSSL и требует передачи ALPN клиентом; иначе ранние данные не рассматриваются до выполнения рукопожатия.

alpn <protocols>

alpn <protocols>

Включает расширение TLS ALPN и объявляет через него указанный список поддерживаемых протоколов. Имена протоколов разделяются запятыми, например “http/1.1,http/1.0” (без кавычек). Библиотека SSL должна быть собрана с поддержкой расширений TLS (проверяется командой haproxy -vv). Расширение ALPN заменяет первоначальное расширение NPN. На уровне протокола ALPN требуется для включения HTTP/2 на фронтенде HTTPS и HTTP/3 на фронтенде QUIC. Однако если на таком фронтенде не задан ни один из параметров “npn”, “alpn” и “no-alpn”, по умолчанию используется “h2,http/1.1” для обычного фронтенда HTTPS и “h3” для фронтенда QUIC. Версии OpenSSL до 1.0.2 не поддерживали ALPN и поддерживали лишь устаревшее теперь расширение NPN. На момент написания большинство браузеров всё ещё поддерживает и ALPN, и NPN для HTTP/2, поэтому переход на NPN может ещё некоторое время работать. Но ALPN необходимо использовать всякий раз, когда это возможно. Протоколы, отсутствующие в объявленном списке, не согласовываются. Например, так можно принимать только соединения HTTP/2:

bind :443 ssl crt pub.pem alpn h2  # explicitly disable HTTP/1.1

В качестве ALPN QUIC поддерживает только h3 и hq-interop. h3 предназначен для HTTP/3, а hq-interop — для http/0.9 и QUIC interop runner (см. https://interop.seemann.io ). Каждая директива “alpn” заменяет предыдущую. Для удаления списка служит “no-alpn”.

Некоторые старые браузеры, например Firefox 88, испытывали проблемы с WebSocket через H2. В такой конфигурации может потребоваться явно отключить HTTP/2 в строке “alpn”, задав “http/1.1” или “no-alpn”, либо глобально включить “h2-workaround-bogus-websocket-clients”.

backlog <backlog>

backlog <backlog>

Задаёт размер очереди ожидающих соединений сокета. Если параметр не указан или равен 0, используется backlog фронтенда, который обычно по умолчанию равен maxconn.

ca-file <cafile>

ca-file <cafile>

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он задаёт файл PEM с сертификатами CA для проверки сертификата клиента. Можно загрузить каталог с несколькими CA: HAProxy попытается загрузить все файлы с расширениями “.pem”, “.crt”, “.cer” и “.crl” в этом каталоге. Файлы, имена которых начинаются с точки, игнорируются.

Предупреждение: вместо cafile можно указать “@system-ca”, чтобы использовать доверенные CA системы, как в директиве server. Но этого нельзя делать, не понимая последствий. При такой настройке bind принимает любой сертификат клиента, выданный одним из CA системы, что крайне небезопасно.

ca-ignore-err [all|<errorID>,...]

ca-ignore-err [all|<errorID>,...]

Этот параметр доступен только при сборке с поддержкой OpenSSL. Задаёт через запятую список идентификаторов ошибок, которые игнорируются при проверке на глубине > 0. Можно использовать числовой идентификатор или имя константы (X509_V_ERR) из документации OpenSSL: https://www.openssl.org/docs/manmaster/man3/X509_STORE_CTX_get_error.html#ERROR-CODES Рекомендуется имя константы, поскольку числовое значение может измениться в новой версии OpenSSL. Значение ‘all’ позволяет игнорировать все ошибки. Если ошибка игнорируется, рукопожатие SSL не прерывается.

ca-sign-file <cafile>

ca-sign-file <cafile>

Этот параметр доступен только тогда, когда в HAProxy включена поддержка OpenSSL. Он обозначает файл PEM, содержащий как сертификат доверенного центра (CA), так и приватный ключ этого центра, используемый для создания и подписи сертификатов серверов. Этот параметр является обязательным при включении динамической генерации сертификатов. См. ‘generate-certificates’ для подробностей.

ca-sign-pass <passphrase>

ca-sign-pass <passphrase>

Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Это пароль от приватного ключа CA. Параметр является необязательным и используется только при включении динамической генерации сертификатов. См. ‘generate-certificates’ для подробностей.

ca-verify-file <cafile>

ca-verify-file <cafile>

Этот параметр задаёт файл PEM с сертификатами CA для проверки сертификата клиента. Имена этих CA не должны включаться в список имён CA, отправляемый в сообщении server hello. Обычно в “ca-file” необходимо указать промежуточные сертификаты, а в “ca-verify-file” — сертификаты, завершающие цепочку, например корневого CA.

cc <algo>

cc <algo>

Этот параметр доступен только на системах, которые определяют TCP_CONGESTION, и был протестирован на Linux и FreeBSD. Он принимает имя алгоритма управления перегрузкой TCP и настраивает слушатель на использование этого алгоритма для всех соединений, принимаемых через данный слушатель. Типичные имена включают “reno”, “cubic” и зависят от операционной системы. На некоторых системах для настройки определённых алгоритмов могут потребоваться специальные разрешения. На Linux список доступных алгоритмов можно найти в sysctl “net.ipv4.tcp_available_congestion_control”, а список разрешённых без привилегий — в “net.ipv4.tcp_allowed_congestion_control”. Для доступа к алгоритмам, требующим дополнительных разрешений, может потребоваться capability “cap_net_admin” (см. “setcap” в глобальной секции). В случае неудачи при настройке конкретного алгоритма управления перегрузкой используется значение по умолчанию, и выводится предупреждение, сообщающее об ошибке. См. также: ключевое слово сервера “cc” (раздел 5.2 ). Пример:

frontend public
    bind :443 cc bbr   # use the BBR algorithm for high bandwidths

ciphers <ciphers>

ciphers <ciphers>

Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он задаёт строку, описывающую список наборов шифров (“cipher suite”), согласуемых при рукопожатии SSL/TLS вплоть до TLSv1.2. Формат строки определён в документации “man 1 ciphers” от OpenSSL. Для дополнительной информации и рекомендаций см. например, (https://wiki.mozilla.org/Security/Server_Side_TLS ) и (https://mozilla.github.io/server-side-tls/ssl-config-generator/ ). Для настройки алгоритмов шифрования в TLSv1.3, см. ключевое слово “ciphersuites”.

ciphersuites <ciphersuites>

ciphersuites <ciphersuites>

Этот параметр доступен только при сборке HAProxy с поддержкой OpenSSL версии 1.1.1 или новее. Он задаёт строку со списком наборов шифров (“cipher suite”), согласуемых при рукопожатии TLSv1.3. Формат строки описан в разделе “ciphersuites” страницы “man 1 ciphers” руководства OpenSSL. Для настройки шифров TLSv1.2 и более ранних версий служит ключевое слово “ciphers”. Этот параметр может принимать и наборы шифров TLSv1.2, однако такое поведение не документировано и не рекомендуется, поскольку может быть непоследовательным или содержать ошибки. По умолчанию в OpenSSL используются наборы шифров TLSv1.3: “TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256”

TLSv1.3 поддерживает только 5 наборов шифров:

  • TLS_AES_128_GCM_SHA256
  • TLS_AES_256_GCM_SHA384
  • TLS_CHACHA20_POLY1305_SHA256
  • TLS_AES_128_CCM_SHA256
  • TLS_AES_128_CCM_8_SHA256

Пример:

ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256
ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256

client-sigalgs <sigalgs>

client-sigalgs <sigalgs>

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он задаёт строку со списком согласуемых алгоритмов подписи для аутентификации клиента. Формат строки описан на странице “man 3 SSL_CTX_set1_client_sigalgs” руководства OpenSSL. Не рекомендуется использовать параметр без конкретной необходимости.

crl-file <crlfile>

crl-file <crlfile>

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он задаёт файл PEM со списком отзыва сертификатов для проверки сертификата клиента. Необходимо предоставить список отзыва для каждого сертификата в цепочке центра сертификации.

crt <cert>

crt <cert>

Этот параметр доступен только при сборке с поддержкой OpenSSL.

HAProxy использует кеш: файлы загружаются в хранилище сертификатов только один раз, а каждое последующее ключевое слово “crt” использует кешированную версию. Если сертификат объявлен в “crt-store”, хранилище заполняется оттуда, без попыток загрузить дополнительные файлы по их расширениям.

Задаёт файл PEM с необходимыми сертификатами и связанными с ними закрытыми ключами. Его можно создать, объединив несколько файлов PEM (например, cat cert.pem key.pem > combined.pem). Если CA требует промежуточный сертификат, его также можно добавить в этот файл. Промежуточный сертификат можно предоставить для совместного использования из каталога с помощью директивы “issuers-chain-path”.

Если файл не содержит приватного ключа, HAProxy попытается загрузить ключ по тому же пути, дополненному суффиксом “.key”.

Если в используемом OpenSSL поддерживается Diffie-Hellman, параметры, присутствующие в этом файле, загружаются.

Если вместо файла PEM используется имя каталога, то все файлы, найденные в этом каталоге, будут загружены в алфавитном порядке, за исключением тех, названия которых заканчиваются на ‘.key’, ‘.issuer’, ‘.ocsp’ или ‘.sctl’ (зарезервированные расширения). Файлы, начинающиеся с точки, также игнорируются. Данная директива может быть указана несколько раз для загрузки сертификатов из нескольких файлов или каталогов. Сертификаты будут представлены клиентам, предоставляющим действительное поле TLS Server Name Indication, соответствующее одному из их CN или альтернативных имён субъекта. Поддерживаются шаблоны, где символ ‘*’ используется вместо первого компонента имени хоста (например, *.example.org соответствует www.example.org , но не www.sub.example.org ). Если используется пустой каталог, HAProxy не запустится, если не используется ключевое слово “strict-sni”.

Если клиент не передал SNI, библиотека SSL не поддерживает расширения TLS или имя узла в SNI не соответствует ни одному сертификату, предоставляется первый загруженный сертификат. Поэтому при загрузке из каталога настоятельно рекомендуется сначала загрузить сертификат по умолчанию как отдельный файл либо обеспечить его первое место в каталоге. Для выбора нескольких сертификатов по умолчанию (1 rsa и 1 ecdsa) есть 3 варианта:

  • Многосертификатный пакет может быть настроен как первый сертификат (crt foobar.pem в конфигурации, где существующие файлы являются foobar.pem.ecdsa и foobar.pem.rsa).
  • Или фильтр ‘*’ для каждого сертификата в строке crt-list.
  • Можно использовать ключевое слово ‘default-crt’.

Один и тот же сертификат можно загрузить несколько раз без побочных эффектов.

Некоторые CA (например, GoDaddy) предлагают выпадающий список типов серверов, в котором HAProxy не включён при получении сертификата. Если такое происходит, убедитесь, что выбран тип веб-сервера, который по мнению CA требует промежуточного CA (для GoDaddy выбор Apache Tomcat обеспечит правильный пакет, в то время как многие другие, например nginx, приводят к неправильному пакету, который не будет работать для некоторых клиентов).

Для каждого файла PEM HAProxy проверяет наличие файла по тому же пути, дополняемого суффиксом “.ocsp”. Если такой файл найден, поддержка расширения запроса статуса сертификата TLS (также известного как «OCSP stapling») включается автоматически. Содержимое этого файла является необязательным. Если оно не пустое, оно должно содержать действительный ответ OCSP в формате DER. Для того чтобы ответ OCSP был действительным, он должен соответствовать следующим правилам: он должен указывать хороший статус, должен быть единственным ответом на сертификат файла PEM и должен быть действительным в момент добавления. Если эти правила не соблюдены, ответ OCSP игнорируется и выдается предупреждение. Для определения того, к какому сертификату относится ответ OCSP, необходим сертификат издателя. Если сертификат издателя не найден в файле PEM, он будет загружен из файла по тому же пути, что и файл PEM, дополняемого суффиксом “.issuer”, если такой файл существует, иначе будет выдано сообщение об ошибке.

Для каждого файла PEM HAProxy также проверяет наличие файла по тому же пути, дополняемого суффиксом “.sctl”. Если такой файл найден, поддержка расширения прозрачности сертификатов (RFC6962) TLS включается. Файл должен содержать действительный список подписанных временных меток сертификата, как описано в RFC. Файл анализируется для проверки базовой синтаксической корректности, но подписи не проверяются.

В некоторых случаях желательно поддерживать несколько типов ключей, например RSA и ECDSA, в наборах шифров, предлагаемых клиентам. Тогда клиенты с поддержкой сертификатов EC могут использовать шифры EC, а поддержка старых клиентов, работающих только с RSA, сохраняется.

Для этого требуется OpenSSL 1.1.1. Такое поведение можно настроить, указав по одной записи crt на каждый тип сертификата либо настроив «пакет сертификатов», как требовалось до HAProxy 1.8. См. “ssl-load-extra-files”.

crt-ignore-err <errors>

crt-ignore-err <errors>

Этот параметр доступен только при сборке с поддержкой OpenSSL. Задаёт через запятую список идентификаторов ошибок, которые игнорируются при проверке на глубине == 0. Можно использовать числовой идентификатор или имя константы (X509_V_ERR) из документации OpenSSL: https://www.openssl.org/docs/manmaster/man3/X509_STORE_CTX_get_error.html#ERROR-CODES Рекомендуется имя константы, поскольку числовое значение может измениться в новой версии OpenSSL. Значение ‘all’ позволяет игнорировать все ошибки. Если ошибка игнорируется, рукопожатие SSL не прерывается.

crt-list <file>

crt-list <file>

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он задаёт список файлов PEM, для каждого сертификата в котором можно указать конфигурацию ssl и фильтр SNI. Каждая строка имеет следующий формат:

<crtfile> [\[<sslbindconf> ...\]] [[!]<snifilter> ...]

Пустые строки, а также строки, начинающиеся с символа решётки (’#’), будут игнорироваться.

crt-list можно изменять динамически через сокет статистики. (См. “add ssl crt-list”, “del ssl crt-list”, “show ssl crt-list” в руководстве по управлению).

Обычно crt-list — отдельный файл, однако каталог, загруженный директивой “crt”, также представляется внутри как crt-list. Директива “ssl-f-use” во фронтенде тоже объявляет связанный с ним crt-list.

crtfile:

Имя файла сертификата либо идентификатор, если сертификат уже объявлен
в другом месте (например, через CLI или в crt-store с псевдонимом).

Один и тот же <crtfile> можно использовать в нескольких строках
с разными параметрами и фильтрами.

crt-list поддерживает пакеты из нескольких сертификатов
(см. "ssl-load-extra-files"), если в <crtfile> указано только базовое
имя. При загрузке файла HAProxy дублирует строку crt-list внутри,
добавляя расширение алгоритма (.rsa, .ecdsa, .dsa).

sslbindconf:

 <sslbindconf> поддерживает следующие ключевые слова строки bind
 (см. раздел 5.1. Параметры bind):

 - allow-0rtt
 - alpn
 - ca-file
 - ca-verify-file
 - ciphers
 - ciphersuites
 - client-sigalgs
 - crl-file
 - curves
 - ecdhe
 - no-alpn
 - no-ca-names
 - npn
 - sigalgs
 - ssl-min-ver
 - ssl-max-ver
 - verify

 <sslbindconf> также поддерживает следующие ключевые слова директивы
 load в crt-store (см. раздел 12.7.1. Параметры load):

 - crt
 - key
 - ocsp
 - issuer
 - sctl
 - ocsp-update

В <sslbindconf> наследуются параметры строки bind. Если они не заданы,
наследуются параметры по умолчанию. Параметры, указанные
в <sslbindconf>, переопределяют унаследованные настройки.

snifilter:

Если в строке crt-list указан <snifilter>, при рукопожатии сертификат
из этой строки выбирается по <snifilter>, а CN и SAN не используются.

<snifilter> — список записей, разделённых пробелами. Записи могут быть
доменами или шаблонами DNS с подстановочным знаком: одной звёздочкой
в начале. Домен можно исключить из шаблона отрицательным фильтром,
указав '!' перед отдельным доменом. Знак ! перед * игнорируется.
Отрицательные фильтры без шаблона в той же строке также не поддерживаются.
Специальная запись '*' задаёт сертификаты по умолчанию, используемые,
если ни один домен не совпал.

Сертификаты предоставляются клиентам с действительным полем TLS
Server Name Indication, которое совпало с одним из фильтров SNI либо
с CN и SAN сертификата <crtfile>. Алгоритм сначала ищет положительную
запись домена в списке, затем, если она не найдена, — шаблон.
При совпадении с шаблоном HAProxy проверяет отрицательный фильтр
в той же строке и при необходимости отменяет совпадение. При наличии
нескольких алгоритмов ключей (RSA,ECDSA,DSA) HAProxy пытается найти
по одному сертификату каждого типа и выбирает подходящий в зависимости
от возможностей клиента.

Если клиент не передал SNI или ни один сертификат не совпал, используется
один из сертификатов по умолчанию. Запретить такой переход можно
параметром 'strict-sni'. Если сертификатов по умолчанию несколько,
HAProxy выбирает подходящий ECDSA или RSA по возможностям клиента.

Первый сертификат строки bind, заданный через crt или crt-list,
используется по умолчанию.
Можно также указать фильтр '*', добавляющий сертификат в список
сертификатов по умолчанию. Для ясности конфигурации их можно явно
задать (фильтром '*') в начале списка, чтобы перед ними не добавился
неявный сертификат по умолчанию.
Поскольку пакеты из нескольких сертификатов дублируются в crt-list
для каждого алгоритма, первую строку crt-list занимает один алгоритм,
и только он считается вариантом по умолчанию. Следует либо назначить
весь пакет вариантом по умолчанию с фильтром '*', либо задать его
в строке bind.

Для отладки конфигурации можно использовать команду "show ssl sni"
через сокет статистики (см. "show ssl sni" в руководстве по управлению).

Пример:

# comment
default.pem.rsa *
default.pem.ecdsa *
cert2.pem [alpn h2,http/1.1]
certW.pem *.domain.tld !secure.domain.tld
certS.pem [curves X25519:P-256 ciphers ECDHE-ECDSA-AES256-GCM-SHA384] secure.domain.tld
foo.crt [key bar.pem ocsp foo.ocsp ocsp-update on] foo.bar.com

default-crt <cert>

default-crt <cert>

Этот параметр работает так же, как “crt”, но указанный сертификат используется и как сертификат по умолчанию. Можно добавить несколько сертификатов по умолчанию, чтобы иметь ECDSA и RSA; большее число вряд ли полезно.

Параметр не отключает неявно выбранные сертификаты по умолчанию: если сертификат ‘crt’ объявлен первым, до любого ‘default-crt’ или другого ‘crt’, он по-прежнему будет сертификатом по умолчанию.

Сертификат по умолчанию используется, если в строке bind нет параметра “strict-sni”. Он предоставляется, когда клиент не использует расширение servername или имя servername не соответствует ни одному настроенному сертификату.

Пример:

# this bind line has 2 default certificates
bind *:443 default-crt foobar.pem.rsa default-crt foobar.pem.ecdsa crt website.pem.rsa

# this bind line has 3 default certificates
bind *:443 crt website.pem.rsa default-crt foobar.pem.rsa default-crt foobar.pem.ecdsa

См. также ключевое слово “crt”.

curves <curves>

curves <curves>

Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он задаёт строку, описывающую список алгоритмов эллиптических кривых (“набор кривых”), которые согласовываются при рукопожатии SSL/TLS с ECDHE. Формат строки — это список названий кривых, разделённых двоеточием. Пример: “X25519:P-256” (без кавычек). При задании “curves” параметр “ecdhe” игнорируется.

defer-accept

defer-accept

Необязательное ключевое слово, поддерживаемое лишь некоторыми ядрами Linux. Оно задаёт приём соединения только после поступления данных или, в худшем случае, после первой повторной передачи. Его следует использовать только с протоколами, в которых первым передаёт данные клиент, например HTTP. Производительность может немного повыситься, поскольку к моменту приёма соединения большая часть запроса уже доступна. С другой стороны, соединения, по которым не передаются данные, обнаружить не удастся. Во всех ядрах до 2.6.31 включительно этот параметр работает некорректно: соединение вообще не принимается, пока клиент не передаст данные. Это может вызвать проблемы с межсетевыми экранами перед прокси: они видят установленное соединение, тогда как прокси видит его лишь в SYN_RECV. Параметр поддерживается только для сокетов TCPv4/TCPv6 и игнорируется для остальных.

ecdhe <named curve>

ecdhe <named curve>

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он задаёт имя кривой (RFC 4492), используемой для генерации временных ключей ECDH. По умолчанию используется кривая prime256v1.

ech <dir> [ EXPERIMENTAL ]

ech <dir> [ EXPERIMENTAL ]

Применяет все ключи ECH из <dir> к строке привязки. Файлы должны иметь расширение .ech и должны использовать формат файла PEM для ECH. ( https://datatracker.ietf.org/doc/draft-farrell-tls-pemesni/ )

Это ключевое слово включает ECH в совместном режиме: HAProxy выступает конечной точкой и TLS, и ECH. См. https://datatracker.ietf.org/doc/draft-ietf-tls-esni/

Это экспериментальная функция, которая требует опции “expose-experimental-directives” в секции global. Она также требует версии OpenSSL, поддерживающей ECH (https://github.com/openssl/openssl/tree/feature/ech ), и HAProxy должен быть скомпилирован с USE_ECH=1. API ECH в AWS-LC не поддерживается.

Пример:

$ openssl ech -public_name foobar.com -out /etc/haproxy/echkeydir/foobar.com.ech

$ cat haproxy.cfg
[...]
bind :443 ech /etc/haproxy/echkeydir/ ssl crt example.com.pem

// Use the ECHCONFIG section of your .ech file
$ openssl s_client -tls1_3 -connect example.com:443 -servername example.com \
-ech_config_list AD3+DQA5cwAgACB6ybtgtFYoM5r8nJSotus4c7K0EG..9vYmFyLmNvbQAA

expose-fd listeners

expose-fd listeners

Этот параметр применим только к сокету статистики. Он предоставляет сокету статистики возможность передавать файловые описатели слушателей в другой процесс HAProxy. В режиме master-worker этот параметр уже не требуется: файловые дескрипторы слушателей передаются через внутренние сокет-пары между мастером и рабочими процессами. См. также “-x” в руководстве по управлению.

force-sslv3

force-sslv3

Этот параметр обеспечивает использование только SSLv3 для соединений SSL, созданных из этого слушателя. SSLv3 в целом менее затратен, чем соответствующие варианты TLS, при высокой интенсивности соединений. Данный параметр также доступен в глобальной директиве “ssl-default-bind-options”. См. также “ssl-min-ver” и “ssl-max-ver”.

force-tlsv10

force-tlsv10

Этот параметр обеспечивает использование только TLSv1.0 на соединениях SSL, созданных из этого слушателя. Данный параметр также доступен в глобальной директиве “ssl-default-bind-options”. См. также “ssl-min-ver” и “ssl-max-ver”.

force-tlsv11

force-tlsv11

Этот параметр обеспечивает использование только TLSv1.1 на соединениях SSL, созданных из этого слушателя. Данный параметр также доступен в глобальной директиве “ssl-default-bind-options”. См. также “ssl-min-ver” и “ssl-max-ver”.

force-tlsv12

force-tlsv12

Этот параметр обеспечивает использование только TLSv1.2 на соединениях SSL, созданных из этого слушателя. Данный параметр также доступен в глобальной директиве “ssl-default-bind-options”. См. также “ssl-min-ver” и “ssl-max-ver”.

force-tlsv13

force-tlsv13

Этот параметр обеспечивает использование только TLSv1.3 на соединениях SSL, созданных из этого слушателя. Данный параметр также доступен в глобальной директиве “ssl-default-bind-options”. См. также “ssl-min-ver” и “ssl-max-ver”.

generate-certificates

generate-certificates

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он включает динамическое создание сертификатов SSL. Необходимы сертификат CA и его закрытый ключ (см. ‘ca-sign-file’). Когда HAProxy настроен как прозрачный прямой прокси, запросы SSL вызывают ошибки из-за несовпадения общего имени в сертификате, предоставленном клиенту. При включении параметра HAProxy пытается сформировать сертификат с именем узла SNI, указанным клиентом. Это происходит только в том случае, если ни один сертификат не соответствует имени SNI (см. ‘crt-list’).

При ошибке создания сертификата для соединения используется сертификат по умолчанию. При использовании ‘strict-sni’ сертификат по умолчанию не применяется и рукопожатие завершается неудачей.

Данный параметр также может использоваться при настройке HAProxy как обратного прокси для упрощения развёртывания архитектуры с множеством бэкендов.

Создание SSL сертификата — дорогостоящая операция, поэтому используется LRU кэш для хранения сгенерированных сертификатов (см. ’tune.ssl.ssl-ctx-cache-size’). Это увеличивает потребление памяти HAProxy с целью сокращения задержки при многократном использовании одного сертификата.

gid <gid>

gid <gid>

Задаёт группу сокетов UNIX по системному идентификатору gid. Значение по умолчанию можно также задать директивой “unix-bind” в секции global. Некоторые платформы просто игнорируют этот параметр. Он эквивалентен “group”, но использует идентификатор группы вместо имени. Для сокетов, отличных от UNIX, параметр игнорируется.

group <group>

group <group>

Задаёт группу сокетов UNIX по имени системной группы. Значение по умолчанию можно также задать директивой “unix-bind” в секции global. Некоторые платформы просто игнорируют этот параметр. Он эквивалентен “gid”, но использует имя группы вместо gid. Для сокетов, отличных от UNIX, параметр игнорируется.

guid-prefix <string>

guid-prefix <string>

Генерирует глобально уникальные идентификаторы с учётом регистра для каждого слушающего сокета, созданного этой строкой bind. Префикс соединяется с порядковым индексом слушателя в текущей строке bind через символ ‘-’. Подробнее о формате см. описание ключевого слова “guid” прокси. См. также “shm-stats-file”.

id <id>

id <id>

Фиксирует идентификатор сокета. По умолчанию идентификаторы сокетов автоматически присваиваются, но в некоторых случаях удобнее их фиксировать для упрощения мониторинга. Значение должно быть строго положительным и уникальным в пределах слушателя/фронтенда. Этот параметр можно использовать только при определении единственного сокета.

idle-ping <delay>

idle-ping <delay>

Может использоваться в следующих контекстах: tcp, http, log

Задаёт интервал периодической проверки работоспособности простаивающих соединений фронтенда. Если другая сторона не отвечает до следующей запланированной проверки, соединение закрывается. Иначе тайм-аут клиента обновляется, а соединение сохраняется. Учтите: таймеры http-request/http-keep-alive работают параллельно и не обновляются через idle-ping.

Для этой возможности требуется поддержка нижележащего протокола. Пока она реализована только в мультиплексоре H2. Остальные протоколы просто игнорируют idle-ping.

Параметр особенно полезен при использовании обратного HTTP. Его указание в строке bind полезно для узла, который активно устанавливает соединения, а затем получает по ним входящий трафик.

interface <interface>

interface <interface>

Ограничивает работу сокета указанным интерфейсом. При указании сокет обрабатывает только пакеты, полученные с указанного интерфейса. Данный функционал доступен только на Linux. Интерфейс должен быть первичным системным интерфейсом, а не алиасированным интерфейсом. Возможна привязка нескольких фронтендов к одному адресу, если они привязаны к разным интерфейсам. Примечание: привязка к сетевому интерфейсу требует прав root. Данный параметр совместим только с сокетами TCPv4/TCPv6. При указании, выходной трафик использует тот же интерфейс, что и входной трафик, и соответствующую таблицу маршрутизации, даже если настроены явные маршруты через другие интерфейсы. Это может быть полезно для устранения проблем асимметричной маршрутизации, когда одинаковые IP-адреса клиентов должны быть способны доставлять запросы к фронтендам, размещённым на разных интерфейсах.

ktls <on|off> [ EXPERIMENTAL ]

ktls <on|off> [ EXPERIMENTAL ]

Включает или отключает ktls для соответствующих сокетов. При включении kTLS будет использоваться, если ядро поддерживает kTLS и используемый шифр совместим. Доступно только для ядра Linux 4.17 и выше. Примечание: некоторые сетевые драйверы и/или TLS стеки могут ограничивать использование kTLS только для TLS v1.2. См. также “force-tlsv12”.

label <label>

label <label>

Задаёт необязательную метку сокетов. По ней можно группировать сокеты независимо от места объявления строк bind.

level <level>

level <level>

Этот параметр используется только с сокетами статистики для ограничения характера команд, которые можно отправить по сокету. Он игнорируется другими сокетами. <level> может принимать одно из следующих значений:

  • “user” — наименее привилегированный уровень; допускается только чтение статистики без конфиденциальных данных; изменения запрещены. Подходит для систем, где ограничение доступа к сокету затруднено.
  • “operator” — уровень по умолчанию, подходящий для большинства распространённых случаев. Допускается чтение всех данных, разрешены только изменения, не затрагивающие критичные данные (например, сброс максимальных значений счётчиков).
  • “admin” следует использовать с осторожностью, так как разрешены все действия (например, очистка всех счётчиков).

maxconn <maxconn>

maxconn <maxconn>

Ограничивает сокеты количеством одновременных соединений. Дополнительные соединения остаются в очереди системы до того, как соединение будет освобождено. Если не указано иное, ограничение будет равно maxconn фронтенда. Примечание: в случае диапазонов портов или нескольких адресов одинаковое значение будет применено к каждому сокету. Эта настройка позволяет устанавливать различные ограничения для дорогостоящих сокетов, например точек приёма SSL, которые могут легко занять всю память.

mode <mode>

mode <mode>

Задаёт права доступа к сокету UNIX в восьмеричном виде. Значение по умолчанию можно также задать директивой “unix-bind” секции global. Некоторые платформы просто игнорируют этот параметр. Для сокетов, отличных от UNIX, он игнорируется.

mss <maxseg>

mss <maxseg>

Задаёт значение максимального размера сегмента (MSS) для TCP, которое будет объявляться при входящих соединениях. Это может использоваться для принудительного установления меньшего MSS для определённых портов, например, при соединениях, проходящих через VPN. Обратите внимание, что эта функция зависит от функции ядра, которая теоретически поддерживается в Linux, но была нестабильной во всех версиях до 2.6.28. Она может не работать на других операционных системах. Также возможно, что значение не изменится, но изменится эффективный размер исходящих сегментов. Обычно объявляемое значение TCPv4 в сетях Ethernet составляет 1460 = 1500(MTU) - 40(IP+TCP). Если это значение положительное, оно будет использоваться как объявляемое MSS. Если отрицательное — оно указывает, на сколько следует уменьшить объявляемое MSS входящего соединения для исходящих сегментов. Этот параметр совместим только с сокетами TCP v4/v6.

name <name>

name <name>

Устанавливает опциональное имя для этих сокетов, которое будет отображаться на странице статистики.

namespace <name>

namespace <name>

На Linux возможно указать, какому сетевому пространству имён будет принадлежать сокет. Эта директива позволяет явно привязать слушатель к пространству имен, отличному от стандартного. См. документацию операционной системы для получения дополнительной информации о сетевых пространствах имен.

nbconn <nbconn> [ EXPERIMENTAL ]

nbconn <nbconn> [ EXPERIMENTAL ]

Этот параметр действует только для экземпляров слушателей, использующих обратный HTTP. Он определяет число соединений, которые будут устанавливаться параллельно. Если параметр не указан, используется значение по умолчанию 1.

Обратный HTTP в настоящее время всё ещё находится на стадии активного развития. Механизм конфигурации может измениться в будущем. Поэтому он внутренне помечен как экспериментальный, что означает, что “expose-experimental-directives” должен быть указан в строке перед этой директивой.

nice <nice>

nice <nice>

Устанавливает «дружелюбность» соединений, инициируемых из сокета. Значение должно находиться в диапазоне -1024..1024 включительно и по умолчанию равно нулю. Положительные значения означают, что такие соединения более дружелюбны к другим и легко предоставляют место в планировщике. Напротив, отрицательные значения означают, что соединения хотят работать с более высоким приоритетом по сравнению с другими. Разница проявляется только при высоких нагрузках, когда система приближается к насыщению. Отрицательные значения подходят для служб с низкой задержкой или администрирования, а высокие значения в целом рекомендуются для CPU интенсивных задач, таких как SSL обработка или массовые передачи, которые менее чувствительны к задержке. Например, может быть оправдано использование положительного значения для сокета SMTP и отрицательного значения для сокета RDP.

no-alpn

no-alpn

Отключает обработку ALPN: технически строка ALPN становится пустой и не объявляется. Позволяет отменить предыдущее указание “alpn” и отключить согласование протокола приложения. Также может запрещать слушателю HTTPS или QUIC согласовывать ALPN с клиентом; по умолчанию слушатели HTTPS объявляют “h2,http/1.1”, а QUIC — “h3”. См. также “alpn” выше. При использовании “crt-list” сертификат может переопределить “alpn” и снова включить обработку ALPN.

no-ca-names

no-ca-names

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он предотвращает отправку имён CA в сообщении server hello при использовании ca-file. Используйте “ca-verify-file” вместо “ca-file” с “no-ca-names”.

no-sslv3

no-sslv3

Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он отключает поддержку SSLv3 на любых сокетах, создаваемых из слушателя, при наличии SSL. Примечание: поддержка SSLv2 принудительно отключена в коде и не может быть включена с помощью настроек конфигурации. Этот параметр также доступен в глобальной директиве “ssl-default-bind-options”. Используйте “ssl-min-ver” и “ssl-max-ver” вместо этого.

no-strict-sni

no-strict-sni

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он отменяет строгое применение SNI, заданное предыдущей директивой “strict-sni”. Это может потребоваться, чтобы выборочно отключить strict-sni в строке “bind”, если режим уже включён глобально через “ssl-default-bind-options”. См. также параметр bind “strict-sni”.

no-tls-tickets

no-tls-tickets

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он отключает возобновление сеансов без хранения состояния (расширение TLS Ticket, RFC 5077) и принудительно включает возобновление с хранением состояния. Возобновление без хранения состояния требует больше ресурсов CPU. Параметр также доступен в глобальной директиве “ssl-default-bind-options”. Механизм билетов TLS используется только до TLS 1.2 включительно. При использовании билетов TLS прямая секретность нарушается, если их ключи не заменяются регулярно (через перезагрузку конфигурации или с помощью “tls-ticket-keys”).

no-tlsv10

no-tlsv10

Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он отключает поддержку TLSv1.0 на любых сокетах, создаваемых из слушателя, при наличии поддержки SSL. Примечание: SSLv2 выключена в коде и не может быть включена с помощью любого параметра конфигурации. Этот параметр также доступен в глобальной директиве “ssl-default-bind-options”. Используйте “ssl-min-ver” и “ssl-max-ver” вместо этого.

no-tlsv11

no-tlsv11

Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он отключает поддержку TLSv1.1 на любых сокетах, создаваемых из слушателя, при наличии поддержки SSL. Примечание: SSLv2 принудительно отключена в коде и не может быть включена с помощью любого параметра конфигурации. Этот параметр также доступен в глобальной директиве “ssl-default-bind-options”. Используйте “ssl-min-ver” и “ssl-max-ver” вместо этого.

no-tlsv12

no-tlsv12

Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он отключает поддержку TLSv1.2 на любых сокетах, создаваемых из слушателя, при наличии поддержки SSL. Примечание: SSLv2 выключена в коде и не может быть включена с помощью любого параметра конфигурации. Этот параметр также доступен в глобальной директиве “ssl-default-bind-options”. Используйте “ssl-min-ver” и “ssl-max-ver” вместо этого.

no-tlsv13

no-tlsv13

Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он отключает поддержку TLSv1.3 на любых сокетах, создаваемых из слушателя, при наличии поддержки SSL. Примечание: SSLv2 принудительно отключена в коде и не может быть включена с помощью любого параметра конфигурации. Этот параметр также доступен в глобальной директиве “ssl-default-bind-options”. Используйте “ssl-min-ver” и “ssl-max-ver” вместо этого.

npn <protocols>

npn <protocols>

Включает расширение TLS NPN и объявляет через него указанный список поддерживаемых протоколов. Имена протоколов разделяются запятыми, например “http/1.1,http/1.0” (без кавычек). Библиотека SSL должна быть собрана с поддержкой расширений TLS (проверяется командой haproxy -vv). Расширение NPN заменено расширением ALPN (см. “alpn”), но последнее доступно лишь начиная с OpenSSL 1.0.2. Если HTTP/2 требуется с более старой версией OpenSSL, можно по-прежнему использовать NPN, поскольку на момент написания его поддерживает большинство клиентов. Можно включить NPN и ALPN одновременно, хотя за пределами тестирования это, вероятно, не имеет смысла.

prefer-client-ciphers

prefer-client-ciphers

При выборе набора шифров использует предпочтения клиента; по умолчанию действуют предпочтения сервера. Параметр также доступен в глобальной директиве “ssl-default-bind-options”.

Примечание: при использовании OpenSSL >= 1.1.1 ChaCha20-Poly1305 автоматически приоритизируется (без настройки данного параметра), если шифр ChaCha20-Poly1305 находится на вершине списка шифров клиента.

При использовании настройки с двумя алгоритмами (RSA + ECDSA) алгоритм выбора будет выбирать между RSA и ECDSA и всегда будет приоритизировать ECDSA. После выбора правильного сертификата, библиотека SSL будет приоритизировать шифры, кривые и т.д. Следовательно, данный параметр не может быть использован для приоритизации сертификата RSA над сертификатом ECDSA.

proto <name>

proto <name>

Принудительно задаёт протокол мультиплексора для входящих соединений. Протокол должен быть совместим с режимом фронтенда (TCP или HTTP) и пригоден для использования на стороне фронтенда. Список доступных протоколов выводит haproxy -vv. Для них указываются режим (TCP/HTTP), сторона (FE/BE), имя мультиплексора и его флаги.

Некоторые протоколы подвержены блокировке начала очереди на стороне сервера (flag=HOL_RISK). Некоторые не поддерживают смену протокола в существующем соединении (flag=NO_UPG). Также указывается совместимость с HTX (flag=HTX).

Вот протоколы, которые могут использоваться в качестве аргумента директивы “proto” на строке bind:

quic: mode=HTTP  side=FE|BE  mux=QUIC  flags=HTX|NO_UPG|FRAMED
 qmux: mode=HTTP  side=FE|BE  mux=QMUX  flags=HTX|NO_UPG
 h2  : mode=HTTP  side=FE|BE  mux=H2    flags=HTX|HOL_RISK|NO_UPG
 h1  : mode=HTTP  side=FE|BE  mux=H1    flags=HTX|NO_UPG
 none: mode=TCP   side=FE|BE  mux=PASS  flags=NO_UPG

Параметр позволяет обойти выбор наиболее подходящего протокола мультиплексора для всех соединений, принятых этим слушающим сокетом. Например, можно принудительно использовать http/2 поверх незашифрованного TCP, указав “proto h2” в строке bind.

Если настроены ALPN или NPN, указанные в них протоколы следует согласовать с протоколом мультиплексора, чтобы избежать проблем. Например, при “proto h1” не следует задавать ALPN “h2”.

QMux — подмножество QUIC, работающее над TCP. Оно соответствует следующему черновому протоколу https://www.ietf.org/archive/id/draft-ietf-quic-qmux-01.html . На данный момент оно считается экспериментальным в HAProxy.

quic-cc-algo { cubic | newreno | bbr | nocc }[(<args,...>)]

quic-cc-algo { cubic | newreno | bbr | nocc }[(<args,...>)]

Специальный параметр QUIC для выбора алгоритма управления перегрузкой для всех попыток подключения к настроенным слушателям QUIC. Эти алгоритмы аналогичны используемым в TCP.

В дополнение к алгоритму управления перегрузкой включено равномерное распределение отправки пакетов во времени (pacing), которое снижает потери и повышает пропускную способность. Его можно отключить глобальным ключевым словом “tune.quic.fe.tx.pacing”. В большинстве случаев pacing следует оставлять включённым, особенно при использовании BBR, поскольку для корректной работы этот алгоритм зависит от pacing. Использование BBR без pacing может вызвать замедления или высокую долю потерь при передаче.

Значение по умолчанию: cubic

Для дополнительной настройки после имени алгоритма можно указать в скобках параметры, разделённые запятыми. Каждый аргумент необязателен и при необходимости может быть пустым. Параметры должны следовать в таком порядке:

  • максимальный размер окна в байтах. Он должен быть больше 10k и меньше 4g. По умолчанию используется значение “tune.quic.fe.cc.max-win-size”.

Пример:

# newreno congestion control algorithm
quic-cc-algo newreno
# cubic congestion control algorithm with one megabytes as window
quic-cc-algo cubic(1m)

Значение «nocc» может быть использовано для принудительного установления окна перегрузки в фиксированном режиме, при котором оно всегда будет равно максимальному размеру. Оно предназначено исключительно для случаев отладки с целью исключения любых побочных эффектов, вызванных контроллером перегрузки. Оно не должно использоваться в производственной среде, поскольку может быстро привести к сетевым проблемам, таким как высокий уровень потерь.

quic-force-retry

quic-force-retry

Специальный параметр QUIC, принудительно включающий QUIC Retry для всех попыток подключения к настроенным слушателям QUIC. Он проверяет, способны ли удалённые узлы получать пакеты по транспортному адресу, с которого они начали новое соединение: им отправляется пакет Retry с токеном. Токен должен быть возвращён отправителю Retry, поскольку только тот может проверить его. Учтите, что QUIC Retry будет использоваться всегда, даже если задан порог Retry (см. “tune.quic.fe.sec.retry-threshold”).

Для этого параметра должен быть задан секрет кластера, иначе при запуске будет выдана ошибка (см. “cluster-secret”).

Дополнительные сведения о QUIC retry см. в https://www.rfc-editor.org/rfc/rfc9000.html#section-8.1.2 .

quic-socket [ connection | listener ]

quic-socket [ connection | listener ]

Специальный параметр QUIC, задающий способ выделения сокетов для конкретных слушателей. Полное описание преимуществ и недостатков каждого режима приведено в “tune.quic.fe.sock-per-conn”.

Параметр применяется совместно с глобальным “tune.quic.fe.sock-per-conn”. Если глобально включён режим “default-on” (значение по умолчанию), каждое соединение QUIC использует собственный сокет, кроме слушателей с “quic-socket listener”. Однако при глобальном режиме “force-off” настройки отдельных слушателей игнорируются.

severity-output <format>

severity-output <format>

Этот параметр применяется только к сокетам статистики и настраивает вывод уровня важности перед информационными сообщениями обратной связи. Уровень может принимать значения от 0 до 7 согласно syslog rfc5424. Перед результатами корректных и успешных команд запроса данных, например “show map” или “get acl foo”, уровень не выводится никогда. Для остальных сокетов параметр игнорируется. <format> принимает одно из значений:

  • “none” (по умолчанию) к сообщениям не добавляется уровень важности.
  • “number” уровень важности добавляется как число.
  • “string” уровень важности добавляется как строка согласно rfc5424.

shards { <number> | by-thread | by-group }

shards { <number> | by-thread | by-group }

В многопоточном режиме, если операционная система поддерживает несколько слушателей на одном IP:port, автоматически создаёт для этой строки указанное число одинаковых слушателей. Потоки исходного слушателя распределяются между ними поровну. Это иногда полезно при очень большом числе потоков, когда блокировки ядра на одном сокете создают значительные накладные расходы. Входящий трафик тогда распределяется по нескольким сокетам, снижая конкуренцию за них. При этом нагрузка на CPU может легко вырасти, поскольку больше потоков выполняет небольшую часть работы.

Если количество шардов превышает количество доступных потоков, оно автоматически будет сокращено до количества потоков (то есть один шард на поток). Специальное значение «by-thread» также создаёт столько шардов, сколько потоков на строке “bind”. Поскольку система равномерно распределяет входящий трафик между всеми этими шардами, важно, чтобы это число было целым делителем количества потоков. Альтернативно, другое специальное значение «by-group» создаёт один шард на группу потоков. Это может быть полезно при работе с большим количеством потоков и желании избежать создания слишком большого числа сокетов. Распределение нагрузки будет немного менее оптимальным, но конкуренция (особенно в системе) всё ещё будет ниже, чем при использовании одного сокета.

На операционных системах, не поддерживающих несколько сокетов, привязанных к одному адресу, «by-thread» и «by-group» автоматически переходят к одному шарду. Для «by-group» это делается без предупреждения, поскольку это не меняет ничего в случае одной группы, и сокеты всё равно будут дублироваться для каждой группы. Однако для «by-thread» при этом будет выдано диагностическое предупреждение, поскольку итоговое количество слушателей не будет соответствовать ожидаемому.

sigalgs <sigalgs>

sigalgs <sigalgs>

Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он задаёт строку, описывающую список алгоритмов подписи, согласуемых при рукопожатии TLSv1.2 и TLSv1.3. Формат строки определён в «man 3 SSL_CTX_set1_sigalgs» из справочной документации OpenSSL. Использование этого параметра не рекомендуется, если не требуется совместимость с промежуточным устройством.

ssl

ssl

Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Он включает расшифровку SSL на соединениях, создаваемых из этого слушателя. Необходим сертификат (см. “crt” выше). Все содержимое в буферах будет отображаться в открытом виде, поэтому ACL и обработка HTTP будут иметь доступ только к расшифрованному содержимому. Поддержка SSLv3 отключена по умолчанию; для включения используйте “ssl-min-ver SSLv3”.

ssl-max-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]

ssl-max-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]

Этот параметр обеспечивает использование <version> или ниже на соединениях SSL, создаваемых из этого слушателя. Использование этого параметра без “ssl-min-ver” может быть неоднозначным, поскольку значение по умолчанию ssl-min-ver может измениться в будущих версиях HAProxy. Этот параметр также доступен в глобальной директиве “ssl-default-bind-options”. См. также “ssl-min-ver”.

ssl-min-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]

ssl-min-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]

Этот параметр обеспечивает использование <version> или выше на соединениях SSL, создаваемых из этого слушателя. Значение по умолчанию — “TLSv1.2”. Этот параметр также доступен в глобальной директиве “ssl-default-bind-options”. См. также “ssl-max-ver”.

strict-sni

strict-sni

Этот параметр доступен только при сборке с поддержкой OpenSSL. Согласование SSL/TLS разрешено лишь в том случае, если клиент передал SNI, соответствующий сертификату. Сертификат по умолчанию не используется. Параметр также позволяет запускаться без сертификатов в строке bind: можно указать пустой каталог и позже заполнить его через сокет статистики. Он доступен и в глобальной директиве “ssl-default-bind-options”, а выборочно отключить его в строке “bind” можно с помощью “no-strict-sni”. Подробнее см. “crt” и команду “add ssl crt-list” в руководстве по управлению.

tcp-md5sig <password>

tcp-md5sig <password>

Включает подпись TCP MD5 (RFC 2385 Защита сессий BGP через опцию подписи TCP MD5) для всех входящих соединений, инициированных из этого прослушиваемого сокета. Эта опция доступна только на Linux. При включении используется строка <password> для подписи каждого сегмента TCP с помощью 16-байтового MD5 хэша. Это обеспечивает защиту соединения TCP от подделки. Основное применение этой опции — защита BGP от введения фальшивых сегментов TCP в поток соединения. Однако она может быть полезна для любых очень долговременных соединений TCP.

tcp-ss <mode>

tcp-ss <mode>

Задаёт параметр TCP Save SYN для всех входящих соединений, создаваемых этим прослушивающим сокетом. Он доступен в Linux начиная с версии 4.3 и предписывает ядру попытаться сохранить копию входящего пакета IP с флагом TCP SYN для последующего анализа через функцию извлечения образцов “fc_saved_syn”. Поддерживаются 3 режима: 0 — сохранение пакета SYN отключено, это значение по умолчанию; 1 — сохранение пакета SYN включено, сохраняются заголовки IP и TCP; 2 — сохранение пакета SYN включено, сохраняются заголовки ETH, IP и TCP.

Это работает только для обычных соединений TCP и игнорируется для других протоколов (например, UNIX сокетов). См. также “fc_saved_syn”.

tcp-ut <delay>

tcp-ut <delay>

Устанавливает тайм-аут пользователя TCP для всех входящих соединений, создаваемых из этого слушающего сокета. Опция доступна на Linux с версии 2.6.37. Позволяет HAProxy настроить тайм-аут для сокетов, содержащих данные, не получающие подтверждения в течение заданного периода. Особенно полезна в случае долговременных соединений с длительными периодами бездействия, таких как удалённые терминалы или пулы соединений с базами данных, где тайм-ауты клиента и сервера должны быть высокими, чтобы допускать длительный период бездействия, но при этом важно обнаруживать исчезновение клиента для освобождения всех ресурсов, связанных с его соединением (и сессией сервера). Аргумент — задержка, выраженная в миллисекундах по умолчанию. Работает только для обычных TCP соединений и игнорируется для других протоколов.

tfo

tfo

Необязательное ключевое слово, поддерживаемое только в ядрах Linux >= 3.7. Включает TCP Fast Open на слушающем сокете. Начиная со второго соединения, клиенты с такой поддержкой могут отправить запрос и получить ответ в ходе 3-этапного рукопожатия, экономя один цикл обмена по сравнению с первым соединением. Это имеет смысл только для протоколов с высокой частотой соединений, где важен каждый цикл обмена. Возможны проблемы со многими межсетевыми экранами, которые не принимают данные в пакетах SYN, поэтому параметр следует включать только после тщательного тестирования. Он поддерживается только для сокетов TCPv4/TCPv6 и игнорируется для остальных. Если libc не определяет TCP_FASTOPEN, может потребоваться сборка HAProxy с USE_TFO=1.

thread [<thread-group>/]<thread-set>[,...]

thread [<thread-group>/]<thread-set>[,...]

Ограничивает список потоков, в которых разрешено работать слушателю. Параметр не назначает ни один из них принудительно, а исключает неподходящие. Тем самым ограничиваются потоки, которым разрешено обрабатывать входящие соединения этого слушателя.

Существуют две схемы нумерации. По умолчанию номера потоков являются абсолютными в процессе и варьируются от 1 до значения, указанного в global.nbthread. Также возможно указать номер потока с помощью его относительного номера внутри группы потоков, указав сначала номер группы потоков, затем слэш (’/’) и относительный номер потока(ов). В этом случае номера потоков также начинаются с 1 и заканчиваются на 32 или 64 в зависимости от платформы. При указании абсолютных номеров потоков они автоматически переводятся в относительные номера после того, как известны группы потоков. Обычно для простых конфигураций предпочтительны абсолютные номера, а для сложных конфигураций, где размещение на CPU имеет значение для производительности, — относительные.

После необязательного номера группы потоков спецификация “thread-set” должна иметь следующий формат:

"all" | "odd" | "even" | [number][-[number]]

Как следует из названий, “all” выбирает все потоки набора: все потоки указанной группы либо все потоки процесса. “odd” выбирает нечётные потоки (каждый второй, начиная с 1), а “even” — чётные (каждый второй, начиная с 2), также для процесса или группы. Если указаны диапазоны номеров, выбираются все потоки от первого до последнего номера включительно. Номера относительны к группе или абсолютны в зависимости от наличия номера группы потоков. Если первый номер пропущен, используется “1” — первый поток группы либо процесса. Если последний номер пропущен, используется последний номер потока группы (32 или 64) либо процесса (global.nbthread).

Диапазоны можно повторять через запятую, задавая несмежные наборы потоков. Если указана группа, её необходимо повторить для каждого нового диапазона. Смешивать относительные к группе и абсолютные номера запрещено: вся строка “bind” должна использовать один вид записи, поскольку неуказанные значения определяются в конце разбора.

Важно понимать, что каждый слушатель, описанный строкой “bind”, создаёт как минимум один сокет, представленный как минимум одним файловым описателем. Поскольку файловые описатели не могут охватывать несколько групп потоков, если строка “bind” указывает диапазон потоков, охватывающий более одной группы, автоматически создаются несколько файловых описателей, чтобы для каждой группы был хотя бы один. Технически все они ссылаются на один и тот же сокет в ядре, но они получат отдельный идентификатор в HAProxy и даже будут иметь отдельную запись в статистике, если используется “option socket-stats”.

Основная цель — иметь несколько строк bind, использующих одинаковый IP:порт, но разные потоки в слушателе, чтобы система могла распределять входящие соединения по нескольким очередям, обходя внутреннюю балансировку нагрузки очередей HAProxy. В настоящее время поддержка такой конфигурации известна для Linux 3.9 и выше. См. также ключевое слово “shards”, описанное выше, которое автоматически дублирует строки “bind” и присваивает их нескольким группам потоков.

Это ключевое слово совместимо со строками bind для обратного HTTP. Однако запрещено указывать набор потоков, охватывающий несколько групп потоков для такого слушателя, поскольку это может привести к тому, что “nbconn” не работает как задумано.

tls-tickets

tls-tickets

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он включает возобновление сеансов без хранения состояния (расширение TLS Ticket, RFC 5077). Это поведение по умолчанию, но параметр может потребоваться, чтобы выборочно включить его в строке “bind”, если оно отключено глобально через “no-tls-tickets” в “ssl-default-bind-options”. См. также ключевое слово bind “no-tls-tickets”.

tls-ticket-keys <keyfile>

tls-ticket-keys <keyfile>

Задаёт файл, из которого загружаются ключи билетов TLS. Длина ключа должна составлять 48 или 80 байт в зависимости от использования aes128 или aes256. Ключи кодируются в base64, по одному в строке (например, openssl rand 80 | openssl base64 -A | xargs echo). Первый ключ определяет длину последующих: смешивать ключи aes128 и aes256 нельзя. Число ключей задаётся параметром сборки TLS_TICKETS_NO (по умолчанию 3), и файл должен содержать не меньше этого числа ключей. Последние TLS_TICKETS_NO ключей используются для расшифрования, а предпоследний — для шифрования. Это позволяет легко заменять ключи: достаточно добавить новый ключ в конец файла и перезагрузить процесс. Ключи необходимо регулярно менять (например, каждые 12h), иначе нарушается совершенная прямая секретность. Также рекомендуется не хранить ключи на постоянных носителях, например жёстких дисках: можно использовать tmpfs и исключить вытеснение этих файлов в swap. Подсказку о сроке действия можно изменить через tune.ssl.timeout.

transparent

transparent

Является опциональным ключевым словом, поддерживающимся только на определённых версиях ядра Linux. Оно указывает на то, что адреса будут привязаны даже в случае, если они не принадлежат локальной машине, и пакеты, направляемые к этим адресам, будут перехвачены так же, как если бы эти адреса были настроены локально. Обычно требуется включение пересылки IP-пакетов. Внимание! не используйте это в сочетании с стандартным адресом ‘*’, иначе произойдёт перенаправление всего трафика на указанном порту. Это ключевое слово доступно только при сборке HAProxy с USE_LINUX_TPROXY=1. Этот параметр совместим только с сокетами TCPv4 и TCPv6, в зависимости от версии ядра. Некоторые дистрибутивы ядер включают бэкпорт данной функции, поэтому проверьте поддержку у поставщика.

uid <uid>

uid <uid>

Задаёт владельца сокетов UNIX по системному идентификатору uid. Значение по умолчанию можно также задать директивой “unix-bind” секции global. Некоторые платформы просто игнорируют параметр. Он эквивалентен “user”, но использует числовой идентификатор пользователя вместо имени. Для сокетов, отличных от UNIX, параметр игнорируется.

user <user>

user <user>

Задаёт владельца сокетов UNIX по имени системного пользователя. Значение по умолчанию можно также задать директивой “unix-bind” секции global. Некоторые платформы просто игнорируют параметр. Он эквивалентен “uid”, но использует имя пользователя вместо uid. Для сокетов, отличных от UNIX, параметр игнорируется.

v4v6

v4v6

Является опциональным ключевым словом, поддерживающимся только на наиболее новых системах, включая ядра Linux >= 2.4.21. Используется для привязки сокета как к IPv4, так и к IPv6 при использовании стандартного адреса. Такая настройка иногда необходима на системах, которые по умолчанию привязываются только к IPv6. Не оказывает влияния на сокеты, не относящиеся к IPv6, и подавляется опцией “v6only”.

v6only

v6only

Является опциональным ключевым словом, поддерживающимся только на последних системах, включая ядра Linux >= 2.4.21. Используется для привязки сокета только к IPv6, когда используется адрес по умолчанию. Такое действие иногда предпочтительнее выполнения системно в целом, поскольку оно действует на уровне слушателя. Не влияет на сокеты, не относящиеся к IPv6, и имеет приоритет перед опцией “v4v6”.

verify [none|optional|required]

verify [none|optional|required]

Этот параметр доступен только при сборке с поддержкой OpenSSL. При значении ’none’ сертификат клиента не запрашивается. Это значение по умолчанию. В остальных случаях сертификат запрашивается. Если клиент не предоставил его после запроса, рукопожатие прерывается при ‘verify required’, но завершается успешно при ‘verify optional’. Предоставленный сертификат всегда проверяется с помощью CA из ‘ca-file’ и необязательных списков отзыва CRL из ‘crl-file’. При неудачной проверке рукопожатие прерывается независимо от значения ‘verify’, кроме случаев точного совпадения кода ошибки с одним из перечисленных в ‘ca-ignore-err’ или ‘crt-ignore-err’.

5.2. Параметры server и default-server

Ключевые слова “server” и “default-server” поддерживают ряд настроек, передаваемых аргументами в строке сервера. Порядок аргументов не имеет значения; все они необязательны. Некоторые настройки состоят из одного слова (логические параметры), другие требуют одного или нескольких значений. Значения должны следовать непосредственно за именем настройки. Кроме случая “default-server”, все используемые настройки должны указываться после адреса сервера:

server <name> <address>[:port] [settings ...]
default-server [settings ...]

Примечание: все эти настройки поддерживаются как для “server”, так и для “default-server”, за исключением “id”, который поддерживается только для “server”.

На данный момент поддерживаются следующие настройки.

addr <ipv4|ipv6>

addr <ipv4|ipv6>

Допустимые контексты: tcp, http, log

Параметр “addr” позволяет направлять проверки работоспособности или проверки агента на другой IP-адрес. На некоторых серверах может быть полезно выделить адрес отдельному компоненту, способному выполнять сложные тесты и лучше подходящему для проверок, чем само приложение. Параметр игнорируется, если не задан “check”. См. также “port”.

agent-check

agent-check

Допустимые контексты: tcp, http, log

Включает дополнительную проверку через агента, выполняемую независимо от обычной проверки работоспособности. Проверка работоспособности агента осуществляется путём установления соединения TCP на порт, заданный параметром “agent-port”, и чтения строки ASCII, завершающейся первым вхождением ‘\r’ или ‘\n’. Строка состоит из ряда слов, разделённых пробелами, табуляциями или запятыми в любом порядке, каждое из которых состоит из:

  • Представление ASCII положительного целого процента, например, “75%”. Значения в этом формате будут устанавливать вес пропорционально начальному весу сервера, заданному при запуске HAProxy. Примечание: нулевой вес отображается на странице статистики как “DRAIN”, поскольку он оказывает одинаковое влияние на сервер (сервер удаляется из группы балансировки). Это устаревший способ установки веса сервера. Рекомендуется использовать установку с префиксом “weight:”.

  • Строка “weight:” за которой следует положительное целое число или положительное целое число в процентах, без пробела. Если значение заканчивается знаком ‘%’, то новый вес будет пропорционален первоначальному весу сервера. В противном случае значение считается абсолютным весом и должно находиться в диапазоне 0 до 256. Серверы, входящие в ферму, работающую по статическому алгоритму балансировки нагрузки, имеют более жесткие ограничения, поскольку вес не может изменяться после установки. Таким образом, для этих серверов допускаются только значения 0 и 100% (или 0 и первоначальный вес). Изменения вступают в силу немедленно, хотя некоторые алгоритмы балансировки нагрузки требуют определённого количества запросов, чтобы учесть изменения. Примечание: нулевой вес отображается на странице статистики как “DRAIN”, поскольку он оказывает такое же влияние на сервер (сервер удаляется из фермы балансировки нагрузки).

  • Строка “maxconn:” за которой следует целое число (без пробела). Значения в таком формате устанавливают параметр maxconn сервера. Максимальное количество соединений, объявленное в этом параметре, должно быть умножено на количество балансировщиков нагрузки и различных бэкендов, использующих эту проверку работоспособности, чтобы получить общее количество соединений, которое может получить сервер. Пример: maxconn:30

  • Слово “ready”. Это изменит административное состояние сервера на режим READY, тем самым отменяя любые состояния DRAIN или MAINT

  • Слово “drain”. Это изменит административное состояние сервера на режим DRAIN, тем самым он не будет принимать новые соединения, кроме соединений, направленных на него механизмом привязки сеансов.

  • Слово “maint”. Это установит административное состояние сервера в режиме MAINT, таким образом, он не будет принимать никакие новые соединения, и проверки работоспособности будут остановлены.

  • Слова “down”, “fail” или “stopped”, опционально сопровождаемые описательной строкой после знака решетки (’#’). Все эти слова указывают на состояние работы сервера как DOWN, но поскольку само слово отображается на странице статистики, различие позволяет администратору понять, было ли это ожидаемым или нет: сервис может быть намеренно остановлен, может быть в состоянии “up”, но не проходить некоторые проверки работоспособности, или может быть отмечен как “down” (например, отсутствует процесс, или порт не отвечает).

  • Слово “up” устанавливает состояние работы сервера как UP, если проверки работоспособности также сообщают, что сервис доступен.

Параметры, которые не объявляются агентом, не изменяются. Например, агент может быть спроектирован для мониторинга CPU и передачи только относительного веса, не взаимодействуя с состоянием работы. Аналогично, агент может быть спроектирован как интерфейс для конечного пользователя с 3 переключателями, позволяющими администратору изменять только административное состояние. Однако важно учитывать, что только сам агент может отменить свои действия, поэтому если сервер установлен в режим DRAIN или в состояние DOWN с помощью агента, то агент должен реализовать другие эквивалентные действия для возврата сервиса в рабочее состояние.

Невозможность подключения к агенту не считается ошибкой, поскольку подключение проверяется через регулярную проверку работоспособности, включаемую с помощью параметра “check”. Предупреждение: не рекомендуется останавливать агент после того, как он сообщает «down», поскольку только агент, сообщивший “up”, сможет включить сервер. Примечание: CLI на Unix-сокете статистики также может принудительно установить результат агента для обхода ошибочного агента, если это необходимо.

Требуется установить параметр “agent-port”. См. также параметры “agent-inter” и “no-agent-check”.

agent-send <string>

agent-send <string>

Допустимые контексты: tcp, http, log

Если параметр задан, после подключения HAProxy отправляет указанную строку агенту без изменений. Например, в неё можно включить имя бэкенда, чтобы агент выдавал разные ответы в зависимости от бэкенда. Для завершения запроса переводом строки необходимо включить в него ‘\n’.

agent-inter <delay>

agent-inter <delay>

Допустимые контексты: tcp, http, log

Параметр “agent-inter” задаёт интервал между двумя проверками агента в <delay> миллисекунд. Если параметр не указан, задержка по умолчанию равна 2000 ms.

Так же, как и для любого другого параметра, зависящего от времени, значение может быть указано в любой из явных единиц: { us, ms, s, m, h, d }. Параметр “agent-inter” также служит тайм-аутом для проверок работоспособности агента, если “timeout check” не задан. Чтобы снизить эффекты «резонанса» при размещении нескольких серверов на одном оборудовании, запуск проверок через агента и обычных проверок работоспособности всех серверов производится с небольшим временным сдвигом между ними. Также возможно добавить некоторое случайное отклонение в интервалы проверок через агента и обычных проверок работоспособности с помощью глобального параметра “spread-checks”. Это имеет смысл, например, когда большое количество бэкендов использует одни и те же серверы.

См. также параметры “agent-check” и “agent-port”.

agent-addr <addr>

agent-addr <addr>

Допустимые контексты: tcp, http, log

Параметр “agent-addr” задаёт адрес проверки агента.

Проверку agent-check можно перенести на другой узел, централизовав управление состоянием и весами серверов, определённых в HAProxy, если сами сервисы не могут отслеживать своё состояние и управлять им. Можно указать IP-адрес или имя узла; для имени будет выполнено разрешение.

agent-port <port>

agent-port <port>

Допустимые контексты: tcp, http, log

Параметр “agent-port” задаёт порт TCP, используемый для проверок агента.

См. также параметры “agent-check” и “agent-inter”.

allow-0rtt

allow-0rtt

Может быть использован в следующих контекстах: tcp, http, log, peers, ring

Разрешает отправку ранних данных серверу при использовании TLS 1.3. Примечание: ранние данные будут отправлены только если клиент использовал ранние данные, или если бэкенд использует “retry-on” с ключевым словом “0rtt-rejected”. С QUIC, 0rtt поддерживается с QuicTLS, OpenSSL >= 3.5.2 и AWS-LC. С TCP/TLS, 0rtt поддерживается только с OpenSSL.

alpn <protocols>

alpn <protocols>

Допустимые контексты: tcp, http

Включает расширение TLS ALPN и объявляет через него указанный список поддерживаемых протоколов. Имена протоколов разделяются запятыми, например “http/1.1,http/1.0” (без кавычек). Библиотека SSL должна быть собрана с поддержкой расширений TLS (проверяется командой haproxy -vv). ALPN заменяет первоначальное расширение NPN. ALPN требуется для подключения к серверам HTTP/2, а также для использования HTTP/3 через сервер QUIC. Для серверов QUIC без “alpn” по умолчанию используется “h3”. Версии OpenSSL до 1.0.2 не поддерживали ALPN и поддерживали только устаревшее теперь расширение NPN. Если предполагается поддержка и HTTP/2, и HTTP/1.1, можно объявить обе версии в порядке предпочтения, как ниже:

server 127.0.0.1:443 ssl crt pub.pem alpn h2,http/1.1

См. также “ws” для использования альтернативного ALPN для потоков WebSocket.

backup

backup

Допустимые контексты: tcp, http, log

При наличии “backup” в строке сервера он участвует в балансировке нагрузки только тогда, когда недоступны все остальные нерезервные серверы. Однако запросы с cookie привязки сеанса, указывающим на этот сервер, обслуживаются всегда. По умолчанию используется только первый работоспособный резервный сервер, если в бэкенде не задан параметр “allbackups”. См. также “no-backup” и “allbackups”.

ca-file <cafile>

ca-file <cafile>

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр доступен только тогда, когда в HAProxy включена поддержка OpenSSL. Он указывает на файл PEM из которого загружаются сертификаты CA, используемые для проверки сертификата сервера. Возможна загрузка каталога, содержащего несколько CA, в этом случае HAProxy попытается загрузить каждый “.pem”, “.crt”, “.cer” и .crl, доступный в каталоге, файлы, начинающиеся с точки, игнорируются.

Чтобы использовать доверенные CA вашей системы, параметр “@system-ca” может быть использован вместо cafile. Путь к этому каталогу может быть перезаписан с помощью установки переменной среды SSL_CERT_DIR.

cc <algo>

cc <algo>

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр доступен только на системах, которые определяют TCP_CONGESTION, и был протестирован на Linux и FreeBSD. Он принимает имя алгоритма управления перегрузкой TCP и настраивает исходящие соединения на использование этого алгоритма. Типичные имена включают “reno” или “cubic” и зависят от операционной системы. На некоторых системах для настройки определённых алгоритмов могут потребоваться специальные разрешения. На Linux доступные алгоритмы перечислены в sysctl “net.ipv4.tcp_available_congestion_control”, а разрешённые без привилегий — в “net.ipv4.tcp_allowed_congestion_control”. Для доступа к алгоритмам, требующим дополнительных разрешений, может потребоваться capability “cap_net_admin” (см. “setcap” в глобальной секции). В случае неудачи при настройке конкретного алгоритма управления перегрузкой используется алгоритм по умолчанию. См. также: ключевое слово bind “cc” (раздел 5.1 ).

check

check

Допустимые контексты: tcp, http, log

Этот параметр включает проверки работоспособности сервера: — если он не задан, проверки не выполняются и сервер всегда считается доступным. — Если он задан и другие методы проверки не настроены, сервер считается доступным, когда удалось установить соединение на самом верхнем из настроенных транспортных уровней. По умолчанию это TCP, а при “ssl” или “check-ssl” — SSL/TLS. В обоих случаях возможны префиксы соединения, например заголовок протокола PROXY при “send-proxy” или “check-send-proxy”. Для динамических серверов поведение немного отличается; подробности приведены ниже. — Если параметр задан и определена проверка на уровне приложения, обмены на этом уровне выполняются поверх настроенного транспорта. Сервер считается доступным, если все обмены успешны.

По умолчанию проверки выполняются по адресу и порту сервера с теми же параметрами инкапсуляции (SSL/TLS, заголовок протокола PROXY и т. д.). Адрес назначения можно изменить через “addr”, а порт — через “port”. В таком случае предполагается, что проверяется не порт сервиса, поэтому настроенные параметры инкапсуляции не используются повторно. Для отправки заголовков соединения необходимо явно задать “check-send-proxy”, а для использования SSL/TLS — “check-ssl”.

Примечание: не выполняется неявная настройка ssl и протокола PROXY для динамических серверов. В этом случае требуется явно использовать “check-ssl” и “check-send-proxy” при необходимости, даже если порт проверки не переопределён.

Когда “sni” или “alpn” заданы на строке сервера, их значение не используется для проверки работоспособности и необходимо использовать “check-sni” или “check-alpn”.

По умолчанию адрес источника для трафика проверки работоспособности совпадает с тем, который определён в бэкенде. Он может быть изменён с помощью ключевого слова “source”.

Интервал между проверками можно задать с помощью ключевого слова “inter”, а ключевые слова “rise” и “fall” могут быть использованы для определения количества успешных или неудачных проверок работоспособности, необходимых для обозначения сервера как доступного или недоступного.

Опциональные проверки работоспособности на уровне приложения могут быть настроены с помощью “option httpchk”, “option mysql-check” “option smtpchk”, “option pgsql-check”, “option ldap-check”, или “option redis-check”.

Пример:

# simple tcp check
backend foo
  server s1 192.168.0.1:80 check
# this does a tcp connect + tls handshake
backend foo
  server s1 192.168.0.1:443 ssl check
# simple tcp check is enough for check success
backend foo
  option tcp-check
  tcp-check connect
  server s1 192.168.0.1:443 ssl check

check-reuse-pool

check-reuse-pool

Допустимые контексты: tcp, http

Параметр позволяет проверкам повторно использовать свободные соединения при их наличии, не открывая отдельное соединение. После проверки соединение возвращается в пул. Основная цель — уменьшить число открытий и закрытий соединений с конкретным сервером. Возможность совместима только с наборами правил http-check и без предупреждения игнорируется для остальных типов проверок. Кроме того, в бэкенде следует задать политику повторного использования aggressive, поскольку каждая попытка проверки выполняется в отдельном сеансе.

Для упрощения конфигурации этот параметр игнорируется без уведомления, если определён какой-либо конкретный параметр подключения проверки, либо на строке сервера, либо в собственном правиле tcp-check connect.

Этот параметр автоматически включается для серверов, работающих в качестве пассивного шлюза обратного HTTP, поскольку для таких серверов подключение поддерживается только через переиспользование.

См. также: “check-pool-conn-name”

check-send-proxy

check-send-proxy

Допустимые контексты: tcp, http

Этот параметр заставляет генерировать строку протокола PROXY при исходящих проверках работоспособности, независимо от того, использует ли сервер send-proxy для обычного трафика. По умолчанию, протокол PROXY включается для проверок работоспособности, если он уже включен для обычного трафика, и если отсутствуют директивы “port” и “addr”. Однако, если такие директивы присутствуют, для принудительного использования протокола необходимо использовать параметр “check-send-proxy”. Дополнительную информацию см. в отношении параметра “send-proxy”.

check-alpn <protocols>

check-alpn <protocols>

Допустимые контексты: tcp, http

Задаёт протоколы, объявляемые через ALPN. Имена разделяются запятыми, например “http/1.1,http/1.0” (без кавычек). Если параметр не задан, используется ALPN сервера.

check-pool-conn-name <name>

check-pool-conn-name <name>

Допустимые контексты: tcp, http

При повторном использовании соединений для проверок заданное <name> служит идентификатором для поиска соответствующего соединения в пуле. Это аналог параметра сервера “pool-conn-name”. Если текущий параметр не задан, запасным значением служит “check-sni”.

См. также: “check-reuse-pool”

check-proto <name>

check-proto <name>

Допустимые контексты: tcp, http

Принудительно задаёт протокол мультиплексора для соединений проверки работоспособности сервера. Протокол должен быть совместим с типом проверки (TCP или HTTP) и пригоден для использования на стороне бэкенда. Список доступных протоколов выводит haproxy -vv. Для них указываются режим (TCP/HTTP), сторона (FE/BE), имя мультиплексора и его флаги.

Некоторые протоколы подвержены блокировке начала очереди на стороне сервера (flag=HOL_RISK). Некоторые не поддерживают смену протокола в существующем соединении (flag=NO_UPG). Также указывается совместимость с HTX (flag=HTX).

Здесь приведены протоколы, которые могут быть использованы в качестве аргумента директивы “check-proto” на строке сервера:

h2  : mode=HTTP  side=FE|BE  mux=H2    flags=HTX|HOL_RISK|NO_UPG
fcgi: mode=HTTP  side=BE     mux=FCGI  flags=HTX|HOL_RISK|NO_UPG
h1  : mode=HTTP  side=FE|BE  mux=H1    flags=HTX|NO_UPG
none: mode=TCP   side=FE|BE  mux=PASS  flags=NO_UPG
quic: mode=HTTP  side=FE|BE  mux=QUIC  flags=HTX|NO_UPG|FRAMED
spop: mode=SPOP  side=BE     mux=SPOP  flags=HOL_RISK|NO_UPG

Параметр позволяет обойти выбор наиболее подходящего протокола мультиплексора для соединений проверки работоспособности с этим сервером. Если он не определён, используется протокол сервера, если тот задан.

Если настроены ALPN или NPN, указанные в них протоколы следует согласовать с протоколом мультиплексора, чтобы избежать проблем. Например, при “proto h1” не следует задавать ALPN “h2”.

Настройка проверки работоспособности QUIC пока не полностью реализована. Во-первых, проверки QUIC могут выполняться только для серверов QUIC. Во-вторых, если указаны специфические параметры соединения для проверки на сервере QUIC, протокол проверки перейдёт к использованию TCP.

check-sni-auto

check-sni-auto

Допустимые контексты: tcp, http, log

Этот параметр включает автоматический выбор SNI при проверке работоспособности серверов через SSL, если значение не было задано ранее. Параметр включён по умолчанию, но может быть использован как “server” для сброса любого значения “no-check-sni-auto”, наследуемого из директивы “default-server” как значение по умолчанию. Он также может быть использован как “default-server” для сброса любого предыдущего значения “default-server” “no-check-sni-auto”.

Для соединений HTTPS SNI выбирается автоматически только при отсутствии правила “http-check connect”. Выбор основан на значении заголовка host, заданном директивой “option httpchk” или правилом “http-check send”. В правилах “http-check connect” автоматический выбор не выполняется. Для других протоколов параметр игнорируется.

Если используется автоматическое определение SNI для проверки работоспособности, то значение присваивается имени соединения, если задан параметр “check-reuse-pool”, за исключением случая, когда оно перекрывается ключевым словом сервера “check-pool-conn-name”.

См. опцию “sni-auto” для включения автоматического выбора SNI для прокси-трафика.

check-sni <sni>

check-sni <sni>

Допустимые контексты: tcp, http, log

Этот параметр позволяет указать SNI, используемый при проверке работоспособности через SSL. Возможна только строка для задания <sni>. Если необходимо задать SNI для проксированных потоков, см. “sni”.

check-ssl

check-ssl

Допустимые контексты: tcp, http, log

Этот параметр обеспечивает шифрование всех проверок работоспособности через SSL, независимо от того, использует ли сервер SSL для обычного трафика. Обычно этот параметр применяется тогда, когда указано явное “port” или “addr”, а проверки работоспособности через SSL не наследуются. Важно понимать, что данный параметр вставляет слой SSL на транспортном уровне ниже проверок, таким образом, простая проверка TCP соединения превращается в проверку SSL соединения, которая заменяет старую проверку ssl-hello-chk. Наиболее распространённый случай — отправка проверок HTTPS путём объединения проверок “httpchk” и SSL. Все настройки SSL распространяются на проверки работоспособности и трафик (например, шифры). См. параметр “ssl” для дополнительной информации и “no-check-ssl” для отключения этого параметра.

check-via-socks4

check-via-socks4

Допустимые контексты: tcp, http, log

Этот параметр включает исходящие проверки работоспособности с использованием прокси upstream socks4. По умолчанию проверки работоспособности не проходят через туннель socks, даже если такой туннель включен для обычного трафика.

ciphers <ciphers>

ciphers <ciphers>

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр доступен только при сборке с поддержкой OpenSSL. Этот параметр задаёт строку, описывающую список алгоритмов шифрования, согласуемых при рукопожатии SSL/TLS с сервером. Формат строки определён в документации “man 1 ciphers” от OpenSSL. Для дополнительной информации и рекомендаций см. например, (https://wiki.mozilla.org/Security/Server_Side_TLS ) и (https://mozilla.github.io/server-side-tls/ssl-config-generator/ ). Для настройки шифрования TLSv1.3 см. параметр “ciphersuites”.

ciphersuites <ciphersuites>

ciphersuites <ciphersuites>

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр доступен только при сборке с поддержкой OpenSSL и использовании OpenSSL 1.1.1 или более поздней версии для сборки HAProxy. Этот параметр задаёт строку, описывающую список алгоритмов шифрования, согласуемых во время TLS 1.3 рукопожатия с сервером. Формат строки определён в разделе “ciphersuites” документации OpenSSL, доступной по команде “man 1 ciphers”. Для настройки шифров TLSv1.2 и ранее обратитесь к ключевому слову “ciphers”.

client-sigalgs <sigalgs>

client-sigalgs <sigalgs>

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр доступен только при сборке с поддержкой OpenSSL. Устанавливает строку, описывающую список алгоритмов подписи, связанных с аутентификацией клиента, которые согласовываются. Формат строки определён в “man 3 SSL_CTX_set1_client_sigalgs” из страниц справки OpenSSL. Не рекомендуется использовать этот параметр, если не определён конкретный сценарий использования.

cookie <value>

cookie <value>

Допустимые контексты: http

Параметр “cookie” устанавливает значение куки, присваиваемое серверу, в <value>. Это значение будет проверяться в входящих запросах, и первый рабочий сервер, обладающий таким же значением, будет выбран. В ответ, в режимах вставки или переписывания куки, это значение будет присваиваться куки, отправляемой клиенту. Нет ничего неправильного в том, чтобы несколько серверов делили одно и то же значение куки, и это, в действительности, довольно распространено между обычными и резервными серверами. См. также ключевое слово “cookie” в секции бэкенда.

crl-file <crlfile>

crl-file <crlfile>

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он обозначает файл PEM из которого загружается список отозванных сертификатов, используемый для проверки сертификата сервера.

crt <cert>

crt <cert>

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он указывает на файл PEM из которого необходимо загружать как сертификат, так и соответствующий приватный ключ. Такой файл может быть создан путем конкатенации двух файлов PEM. Данный сертификат будет отправлен, если сервер запрашивает сертификат клиента.

Если файл не содержит приватного ключа, HAProxy попытается загрузить ключ по тому же пути, но с суффиксом “.key” (при условии, что опция “ssl-load-extra-files” установлена соответствующим образом).

curves <curves>

curves <curves>

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр доступен только при сборке с поддержкой OpenSSL. Устанавливает строку, описывающую список алгоритмов эллиптических кривых (“набор кривых”), которые согласовываются при рукопожатии SSL/TLS с ECDHE. Формат строки — это список названий кривых, разделённых двоеточием. Пример: “X25519:P-256” (без кавычек)

disabled

disabled

Допустимые контексты: tcp, http, log

Ключевое слово “disabled” запускает сервер в состоянии “disabled”. Это означает, что сервер отмечен как выключенный в режиме технического обслуживания, и никакое соединение, кроме тех, которые разрешены режимом persist, не достигнет его. Оно очень хорошо подходит для настройки новых серверов, поскольку обычный трафик никогда не достигнет их, при этом возможно тестирование сервиса с использованием механизма force-persist. См. также настройку “enabled”.

enabled

enabled

Допустимые контексты: tcp, http, log

В строке ‘server’ этот параметр позволяет сбросить настройку ‘disabled’, унаследованную из директивы ‘default-server’ как значение по умолчанию. В директиве ‘default-server’ он также может сбросить предыдущую настройку ‘default-server’ ‘disabled’.

error-limit <count>

error-limit <count>

Допустимые контексты: tcp, http, log

Если включено наблюдение за работоспособностью, параметр “error-limit” задаёт число последовательных ошибок, вызывающее событие, выбранное параметром “on-error”. По умолчанию — 10 последовательных ошибок.

См. также “check”, “error-limit” и “on-error”.

fall <count>

fall <count>

Допустимые контексты: tcp, http, log

Параметр “fall” устанавливает, что сервер считается неисправным после <count> последовательных неудачных проверок работоспособности. Значение по умолчанию для этого параметра равно 3, если параметр не указан. См. также параметры “check”, “inter” и “rise”.

force-sslv3

force-sslv3

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр обеспечивает использование только SSLv3 при SSL для связи с сервером. SSLv3 в целом менее затратен, чем соответствующие TLS при высокой интенсивности соединений. Этот параметр также доступен в глобальной директиве “ssl-default-server-options”. См. также “ssl-min-ver” и ssl-max-ver.

force-tlsv10

force-tlsv10

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр обеспечивает использование только TLSv1.0 при использовании SSL для связи с сервером. Этот параметр также доступен в глобальной директиве “ssl-default-server-options”. См. также “ssl-min-ver” и ssl-max-ver.

force-tlsv11

force-tlsv11

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр обеспечивает использование только TLSv1.1 при использовании SSL для связи с сервером. Этот параметр также доступен в глобальной директиве “ssl-default-server-options”. См. также “ssl-min-ver” и ssl-max-ver.

force-tlsv12

force-tlsv12

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр обеспечивает использование только TLSv1.2 при использовании SSL для связи с сервером. Этот параметр также доступен в глобальной директиве “ssl-default-server-options”. См. также “ssl-min-ver” и ssl-max-ver.

force-tlsv13

force-tlsv13

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр обеспечивает использование только TLSv1.3 при использовании SSL для связи с сервером. Этот параметр также доступен в глобальной директиве “ssl-default-server-options”. См. также “ssl-min-ver” и ssl-max-ver.

guid <string>

guid <string>

Допустимые контексты: tcp, http, log

Задаёт глобально уникальный идентификатор с учётом регистра для этого сервера. Этот идентификатор должен быть уникальным во всей конфигурации HAProxy на всех типах объектов. См. описание ключевого слова “guid” прокси для получения дополнительной информации о его формате. См. также “shm-stats-file”.

hash-key <key>

hash-key <key>

Допустимые контексты: tcp, http, log

Задаёт способ вычисления ключей узлов для “hash-type consistent”

Аргументы:

<key>   <key> может принимать одно из следующих значений:

  id         Ключи узлов вычисляются из числового идентификатора сервера,
             заданного через "id" или по умолчанию равного его позиции
             в списке серверов. Это значение по умолчанию. Используются
             только 20 младших битов ID (то есть (id % 1048576)),
             поэтому во избежание пересечений лучше задавать значения
             от 1 до этого числа.

  id32       Ключи узлов вычисляются из числового идентификатора сервера,
             заданного через "id" или по умолчанию равного его позиции
             в списке серверов. Используются все 32 бита ID, чтобы
             исключить коллизии. В отличие от "id", значение
             не масштабируется, поэтому рекомендуется всегда применять
             его с хеш-функцией (см. "hash-key") либо с явно заданными
             ID, равномерно распределёнными по 32-битному пространству.

  guid       Ключи узлов вычисляются из guid сервера, если он есть;
             иначе используется "id". Преимущество — полная независимость
             от порядка: используется только внутренний стабильный
             идентификатор, который можно повторить на множестве
             балансировщиков нагрузки.

  addr       Ключи узлов вычисляются из адреса сервера, если он есть;
             иначе используется "id".

  addr-port  Ключи узлов вычисляются из адреса и порта сервера,
             если они доступны; иначе используется "id".

Опции “addr” и “addr-port” могут быть полезны в сценариях, когда несколько процессов HAProxy распределяют трафик между одним и тем же набором серверов. Если порядок серверов в каждом процессе отличается (например, из-за того, что DNS записи были разрешены в различных порядках), то это позволит независимым процессам HAProxy согласовывать решения по маршрутизации. Примечание: “balance random” также использует “hash-type consistent”, и качество распределения будет зависеть от качества ключей.

healthcheck <name>

healthcheck <name>

Допустимые контексты: tcp, http

Задаёт секцию healthcheck, используемую для проверки сервера.

Аргумент:

<name>    — имя секции healthcheck.

Параметр позволяет использовать отдельную конфигурацию проверки работоспособности для сервера вместо конфигурации прокси. См. также раздел о секции “healthcheck”.

id <value>

id <value>

Допустимые контексты: tcp, http, log

Установите постоянный идентификатор для сервера. Этот идентификатор должен быть положительным 32-битным числом и уникальным для прокси. Если идентификатор не задан, будет автоматически назначено свободное значение. Первое назначаемое значение будет 1. Этот идентификатор в настоящее время возвращается только в статистике и используется для размещения узлов балансировки нагрузки при использовании алгоритмов консистентного хэша, когда “hash-key” установлен в “id” (по умолчанию). В этом случае используются только 20 младших битов значения (то есть (id % 1048576)), поэтому лучше использовать значения, включенные в диапазон от 1 до этого значения, чтобы избежать пересечения.

idle-ping <delay>

idle-ping <delay>

Допустимые контексты: tcp, http, log

Задаёт интервал периодической проверки работоспособности простаивающих соединений бэкенда. Если другая сторона не ответит до следующей запланированной проверки, соединение закрывается. Ключевое слово относится к стороне бэкенда и позволяет убедиться, что простаивающие соединения всё ещё пригодны для использования. Это не предотвращает закрытие соединения при очистке пула простаивающих соединений.

Для этой возможности требуется поддержка нижележащего протокола. Пока она реализована только в мультиплексоре H2. Остальные протоколы просто игнорируют idle-ping.

Этот параметр особенно полезен при использовании обратного HTTP. Установка его на строке сервера полезна для однорангового узла, который ожидает входящие соединения и присоединяет их к соответствующему серверу, чтобы позже использовать для пересылки трафика.

init-addr {last | libc | none | <ip>},[...]*

init-addr {last | libc | none | <ip>},[...]*

Допустимые контексты: tcp, http, log

Укажите порядок разрешения адреса сервера при запуске, если он использует FQDN. При попытке разрешения адреса применяются по очереди все методы, перечисленные в списке, разделённом запятыми. Первый метод, который успешно работает, используется. Если конец списка достигнут без нахождения рабочего метода, генерируется ошибка. Метод “last” означает выбор адреса, присутствующего в файле состояния (см. “server-state-file”). Метод “libc” использует внутренний разрешитель libc (gethostbyname() или getaddrinfo() в зависимости от операционной системы и опций сборки). Метод “none” явно указывает на то, что сервер должен запускаться без действительного IP-адреса в состоянии down. Это может быть полезно для игнорирования некоторых DNS проблем при запуске, ожидая, пока ситуация будет исправлена позже. Наконец, может быть указан IP-адрес (IPv4 или IPv6). Он может быть текущим известным адресом сервера (например, заполненным конфигурационным генератором) или адресом виртуального сервера, используемого для перехвата старых сессий и предоставления при этом уместного сообщения об ошибке. При использовании алгоритма балансировки нагрузки “first” такой IP-адрес может указывать на фейковый сервер, используемый для запуска новых экземпляров на лету. Эта опция по умолчанию равна “last,libc”, что означает, что сначала используется предыдущий адрес из файла состояния (если он есть), иначе используется разрешитель libc. Это обеспечивает совместимость с историческим поведением. При использовании внутренних разрешителей рекомендуется либо отключать разрешение на основе libc, либо делать это явно (см. раздел 5.3 для дополнительной информации).

Пример 1:

defaults
    # never fail on address resolution
    default-server init-addr last,libc,none

Пример 2:

defaults
    # disable libc resolution in combination with resolvers
    default-server init-addr last,none

inter <delay>

inter <delay>
fastinter <delay>
downinter <delay>

Допустимые контексты: tcp, http, log

Параметр “inter” устанавливает интервал между двумя последовательными проверками работоспособности в <delay> миллисекунд. Если не указан, задержка по умолчанию равна 2000 ms. Также возможно использовать «fastinter» и «downinter» для оптимизации задержек между проверками в зависимости от состояния сервера:

    Состояние сервера                                       | Используемый интервал
    --------------------------------------------------------+------------------------------
    UP 100% (устойчивое состояние)                          | "inter"
    --------------------------------------------------------+------------------------------
    Переходное UP (в сторону отказа, "fall"),               | "fastinter", если задан,
    переходное DOWN (в сторону восстановления, "rise"),     | иначе "inter".
    либо ещё не проверен.                                   |
    --------------------------------------------------------+------------------------------
    DOWN 100% (устойчивое состояние)                        | "downinter", если задан,
                                                            | иначе "inter".
    --------------------------------------------------------+------------------------------

Так же, как и для всех других параметров, зависящих от времени, они могут быть указаны в любой из явных единиц: { us, ms, s, m, h, d }. Параметр “inter” также служит тайм-аутом для проверок работоспособности, отправляемых серверам, если “timeout check” не задан. Чтобы снизить эффект “резонанса” при размещении нескольких серверов на одном оборудовании, запуск проверок через агента и обычных проверок работоспособности всех серверов производится с небольшим временным смещением между ними. Также возможно добавить некоторое случайное отклонение в интервалы проверок через агента и обычных проверок работоспособности с помощью глобального параметра “spread-checks”. Это имеет смысл, например, когда большое количество бэкендов использует одни и те же серверы. Глобальный параметр “tune.max-checks-per-thread”, если задан с ненулевым значением, ограничивает количество одновременно выполняемых проверок на любом из потоков. Для достижения этого HAProxy помещает в очередь проверки, которые планировались начать на потоке, достигшем этого предела, до тех пор, пока не завершится другая проверка. Это приведёт к увеличению эффективного интервала проверок. В таком случае сокращение параметра “inter” будет иметь очень ограниченное влияние, поскольку не сможет сократить время, затрачиваемое на ожидание в очереди.

init-state { fully-up | up | down | fully-down | none }

init-state { fully-up | up | down | fully-down | none }

Допустимые контексты: tcp, http

Допустимые секции: defaults | frontend | listen | backend нет | нет | да | да

Опция “init-state” устанавливает начальное состояние сервера: - при значении ‘fully-up’ сервер считается немедленно доступным и, если включены проверки работоспособности для этого сервера, он будет переключен в состояние DOWN при неудаче всех проверок работоспособности. - при значении ‘up’ сервер считается немедленно доступным и, если включены проверки работоспособности для этого сервера, он будет немедленно переключен в состояние DOWN при неудаче следующей проверки работоспособности. - при значении ‘down’ сервер считается изначально недоступным и, если включены проверки работоспособности для этого сервера, он может быть переключен в состояние UP при успешной следующей проверке работоспособности. - при значении ‘fully-down’ сервер считается изначально недоступным и, если включены проверки работоспособности для этого сервера, он будет переключен в состояние UP при успешности всех проверок работоспособности. - при значении ’none’ (по умолчанию), управление init-state отключено. Оно может использоваться для восстановления стандартного поведения, когда этот параметр наследовался от директивы ‘default-server’.

Когда HAProxy-экземпляр запускается (перезапускается), обнаруживается новый сервер (например, через обнаружение сервисов / разрешение имён DNS), динамический сервер включается, сервер выходит из режима технического обслуживания и т.д., используется директива сервера init-state. Эта директива не может использоваться, когда сервер отслеживает другой сервер.

Примеры:

# pass client traffic ONLY to Redis "master" node
backend redis-master
  mode tcp
  balance first
  option tcp-check
  tcp-check send role\r\n
  tcp-check expect string master
  server-template redis 3 _redis._tcp.redis-headless-service.sandbox.svc.cluster.local:6379 check ... init-state down

# pass traffic to the server only after 3 successful health checks
backend google-backend
  mode http
  server srv1 google.com:80 check init-state fully-down rise 3
  server srv2 google.com:80 check init-state fully-down rise 3

См. также: “option tcp-check”, “option httpchk”

ktls <on|off> [ EXPERIMENTAL ]

ktls <on|off> [ EXPERIMENTAL ]

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Включает или отключает ktls для этих сокетов. При включении kTLS будет использоваться, если ядро поддерживает kTLS и используемый шифр совместим. Доступно только на Linux 4.17 и выше. Примечание: некоторые сетевые драйверы и/или TLS стеки могут ограничивать использование kTLS только для TLS v1.2. См. также “force-tlsv12”.

log-bufsize <bufsize>

log-bufsize <bufsize>

Допустимые контексты: log

“log-bufsize” задаёт размер буфера неявного кольца, которое связывается с сервером журналов в бэкенде log. По умолчанию используется BUFSIZE. Большее значение увеличивает расход памяти, но может предотвратить потерю сообщений при медленных серверах, поскольку буфер вмещает больше ожидающих отправки сообщений. Ключевое слово допустимо только в секциях backend для журналов (с “mode log”).

log-proto <logproto>

log-proto <logproto>

Допустимые контексты: log, ring

“log-proto” задаёт протокол передачи сообщений о событиях серверу, настроенному в секции log или ring. Допустимы “legacy” и “octet-count”, соответствующие методам «непрозрачного разделения кадров» и «подсчёта октетов» в rfc6587. По умолчанию — “legacy”.

maxconn <maxconn>

maxconn <maxconn>

Допустимые контексты: tcp, http

Параметр “maxconn” указывает на максимальное количество одновременных соединений, которые будут отправлены на этот сервер. Если количество входящих одновременных соединений превышает указанное значение, они будут помещены в очередь и ожидать освобождения слота. Этот параметр очень важен, поскольку может предотвратить выход слабых серверов из строя под экстремальными нагрузками. Если указан параметр “minconn”, ограничение становится динамическим. Значение по умолчанию — “0”, что означает неограниченное количество. См. также параметры “minconn” и “maxqueue”, а также ключевое слово “fullconn” бэкенда.

В режиме HTTP этот параметр ограничивает количество одновременных запросов, а не количество соединений. Множественные запросы могут быть мультиплексированы через одно соединение TCP к серверу. Например, если вы укажете значение maxconn в виде 50, вы можете наблюдать от 1 до 50 фактических соединений с сервером, но не более чем 50 одновременных запросов.

maxqueue <maxqueue>

maxqueue <maxqueue>

Допустимые контексты: tcp, http

Параметр “maxqueue” задаёт максимальное количество соединений, которые будут ждать в очереди для этого сервера. Если это ограничение достигнуто, последующие запросы будут перенаправлены на другие серверы вместо бесконечного ожидания обслуживания. Это нарушит привязку сеанса, но может позволить пользователям быстро повторно войти, если сервер, к которому они пытаются подключиться, выходит из строя. Некоторые алгоритмы балансировки нагрузки, такие как leastconn, учитывают это и допускают добавление запросов в очередь сервера до указанного значения, если оно явно установлено в значение, превышающее ноль, что часто позволяет лучше сгладить нагрузку при работе с однозначными значениями maxconn. Значение по умолчанию — “0”, что означает отсутствие ограничения на очередь. См. также параметры “maxconn” и “minconn” и “balance leastconn”.

max-reuse <count>

max-reuse <count>

Может использоваться в следующих контекстах: http, ring

При использовании в контексте http:

Аргумент “max-reuse” указывает обработчикам соединений HTTP не использовать соединение с сервером повторно для новых запросов больше заданного числа раз. Допустимы -1 (по умолчанию), отключающее ограничение, и любое положительное значение. Ноль фактически отключает keep-alive. Параметр служит только для обхода ошибок серверов, приводящих к постепенной утечке ресурсов. Нижележащие уровни не обязательно соблюдают его из-за технических ограничений. По крайней мере соединения HTTP/2 с серверами это ограничение соблюдают.

При использовании в контексте ring:

Аргумент “max-reuse” указывает обработчикам соединений TCP приёмника не использовать соединение с сервером повторно для отправки сообщений больше заданного числа раз. Соединение принудительно закрывается после обработки в нём не менее “max-reuse + 1” сообщений, затем создаётся заново автоматически. При большом числе сообщений и многопоточной работе это помогает равномернее распределять нагрузку кольца между потоками. Каждое соединение привязано к одному потоку CPU на всё время существования: в отличие от HTTP, в syslog нет транзакций, поэтому соединение может жить неограниченно долго, пока сервер его не закроет или не произойдёт сетевая ошибка. Периодическое закрытие даёт другим потокам возможность по очереди обрабатывать сообщения. Это также может помочь плавно сменять серверы журналов, когда между ними и HAProxy есть дополнительный уровень балансировки нагрузки. Однако после каждого пересоздания соединения исходящий порт остаётся в TIME_WAIT и на современных ОС около минуты недоступен для повторного использования. Поэтому нельзя задавать слишком малые значения, чтобы быстро не исчерпать исходящие порты. Как правило, следует закрывать соединения не чаще нескольких раз в секунду, а лучше значительно реже. Допустимы -1 (по умолчанию), отключающее ограничение, и любое положительное значение. В отличие от HTTP, для серверов-приёмников “max-reuse” соблюдается по мере возможности: сообщения кольца обрабатываются пакетами, и ограничение проверяется между пакетами.

minconn <minconn>

minconn <minconn>

Допустимые контексты: tcp, http

При заданном “minconn” ограничение maxconn становится динамическим и зависит от нагрузки бэкенда. Сервер всегда допускает не менее <minconn> соединений и не более <maxconn>. Если в бэкенде меньше <fullconn> одновременных соединений, предел плавно растёт между этими значениями. Это ограничивает нагрузку на сервер в обычном режиме и позволяет повысить её при большой нагрузке, не перегружая сервер при исключительных пиках. См. также “maxconn”, “maxqueue” и ключевое слово бэкенда “fullconn”.

namespace <name>

namespace <name>

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

В Linux возможно указать, какому сетевому пространству имён будет принадлежать сокет. Эта директива позволяет явно привязать сервер к пространству имен, отличному от стандартного. Для получения дополнительной информации о сетевых пространствах см. документацию операционной системы.

no-agent-check

no-agent-check

Допустимые контексты: tcp, http, log

В строке “server” этот параметр позволяет сбросить настройку “agent-check”, унаследованную из директивы “default-server” как значение по умолчанию. В директиве “default-server” он также может сбросить предыдущую настройку “default-server” “agent-check”.

no-backup

no-backup

Допустимые контексты: tcp, http, log

В строке “server” этот параметр позволяет сбросить настройку “backup”, унаследованную из директивы “default-server” как значение по умолчанию. В директиве “default-server” он также может сбросить предыдущую настройку “default-server” “backup”.

no-check

no-check

Допустимые контексты: tcp, http, log

В строке “server” этот параметр позволяет сбросить настройку “check”, унаследованную из директивы “default-server” как значение по умолчанию. В директиве “default-server” он также может сбросить предыдущую настройку “default-server” “check”.

no-check-reuse-pool

no-check-reuse-pool

Допустимые контексты: tcp, http

Отменяет ранее заданный “check-reuse-pool”, в том числе унаследованный из “default-server”. Каждая проверка выполняется через отдельное соединение.

no-check-sni-auto

no-check-sni-auto

Допустимые контексты: tcp, http, log

В строке “server” этот параметр позволяет отключить автоматический выбор SNI для проверок работоспособности через SSL. По умолчанию автоматический выбор включён.

См. опцию “no-sni-auto” для отключения автоматического выбора SNI для прокси-трафика.

no-check-ssl

no-check-ssl

Допустимые контексты: tcp, http, log

В строке “server” этот параметр позволяет сбросить настройку “check-ssl”, унаследованную из директивы “default-server” как значение по умолчанию. В директиве “default-server” он также может сбросить предыдущую настройку “default-server” “check-ssl”.

no-renegotiate

no-renegotiate

Допустимые контексты: tcp, http, log

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он отключает механизмы повторного согласования SSL для указанного бэкенда: и устаревший небезопасный, и более новый безопасный (расширение TLS Renegotiation Indication, RFC 5746). Параметр также доступен в глобальной директиве “ssl-default-server-options”. В TLS 1.3 повторное согласование уже невозможно. Если не указан ни “renegotiate”, ни “no-renegotiate”, сохраняется поведение библиотеки SSL по умолчанию. Например, OpenSSL по умолчанию включает безопасное повторное согласование, а AWS-LC отключает. См. также “renegotiate”.

no-send-proxy

no-send-proxy

Допустимые контексты: tcp, http

В строке “server” этот параметр позволяет сбросить настройку “send-proxy”, унаследованную из директивы “default-server” как значение по умолчанию. В директиве “default-server” он также может сбросить предыдущую настройку “default-server” “send-proxy”.

no-send-proxy-v2

no-send-proxy-v2

Допустимые контексты: tcp, http

В строке “server” этот параметр позволяет сбросить настройку “send-proxy-v2”, унаследованную из директивы “default-server” как значение по умолчанию. В директиве “default-server” он также может сбросить предыдущую настройку “default-server” “send-proxy-v2”.

no-send-proxy-v2-ssl

no-send-proxy-v2-ssl

Допустимые контексты: tcp, http

В строке “server” этот параметр позволяет сбросить настройку “send-proxy-v2-ssl”, унаследованную из директивы “default-server” как значение по умолчанию. В директиве “default-server” он также может сбросить предыдущую настройку “default-server” “send-proxy-v2-ssl”.

no-send-proxy-v2-ssl-cn

no-send-proxy-v2-ssl-cn

Допустимые контексты: tcp, http

В строке “server” этот параметр позволяет сбросить настройку “send-proxy-v2-ssl-cn”, унаследованную из директивы “default-server” как значение по умолчанию. В директиве “default-server” он также может сбросить предыдущую настройку “default-server” “send-proxy-v2-ssl-cn”.

no-sni-auto

no-sni-auto

Может быть использован в следующих контекстах: tcp, http, log, peers, ring

Этот параметр может быть использован как “server” настройка для отключения автоматического выбора SNI, включенного по умолчанию.

См. параметр “no-check-sni-auto” для отключения автоматического выбора SNI для проверки работоспособности SSL.

no-ssl

no-ssl

Может быть использован в следующих контекстах: tcp, http, log, peers, ring

В строке “server” этот параметр позволяет сбросить настройку “ssl”, унаследованную из директивы “default-server” как значение по умолчанию. В директиве “default-server” он также может сбросить предыдущую настройку “default-server” “ssl”.

Примечание: использование default-server ssl настройки и no-ssl на сервере инициализирует SSL соединение, поэтому его можно включить позже через runtime API: см. команды set server в документации по управлению.

no-ssl-reuse

no-ssl-reuse

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр отключает повторное использование сеансов SSL при использовании SSL для связи с сервером. Он будет вынуждать сервер выполнять полное рукопожатие для каждого нового соединения. Вероятно, полезен только для бенчмаркинга, устранения неполадок и для пользователей с повышенной осторожностью.

no-sslv3

no-sslv3

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр отключает поддержку SSLv3 при использовании SSL для связи с сервером. Примечание, что SSLv2 отключён в коде и не может быть включён с помощью любого параметра конфигурации. Используйте “ssl-min-ver” и “ssl-max-ver” вместо этого.

Доступен в default-server: Нет

no-tls-tickets

no-tls-tickets

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр доступен только при сборке с поддержкой OpenSSL. Он отключает возобновление сеансов без хранения состояния (расширение TLS Ticket, RFC 5077) и принудительно включает возобновление с хранением состояния. Возобновление без хранения состояния требует больше ресурсов CPU на серверах. Параметр также доступен в глобальной директиве “ssl-default-server-options”. Механизм билетов TLS используется только до TLS 1.2 включительно. При использовании билетов TLS прямая секретность нарушается, если их ключи не заменяются регулярно (через перезагрузку конфигурации или с помощью “tls-ticket-keys”). См. также “tls-tickets”.

no-tlsv10

no-tlsv10

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр отключает поддержку TLSv1.0 при использовании SSL для связи с сервером. Примечание, что SSLv2 отключён в коде и не может быть включён с помощью любого параметра конфигурации. TLSv1 дороже, чем SSLv3, поэтому часто имеет смысл отключать его при связи с локальными серверами. Этот параметр также доступен в глобальной директиве “ssl-default-server-options”. Используйте “ssl-min-ver” и “ssl-max-ver” вместо этого.

Доступен в default-server: Нет

no-tlsv11

no-tlsv11

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр отключает поддержку TLSv1.1 при использовании SSL для связи с сервером. Примечание, что SSLv2 отключён в коде и не может быть включён с помощью любого параметра конфигурации. TLSv1 дороже, чем SSLv3, поэтому часто имеет смысл отключать его при связи с локальными серверами. Этот параметр также доступен в глобальной директиве “ssl-default-server-options”. Используйте “ssl-min-ver” и “ssl-max-ver” вместо этого.

Доступен в default-server: Нет

no-tlsv12

no-tlsv12

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр отключает поддержку TLSv1.2 при использовании SSL для связи с сервером. Примечание, что SSLv2 отключён в коде и не может быть включён с помощью любого параметра конфигурации. TLSv1 дороже, чем SSLv3, поэтому часто имеет смысл отключать его при связи с локальными серверами. Этот параметр также доступен в глобальной директиве “ssl-default-server-options”. Используйте “ssl-min-ver” и “ssl-max-ver” вместо этого.

Доступен в default-server: Нет

no-tlsv13

no-tlsv13

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр отключает поддержку TLSv1.3 при использовании SSL для связи с сервером. Примечание, что SSLv2 отключён в коде и не может быть включён с помощью любого параметра конфигурации. TLSv1 дороже, чем SSLv3, поэтому часто имеет смысл отключать его при связи с локальными серверами. Этот параметр также доступен в глобальной директиве “ssl-default-server-options”. Используйте “ssl-min-ver” и “ssl-max-ver” вместо этого.

Доступен в default-server: Нет

no-verifyhost

no-verifyhost

Может быть использован в следующих контекстах: tcp, http, log, peers, ring

В строке “server” этот параметр позволяет сбросить настройку “verifyhost”, унаследованную из директивы “default-server” как значение по умолчанию. В директиве “default-server” он также может сбросить предыдущую настройку “default-server” “verifyhost”.

no-tfo

no-tfo

Может быть использован в следующих контекстах: tcp, http, log, peers, ring

В строке “server” этот параметр позволяет сбросить настройку “tfo”, унаследованную из директивы “default-server” как значение по умолчанию. В директиве “default-server” он также может сбросить предыдущую настройку “default-server” “tfo”.

non-stick

non-stick

Допустимые контексты: tcp, http

Никогда не добавляет соединения, назначенные этому серверу, в stick-table. Может использоваться вместе с backup, чтобы отключить привязку сеансов по stick-table для резервных серверов.

npn <protocols>

npn <protocols>

Допустимые контексты: tcp, http

Включает расширение TLS NPN и объявляет через него указанный список поддерживаемых протоколов. Имена протоколов разделяются запятыми, например “http/1.1,http/1.0” (без кавычек). Библиотека SSL должна быть собрана с поддержкой расширений TLS (проверяется командой haproxy -vv). Расширение NPN заменено расширением ALPN (см. “alpn”), но последнее доступно только начиная с OpenSSL 1.0.2.

observe <mode>

observe <mode>

Допустимые контексты: tcp, http

Этот параметр включает корректировку состояния работоспособности по результатам наблюдения за обменом с сервером. По умолчанию данная функция отключена и для её включения необходимо также включить проверку работоспособности. Поддерживаются два режима: “layer4” и “layer7”. В режиме “layer4” значимы только успешные и неуспешные TCP-соединения. В режиме “layer7”, который допускается только для HTTP-прокси, проверяются ответы, получаемые от сервера, например, корректные/ошибочные HTTP-коды, заголовки, которые невозможно разобрать, тайм-аут и т.д. Корректные коды состояний включают 100 до 499, 501 и 505.

См. также “check”, “on-error” и “error-limit”.

on-error <mode>

on-error <mode>

Допустимые контексты: tcp, http, log

Выберите, что должно произойти при обнаружении достаточного количества последовательных ошибок. В настоящее время доступны четыре режима:

  • fastinter: принудительно включить fastinter
  • fail-check: имитировать неудачную проверку работоспособности, также принудительно включает fastinter (по умолчанию)
  • sudden-death: имитировать неудачную проверку работоспособности перед критическим сбоем, один дополнительный неудачный результат проверки помечает сервер как выключенный, принудительно включает fastinter
  • mark-down: немедленно помечает сервер как выключенный и принудительно включает fastinter

См. также “check”, “observe” и “error-limit”.

on-marked-down <action>

on-marked-down <action>

Допустимые контексты: tcp, http, log

Задаёт действие при переходе сервера в состояние недоступности. В настоящее время доступно одно действие:

  • shutdown-sessions: Завершение потоков однорангового узла. При включении этого параметра все соединения с сервером немедленно прекращаются при выходе сервера из строя. Этот параметр может быть использован, если проверка работоспособности выявляет более сложные случаи, чем простое состояние соединения, и длительные тайм-ауты приводят к тому, что сервис остаётся неотвечаемым слишком долго. Например, проверка работоспособности может обнаружить, что база данных застряла, и уже невозможно использовать существующие соединения. Соединения, завершённые таким образом, логируются с кодом завершения ‘D’ (для “Down”).

Действия отключены по умолчанию

on-marked-up <action>

on-marked-up <action>

Допустимые контексты: tcp, http, log

Задаёт действие при переходе сервера в состояние доступности. В настоящее время доступно одно действие:

  • shutdown-backup-sessions: Завершение потоков на всех резервных серверах. Это выполняется только если сервер не является резервным и не отключён (его эффективный вес > 0). Такое действие может быть использовано в некоторых случаях для принудительного возврата всего трафика на активный сервер после восстановления при работе с длительными сессиями (например, LDAP, SQL, …). Использование этой функции может привести к большему количеству проблем, чем оно решает (например, незавершённые транзакции), поэтому эта функция должна использоваться с крайней осторожностью. Потоки, завершённые из-за восстановления доступности сервера, логируются с кодом завершения ‘U’ (для “Up”).

Действия отключены по умолчанию

pool-conn-name <expr>

pool-conn-name <expr>

Допустимые контексты: http

При установке соединения с бэкендом это выражение вычисляется для формирования имени соединения. Имя — одно из ключевых свойств соединения в пуле простаивающих соединений с серверами. См. “http-reuse”. Когда для запроса ищется существующее простаивающее соединение, выражение вычисляется для поиска совпадения.

Если для соединения с бэкендом используется SSL SNI, имени соединения автоматически присваивается результат выражения “sni”. Это подходит для большинства случаев. Для более сложных конфигураций значение можно переопределить через “pool-conn-name”.

См. также: “http-reuse”, “sni”

pool-low-conn <max>

pool-low-conn <max>

Допустимые контексты: http

Задаёт нижний порог числа простаивающих соединений с сервером, ниже которого поток не пытается забрать соединение у другого потока. Это может улучшить использование CPU при работе со множеством очень быстрых серверов: каждый поток постоянно сохраняет несколько свободных соединений, вместо того чтобы они накапливались в одном потоке и перемещались между потоками. Типичное значение, равное удвоенному числу потоков, по-видимому, уже показывает очень хорошую производительность при времени ответа менее миллисекунды. По умолчанию используется ноль: любое простаивающее соединение можно использовать в любой момент. Это рекомендуемая настройка для обычной работы. Параметр относится только к соединениям, допускающим совместное использование по тем же принципам, что и “http-reuse”. Если совместное использование соединений между потоками отключено через “tune.idle-pool.shared”, параметр может быть особенно важен для сохранения нескольких соединений в каждом потоке. Иначе доля повторно используемых соединений снижается с ростом числа потоков.

pool-max-conn <max>

pool-max-conn <max>

Допустимые контексты: http

Задаёт максимальное число простаивающих соединений с сервером. -1 означает отсутствие ограничения, 0 — отсутствие таких соединений. По умолчанию — -1. Если простаивающие соединения разрешены, соединения, больше не принадлежащие ни одному клиентскому сеансу, перемещаются в отдельный пул для использования будущими клиентами. Это относится только к соединениям, допускающим совместное использование по тем же принципам, что и “http-reuse”.

pool-purge-delay <delay>

pool-purge-delay <delay>

Допустимые контексты: http

Задаёт задержку перед началом очистки простаивающих соединений. Через каждый интервал <delay> закрывается половина таких соединений. 0 означает, что простаивающие соединения не сохраняются. По умолчанию — 5s.

port <port>

port <port>

Допустимые контексты: tcp, http, log

Используя параметр “port”, становится возможным отправлять проверки работоспособности через другой порт или проводить пробы на agent-check. На некоторых серверах может быть желательно выделить порт для конкретного компонента, способного выполнять сложные тесты, более подходящие для проверок работоспособности, чем приложение. Обычно для этого запускают простой скрипт в inetd. Параметр игнорируется, если не задан параметр “check”. См. также параметр “addr”.

proto <name>

proto <name>

Допустимые контексты: tcp, http

Принудительно задаёт протокол мультиплексора для исходящих соединений с этим сервером. Протокол должен быть совместим с режимом бэкенда (TCP или HTTP) и пригоден для использования на стороне бэкенда. Список доступных протоколов выводит haproxy -vv. Для них указываются режим (TCP/HTTP), сторона (FE/BE), имя мультиплексора и его флаги.

Некоторые протоколы подвержены блокировке начала очереди на стороне сервера (flag=HOL_RISK). Некоторые не поддерживают смену протокола в существующем соединении (flag=NO_UPG). Также указывается совместимость с HTX (flag=HTX).

Здесь приведены протоколы, которые могут быть использованы в качестве аргумента директивы “proto” на строке сервера:

quic: mode=HTTP  side=FE|BE  mux=QUIC  flags=HTX|NO_UPG|FRAMED
qmux: mode=HTTP  side=FE|BE  mux=QMUX  flags=HTX|NO_UPG
h2  : mode=HTTP  side=FE|BE  mux=H2    flags=HTX|HOL_RISK|NO_UPG
fcgi: mode=HTTP  side=BE     mux=FCGI  flags=HTX|HOL_RISK|NO_UPG
h1  : mode=HTTP  side=FE|BE  mux=H1    flags=HTX|NO_UPG
none: mode=TCP   side=FE|BE  mux=PASS  flags=NO_UPG
spop: mode=SPOP  side=BE     mux=SPOP  flags=HOL_RISK|NO_UPG

Параметр позволяет обойти выбор наиболее подходящего протокола мультиплексора для всех соединений с этим сервером.

Если настроены ALPN или NPN, указанные в них протоколы следует согласовать с протоколом мультиплексора, чтобы избежать проблем. Например, при “proto h1” не следует задавать ALPN “h2”.

См. также “ws” для использования альтернативного протокола для потоков WebSocket.

QMux — это подмножество QUIC, работающее над TCP. Оно соответствует следующему черновому протоколу https://www.ietf.org/archive/id/draft-ietf-quic-qmux-01.html . На данный момент считается экспериментальным в HAProxy.

quic-cc-algo { cubic | newreno | bbr | nocc }[(<args,...>)]

quic-cc-algo { cubic | newreno | bbr | nocc }[(<args,...>)]

Специальный параметр QUIC для выбора алгоритма управления перегрузкой для всех соединений с этим сервером. Эти алгоритмы аналогичны используемым в TCP. Полное описание настроек приведено у одноимённого параметра bind.

Значение по умолчанию: cubic

См. также: “tune.quic.be.tx.pacing” и “tune.quic.be.cc.max-win-size”

redir <prefix>

redir <prefix>

Допустимые контексты: http

Параметр “redir” включает режим перенаправления для всех запросов GET и HEAD, адресующих данный сервер. Это означает, что вместо того чтобы передавать запрос серверу, HAProxy отправляет ответ «HTTP 302» с заголовком «Location», состоящим из этого префикса, сразу за которым следует запрошенный URI начиная с ведущего ‘/’ компонента пути. Это означает, что после <prefix> не должен использоваться завершающий слэш. Все невалидные запросы будут отклонены, а все запросы, кроме GET и HEAD, будут нормально обрабатываться сервером. Примечание: поскольку ответ полностью синтезирован, в ответе невозможно изменять заголовки или вставлять куки. Однако куки в запросах всё ещё анализируются, что делает это решение полностью применимым для направления пользователей к удалённому месту в случае локальной катастрофы. Основное применение заключается в увеличении пропускной способности статических серверов за счёт прямого подключения клиентов к ним. Примечание: никогда не используйте относительный путь здесь, иначе возникнет цикл между клиентом и HAProxy!

Пример: server srv1 192.168.1.1:80 redir http://image1.mydomain.com check

renegotiate

renegotiate

Допустимые контексты: tcp, http, log

Этот параметр включает механизм безопасного повторного согласования (RFC 5746 TLS Расширение указания повторного согласования) для заданного бэкенда SSL. Это не означает, что клиент SSL будет отправлять запросы на повторное согласование, он лишь разрешает бэкендам проводить повторное согласование при запросе серверов. Требуется, чтобы лежащая в основе библиотека SSL фактически поддерживала повторное согласование. Этот параметр также доступен на глобальном уровне в операторе “ssl-default-server-options”. Повторное согласование больше невозможно в TLS 1.3. Если ни “renegotiate”, ни “no-renegotiate” не указаны, сохраняется поведение по умолчанию библиотеки SSL. Обратите внимание, что, например, библиотека OpenSSL включает безопасное повторное согласование по умолчанию, в то время как AWS-LC отключает его.

rise <count>

rise <count>

Допустимые контексты: tcp, http, log

Параметр “rise” указывает, что сервер будет считаться работоспособным после <count> успешных последовательных проверок работоспособности. Значение по умолчанию равно 2, если параметр не указан. См. также параметры “check”, “inter” и “fall”.

resolve-opts <option>,<option>,… Может быть использован в следующих контекстах: tcp, http, log

Список параметров через запятую, применяемых при разрешении имён DNS для этого сервера.

Доступные варианты:

  • allow-dup-ip По умолчанию HAProxy запрещает дублирование адресов IP в бэкенде при выполнении разрешения DNS в режиме работы. Однако в некоторых случаях оправдано, чтобы два сервера (в одном бэкенде, разрешаемые одним FQDN) имели один и тот же адрес IP. В таком случае включите эту опцию. Это противоположность prevent-dup-ip.

  • ignore-weight Игнорировать любое значение веса, установленное в записи SRV. Это полезно тогда, когда вы хотите управлять весами с помощью альтернативного метода, например, с помощью “agent-check” или через API времени выполнения.

  • prevent-dup-ip Обеспечить соблюдение стандартного поведения HAProxy на сервере: предотвратить повторное использование адреса IP, уже присвоенного серверу в одном бэкенде и имеющего одинаковое полное имя домена. Это противоположность allow-dup-ip.

Пример:

backend b_myapp
  default-server init-addr none resolvers dns
  server s1 myapp.example.com:80 check resolve-opts allow-dup-ip
  server s2 myapp.example.com:81 check resolve-opts allow-dup-ip

С опцией allow-dup-ip:

  • если сервер имён возвращает один IP-адрес, тогда оба сервера будут использовать его
  • Если сервер имён возвращает 2 IP-адреса, тогда каждый сервер будет использовать разный адрес

По умолчанию: не задано

resolve-prefer <family>

resolve-prefer <family>

Допустимые контексты: tcp, http, log

Когда включено разрешение DNS для сервера и возвращаются несколько адресов IP из разных семейств, HAProxy будет предпочтительно использовать адрес из семейства, указанного в параметре “resolve-prefer”. См. также глобальный параметр “dns-accept-family” для принудительного использования конкретного семейства. Доступные семейства: “ipv4” и “ipv6”.

Значение по умолчанию: ipv6

Пример:

server s1 app1.domain.com:80 resolvers mydns resolve-prefer ipv6

resolve-net <network>[,<network[,...]]

resolve-net <network>[,<network[,...]]

Допустимые контексты: tcp, http, log

Этот параметр приоритизирует выбор адреса IP, соответствующего сети. Это полезно в облаках для предпочтения локального IP. В некоторых случаях сервис высокой доступности в облаке может быть объявлен с множеством адресов в разных центрах обработки данных. Задержка между центрами обработки данных не является незначительной, поэтому данный параметр позволяет предпочтать локальный центр обработки данных. Если ни один адрес не соответствует настроенной сети, выбирается другой адрес.

Пример:

server s1 app1.domain.com:80 resolvers mydns resolve-net 10.0.0.0/8

resolvers <id>

resolvers <id>

Допустимые контексты: tcp, http, log

Указывает на существующую секцию “resolvers” для разрешения имени хоста текущего сервера. Часто рекомендуется отключать разрешение на основе libc при использовании разрешителей, хотя существуют исключения (см. раздел 5.3.1 ). В любом случае рекомендуется явно указывать “init-addr” при использовании разрешителей, чтобы не упустить этот элемент.

Пример:

server s1 app1.domain.com:80 init-addr last,none check resolvers mydns

См. также раздел 5.3 для деталей реализации и ловушек, на которые следует обратить внимание.

send-proxy

send-proxy

Допустимые контексты: tcp, http

Параметр “send-proxy” обеспечивает использование протокола PROXY при любом соединении, установленном с этим сервером. Протокол PROXY сообщает другой стороне об адресах уровня 3/4 входящего соединения, чтобы она могла узнать адрес клиента или публичный адрес, к которому он подключился, независимо от протокола верхнего уровня. Для соединений, принятых слушателем “accept-proxy” или “accept-netscaler-cip”, будет использоваться объявленный адрес. Поддерживаются только семейства адресов TCPv4 и TCPv6. Другие семейства, такие как Unix-сокеты, будут отображать семейство UNKNOWN. Серверы, использующие этот параметр, могут полностью быть связаны с другим экземпляром HAProxy, настроенным с параметром “accept-proxy”. Этот параметр не должен использоваться, если сервер не осведомлен о протоколе. При отправке проверок работоспособности на сервер, при наличии этого параметра, автоматически используется протокол PROXY, за исключением явного указания директивы “port” или “addr”, в случае чего потребуется также явная директива “check-send-proxy” для использования протокола PROXY. См. также параметр “no-send-proxy” данной секции и параметры “accept-proxy” и “accept-netscaler-cip” ключевого слова “bind”.

send-proxy-v2

send-proxy-v2

Допустимые контексты: tcp, http

Параметр “send-proxy-v2” обеспечивает использование версии протокола PROXY 2 при любом соединении, установленном с этим сервером. Протокол PROXY сообщает другой стороне об адресах уровня 3/4 входящего соединения, чтобы она могла узнать адрес клиента или публичный адрес, к которому он подключился, независимо от протокола верхнего слоя. Он также передаёт сведения об ALPN, если ALPN был согласован. Этот параметр не должен использоваться, если сервер не осведомлён об этой версии протокола. См. также опцию “no-send-proxy-v2” этой секции и опцию send-proxy ключевого слова “bind”.

set-proxy-v2-tlv-fmt(<id>) <fmt>

set-proxy-v2-tlv-fmt(<id>) <fmt>

Допустимые контексты: tcp, http

Параметр “set-proxy-v2-tlv-fmt” служит для отправки произвольных TLV протокола PROXY версии 2. Диапазоны определённых типов TLV (<id>) описаны в разделе 2.2.8 спецификации протокола PROXY. Значение можно выбирать свободно, если его длина не превышает 65,535 байт. Параметр также позволяет пересылать TLV: функция извлечения “fc_pp_tlv” получает TLV, принятый фронтендом. Параметр допустим в server и default-server. Для фактической отправки TLV PPv2 его необходимо сочетать с send-proxy-v2.

Пример: server srv1 192.168.1.1:80 send-proxy-v2 set-proxy-v2-tlv-fmt(0x20) %[fc_pp_tlv(0x20)]

В этом случае мы получаем TLV с типом 0x20 как строку и устанавливаем его в значение нового TLV, который также имеет тип 0x20.

proxy-v2-options <option>[,<option>]*

proxy-v2-options <option>[,<option>]*

Допустимые контексты: tcp, http

Параметр “proxy-v2-options” добавляет опции отправки в версии протокола PROXY 2 при использовании “send-proxy-v2”. Доступные опции:

  • ssl : См. также “send-proxy-v2-ssl”.
  • cert-cn : См. также “send-proxy-v2-ssl-cn”.
  • ssl-cipher: Название используемого шифра.
  • cert-sig : Алгоритм подписи используемого сертификата.
  • cert-key : Алгоритм ключа используемого сертификата
  • authority: Значение имени хоста, переданное клиентом (поддерживаются только SNI из соединения TLS).
  • crc32c : Контрольная сумма заголовка PROXYv2.
  • unique-id: Передача уникального идентификатора, сгенерированного с помощью “unique-id-format” фронтенда в заголовке PROXYv2. Уникальный идентификатор в первую очередь предназначен для “mode tcp”. Он может привести к непредвиденным результатам в “mode http”, поскольку сгенерированный уникальный идентификатор также используется для первого запроса HTTP в соединении Keep-Alive.

send-proxy-v2-ssl

send-proxy-v2-ssl

Допустимые контексты: tcp, http

Параметр “send-proxy-v2-ssl” обеспечивает использование версии протокола PROXY 2 при любом соединении, установленном с этим сервером. Протокол PROXY сообщает другой стороне об адресах уровня 3/4 входящего соединения, чтобы она могла узнать адрес клиента или публичный адрес, к которому он подключился, независимо от протокола верхнего слоя. Кроме того, в заголовок протокола PROXY добавляется расширение информации SSL протокола PROXY. Этот параметр нельзя использовать, если сервер не осведомлён об этой версии протокола. См. также опцию “no-send-proxy-v2-ssl” этой секции и опцию “send-proxy-v2” ключевого слова “bind”.

send-proxy-v2-ssl-cn

send-proxy-v2-ssl-cn

Допустимые контексты: tcp, http

Параметр “send-proxy-v2-ssl” обеспечивает использование версии протокола PROXY 2 при любом соединении, установленном с этим сервером. Протокол PROXY сообщает другой стороне об адресах уровня 3/4 входящего соединения, чтобы она могла узнать адрес клиента или публичный адрес, к которому он обращался, независимо от протокола верхнего слоя. Кроме того, расширение информации SSL протокола PROXY, а также общее имя (Common Name) из субъекта сертификата клиента (если имеется), добавляется в заголовок протокола PROXY. Этот параметр нельзя использовать, если сервер не осведомлён об этой версии протокола. См. также опцию “no-send-proxy-v2-ssl-cn” этой секции и опцию “send-proxy-v2” ключевого слова “bind”.

shard <shard>

shard <shard>

Допустимые контексты: peers

Параметр используется только при синхронизации stick-table по протоколу peers. “shard” определяет узлы, получающие все обновления stick-table для ключей, чей хеш распределения соответствует этому шарду. Допустимы значения от 0 до значения “shards” в секции “peers”. По умолчанию используется 0: узел получает обновления всех ключей. Значения больше “shards” игнорируются, как и любые значения, заданные локальному узлу.

Пример:

peers mypeers
     shards 3
     peer A 127.0.0.1:40001 # local peer without shard value (0 internally)
     peer B 127.0.0.1:40002 shard 1
     peer C 127.0.0.1:40003 shard 2
     peer D 127.0.0.1:40004 shard 3

sigalgs <sigalgs>

sigalgs <sigalgs>

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр доступен только тогда, когда поддержка OpenSSL была включена. Устанавливает строку, описывающую список алгоритмов подписи, согласовываемых во время рукопожатия TLSv1.2 и TLSv1.3. Формат строки определён в “man 3 SSL_CTX_set1_sigalgs” из справочной документации OpenSSL. Не рекомендуется использовать этот параметр, если не требуется совместимость с промежуточным устройством.

slowstart <start_time_in_ms>

slowstart <start_time_in_ms>

Допустимые контексты: tcp, http

Параметр “slowstart” для сервера принимает значение в миллисекундах, указывающее, через какое время сервер, только что вернувшийся в работу, начнёт функционировать на полной скорости. Как и для любого другого параметра, зависящего от времени, его можно указать в любой другой явной единице измерения: { us, ms, s, m, h, d }. Скорость увеличивается линейно от 0 до 100% в течение этого времени. Ограничение применяется к двум параметрам:

  • maxconn: количество принятых сервером соединений будет расти от 1 до 100% обычного динамического предела, определенного выражением (minconn,maxconn,fullconn).

  • weight: при использовании бэкендом динамического алгоритма с весом, вес растёт линейно от 1 до 100%. В этом случае вес обновляется при каждой проверке работоспособности. Поэтому важно, чтобы параметр “inter” был меньше чем “slowstart”, чтобы максимизировать количество шагов.

При запуске HAProxy механизм slowstart не применяется, иначе это привело бы к проблемам для работающих серверов. Он применяется только тогда, когда сервер ранее был обнаружен как неисправный.

sni <expression>

sni <expression>

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Параметр “sni” вычисляет выражение извлечения данных, преобразует результат в строку и использует её как имя узла, отправляемое серверу в расширении TLS SNI. Типичный случай — передать SNI клиента при работе HAProxy мостом TCP/SSL, используя в выражении функцию “ssl_fc_sni”. ЭТО НЕЛЬЗЯ ИСПОЛЬЗОВАТЬ ДЛЯ HTTPS: вместо этого следует использовать req.hdr(host), поскольку в HTTPS SNI обязательно должно совпадать с полем Host, а клиентам разрешено использовать разные имена узлов в одном соединении. Если задано “verify required” (рекомендуемая настройка), полученное имя также проверяется на соответствие именам в сертификате сервера. Подробнее см. “verify”. Для задания SNI проверок работоспособности служит “check-sni”.

По умолчанию, SNI присваивается имени соединения для “http-reuse”, если не переопределено директивой “pool-conn-name” сервера.

sni-auto

sni-auto

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Параметр “sni-auto” включает автоматический выбор SNI, если значение ещё не задано. Он задаёт выражение “sni” как “req.hdr(host),field(1,:)”, то есть передаёт в SNI имя Host запроса, отправляемого серверу, без номера порта. Автоматический выбор включён по умолчанию, но параметр в строке “server” позволяет сбросить “no-sni-auto”, унаследованный из “default-server”. В директиве “default-server” он также может сбросить предыдущую настройку “default-server” “no-sni-auto”.

Для HTTPS соединений выбранный SNI определяется на основе значения заголовка host запроса, если он присутствует. В противном случае он остаётся неустановленным. Для других протоколов опция игнорируется.

Если используется автоматическое определение SNI, то значение присваивается имени соединения для “http-reuse”, за исключением случая, когда это перекрывается ключевым словом “pool-conn-name” сервера.

См. опцию “check-sni-auto” для включения автоматического выбора SNI при проверке работоспособности для SSL.

source <addr>[:<pl>[-<ph>]] [usesrc { <addr2>[:<port2>] | client | clientip } ]

source <addr>[:<pl>[-<ph>]] [usesrc { <addr2>[:<port2>] | client | clientip } ]
source <addr>[:<port>] [usesrc { <addr2>[:<port2>] | hdr_ip(<hdr>[,<occ>]) } ]
source <addr>[:<pl>[-<ph>]] [interface <name>] ...

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Параметр “source” устанавливает исходный адрес, который будет использоваться при подключении к серверу. Он следует идентичным параметрам и принципам ключа бэкенда “source”, за исключением того, что он применяется только к серверу, который на него ссылается. Для подробной информации см. ключ “source”.

Кроме того, утверждение “source” на строке сервера позволяет указать диапазон исходных портов, задавая нижнюю и верхнюю границы, разделённые дефисом (’-’). Некоторые операционные системы могут требовать действительный IP-адрес при указании диапазона исходных портов. Разрешено указывать один и тот же IP/диапазон для нескольких серверов. Это позволяет обойти ограничение в 64 тыс. одновременных соединений. Ограничение в этом случае достигнет 64 тыс. соединений на каждый сервер.

Начиная с Linux 4.2/libc 2.23, для соединений с заданным исходным адресом без портов устанавливается IP_BIND_ADDRESS_NO_PORT.

ssl

ssl

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Эта опция включает SSL шифрование на исходящих соединениях к серверу. Критически важно проверять сертификаты сервера с помощью “verify” при использовании SSL для подключения к серверам, иначе обмен уязвим к простым атакам «человек посередине», что делает SSL бесполезным. При использовании этой опции проверки работоспособности автоматически отправляются в SSL, если нет директивы “port” или “addr”, указывающей на то, что проверка должна быть направлена в другое место. См. “no-ssl” для отключения опции “ssl” и опцию “check-ssl” для принудительной отправки проверок работоспособности в SSL.

ssl-max-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]

ssl-max-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр обеспечивает использование <version> или ниже при использовании SSL для связи с сервером. Этот параметр также доступен в глобальной директиве “ssl-default-server-options”. См. также “ssl-min-ver”.

ssl-min-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]

ssl-min-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр обеспечивает использование <version> или выше при использовании SSL для связи с сервером. Этот параметр также доступен в глобальной директиве “ssl-default-server-options”. См. также “ssl-max-ver”.

ssl-reuse

ssl-reuse

Может быть использован в следующих контекстах: tcp, http, log, peers, ring

В строке “server” этот параметр позволяет сбросить настройку “no-ssl-reuse”, унаследованную из директивы “default-server” как значение по умолчанию. В директиве “default-server” он также может сбросить предыдущую настройку “default-server” “no-ssl-reuse”.

stick

stick

Допустимые контексты: tcp, http

В строке “server” этот параметр позволяет сбросить настройку “non-stick”, унаследованную из директивы “default-server” как значение по умолчанию. В директиве “default-server” он также может сбросить предыдущую настройку “default-server” “non-stick”.

strict-maxconn

strict-maxconn

Допустимые контексты: tcp, http

Название maxconn для серверов не вполне точно: параметр задаёт максимальное число отправляемых серверу запросов, но с учётом простаивающих соединений общее число соединений может быть больше. Если требуется строгий предел числа соединений с сервером, можно добавить strict-maxconn. Тогда HAProxy никогда не устанавливает больше maxconn соединений с сервером и при необходимости пытается повторно использовать или закрывать соединения. Однако запросы могут завершаться ошибкой, если новое соединение установить нельзя, а простаивающего нет. Это возможно при «частных» соединениях, закреплённых за одним сеансом после аутентификации.

socks4 <addr>:<port>

socks4 <addr>:<port>

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр включает туннели socks4 для исходящих соединений с сервером. Использование данного параметра не будет по умолчанию заставлять проверку работоспособности проходить через socks4. Для включения функции необходимо использовать ключевое слово “check-via-socks4”.

tcp-md5sig <password>

tcp-md5sig <password>

Может быть использован в следующих контекстах: tcp, http, log, peers, ring

Включает подпись TCP MD5 (RFC 2385 Защита BGP Сессий через опцию подписи TCP MD5) для всех исходящих соединений с этим сервером. Эта опция доступна только на Linux. При включении, строка <password> используется для подписи каждого TCP сегмента с помощью 16-байтового MD5 хэша. Это обеспечивает защиту TCP соединения от подделки. Основное применение этой опции — защита BGP от введения фальшивых TCP сегментов в поток соединения. Однако она может быть полезна для любых очень длительных TCP соединений.

tcp-ut <delay>

tcp-ut <delay>

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Устанавливает тайм-аут пользователя TCP для всех исходящих соединений с этим сервером. Этот параметр доступен в Linux начиная с версии 2.6.37. Он позволяет HAProxy настроить тайм-аут для сокетов, содержащих данные, не получающие подтверждения в течение заданного промежутка времени. Это особенно полезно для долговременных соединений с длительными периодами бездействия, таких как удалённые терминалы или пулы соединений с базами данных, где тайм-ауты клиента и сервера должны быть высокими для обеспечения длительного периода бездействия, но при этом важно обнаруживать исчезновение сервера с целью освобождения всех ресурсов, связанных с его соединением (и сессией клиента). Один из типичных сценариев использования — принудительное завершение соединений с недоступным сервером при слишком медленных проверках работоспособности или во время плавной перезагрузки, поскольку при этом проверки работоспособности отключаются. Аргумент — задержка, выраженная в миллисекундах по умолчанию. Работает только для обычных TCP соединений и игнорируется для других протоколов.

tfo

tfo

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр включает использование TCP fast open при подключении к серверам на системах, поддерживающих его (на данный момент — только ядро Linux >= 4.11). Дополнительную информацию о TCP fast open см. в опции “tfo” bind. Обратите внимание, что при использовании tfo следует также использовать ключевые слова “conn-failure”, “empty-response” и “response-timeout” для “retry-on”, иначе HAProxy не сможет повторно подключаться при сбое. См. также “no-tfo”.

track [<backend>/]<server>

track [<backend>/]<server>

Допустимые контексты: tcp, http, log

Этот параметр позволяет устанавливать текущее состояние сервера путём отслеживания другого сервера. Можно отслеживать сервер, который сам отслеживает другой сервер, при условии, что в конце цепочки сервер имеет включённые проверки работоспособности. Если <backend> не указан, используется текущий бэкенд. Если используется disable-on-404, то этот параметр должен быть включён на обоих прокси.

Пример:

backend A
server a1 1.1.1.1:80 track B/b1
server a2 1.1.1.2:80 track B/b1

backend B
server b1 2.2.2.2:80 check

tls-tickets

tls-tickets

Может быть использован в следующих контекстах: tcp, http, log, peers, ring

В строке “server” этот параметр позволяет сбросить “no-tls-tickets”, унаследованный из “default-server” как значение по умолчанию. Механизм билетов TLS используется только до TLS 1.2 включительно. При использовании билетов TLS прямая секретность нарушается, если ключи билетов не заменяются регулярно (через перезагрузку конфигурации или с помощью “tls-ticket-keys”). В директиве “default-server” параметр также может сбросить предыдущую настройку “default-server” “no-tls-tickets”.

verify [none|required]

verify [none|required]

Может быть использован в следующих контекстах: tcp, http, log, peers, ring

Этот параметр доступен только при сборке с поддержкой OpenSSL. При значении ’none’ сертификат сервера не проверяется. В противном случае сначала проверяется, соответствуют ли имена в атрибутах subject и subjectAlternateNames сертификата имени из “sni” либо, при его отсутствии, статическому имени из “verifyhost”. Затем сертификат проверяется с помощью CA из ‘ca-file’ и необязательных списков отзыва CRL из ‘crl-file’. Если имя для проверки не задано, имена сертификата игнорируются. Поэтому без SNI важно использовать “verifyhost”. При неудаче проверки рукопожатие прерывается. При подключении к серверам через SSL критически важно проверять их сертификаты: иначе обмен уязвим к простым атакам «человек посередине», что делает SSL совершенно бесполезным. Если в секции global не указан “ssl_server_verify”, по умолчанию “verify” имеет значение “required”.

verifyhost <hostname>

verifyhost <hostname>

Может использоваться в следующих контекстах: tcp, http, log, peers, ring

Этот параметр доступен только при сборке с поддержкой OpenSSL и действует лишь при ‘verify required’. Он задаёт статическое имя узла по умолчанию для проверки сертификата сервера, если при подключении не использовался SNI. Без SNI это единственный способ включить проверку имени узла. Заданное статическое имя используется и для проверок работоспособности, если они не передают значение SNI. Если ни одно имя в сертификате не совпадает с указанным, рукопожатие прерывается. Имена в сертификате сервера могут содержать подстановочные знаки. См. также “verify”, “sni” и “no-verifyhost”.

weight <weight>

weight <weight>

Допустимые контексты: tcp, http

Параметр “weight” используется для настройки веса сервера по сравнению с другими серверами. Все серверы получают нагрузку пропорционально их весу относительно суммы всех весов, поэтому чем выше вес, тем выше нагрузка. По умолчанию вес равен 1, а максимальное значение — 256. Значение 0 означает, что сервер не участвует в балансировке нагрузки, но по-прежнему принимает соединения, направленные на него механизмом привязки сеансов. Если этот параметр используется для распределения нагрузки в соответствии с возможностями сервера, рекомендуется начинать с значений, которые могут как увеличиваться, так и уменьшаться, например, в диапазоне от 10 до 100, чтобы оставить достаточный запас как сверху, так и снизу для последующих корректировок.

ws { auto | h1 | h2 }

ws { auto | h1 | h2 }

Допустимые контексты: http

Этот параметр позволяет настроить протокол, используемый при пересылке потоков WebSocket. Это особенно полезно при использовании бэкенда HTTP/2 без поддержки WebSocket H2 через RFC8441.

По умолчанию используется “auto”: применяется тот же протокол, что и для основного трафика. Исключение — ALPN: для потоков WebSocket возможна попытка перейти на “http/1.1”, если этот протокол есть в настроенном списке ALPN сервера.

Значение “h1” используется для принудительного задания HTTP/1.1 для потоков WebSocket, через ALPN если SSL ALPN включено для сервера. Аналогично, “h2” может быть использован для принудительного задания HTTP/2.0 WebSocket. Используйте это значение с осторожностью: сервер должен поддерживать RFC8441 или при пересылке WebSocket HAProxy выдаст ошибку.

Примечание, что NPN не учитывается, так как его использование было отменено в пользу расширения ALPN

См. также “alpn” и “proto”.

5.3. Определение IP-адреса сервера через DNS

HAProxy позволяет использовать имя хоста в строке сервера для получения его IP-адреса с помощью серверов имен. По умолчанию HAProxy разрешает имя при разборе конфигурации во время запуска и кеширует результат на всё время жизни процесса. В некоторых случаях это недостаточно, например, в Amazon, где IP-адрес сервера может измениться после перезагрузки или ELB виртуальный IP может изменяться в зависимости от текущей нагрузки.

В этом разделе описывается, как можно настроить HAProxy для выполнения разрешения имени сервера в режиме работы.

Независимо от того, включено ли разрешение имени сервера в режиме работы, по умолчанию HAProxy выполняет первое разрешение при запуске во время парсинга конфигурации через libc, если не отключено параметром “init-addr”.

5.3.1. Общий обзор

Как показано во введении, разрешение имени в HAProxy происходит на двух разных этапах жизненного цикла процесса:

1. При запуске HAProxy разбирает строку определения сервера и обнаруживает
   имя узла. Для его разрешения используются функции libc. Такое разрешение
   опирается на файл /etc/resolv.conf.

2. Во время работы HAProxy периодически разрешает имена серверов,
   которым требуется разрешение DNS.

Несколько других событий могут инициировать разрешение имени в режиме работы:

  • при завершении проверки работоспособности сервера с тайм-аутом соединения: это может быть связано с тем, что сервер получил новый IP-адрес. Следовательно, необходимо инициировать разрешение имени, чтобы узнать новый IP.

При использовании резолверов имя сервера может быть либо именем хоста, либо меткой SRV. HAProxy считает всё, что начинается с подчёркивания, меткой SRV. Если указана метка SRV, то соответствующие записи SRV будут получены с сервера DNS, а указанные имена хостов будут использоваться. Метка SRV будет проверяться периодически, и при добавлении или удалении серверов HAProxy автоматически выполнит аналогичные действия.

Несколько важных моментов, на которые следует обратить внимание:

  • все серверы имён опрашиваются одновременно. HAProxy обрабатывает первый валидный ответ.

  • Результат разрешения считается недействительным (NX, timeout, refused), когда все серверы возвращают ошибку.

  • Клиент DNS, реализованный в HAProxy, является очень простым и не сможет понять большое количество опций и сложных настроек, которые может обрабатывать резолвер операционной системы. Следовательно, за исключением действительно простых конфигураций, в которых сервер, известный только по своему FQDN, имеет ровно один IP-адрес в любой момент времени и может периодически обновлять его (например, после перезагрузки), настоятельно рекомендуется избегать смешивания разрешения имён на этапе инициализации, основанного на библиотеке libc, с разрешением во время выполнения, основанным на DNS. Такие конфигурации известны своей склонностью к сбоям при обновлении адресов. В заключение, если вы не уверены в том, что делаете, всегда следует исключать “libc” из “init-addr” при использовании “resolvers” в строке сервера.

5.3.2. Секция resolvers

В этой секции хранится информация, связанная с разрешением имён в HAProxy. Секций resolvers может быть столько, сколько необходимо; каждая может содержать несколько серверов имён.

При запуске HAProxy пытается сгенерировать секцию resolvers, названную “default”, если в конфигурации нет секции с таким названием. Эта секция по умолчанию используется httpclient и использует ключевое слово parse-resolv-conf. Если HAProxy не может автоматически сгенерировать эту секцию, не выдается ни ошибки, ни предупреждения.

Если в секции resolvers настроено несколько серверов имён, HAProxy использует первый действительный ответ. Если ответы недействительны, обрабатывается только последний. Это даёт медленному серверу возможность вернуть действительный ответ после быстрого сервера, который работает с ошибками или располагает устаревшими данными.

Когда каждый сервер возвращает разный тип ошибки, HAProxy использует только последнюю ошибку. На этой ошибке применяется следующая обработка:

1. HAProxy повторяет тот же запрос DNS с другим типом: A меняется
   на AAAA и наоборот. Это не относится к запросам SRV и ошибкам
   тайм-аута.

2. После переключения типа запроса (или если оно неприменимо) HAProxy
   повторяет исходный запрос DNS с предпочтительным типом.

3. HAProxy повторяет предыдущие шаги <resolve_retries> раз. Если после
   этого действительный ответ не получен, разрешение DNS прекращается
   и сообщается об ошибке.

Например, при настройке 2 серверов в секции resolvers, возможны следующие сценарии:

  • Первый ответ является действительным и применяется немедленно, второй ответ игнорируется

  • Первый ответ является недействительным, второй — действительным, затем применяется второй ответ

  • Первый ответ — NX домен, второй — обрезанный ответ, затем HAProxy повторяет запрос с новым типом

  • Первый ответ — NX домен, второй — тайм-аут, затем HAProxy повторяет запрос с новым типом

  • Запрос истек по тайм-ауту для обоих серверов, затем HAProxy повторяет запрос с тем же типом запроса

Поскольку DNS сервер может не отвечать на все IP в одном DNS запросе, HAProxy хранит кэш предыдущих ответов, ответ считается устаревшим после <hold obsolete> секунд без возврата IP.

resolvers <resolvers id>

resolvers <resolvers id>

Создаёт список серверов имён с меткой <resolvers id>. Как указано выше, специальное имя “default” существует всегда: секция создаётся автоматически, если не объявлена явно. Именно на неё опираются внутренние службы, например httpclient. Объявление “default” влияет на разрешение имён этими службами.

Секция resolvers принимает следующие параметры:

accepted_payload_size <nb>

accepted_payload_size <nb>

Определяет максимальный размер полезной нагрузки, который принимается HAProxy и объявляется всем серверам имен, настроенным в этой секции разрешителей. <nb> измеряется в байтах. Если не задано, HAProxy объявляет 512. (минимальное значение, определённое RFC 6891)

Примечание: максимально допустимое значение — 65535. Рекомендуемое значение для UDP — 4096, и не рекомендуется превышать 8192, за исключением случаев, когда вы уверены, что ваша система и сеть способны справиться с этим (значение, превышающее 65507, не имеет смысла, поскольку это максимальный размер полезной нагрузки UDP). Если вы используете только TCP серверы имен для обработки больших DNS ответов, следует установить это значение на максимум: 65535.

nameserver <name> <address>[:port] [param*]

nameserver <name> <address>[:port] [param*]

Используется для настройки сервера имён. Имя <name> сервера имён должно быть уникальным. По умолчанию <address> считается типом датаграммы. Это означает, что при настройке IPv4 или IPv6 без специальных префиксов адресов (параграф 11) будет использоваться протокол UDP. Если используется префикс адреса потокового протокола, сервер имён будет считаться потоковым сервером (TCP, например), и параметры “server”, указанные в параграфе 5.2, которые относятся к разрешению DNS, будут учитываться.

Примечание: в настоящее время в режиме TCP 4 запроса отправляются конвейером по одному соединению. Каждые 5 секунд закрывается группа простаивающих соединений. Параметр “maxconn” можно настроить для ограничения количества одновременных соединений. Также должна быть возможность использовать TLS, если сервер его поддерживает.

parse-resolv-conf

parse-resolv-conf

Добавляет все серверы имён из /etc/resolv.conf в список серверов этой секции resolvers. Порядок такой, как если бы каждый сервер из /etc/resolv.conf был отдельно указан на месте этой директивы.

hold <status> <period>

hold <status> <period>

После получения ответа DNS со статусом <status> определяет, нужно ли перевести сервер из UP в DOWN. Для этого проверяет, приходил ли действительный ответ за последние <period>, который позволил бы проигнорировать только что полученный недействительный статус.

`<status>`: последний статус разрешения имени.
       nx        После NXDOMAIN проверяется, был ли действительный
                 ответ за прошедший заданный период.

       refused   После REFUSED проверяется, был ли действительный
                 ответ за прошедший заданный период.

       timeout   После истечения "timeout retry" проверяется, был ли
                 действительный ответ за прошедший заданный период.

       other     После любого другого недействительного статуса
                 проверяется, был ли действительный ответ
                 за прошедший заданный период.

       valid     Применяется только к действиям "http-request do-resolve"
                 и "tcp-request content do-resolve". Задаёт время хранения
                 действительного ответа сервером до нового разрешения.
                 Не влияет на динамическое разрешение имён серверов.

       obsolete  Задаёт время ожидания перед удалением устаревших записей
                 DNS после получения обновлённой записи ответа.
                 Применяется к записям SRV.

`<period>`: прошедший период, за который должен быть получен действительный
           ответ. Используется формат времени HAProxy; по умолчанию
           значение указывается в миллисекундах.

Если сервер определяет свой IP-адрес через динамическое разрешение DNS, недействительный ответ, например NXDOMAIN, приводит к переходу из UP в DOWN. Директивы hold задают, насколько далеко в прошлое искать действительный ответ. Если такой ответ получен в течение <period>, только что полученный недействительный статус игнорируется.

Если за прошедший заданный период действительный ответ не получен, сервер помечается DOWN. Например, при “hold nx 30s” и последнем ответе NXDOMAIN сервер перейдёт в DOWN, если за последние 30 секунд не было действительного ответа.

Сервер в состоянии DOWN будет немедленно помечен как UP при получении допустимого статуса от сервера DNS.

Существует отдельное поведение для “hold valid” и “hold obsolete”.

По умолчанию для “valid” используется 10s, для “obsolete” — 0s, для остальных — 30s.

resolve_retries <nb>

resolve_retries <nb>

Определяет количество <nb> запросов, которые необходимо отправить для разрешения имени сервера, прежде чем отказаться. Значение по умолчанию: 3

Повторная попытка выполняется при тайм-ауте сервера имён либо после завершения всей последовательности переключения типов запросов DNS, когда нужно снова начать с типа ANY по умолчанию.

timeout <event> <time>

timeout <event> <time>

Определяет тайм-ауты, связанные с разрешением имен <event>: событие, на котором применяется период тайм-аута <time>. Доступные события: - resolve: время, при котором запускается разрешение имен, если не применяется другое время. Значение по умолчанию: 1s - retry : время между двумя DNS запросами, если не получены действительные ответы. Значение по умолчанию: 1s <time>: время, связанное с событием. Оно следует формату времени HAProxy. <time> выражено в миллисекундах.

Пример:

resolvers mydns
  nameserver dns1 10.0.0.1:53
  nameserver dns2 10.0.0.2:53
  nameserver dns3 tcp@10.0.0.3:53
  parse-resolv-conf
  resolve_retries       3
  timeout resolve       1s
  timeout retry         1s
  hold other           30s
  hold refused         30s
  hold nx              30s
  hold timeout         30s
  hold valid           10s
  hold obsolete        30s

15 - 6. Кеш

Ограничения кеша и настройка в секциях cache и прокси

HAProxy предоставляет кеш, предназначенный для небольших объектов (favicon, css и т. п.). Это минималистичный кеш в оперативной памяти, не требующий сложного обслуживания.

Кеш использует общую для всех потоков область памяти, разделённую на блоки по 1kB.

Если объект больше не используется, его можно удалить, чтобы сохранить новый объект, независимо от срока его действия. При выделении места для нового объекта сначала удаляются самые старые объекты.

В качестве ключа кеш использует хеш заголовка host и URI.

Состояние кеша можно просмотреть командой сокета Unix «show cache»; дополнительные сведения приведены в разделе 9.3 «Команды сокета Unix» руководства по управлению.

Когда объект выдаётся из кеша, имя сервера в журнале заменяется на «<CACHE>».

6.1. Ограничения

Кеш не сохраняет и не выдаёт объекты в следующих случаях:

  • Если код ответа отличается от 200.

  • Если ответ содержит заголовок Vary, а параметр process-vary отключён либо значение Vary содержит заголовок, который пока не поддерживается (сейчас поддерживаются только accept-encoding, referer и origin).

  • Если Content-Length + размер заголовков превышает «max-object-size».

  • Если ответ нельзя кешировать.

  • Если у ответа нет ни явно заданного срока действия (директивы s-maxage или max-age в Cache-Control либо заголовка Expires), ни валидатора (заголовков ETag или Last-Modified).

  • Если параметр process-vary включён и уже существует max-secondary-entries записей с тем же первичным ключом, что и у текущего ответа.

  • Если параметр process-vary включён, ответ зависит от клиентского заголовка accept-encoding и использует неизвестную кодировку (не указанную в https://www.iana.org/assignments/http-parameters/http-parameters.xhtml ).

  • Если метод запроса отличается от GET.

  • Если версия HTTP в запросе ниже 1.1.

  • Если запрос содержит заголовок Authorization.

6.2. Настройка

Для настройки кеша необходимо определить секцию cache и использовать её в прокси с соответствующими действиями http-request и http-response.

6.2.1. Секция cache

cache <name>

cache <name>

Объявляет секцию кеша и выделяет общую память кеша с именем <name>. Размер кеша обязателен (см. директиву «total-max-size» ниже).

max-age <seconds>

max-age <seconds>

Задаёт максимальный срок действия. Срок действия равен меньшему из этого значения и значения директивы s-maxage или max-age (в таком порядке приоритета) в заголовке ответа Cache-Control. Значение по умолчанию — 60 секунд, то есть по умолчанию объект нельзя кешировать дольше 60 секунд.

max-object-size <bytes>

max-object-size <bytes>

Задаёт максимальный размер кешируемого объекта. Он не должен превышать половину «total-max-size». Если не задан, равен 256-й доле размера кеша. Объекты размером больше «max-object-size» не кешируются.

max-secondary-entries <number>

max-secondary-entries <number>

Задаёт максимальное число одновременно существующих вторичных записей с одинаковым первичным ключом в кеше. Для этого должна быть включена поддержка vary. Значение по умолчанию — 10; следует указывать строго положительное целое число.

process-vary <on/off>

process-vary <on/off>

Включает или отключает обработку заголовка Vary. Если она отключена, ответы с таким заголовком никогда не кешируются. Если включена, для части заголовков всех входящих запросов требуется предварительно вычислять хеш (что может потребовать дополнительных ресурсов CPU); он используется для формирования вторичного ключа запроса (см. RFC 7234#4.1). Сейчас вторичный ключ формируется из содержимого заголовков ‘accept-encoding’, ‘referer’ и ‘origin’. Обратите внимание: согласно RFC заголовки ‘origin’ и ‘referer’ имеют по одному значению, поэтому запрос с несколькими вхождениями любого из них следует считать некорректным. Для таких запросов вторичный ключ не формируется и ответ никогда не выдаётся из кеша, чтобы сервер мог сам решить, как обработать ситуацию. Значение по умолчанию — off (отключено).

total-max-size <megabytes>

total-max-size <megabytes>

Задаёт размер кеша в оперативной памяти в мегабайтах. Эта память разделяется на блоки по 1kB, используемые записями кеша. Максимальное значение — 4095.

6.2.2. Секция прокси

Секция прокси, использующая кеш, должна включать действие «cache-use» в набор правил «http-request» для поиска запрошенного объекта в кеше и действие «cache-store» в набор правил «http-response» для сохранения или обновления полученного объекта. Оба действия могут дополнительно содержать условия. Например, можно пропускать «cache-use» для определённого подкаталога, содержимое которого заведомо не кешируется, либо пропускать «cache-store» для типов содержимого, кеширование которых заведомо бесполезно. Учтите, что ключ индексации кеша вычисляется при выполнении «cache-use»: если это действие пропущено, на этапе обработки ответа попытка обновления кеша в любом случае не выполняется.

Пример:

backend bck1
  mode http

  http-request cache-use foobar
  http-response cache-store foobar
  server srv1 127.0.0.1:80

cache foobar
  total-max-size 4
  max-age 240

16 - 7. ACL и извлечение образцов

Сопоставление ACL, условия, преобразователи, извлечение образцов и предопределённые ACL

HAProxy может извлекать данные из потоков запросов или ответов, сведений о клиенте или сервере, таблиц, сведений об окружении и т. д. Извлечение таких данных называется извлечением образца. Полученные образцы могут использоваться для разных целей, например как ключ таблицы привязок, но чаще всего их сопоставляют с предопределёнными постоянными данными, называемыми шаблонами.

7.1. Основы ACL

Списки контроля доступа (ACL) позволяют объявить именованный метод сравнения любых данных со списком предопределённых шаблонов. Их следует считать практически эквивалентными функциям в большинстве языков программирования: объявление делает их доступными для последующего вызова по мере необходимости. Результат вычисления — только совпадение или несовпадение, что сопоставимо с логическими значениями во многих языках программирования. В отличие от функций в языках программирования, ACL можно перегружать сколько угодно раз, определяя дополнительные методы сопоставления для одного и того же имени. В этом случае они будут вычисляться в порядке объявления до первого совпадения.

ACL предоставляют гибкий способ переключения содержимого и, в более общем случае, принятия решений на основе данных, извлечённых из запроса, ответа или сведений о состоянии окружения. Принцип прост:

  • извлечь образец данных из потока, таблицы или окружения
  • при необходимости преобразовать формат извлечённого образца
  • применить к образцу один или несколько методов сопоставления с шаблонами
  • выполнить действия, только если шаблон совпадает с образцом

Действия обычно заключаются в блокировке запроса, выборе бэкенда или добавлении заголовка.

Для определения проверки используется ключевое слово “acl”. Синтаксис:

acl <aclname> <criterion> [flags] [operator] [<value>] ...

Эта запись создаёт новый ACL <aclname> или дополняет существующий новыми проверками. Проверки применяются к части запроса или ответа, указанной в <criterion>, и могут уточняться необязательными флагами [flags]. Некоторые критерии также поддерживают оператор, который можно указать перед набором значений. При необходимости к образцу можно применить операторы преобразования: они задаются списком ключевых слов через запятую сразу после первого ключевого слова. Значения должны иметь тип, поддерживаемый критерием, и разделяются пробелами.

Имена ACL должны состоять из прописных и строчных букв, цифр, ‘-’ (дефиса), ‘_’ (подчёркивания), ‘.’ (точки) и ‘:’ (двоеточия). Имена ACL чувствительны к регистру, поэтому “my_acl” и “My_Acl” — два разных ACL.

Число ACL не ограничено. Неиспользуемые ACL не влияют на производительность и лишь занимают небольшой объём памяти.

Критерий обычно представляет собой имя метода извлечения образца или одного из его вариантов для ACL. Метод проверки по умолчанию определяется типом результата этого метода извлечения образца. Варианты для ACL могут задавать другие методы сопоставления для одного и того же метода извлечения образца. Преобразования поддерживают только методы извлечения образцов.

Методы извлечения образцов возвращают данные следующих типов:

  • логическое значение
  • целое число (со знаком или без знака)
  • адрес IPv4 или IPv6
  • строка
  • блок данных

Преобразователи преобразуют данные любого из этих типов в любой из них. Например, одни преобразователи могут привести строку к нижнему регистру, а другие — преобразовать строку в адрес IPv4 или применить сетевую маску к IP-адресу. Тип итогового образца определяется последним преобразователем в списке; по умолчанию это тип результата метода извлечения образца.

Каждый образец или преобразователь возвращает данные определённого типа, указанного в этой документации рядом с его ключевым словом. При объявлении ACL с помощью стандартного метода извлечения образца для некоторых типов автоматически выбирается метод сопоставления по умолчанию; эти соответствия приведены в таблице ниже:

   +------------------------+------------------------+
   | Выходной тип образца   | Метод сопоставления    |
   | или преобразователя    | по умолчанию           |
   +------------------------+------------------------+
   | boolean                | bool                   |
   +------------------------+------------------------+
   | integer                | int                    |
   +------------------------+------------------------+
   | ip                     | ip                     |
   +------------------------+------------------------+
   | string                 | str                    |
   +------------------------+------------------------+
   | binary                 | нет, используйте "-m"  |
   +------------------------+------------------------+

Для сопоставления двоичных образцов обязательно нужно указать метод сопоставления; см. ниже.

Механизм ACL может сопоставлять эти типы с шаблонами следующих типов:

  • логическое значение
  • целое число или диапазон целых чисел
  • IP-адрес / сеть
  • строка (точное совпадение, подстрока, суффикс, префикс, подкаталог, домен)
  • регулярное выражение
  • блок шестнадцатеричных данных

В настоящее время поддерживаются следующие флаги ACL:

-i: игнорировать регистр при сопоставлении всех последующих шаблонов.
-f: загрузить шаблоны из списка.
-m: использовать указанный метод сопоставления с шаблоном
-n: запретить разрешение имён DNS
-M: загрузить файл, указанный с помощью -f, как карту.
-u: принудительно задать уникальный идентификатор ACL
--: принудительно завершить список флагов. Полезно, если строка похожа на один из флагов.

После флага “-f” указывается имя, которое должно соответствовать формату имён карт и ACL, описанному в разделе 2.7. Если шаблоны нужно загрузить из нескольких списков, можно передать несколько аргументов “-f”. При ссылке на существующий файл каждая его строка считывается как отдельное значение. Пустые строки и строки, начинающиеся с решётки (’#’), игнорируются. Все начальные пробелы и символы табуляции удаляются. Если необходимо указать допустимый шаблон, начинающийся с решётки, перед ним достаточно добавить пробел, чтобы строка не считалась комментарием. В зависимости от типа данных и метода сопоставления HAProxy может загружать строки в двоичное дерево, что обеспечивает очень быстрый поиск. Это применяется к IPv4 и точному сопоставлению строк. В таком случае дубликаты автоматически удаляются.

Флаг “-M” позволяет ACL использовать карту. Если этот флаг задан, список разбирается как записи из двух столбцов. Первый столбец содержит шаблоны, используемые ACL, а второй — образцы. Образец впоследствии может использоваться картой. Это полезно в некоторых редких случаях, когда ACL нужен лишь для проверки наличия шаблона в карте перед применением отображения.

Флаг “-u” принудительно задаёт уникальный идентификатор ACL. Этот идентификатор используется через сокетный интерфейс для идентификации ACL и динамического изменения его значений. Обратите внимание: файл всегда идентифицируется по имени, даже если задан идентификатор.

Также обратите внимание: флаг “-i” применяется к последующим записям, но не к записям, загруженным из файлов, указанных перед ним. Например:

acl valid-ua hdr(user-agent) -f exact-ua.lst -i -f generic-ua.lst test

В этом примере каждая строка из “exact-ua.lst” точно сопоставляется с заголовком “user-agent” запроса. Затем каждая строка из “generic-ua” сопоставляется без учёта регистра. После этого слово “test” также сопоставляется без учёта регистра.

Флаг “-m” выбирает конкретный метод сопоставления входного образца с шаблонами. Все критерии, специфичные для ACL, подразумевают определённый метод сопоставления и обычно не требуют этого флага. Однако он полезен с универсальными методами извлечения образцов, поскольку задаёт, как их результаты будут сопоставляться с шаблонами. Это необходимо для методов извлечения, возвращающих данные типа, для которого нет очевидного метода сопоставления (например, строки или двоичные данные). Если после “-m” указано имя метода сопоставления с шаблоном, этот метод используется вместо метода по умолчанию для данного критерия. Это позволяет сопоставлять содержимое способами, которые изначально не предусматривались, или использовать методы извлечения образцов, возвращающие строку. Метод сопоставления также влияет на разбор шаблонов. Поэтому его нельзя использовать с методами извлечения образцов, имеющими суффикс сопоставления (_beg, _end, _sub…). Кроме того, нельзя задавать несколько методов сопоставления с помощью “-m”.

Флаг “-n” запрещает разрешение имён DNS. Он используется при загрузке файлов с IP-адресами. По умолчанию, если парсер не может разобрать IP-адрес, он предполагает, что строка может быть доменным именем, и пытается выполнить разрешение DNS. Флаг “-n” отключает разрешение имён. Это полезно для выявления некорректных списков IP-адресов. Обратите внимание: если сервер DNS недоступен, разбор конфигурации HAProxy может длиться много минут в ожидании тайм-аута. В это время сообщения об ошибках не выводятся. Флаг “-n” отключает такое поведение. Также следует учитывать, что при динамическом изменении ACL во время выполнения разрешение имён отключено.

Однако есть ограничения. Не все методы сопоставления можно использовать со всеми методами извлечения образцов. Кроме того, если “-m” используется вместе с “-f”, он должен быть указан первым. Метод сопоставления с шаблонами должен быть одним из следующих:

  • “found”: только проверить, найден ли запрошенный образец в потоке, без сравнения с каким-либо шаблоном. Чтобы избежать путаницы, рекомендуется не указывать шаблоны. Этот метод сопоставления особенно полезен для обнаружения определённого содержимого, например заголовков, cookie и т. д., даже если они пусты, без сравнения с чем-либо и без подсчёта.

  • “bool” : проверить значение как логическое. Применяется только к методам извлечения, возвращающим логическое или целочисленное значение, и не принимает шаблон. Ноль и false не совпадают; все остальные значения совпадают.

  • “int” : сопоставить значение как целое число. Можно использовать с целочисленными и логическими образцами. Логическому false соответствует целое число 0, а true — целое число 1.

  • “ip” : сопоставить значение как адрес IPv4 или IPv6. Совместим только с образцами IP-адресов, поэтому подразумевается и никогда не требует явного указания.

  • “bin” : сопоставить содержимое с шестнадцатеричной строкой, представляющей двоичную последовательность. Можно использовать с двоичными или строковыми образцами.

  • “len” : сопоставить длину образца как целое число. Можно использовать с двоичными или строковыми образцами.

  • “str” : точное сопоставление: сопоставить содержимое со строкой. Можно использовать с двоичными или строковыми образцами.

  • “sub” : сопоставление по подстроке: найти в содержимом хотя бы один из заданных строковых шаблонов. Можно использовать с двоичными или строковыми образцами.

  • “reg” : сопоставление по регулярному выражению: сопоставить содержимое со списком регулярных выражений. Можно использовать с двоичными или строковыми образцами.

  • “beg” : сопоставление по префиксу: проверить начало содержимого на совпадение с заданными строковыми шаблонами. Можно использовать с двоичными или строковыми образцами.

  • “end” : сопоставление по суффиксу: проверить окончание содержимого на совпадение с заданными строковыми шаблонами. Можно использовать с двоичными или строковыми образцами.

  • “dir” : сопоставление по подкаталогу: проверить, совпадает ли часть содержимого, ограниченная косыми чертами, в точности с одним из заданных строковых шаблонов. Можно использовать с двоичными или строковыми образцами.

  • “dom” : сопоставление по домену: проверить, совпадает ли часть содержимого, ограниченная точками, в точности с одним из заданных строковых шаблонов. Можно использовать с двоичными или строковыми образцами.

Например, чтобы быстро проверить наличие cookie “JSESSIONID” в запросе HTTP, можно записать:

acl jsess_present req.cook(JSESSIONID) -m found

Чтобы применить регулярное выражение к первым 500 байтам данных в буфере, используется следующий ACL:

acl script_tag req.payload(0,500) -m reg -i <script>

В системах, где библиотека регулярных выражений значительно медленнее работает с “-i”, образец можно перед сопоставлением привести к нижнему регистру:

acl script_tag req.payload(0,500),lower -m reg <script>

Все критерии, специфичные для ACL, подразумевают метод сопоставления по умолчанию. Чаще всего такие критерии образуются объединением имени исходного метода извлечения образца и имени метода сопоставления. Например, “hdr_beg” применяет сопоставление “beg” к образцам, полученным методом извлечения “hdr”. Такой метод сопоставления применяется, только когда ключевое слово используется само по себе, без преобразователей. Если после такого ключевого слова ACL применяется преобразователь, метод сопоставления по умолчанию из ключевого слова ACL просто игнорируется: значение имеет тип результата последнего преобразователя. Поскольку все критерии, специфичные для ACL, основаны на методе извлечения образца, вместо них всегда можно использовать исходный метод извлечения и явно указать метод сопоставления с помощью “-m”.

Если для критерия, специфичного для ACL, с помощью “-m” задан другой метод сопоставления, он просто применяется к лежащему в основе критерия методу извлечения образца. Например, все следующие ACL в точности эквивалентны:

acl short_form  hdr_beg(host)        www.
acl alternate1  hdr_beg(host) -m beg www.
acl alternate2  hdr_dom(host) -m beg www.
acl alternate3  hdr(host)     -m beg www.

В таблице ниже приведена матрица совместимости типов образцов или преобразователей с типами шаблонов для сопоставления. Для каждой совместимой комбинации указано имя необходимого метода сопоставления. Угловые скобки “>” и “<” вокруг имени означают, что этот метод используется по умолчанию и работает без “-m”.

                           +-------------------------------------------------+
                           | Тип входного образца                            |
    +----------------------+---------+---------+---------+---------+---------+
    | Тип шаблона          | boolean | integer |   ip    | string  | binary  |
    +----------------------+---------+---------+---------+---------+---------+
    | нет (только наличие) |  found  |  found  |  found  |  found  |  found  |
    +----------------------+---------+---------+---------+---------+---------+
    | нет (логич. знач.)   |>  bool <|   bool  |         |   bool  |         |
    +----------------------+---------+---------+---------+---------+---------+
    | целое (значение)     |   int   |>  int  <|   int   |   int   |         |
    +----------------------+---------+---------+---------+---------+---------+
    | целое (длина)        |   len   |   len   |   len   |   len   |   len   |
    +----------------------+---------+---------+---------+---------+---------+
    | IP-адрес             |         |         |>   ip  <|    ip   |    ip   |
    +----------------------+---------+---------+---------+---------+---------+
    | точная строка        |   str   |   str   |   str   |>  str  <|   str   |
    +----------------------+---------+---------+---------+---------+---------+
    | префикс              |   beg   |   beg   |   beg   |   beg   |   beg   |
    +----------------------+---------+---------+---------+---------+---------+
    | суффикс              |   end   |   end   |   end   |   end   |   end   |
    +----------------------+---------+---------+---------+---------+---------+
    | подстрока            |   sub   |   sub   |   sub   |   sub   |   sub   |
    +----------------------+---------+---------+---------+---------+---------+
    | подкаталог           |   dir   |   dir   |   dir   |   dir   |   dir   |
    +----------------------+---------+---------+---------+---------+---------+
    | домен                |   dom   |   dom   |   dom   |   dom   |   dom   |
    +----------------------+---------+---------+---------+---------+---------+
    | регулярное выражение |   reg   |   reg   |   reg   |   reg   |   reg   |
    +----------------------+---------+---------+---------+---------+---------+
    | шестнадцатерич. блок |         |         |         |   bin   |   bin   |
    +----------------------+---------+---------+---------+---------+---------+

7.1.1. Сопоставление логических значений

Для сопоставления логического значения указывать значение не требуется; все заданные значения игнорируются. Логическое сопоставление используется по умолчанию для всех методов извлечения типа “boolean”. При таком сопоставлении извлечённое значение возвращается без изменений: логическое “true” всегда даёт совпадение, а логическое “false” — никогда.

Логическое сопоставление также можно принудительно задать с помощью “-m bool” для методов извлечения, возвращающих целое число. В этом случае целое число 0 преобразуется в логическое “false”, а все остальные значения — в “true”.

7.1.2. Сопоставление целых чисел

Целочисленное сопоставление применяется по умолчанию к методам извлечения целых чисел. Его также можно принудительно задать для методов извлечения логических значений с помощью “-m int”. В этом случае “false” преобразуется в целое число 0, а “true” — в целое число 1.

Целочисленное сопоставление также поддерживает диапазоны целых чисел и операторы. Обратите внимание: целочисленное сопоставление применяется только к положительным значениям. Диапазон задаётся нижней и верхней границами, разделёнными двоеточием; обе границы необязательны.

Например, “1024:65535” — допустимый диапазон непривилегированных портов; запись “1024:” также подходит. “0:1023” — допустимое представление привилегированных портов; запись “:1023” также подходит.

В качестве особого случая некоторые функции ACL поддерживают десятичные числа, которые фактически представляют собой два целых числа, разделённых точкой. Это используется, например, в некоторых проверках версий. К таким десятичным числам применимы все свойства целых чисел, в том числе диапазоны и операторы.

Для удобства также поддерживаются операторы сравнения. Обратите внимание: использование операторов с диапазонами не имеет особого смысла и настоятельно не рекомендуется. Аналогично, сравнение на больше или меньше с набором значений также не имеет особого смысла.

Для целочисленного сопоставления доступны следующие операторы:

eq: true, если проверяемое значение равно хотя бы одному значению
ge: true, если проверяемое значение больше или равно хотя бы одному значению
gt: true, если проверяемое значение больше хотя бы одного значения
le: true, если проверяемое значение меньше или равно хотя бы одному значению
lt: true, если проверяемое значение меньше хотя бы одного значения

Например, следующий ACL соответствует любому отрицательному значению заголовка Content-Length:

acl negative-length req.hdr_val(content-length) lt 0

Этот ACL соответствует версиям SSL от 3.0 до 3.1 включительно:

acl sslv3 req.ssl_ver 3:3.1

7.1.3. Сопоставление строк

Строковое сопоставление применяется к методам извлечения строк или двоичных данных и существует в 6 формах:

  • точное сопоставление (-m str): извлечённая строка должна в точности совпадать с шаблонами;

  • сопоставление по подстроке (-m sub): шаблоны ищутся внутри извлечённой строки; ACL совпадает, если найден хотя бы один из них;

  • сопоставление по префиксу (-m beg): шаблоны сравниваются с началом извлечённой строки; ACL совпадает, если совпал хотя бы один из них.

  • сопоставление по суффиксу (-m end): шаблоны сравниваются с концом извлечённой строки; ACL совпадает, если совпал хотя бы один из них.

  • сопоставление по подкаталогу (-m dir): шаблоны ищутся в любом месте извлечённой строки, с границами в виде косых черт ("/"), начала или конца строки. ACL совпадает, если совпал хотя бы один из них. Таким образом, строка “/images/png/logo/32x32.png” совпадёт с “/images”, “/images/png”, “images/png”, “/png/logo”, “logo/32x32.png” или “32x32.png”, но не с “png” и не с “32x32”.

  • сопоставление по домену (-m dom): шаблоны ищутся в любом месте извлечённой строки, с границами в виде точек ("."), двоеточий (":"), косых черт ("/"), вопросительных знаков ("?"), начала или конца строки. Этот метод предназначен для URL. Начальные и конечные разделители в шаблоне игнорируются. ACL совпадает, если совпал хотя бы один из шаблонов. Например, со строкой “http://www1.dc-eu.example.com:80/blah ” совпадут шаблоны “http”, “www1”, “.www1”, “dc-eu”, “example”, “com”, “80”, “dc-eu.example”, “blah”, “:www1:”, “dc-eu.example:80”, но не “eu” и не “dc”. Использовать этот метод для сопоставления доменных суффиксов при фильтрации или маршрутизации обычно нежелательно: маршрутизацию легко обмануть, например добавив совпадающий префикс перед другим доменом.

При строковом сопоставлении строки используются буквально, в том виде, в каком переданы, за исключением обратной косой черты ("\"), позволяющей экранировать некоторые символы, например пробел. Если перед первой строкой указан флаг “-i”, сопоставление выполняется без учёта регистра. Для сопоставления со строкой “-i” нужно либо указать её второй, либо перед первой строкой передать флаг “–”. То же, разумеется, относится и к сопоставлению со строкой “–”.

Не используйте строковое сопоставление для двоичных образцов, которые могут содержать нулевые байты (0x00): сравнение останавливается на первом нулевом байте. Вместо этого сначала преобразуйте двоичный образец в шестнадцатеричную строку с помощью преобразователя hex.

Пример:

# matches if the string <tag> is present in the binary sample
acl tag_found req.payload(0,0),hex -m sub 3C7461673E

7.1.4. Сопоставление по регулярным выражениям (regex)

Как и при строковом сопоставлении, при сопоставлении по регулярным выражениям строки используются буквально, в том виде, в каком переданы, за исключением обратной косой черты ("\"), позволяющей экранировать некоторые символы, например пробел. Если перед первым регулярным выражением указан флаг “-i”, сопоставление выполняется без учёта регистра. Для сопоставления со строкой “-i” нужно либо указать её второй, либо перед первой строкой передать флаг “–”. Тот же принцип, разумеется, применяется и к сопоставлению со строкой “–”.

7.1.5. Сопоставление произвольных блоков данных

Извлечённые образцы можно сопоставлять с двоичным блоком, который не всегда можно безопасно представить строкой. Для этого при двоичном методе сопоставления шаблоны должны передаваться последовательностью из чётного числа шестнадцатеричных цифр. Каждая пара цифр представляет байт. Шестнадцатеричные цифры можно записывать в верхнем или нижнем регистре.

Пример:

# match "Hello\n" in the input stream (\x48 \x65 \x6c \x6c \x6f \x0a)
acl hello req.payload(0,6) -m bin 48656c6c6f0a

7.1.6. Сопоставление адресов IPv4 и IPv6

Значения адресов IPv4 можно задавать как обычные адреса или с сетевой маской. Во втором случае адрес IPv4 совпадает, если находится в указанной сети. Вместо обычного адреса можно также указать разрешаемое имя узла, но обычно это не рекомендуется, поскольку затрудняет чтение и отладку конфигурации. Если используются имена узлов, следует как минимум обеспечить их наличие в /etc/hosts, чтобы конфигурация не зависела от случайного результата DNS в момент её разбора.

Поддерживается как обычная точечная запись адреса IPv4, так и сокращённая форма, в которой опущены октеты со значением 0:

    +------------------+------------------+------------------+
    |   Пример 1       |     Пример 2     |     Пример 3     |
    +------------------+------------------+------------------+
    |  192.168.0.1     |   10.0.0.12      |   127.0.0.1      |
    |  192.168.1       |   10.12          |   127.1          |
    |  192.168.0.1/22  |   10.0.0.12/8    |   127.0.0.1/8    |
    |  192.168.1/22    |   10.12/8        |   127.1/8        |
    +------------------+------------------+------------------+

Обратите внимание: это отличается от записи адресов CIDR по RFC 4632, в которой 192.168.42/24 эквивалентно 192.168.42.0/24.

Адреса IPv6 можно вводить в обычном виде, с сетевой маской или без неё. Для масок IPv6 допускается только количество битов. Чтобы исключить риск проблем со случайным результатом разрешения IP-адресов, имена узлов в шаблонах IPv6 никогда не допускаются.

HAProxy также может сопоставлять адреса IPv4 с адресами IPv6 в следующих случаях:

  • проверяемый адрес — IPv4, адрес шаблона — IPv4: сопоставление выполняется в IPv4 с указанной маской, если она задана.
  • проверяемый адрес — IPv6, адрес шаблона — IPv6: сопоставление выполняется в IPv6 с указанной маской, если она задана.
  • проверяемый адрес — IPv6, адрес шаблона — IPv4: сопоставление выполняется в IPv4 с маской шаблона, если адрес IPv6 соответствует 2002:IPV4::, ::IPV4 или ::ffff:IPV4; иначе совпадения нет.
  • проверяемый адрес — IPv4, адрес шаблона — IPv6: адрес IPv4 сначала преобразуется в IPv6 добавлением префикса ::ffff:, после чего сопоставление выполняется в IPv6 с указанной маской IPv6.

7.2. Использование ACL для построения условий

Некоторые действия выполняются только при выполнении условия. Условие — это комбинация ACL с операторами. Поддерживаются 3 оператора:

  • AND (неявный)
  • OR (явный, с ключевым словом “or” или оператором “||”)
  • отрицание с восклицательным знаком ("!")

Условие задаётся в дизъюнктивной форме:

[!]acl1 [!]acl2 ... [!]acln  { or [!]acl1 [!]acl2 ... [!]acln } ...

Такие условия обычно используются после “if” или “unless”, указывающих, когда условие запускает действие.

Например, чтобы заблокировать запросы HTTP к URL “*” с методами, отличными от “OPTIONS”, а также запросы POST без content-length, запросы GET или HEAD с content-length больше 0 и, наконец, все запросы, метод которых не входит в GET/HEAD/POST/OPTIONS!

acl missing_cl req.hdr_cnt(Content-length) eq 0
http-request deny if HTTP_URL_STAR !METH_OPTIONS || METH_POST missing_cl
http-request deny if METH_GET HTTP_CONTENT
http-request deny unless METH_GET or METH_POST or METH_OPTIONS

Чтобы выбрать другой бэкенд для запросов статического содержимого сайта “www”, а также для всех запросов к узлам “img”, “video”, “download” и “ftp”:

acl url_static  path_beg         /static /images /img /css
acl url_static  path_end         .gif .png .jpg .css .js
acl host_www    hdr_beg(host) -i www
acl host_static hdr_beg(host) -i img. video. download. ftp.
# now use backend "static" for all static-only hosts, and for static URLs
# of host "www". Use backend "www" for the rest.
use_backend static if host_static or host_www url_static
use_backend www    if host_www

Также можно составлять правила с помощью «анонимных ACL». Это безымянные выражения ACL, создаваемые на месте без предварительного объявления. Они должны заключаться в фигурные скобки, с пробелом перед каждой скобкой и после неё: скобки должны восприниматься как отдельные слова. Пример:

Следующее правило:

    acl missing_cl req.hdr_cnt(Content-length) eq 0
    http-request deny if METH_POST missing_cl

Можно записать и так:

    http-request deny if METH_POST { req.hdr_cnt(Content-length) eq 0 }

Обычно использовать эту конструкцию не рекомендуется: при такой записи гораздо легче оставить в конфигурации ошибки. Однако для очень простых правил, например сопоставляющих только один IP-адрес источника, она может быть уместнее, чем объявление ACL с произвольными именами. Ещё один пример подходящего применения:

С именованными ACL:

     acl site_dead nbsrv(dynamic) lt 2
     acl site_dead nbsrv(static)  lt 2
     monitor fail  if site_dead

С анонимными ACL:

     monitor fail if { nbsrv(dynamic) lt 2 } || { nbsrv(static) lt 2 }

Подробное описание ключевых слов “http-request deny” и “use_backend” см. в разделе 4.2 .

7.3. Извлечение образцов

Исторически методы извлечения образцов использовались только для получения данных, сопоставляемых с шаблонами посредством ACL. С появлением таблиц привязок возник новый класс методов извлечения образцов, обычно с тем же синтаксисом, что и их аналоги для ACL. Эти методы также называют «методами извлечения» (fetches). Сейчас ACL и методы извлечения сблизились: все методы извлечения ACL доступны как обычные методы извлечения, а ACL, в свою очередь, могут использовать любой метод извлечения образцов.

В этом разделе подробно описаны все доступные методы извлечения образцов и типы их результатов. У некоторых методов есть устаревшие псевдонимы, сохраняемые для совместимости с существующими конфигурациями. Они явно помечены как устаревшие, и их не следует использовать в новых конфигурациях.

У образцов есть тип. Он определяет, с какими шаблонами можно сопоставлять образец, какие преобразователи к нему применимы и как он преобразуется, когда ожидается другой тип. Используются следующие типы:

  • boolean: истинное или ложное значение, возвращаемое методами извлечения, которые сообщают только о выполнении условия. Такие образцы сопоставляются без параметра “-m”. Целое число считается истинным, если оно не равно нулю; строка сначала разбирается как целое число.

  • integer: знаковое 64-битное целое число, то есть значение от -2^63 до 2^63-1 (-9223372036854775808 и 9223372036854775807). При преобразовании строки в целое число разбор останавливается на первом символе, который не является цифрой или начальным знаком (’+’ либо ‘-’). Используется число, составленное из прочитанных цифр; если их не было, получается ноль, однако пустые строки не преобразуются. Значения вне допустимого диапазона ограничиваются наименьшим или наибольшим представимым целым числом.

  • адрес IPv4 и адрес IPv6: это два разных типа, хотя большинство мест, принимающих один из них, принимают и другой и описаны просто как принимающие адрес. Адрес IPv4 можно преобразовать в целое число, получив 32-битное значение адреса, либо в адрес IPv6 в форме IPv4-mapped ("::ffff:a.b.c.d"). Обратные преобразования более ограничены: у адреса IPv6 нет целочисленной формы, а преобразование в IPv4 возможно только для адресов IPv4-mapped, IPv4-compatible или 6to4.

  • string: последовательность байтов, заканчивающаяся первым символом NUL (0x00), который не входит в строку. Если нужен встроенный символ NUL, используйте тип binary. Кодировка не определяется: HAProxy не пытается трактовать байты как символы. Представляют ли они текст, в какой кодировке и как он отображается, зависит только от использования строки. Поэтому явное или неявное преобразование образца binary в строку без предупреждения отбрасывает всё начиная с первого символа NUL.

  • binary: блок байтов известной длины, в котором каждый байт может иметь любое значение от 0 до 255, включая NUL. Этот тип возвращают методы извлечения необработанных данных, например тела запроса или содержимого двоичного протокола. Такой образец нельзя преобразовать в boolean, целое число или адрес. Его нужно либо сопоставлять как двоичный блок с помощью “-m bin” (см. раздел 7.1.5 ), либо сначала переводить в печатный вид, например преобразователем “hex”. Обратное преобразование ничем не ограничено, поскольку строка всегда является допустимым двоичным блоком.

  • method: метод HTTP. Известные HAProxy методы представлены идентификатором; остальные сохраняют исходную строку.

В таблице преобразователей ниже также используется “any” для обозначения преобразователей, принимающих любой тип входных данных.

Также, если они существуют, указаны производные варианты ACL с соответствующими методами сопоставления. Для всех таких вариантов однозначно определён метод сопоставления с шаблонами по умолчанию, поэтому передавать параметр “-m”, чтобы указать способ сопоставления образца в ACL, никогда не требуется, хотя это и разрешено.

Как показано выше в матрице совместимости типов образцов и методов сопоставления, при использовании универсального метода извлечения образца в ACL параметр “-m” обязателен, кроме случаев, когда тип образца — логическое значение, целое число, IPv4 или IPv6. Если одно и то же ключевое слово существует и для ACL, и для обычного метода извлечения, механизм ACL по умолчанию автоматически выбирает вариант, предназначенный только для ACL.

Некоторые из этих ключевых слов поддерживают один или несколько обязательных и один или несколько необязательных аргументов. Аргументы имеют строгие типы и проверяются при разборе конфигурации, поэтому риска запуска с некорректным аргументом, например неразрешённым именем бэкенда, нет. Аргументы функции извлечения передаются в круглых скобках и разделяются запятыми. Необязательные аргументы ниже обозначаются квадратными скобками (’[ ]’). Если все аргументы необязательны, круглые скобки можно опустить.

Таким образом, стандартный метод извлечения образца имеет один из следующих вариантов синтаксиса:

  • name
  • name(arg1)
  • name(arg1,arg2)

7.3.1. Преобразователи

Методы извлечения образцов можно сочетать с преобразованиями, применяемыми к извлечённому образцу; такие преобразования также называются «преобразователями». Эти сочетания образуют «выражения образцов», а их результатом является «образец». Изначально это поддерживалось только в директивах “stick on” и “stick store-request”, но теперь доступно везде, где можно использовать образцы: ACL, log-format, unique-id-format, add-header и т. д.

Преобразования перечисляются в виде определённых ключевых слов после метода извлечения образца. Эти ключевые слова также можно добавлять непосредственно после аргумента ключевого слова извлечения, отделяя их запятой. Они тоже могут принимать аргументы, например сетевую маску, которые должны передаваться в круглых скобках.

Отдельную категорию преобразователей составляют побитовые и арифметические операторы, позволяющие выполнять основные операции над целыми числами. Поддерживаются некоторые побитовые операции (and, or, xor, cpl) и арифметические операции (add, sub, mul, div, mod, neg). Также доступны операции сравнения (odd, even, not, bool), позволяющие получить результат сопоставления без написания ACL.

Поддерживаются следующие ключевые слова:

   Ключевое слово                                  Входной тип  Выходной тип
------------------------------------------------+-------------+----------------
51d.single(prop[,prop*])                           string       string
add(value)                                         integer      integer
add_item(delim[,var[,suff]])                       string       string
aes_cbc_dec(bits,nonce,key[,<aad>])                binary       binary
aes_cbc_enc(bits,nonce,key[,<aad>])                binary       binary
aes_gcm_dec(bits,nonce,key,aead_tag[,aad])         binary       binary
aes_gcm_enc(bits,nonce,key,aead_tag[,aad])         binary       binary
and(value)                                         integer      integer
b64dec                                             string       binary
base2                                              binary       string
base64                                             binary       string
be2dec(separator,chunk_size[,truncate])            binary       string
le2dec(separator,chunk_size[,truncate])            binary       string
be2hex([separator[,chunk_size[,truncate]]])        binary       string
bool                                               integer      boolean
bytes(offset[,length])                             binary       binary
capture-req(id)                                    string       string
capture-res(id)                                    string       string
concat([start[,var[,end]]])                        string       string
cpl                                                integer      integer
crc32([avalanche])                                 binary       integer
crc32c([avalanche])                                binary       integer
cut_crlf                                           string       string
da-csv-conv(prop[,prop*])                          string       string
date                                               string       integer
debug([prefix][,destination])                       any          same
-- Ключевое слово -----------------------------+- Входной тип + Выходной тип -
digest(algorithm)                                  binary       binary
div(value)                                         integer      integer
djb2([avalanche])                                  binary       integer
eth.data                                           binary       binary
eth.dst                                            binary       binary
eth.hdr                                            binary       binary
eth.proto                                          binary       integer
eth.src                                            binary       binary
eth.vlan                                           binary       integer
even                                               integer      boolean
fe_exists                                          string       boolean
field(index,delimiters[,count])                    string       string
fix_is_valid                                       binary       boolean
fix_tag_value(tag)                                 binary       binary
has_ctl([mask])                                    binary       boolean
hex                                                binary       string
hex2i                                              binary       integer
hmac(algorithm,key)                                binary       binary
host_only                                          string       string
htonl                                              integer      integer
http_date([offset[,unit]])                         integer      string
iif(true,false)                                    boolean      string
in_table([table])                                  any          boolean
ip.data                                            binary       binary
ip.df                                              binary       integer
ip.dst                                             binary       address
ip.fp                                              binary       binary
ip.hdr                                             binary       binary
ip.proto                                           binary       integer
ip.src                                             binary       address
ip.tos                                             binary       integer
ip.ttl                                             binary       integer
ip.ver                                             binary       integer
ipmask(mask4[,mask6])                              address      address
json([input-code])                                 string       string
json_query(json_path[,output_type])                string       _outtype_
jwt_decrypt_jwk(<jwk>)                             string       binary
jwt_decrypt_cert(<cert>)                           string       binary
jwt_decrypt_secret(<secret>)                       string       binary
jwt_header_query([json_path[,output_type]])        string       string
jwt_payload_query([json_path[,output_type]])       string       string
-- Ключевое слово -----------------------------+- Входной тип + Выходной тип -
jwt_verify(alg,key)                                string       integer
jwt_verify_cert(alg,cert)                          string       integer
language(value[,default])                          string       string
length                                             string       integer
lower                                              string       string
ltime(format[,offset])                             integer      string
ltrim(chars)                                       string       string
map(map_name[,default_value])                      string       string
map_match(map_name[,default_value])                _match_      string
map_match_output(map_name[,default_value])         _match_      _output_
mod(value)                                         integer      integer
mqtt_field_value(pkt_type,fieldname_or_prop_ID)    binary       binary
mqtt_is_valid                                      binary       boolean
ms_ltime(format[,offset])                          integer      string
ms_utime(format[,offset])                          integer      string
mul(value)                                         integer      integer
nbsrv                                              string       integer
neg                                                integer      integer
not                                                integer      boolean
odd                                                integer      boolean
or(value)                                          integer      integer
-- Ключевое слово -----------------------------+- Входной тип + Выходной тип -
param(name[,delim])                                string       string
port_only                                          string       integer
protobuf(field_number[,field_type])                binary       binary
regsub(regex,subst[,flags])                        string       string
reverse                                            string       string
reverse_dom                                        string       string
rfc7239_field(field)                               string       string
rfc7239_is_valid                                   string       boolean
rfc7239_n2nn                                       string       address / str
rfc7239_n2np                                       string       integer / str
rfc7239_nn                                         address/str  string
rfc7239_np                                         integer/str  string
rtrim(chars)                                       string       string
sdbm([avalanche])                                  binary       integer
secure_memcmp(var)                                 string       boolean
set-var(var[,cond...])                              any          same
sha1                                               binary       binary
sha2([bits])                                       binary       binary
srv_is_up                                          string       boolean
srv_queue                                          string       integer
strcmp(var)                                        string       boolean
sub(value)                                         integer      integer
table_bytes_in_rate([table])                       any          integer
table_bytes_out_rate([table])                      any          integer
table_clr_gpc(idx[,table])                         any          integer
table_clr_gpc0([table])                            any          integer
table_clr_gpc1([table])                            any          integer
table_conn_cnt([table])                            any          integer
-- Ключевое слово -----------------------------+- Входной тип + Выходной тип -
table_conn_cur([table])                            any          integer
table_conn_rate([table])                           any          integer
table_expire([table[,default_value]])              any          integer
table_glitch_cnt([table])                          any          integer
table_glitch_rate([table])                         any          integer
table_gpc(idx[,table])                             any          integer
table_gpc0([table])                                any          integer
table_gpc0_rate([table])                           any          integer
table_gpc1([table])                                any          integer
table_gpc1_rate([table])                           any          integer
table_gpc_rate(idx[,table])                        any          integer
table_gpt(idx[,table])                             any          integer
table_gpt0([table])                                any          integer
table_http_err_cnt([table])                        any          integer
table_http_err_rate([table])                       any          integer
table_http_fail_cnt([table])                       any          integer
table_http_fail_rate([table])                      any          integer
table_http_req_cnt([table])                        any          integer
table_http_req_rate([table])                       any          integer
table_idle([table[,default_value]])                any          integer
table_inc_gpc(idx[,table])                         any          integer
table_inc_gpc0([table])                            any          integer
table_inc_gpc1([table])                            any          integer
table_kbytes_in([table])                           any          integer
-- Ключевое слово -----------------------------+- Входной тип + Выходной тип -
table_kbytes_out([table])                          any          integer
table_server_id([table])                           any          integer
table_sess_cnt([table])                            any          integer
table_sess_rate([table])                           any          integer
table_trackers([table])                            any          integer
tcp.dst                                            binary       integer
tcp.flags                                          binary       integer
tcp.options.mss                                    binary       integer
tcp.options.sack                                   binary       integer
tcp.options.tsopt                                  binary       integer
tcp.options.tsval                                  binary       integer
tcp.options.wscale                                 binary       integer
tcp.options.wsopt                                  binary       integer
tcp.options_list                                   binary       binary
tcp.seq                                            binary       integer
tcp.src                                            binary       integer
tcp.win                                            binary       integer
ub64dec                                            string       string
ub64enc                                            string       string
ungrpc(field_number[,field_type])                  binary       binary / int
unset-var(var)                                      any          same
upper                                              string       string
url_dec([in_form])                                 string       string
url_enc([enc_type])                                string       string
us_ltime(format[,offset])                          integer      string
us_utime(format[,offset])                          integer      string
utime(format[,offset])                             integer      string
when(condition)                                     any          same
word(index,delimiters[,count])                     string       string
wt6([avalanche])                                   binary       integer
x509_v_err_str                                     integer      string
xor(value)                                         integer      integer
-- Ключевое слово -----------------------------+- Входной тип + Выходной тип -
xxh3([seed])                                       binary       integer
xxh32([seed])                                      binary       integer
xxh64([seed])                                      binary       integer

Далее приведён подробный список ключевых слов преобразователей:

51d.single(<prop>[,<prop>*])

51d.single(<prop>[,<prop>*])

Возвращает значения запрошенных свойств строкой, разделяя их разделителем, заданным параметром “51degrees-property-separator”. Устройство определяется по заголовку User-Agent, переданному преобразователю. Функции можно передать до пяти имён свойств; если имя свойства не найдено, возвращается значение “NoData”.

Пример:

# Here the header "X-51D-DeviceTypeMobileTablet" is added to the request,
# containing values for the three properties requested by using the
# User-Agent passed to the converter.
frontend http-in
  bind *:8081
  default_backend servers
  http-request set-header X-51D-DeviceTypeMobileTablet \
    %[req.fhdr(User-Agent),51d.single(DeviceType,IsMobile,IsTablet)]

add(<value>)

add(<value>)

Прибавляет <value> к входному значению типа целого числа со знаком и возвращает результат как целое число со знаком. <value> может быть числом или именем переменной. Подробности о переменных см. в разделе 2.8 .

add_item(<delim>[,<var>[,<suff>]])

add_item(<delim>[,<var>[,<suff>]])

Присоединяет к текущему образцу от 2 до 3 полей, после чего образец преобразуется в строку. Первое поле, <delim>, — постоянная строка, добавляемая сразу после существующего образца, если он не пуст и при этом хотя бы одно из полей <var> или <suff> не пусто. Второе поле, <var>, — имя переменной. Переменная ищется, её содержимое преобразуется в строку и добавляется сразу после части <delim>. Если переменная не найдена, ничего не добавляется. Этот аргумент необязателен; после него можно также указать постоянную строку <suff>. Однако если <var> опущен, <suff> обязателен. Преобразователь похож на concat и позволяет создавать новые переменные из последовательности других переменных. Основное отличие в том, что он проверяет, имеет ли смысл добавлять разделитель: например, это не нужно, если текущий образец пуст. С преобразователем concat в таком случае потребовались бы 2 отдельных правила, причём первое должно было бы проверять, пуста ли строка текущего образца, прежде чем добавлять разделитель. Если разделителем должна быть запятая или закрывающая круглая скобка, её нужно защитить кавычками или обратными косыми чертами. Сами эти символы также должны быть защищены от удаления парсером первого уровня; о кавычках и экранировании см. раздел 2.2 . Примеры приведены ниже.

Пример:

http-request set-var(req.tagged) 'var(req.tagged),add_item(",",req.score1,"(site1)") if src,in_table(site1)'
http-request set-var(req.tagged) 'var(req.tagged),add_item(",",req.score2,"(site2)") if src,in_table(site2)'
http-request set-var(req.tagged) 'var(req.tagged),add_item(",",req.score3,"(site3)") if src,in_table(site3)'
http-request set-header x-tagged %[var(req.tagged)]

http-request set-var(req.tagged) 'var(req.tagged),add_item(",",req.score1),add_item(",",req.score2)'
http-request set-var(req.tagged) 'var(req.tagged),add_item(",",,(site1))' if src,in_table(site1)

aes_cbc_dec(<bits>,<nonce>,<key>[,<aad>])

aes_cbc_dec(<bits>,<nonce>,<key>[,<aad>])

Расшифровывает входные необработанные байты алгоритмом AES128-CBC, AES192-CBC или AES256-CBC в зависимости от параметра <bits>. Все остальные параметры должны быть закодированы в base64, а результат возвращается в виде необработанных байтов. Параметр <aad> необязателен. Если проверка <aad> не проходит, преобразователь не возвращает данных. <nonce>, <key> и <aad> могут быть строками или переменными. Для этого преобразователя требуется OpenSSL версии не ниже 1.0.1.

Пример:

http-response set-header X-Decrypted-Text %[var(txn.enc),\
  aes_cbc_dec(128,txn.nonce,Zm9vb2Zvb29mb29wZm9vbw==)]

aes_cbc_enc(<bits>,<nonce>,<key>[,<aad>])

aes_cbc_enc(<bits>,<nonce>,<key>[,<aad>])

Шифрует входные необработанные байты алгоритмом AES128-CBC, AES192-CBC или AES256-CBC в зависимости от параметра <bits>. Параметры <nonce>, <key> и <aad> должны быть закодированы в base64. Параметр <aad> необязателен. Результат возвращается в виде необработанных байтов. <nonce>, <key> и <aad> могут быть строками или переменными. Для этого преобразователя требуется OpenSSL версии не ниже 1.0.1.

Пример:

http-response set-header X-Encrypted-Text %[var(txn.plain),\
  aes_cbc_enc(128,txn.nonce,Zm9vb2Zvb29mb29wZm9vbw==)]

aes_gcm_dec(<bits>,<nonce>,<key>,<aead_tag>[,<aad>])

aes_gcm_dec(<bits>,<nonce>,<key>,<aead_tag>[,<aad>])

Расшифровывает входные необработанные байты алгоритмом AES128-GCM, AES192-GCM или AES256-GCM в зависимости от параметра <bits>. Все остальные параметры должны быть закодированы в base64, а результат возвращается в виде необработанных байтов. Если проверка <aead_tag> или <aad> не проходит, преобразователь не возвращает данных. Параметр <aad> необязателен. <nonce>, <key>, <aead_tag> и <aad> могут быть строками или переменными. Для этого преобразователя требуется OpenSSL версии не ниже 1.0.1.

Пример:

http-response set-header X-Decrypted-Text %[var(txn.enc),\
  aes_gcm_dec(128,txn.nonce,Zm9vb2Zvb29mb29wZm9vbw==,txn.aead_tag)]

aes_gcm_enc(<bits>,<nonce>,<key>,<aead_tag>[,<aad>])

aes_gcm_enc(<bits>,<nonce>,<key>,<aead_tag>[,<aad>])

Шифрует входные необработанные байты алгоритмом AES128-GCM, AES192-GCM или AES256-GCM в зависимости от параметра <bits>. Параметры <nonce>, <key> и <aad> должны быть закодированы в base64. Параметр <aead_tag> должен быть переменной: в неё будет сохранён тег AEAD, закодированный в base64. Параметр <aad> необязателен. Результат возвращается в виде необработанных байтов. <nonce>, <key> и <aad> могут быть строками или переменными. Для этого преобразователя требуется OpenSSL версии не ниже 1.0.1.

Пример:

http-response set-header X-Encrypted-Text %[var(txn.plain),\
  aes_gcm_enc(128,txn.nonce,Zm9vb2Zvb29mb29wZm9vbw==,txn.aead_tag)]

and(<value>)

and(<value>)

Выполняет побитовое “AND” между <value> и входным значением типа целого числа со знаком; результат возвращается как целое число со знаком. <value> может быть числом или именем переменной. Подробности о переменных см. в разделе 2.8 .

b64dec

b64dec

Преобразует (декодирует) входную строку, закодированную в base64, в двоичное представление. Это операция, обратная base64(). Для варианта base64url(“URL and Filename Safe Alphabet” (RFC 4648)) см. “ub64dec”.

base2

base2

Преобразует входной двоичный образец в строку двоичных цифр, содержащую восемь цифр на каждый входной байт. Используется для сопоставления по самому длинному префиксу с типами, чьё собственное представление не допускает сопоставления по префиксу, например с IP-префиксами.

base64

base64

Преобразует входной двоичный образец в строку base64. Используется для записи в журнал или передачи двоичного содержимого в виде, пригодном для надёжной передачи; например, идентификатор SSL можно скопировать в заголовок. Для варианта base64url(“URL and Filename Safe Alphabet” (RFC 4648)) см. “ub64enc”.

be2dec(<separator>,<chunk_size>[,<truncate>])

be2dec(<separator>,<chunk_size>[,<truncate>])

Преобразует входной двоичный образец с порядком байтов от старшего к младшему в строку, содержащую по одному беззнаковому целому числу на каждые <chunk_size> входных байтов. Если указан <separator>, он вставляется через каждые <chunk_size> двоичных входных байтов. Флаг <truncate> определяет, усекаются ли входные двоичные данные по границам <chunk_size>. Максимальное значение <chunk_size> ограничено размером long long int (8 байт).

Пример:

bin(01020304050607),be2dec(:,2)   # 258:772:1286:7
bin(01020304050607),be2dec(-,2,1) # 258-772-1286
bin(01020304050607),be2dec(,2,1)  # 2587721286
bin(7f000001),be2dec(.,1)         # 127.0.0.1

le2dec(<separator>,<chunk_size>[,<truncate>])

le2dec(<separator>,<chunk_size>[,<truncate>])

Преобразует входной двоичный образец с порядком байтов от младшего к старшему в строку, содержащую по одному беззнаковому целому числу на каждые <chunk_size> входных байтов. Если указан <separator>, он вставляется через каждые <chunk_size> двоичных входных байтов. Флаг <truncate> определяет, усекаются ли входные двоичные данные по границам <chunk_size>. Максимальное значение <chunk_size> ограничено размером long long int (8 байт).

Пример:

bin(01020304050607),le2dec(:,2)   # 513:1284:2055:7
bin(01020304050607),le2dec(-,2,1) # 513-1284-2055
bin(01020304050607),le2dec(,2,1)  # 51312842055
bin(7f000001),le2dec(.,1)         # 127.0.0.1

be2hex([<separator>[,<chunk_size>[,<truncate>]]])

be2hex([<separator>[,<chunk_size>[,<truncate>]]])

Преобразует входной двоичный образец с порядком байтов от старшего к младшему в шестнадцатеричную строку, содержащую по две цифры на каждый входной байт. Используется для записи в журнал или передачи шестнадцатеричных дампов двоичных входных данных в виде, пригодном для надёжной передачи; например, идентификатор SSL можно скопировать в заголовок. Если указан <separator>, он вставляется через каждые <chunk_size> двоичных входных байтов. Флаг <truncate> определяет, усекаются ли входные двоичные данные по границам <chunk_size>.

Пример:

bin(01020304050607),be2hex         # 01020304050607
bin(01020304050607),be2hex(:,2)    # 0102:0304:0506:07
bin(01020304050607),be2hex(--,2,1) # 0102--0304--0506
bin(0102030405060708),be2hex(,3,1) # 010203040506

bool

bool

Возвращает логическое TRUE, если входное значение типа целого числа со знаком ненулевое, иначе возвращает FALSE. Совместно с and() может использоваться для получения true/false при проверке битов входного значения, например для проверки наличия флага.

bytes(<offset>[,<length>])

bytes(<offset>[,<length>])

Извлекает несколько байтов из входного двоичного образца. Результат — двоичный образец, начинающийся с указанного смещения (в байтах) относительно исходного образца и при необходимости усечённый до заданной длины. <offset> и <length> могут быть числами или именами переменных. Преобразователь возвращает пустой образец, если <offset> или <length> недопустимо. Недопустимое <offset> — отрицательное значение или значение >= длины входного образца. Недопустимое <length> — отрицательное значение.

Пример:

http-request set-var(txn.input) req.hdr(input) # let's say input is "012345"

http-response set-header bytes_0 "%[var(txn.input),bytes(0)]"  # outputs "012345"
http-response set-header bytes_1_3 "%[var(txn.input),bytes(1,3)]"  # outputs "123"

http-response set-var(txn.var_start) int(1)
http-response set-var(txn.var_length) int(3)
http-response set-header bytes_var1_var3    "%[var(txn.input),bytes(txn.var_start,txn.var_length)]"  # outputs "123"

capture-req(<id>)

capture-req(<id>)

Сохраняет строковое значение в слоте запроса <id> и возвращает его без изменений. Если слот не существует, захват завершается неудачей без сообщения об ошибке.

См. также: “declare capture”, “http-request capture”, “http-response capture”, “capture.req.hdr” и “capture.res.hdr” (методы извлечения образцов).

capture-res(<id>)

capture-res(<id>)

Сохраняет строковое значение в слоте ответа <id> и возвращает его без изменений. Если слот не существует, захват завершается неудачей без сообщения об ошибке.

См. также: “declare capture”, “http-request capture”, “http-response capture”, “capture.req.hdr” и “capture.res.hdr” (методы извлечения образцов).

concat([<start>[,<var>[,<end>]]])

concat([<start>[,<var>[,<end>]]])

Присоединяет к текущему образцу до 3 полей, после чего образец преобразуется в строку. Первое поле, <start>, — постоянная строка, добавляемая сразу после существующего образца. Если она не нужна, поле можно опустить. Второе поле, <var>, — имя переменной. Переменная ищется, её содержимое преобразуется в строку и добавляется сразу после части <first>. Если переменная не найдена, ничего не добавляется. Это поле тоже можно опустить. Третье поле, <end>, — постоянная строка, добавляемая после переменной; её также можно опустить. Вместе эти элементы позволяют присоединять переменные с разделителями к уже существующему набору переменных. Так можно создавать новые переменные из последовательности других переменных, например со значениями, разделёнными двоеточиями. Если разделителем должна быть запятая или закрывающая круглая скобка, её нужно защитить кавычками или обратными косыми чертами. Сами эти символы также должны быть защищены от удаления парсером первого уровня. Это часто используется для создания составных переменных из других, хотя иногда удобнее использовать строку формата с несколькими полями. Примеры приведены ниже.

Пример:

tcp-request session set-var(sess.src) src
tcp-request session set-var(sess.dn)  ssl_c_s_dn
tcp-request session set-var(txn.sig) str(),concat(<ip=,sess.ip,>),concat(<dn=,sess.dn,>)
tcp-request session set-var(txn.ipport) "str(),concat('addr=(',sess.ip),concat(',',sess.port,')')"
tcp-request session set-var-fmt(txn.ipport) "addr=(%[sess.ip],%[sess.port])"  ## does the same
http-request set-header x-hap-sig %[var(txn.sig)]

cpl

cpl

Вычисляет обратный код входного целого числа со знаком (инвертирует все биты) и возвращает результат как целое число со знаком.

crc32([<avalanche>])

crc32([<avalanche>])

Хэширует двоичный входной образец в беззнаковое 32-битное значение с использованием хэш-функции CRC32. К результату можно дополнительно применить хеш-функцию с полным лавинным эффектом, если необязательный аргумент <avalanche> равен 1. Этот преобразователь использует те же функции, что и различные алгоритмы балансировки нагрузки на основе хэширования, поэтому обеспечивает точно такие же результаты. Предназначен для совместимости с другими программными продуктами, которым требуется вычисление CRC32 на основе входных ключей, следуя наиболее распространённой реализации, как в Ethernet, Gzip, PNG и т.д. Он медленнее других алгоритмов, но может обеспечить лучшее или по крайней мере менее предсказуемое распределение. Не должен использоваться в целях безопасности, так как хэш размером 32 бит легко взломать. См. также “djb2”, “sdbm”, “wt6”, “crc32c” и директиву “hash-type”.

crc32c([<avalanche>])

crc32c([<avalanche>])

Хэширует двоичный входной образец в беззнаковое 32-битное значение с использованием хэш-функции CRC32C. К результату можно дополнительно применить хеш-функцию с полным лавинным эффектом, если необязательный аргумент <avalanche> равен 1. Этот преобразователь использует те же функции, что описаны в RFC4960, Приложение B [8]. Предназначен для совместимости с другими программными продуктами, которым требуется вычисление CRC32C на основе входных ключей. Он медленнее других алгоритмов и не должен использоваться в целях безопасности, так как хэш размером 32 бит легко взломать. См. также “djb2”, “sdbm”, “wt6”, “crc32” и директиву “hash-type”.

cut_crlf

cut_crlf

Обрезает строковое представление входного образца по первому символу возврата каретки (’\r’) или новой строки (’\n’). Изменяется только длина строки.

da-csv-conv(<prop>[,<prop>*])

da-csv-conv(<prop>[,<prop>*])

Вызывает преобразователь DeviceAtlas для распознавания переданной на вход строки User Agent и возвращает строку из объединённых свойств, перечисленных в аргументе. Они разделяются символом, заданным глобальным ключевым словом “deviceatlas-property-separator”, а по умолчанию — вертикальной чертой (’|’). Язык конфигурации HAProxy ограничивает число различных свойств значением 12.

Пример:

frontend www
  bind *:8881
  default_backend servers
  http-request set-header X-DeviceAtlas-Data %[req.fhdr(User-Agent),da-csv(primaryHardwareType,osName,osVersion,browserName,browserVersion,browserRenderingEngine)]

date

date

Этот преобразователь используется для преобразования даты из заголовка HTTP. Это может быть дата в формате IMF, ASCTIME или RFC850. Выводит метку времени в формате UNIX.

Пример:

http-request return lf-string "%[str('Sun, 06 Nov 1994 08:49:37 GMT'),date]\n" content-type text/plain

debug([<prefix][,<destination>])

debug([<prefix][,<destination>])

Этот преобразователь используется для отладки. Он захватывает входной образец и отправляет его в приёмник событий <destination>, который может обозначать кольцевой буфер, например “buf0”, а также “stdout” или “stderr”. Доступные приёмники можно посмотреть во время работы командой “show events” в CLI. Если приёмник не указан, вывод направляется в “buf0”, который можно просмотреть командой CLI “show events”. Чтобы различать вывод нескольких выражений, можно передать необязательный префикс <prefix>. Он появится перед двоеточием в выводимом сообщении. Входной образец передаётся на выход без изменений, поэтому преобразователь debug можно безопасно вставить в любое место цепочки, даже для образцов непечатаемых типов.

Пример:

tcp-request connection track-sc0 src,debug(track-sc)

digest(<algorithm>)

digest(<algorithm>)

Преобразует входной двоичный образец в хеш сообщения. Результат — двоичный образец. <algorithm> должен быть именем хеш-функции OpenSSL, например sha256.

Обратите внимание: этот преобразователь доступен только в том случае, если HAProxy собран с USE_OPENSSL.

div(<value>)

div(<value>)

Делит входное целое число со знаком на <value> и возвращает результат как целое число со знаком. Если <value> равен нулю, возвращается наибольшее беззнаковое целое число, обычно 2^63-1. <value> может быть числом или именем переменной. Подробности о переменных см. в разделе 2.8 .

djb2([<avalanche>])

djb2([<avalanche>])

Хэширует двоичный входной образец в беззнаковое 32-битное значение с использованием хэш-функции DJB2. К результату можно дополнительно применить хеш-функцию с полным лавинным эффектом, если необязательный аргумент <avalanche> равен 1. Этот преобразователь использует те же функции, что и различные алгоритмы балансировки нагрузки на основе хэширования, поэтому обеспечивает точно такие же результаты. В основном предназначен для отладки, но может использоваться как запись в таблице привязок для сбора приблизительной статистики. Не должен использоваться в целях безопасности, так как хэш размером 32 бит легко взломать. См. также “crc32”, “sdbm”, “wt6”, “crc32c” и директиву “hash-type”.

eth.data

eth.data

Используется с входным образцом, представляющим двоичный кадр Ethernet, который возвращает “fc_saved_syn”, когда параметр “tcp-ss” директивы bind равен “2”. Пропускает весь заголовок Ethernet, включая возможные VLAN, и возвращает блок двоичных данных, начинающийся с протокола уровня 3 (обычно IPv4 или IPv6). См. также “fc_saved_syn” и “tcp-ss”.

eth.dst

eth.dst

Используется с входным образцом, представляющим двоичный кадр Ethernet, который возвращает “fc_saved_syn”, когда параметр “tcp-ss” директивы bind равен “2”. Возвращает 6 байт заголовка Ethernet, соответствующих адресу назначения кадра, как двоичный блок. См. также “fc_saved_syn” и “tcp-ss”.

eth.hdr

eth.hdr

Используется с входным образцом, представляющим двоичный кадр Ethernet, который возвращает “fc_saved_syn”, когда параметр “tcp-ss” директивы bind равен “2”. Обрезает всё, что находится после заголовка Ethernet, но сохраняет возможные VLAN, и возвращает этот заголовок как двоичный блок. См. также “fc_saved_syn” и “tcp-ss”.

eth.proto

eth.proto

Используется с входным образцом, представляющим двоичный кадр Ethernet, который возвращает “fc_saved_syn”, когда параметр “tcp-ss” директивы bind равен “2”. Возвращает номер протокола (также известный как EtherType), найденный в заголовке Ethernet после любого необязательного VLAN, в виде целого числа. Обычно это 0x800 для IPv4 или 0x86DD для IPv6. См. также “fc_saved_syn” и “tcp-ss”.

eth.src

eth.src

Используется с входным образцом, представляющим двоичный кадр Ethernet, который возвращает “fc_saved_syn”, когда параметр “tcp-ss” директивы bind равен “2”. Возвращает 6 байт заголовка Ethernet, соответствующих адресу источника кадра, как двоичный блок. См. также “fc_saved_syn” и “tcp-ss”.

eth.vlan

eth.vlan

Используется с входным образцом, представляющим двоичный кадр Ethernet, который возвращает “fc_saved_syn”, когда параметр “tcp-ss” директивы bind равен “2”. Возвращает последний VLAN ID, найденный в заголовке Ethernet, в виде целого числа. См. также “fc_saved_syn” и “tcp-ss”.

even

even

Возвращает логическое TRUE, если входное целое число со знаком чётное, иначе возвращает FALSE. Функционально эквивалентен “not,and(1),bool”.

field(<index>,<delimiters>[,<count>])

field(<index>,<delimiters>[,<count>])

Извлекает из входной строки подстроку по заданному индексу с учётом указанных разделителей. Отсчёт ведётся от начала при положительном индексе или от конца при отрицательном. Индексы начинаются с 1 или -1, а разделители задаются списком символов в виде строки. Можно указать количество извлекаемых полей <count>; по умолчанию оно равно 1. Значение 0 означает извлечение всех оставшихся полей.

Пример:

str(f1_f2_f3__f5),field(4,_)    # <empty>
str(f1_f2_f3__f5),field(5,_)    # f5
str(f1_f2_f3__f5),field(2,_,0)  # f2_f3__f5
str(f1_f2_f3__f5),field(2,_,2)  # f2_f3
str(f1_f2_f3__f5),field(-2,_,3) # f2_f3_
str(f1_f2_f3__f5),field(-3,_,0) # f1_f2_f3

fe_exists

fe_exists

Принимает на вход имя фронтенда и возвращает логическое TRUE, если фронтенд с таким именем существует в текущей конфигурации; иначе возвращает FALSE. Может использоваться там, где полезна проверка наличия фронтенда по динамическому имени, например при поиске в таблице соответствий или ответе на внешнюю проверку.

Пример:

http-request deny unless { var(txn.fe_name),fe_exists }

fix_is_valid

fix_is_valid

Разбирает двоичную полезную нагрузку и выполняет проверки корректности для FIX (Financial Information eXchange):

  • проверяет, что все идентификаторы тегов и их значения не пустые, а идентификаторы тегов — корректные числа
  • проверяет, что тег BeginString является первым тегом с допустимой версией FIX
  • проверяет, что тег BodyLength — второй тег с правильной длиной тела
  • проверяет, что тег MsgType — третий тег
  • проверяет, что последний тег в сообщении — это тег CheckSum с корректной контрольной суммой

Из-за текущего устройства HAProxy можно разобрать только первое сообщение клиента и первое сообщение сервера.

Этот преобразователь возвращает логическое значение: true, если полезная нагрузка содержит корректное сообщение FIX, и false — в противном случае.

См. также преобразователь fix_tag_value.

Пример:

tcp-request inspect-delay 10s
tcp-request content reject unless { req.payload(0,0),fix_is_valid }

fix_tag_value(<tag>)

fix_tag_value(<tag>)

Анализирует сообщение FIX (Financial Information eXchange) и извлекает значение из тега <tag>. <tag> может быть строкой или целым числом, указывающим на нужный тег. Любое целочисленное значение допускается, но только следующие строки преобразуются в их целочисленные эквиваленты: BeginString, BodyLength, MsgType, SenderCompID, TargetCompID, CheckSum. Другие имена тегов можно легко добавить.

Из-за текущего устройства HAProxy можно разобрать только первое сообщение клиента и первое сообщение сервера. Этот преобразователь не проверяет корректность сообщения. Настоятельно рекомендуется сначала проверить сообщение преобразователем fix_is_valid.

См. также преобразователь fix_is_valid.

Пример:

tcp-request inspect-delay 10s
tcp-request content reject unless { req.payload(0,0),fix_is_valid }
# MsgType tag ID is 35, so both lines below will return the same content
tcp-request content set-var(txn.foo) req.payload(0,0),fix_tag_value(35)
tcp-request content set-var(txn.bar) req.payload(0,0),fix_tag_value(MsgType)

has_ctl([mask])

has_ctl([mask])

Проверяет входной двоичный образец на наличие управляющих символов, заданных аргументом маски. Маска — 33-битное число, десятичное или шестнадцатеричное с префиксом “0x”. В ней устанавливается бит для каждого искомого символа в диапазоне от 0x00 до 0x1F; бит 32 соответствует символу DEL (0x7F). Если маска не задана, преобразователь использует значение 0x1FFFFFDFF: оно соответствует всем управляющим символам, кроме TAB (0x09), часто используемого в заголовках HTTP. Специальная маска “any” равна 0x1FFFFFFFF и соответствует всем управляющим символам, включая TAB. Специальная маска “http” равна 0x2401 и позволяет обнаруживать только управляющие символы, запрещённые в значениях заголовков HTTP: CR (0x0D), LF (0x0A) и NUL (0x00).

Примеры:

# reject presence of DEL, CR, LF, NUL characters in the referer header
http-request deny if { req.fhdr(referer),has_ctl(0x100002401) }
# reject presence of any control char but tab in any HTTP header value
http-request deny if { req.hdr(),has_ctl }

hex

hex

Преобразует двоичный образец в шестнадцатеричную строку, содержащую по две шестнадцатеричные цифры на каждый байт входных данных. Используется для ведения журнала или передачи шестнадцатеричных дампов некоторых двоичных данных таким образом, чтобы их можно было надёжно передавать (например, идентификатор SSL может быть скопирован в заголовок).

hex2i

hex2i

Преобразует шестнадцатеричную строку, содержащую по две шестнадцатеричные цифры на каждый байт входных данных, в целое число. Если входное значение содержит символ, не являющийся шестнадцатеричной цифрой, преобразователь завершается неуспешно и ничего не возвращает. Это позволяет отличить некорректные входные данные от допустимого нулевого значения.

hmac(<algorithm>,<key>)

hmac(<algorithm>,<key>)

Преобразует двоичный образец в код аутентификации сообщения с заданным ключом. Результат — двоичный образец. Параметр <algorithm> должен быть одним из зарегистрированных имён хеш-функций OpenSSL (например, sha256). Параметр <key> должен быть закодирован в base64 и может быть строкой или переменной.

Обратите внимание: этот преобразователь доступен только в том случае, если HAProxy собран с USE_OPENSSL.

host_only

host_only

Преобразует строку, содержащую значение заголовка Host, и удаляет из неё порт. Входные данные должны соответствовать формату значения заголовка Host (rfc9110#section-7.2). Поддерживаются следующие форматы: hostname, hostname:80, 127.0.0.1, 127.0.0.1:80, [::1], [::1]:80.

Этот преобразователь также приводит строку к нижнему регистру.

См. также преобразователь “port_only”, который вернёт порт.

htonl

htonl

Преобразует входное целое число в его 32-битное двоичное представление с сетевым порядком байтов. Поскольку методы извлечения образцов используют 64-битные целые числа со знаком, этот преобразователь сначала приводит входное число к беззнаковому 32-битному целому.

http_date([<offset[,<unit>]])

http_date([<offset[,<unit>]])

Преобразует целое число, рассматриваемое как дата, отсчитанная от начала эпохи, в строку с этой датой в формате, пригодном для полей заголовков HTTP. Если задано смещение, оно прибавляется к дате до преобразования. Это особенно полезно для формирования заголовка Date, значений Expires в ответах при положительном смещении или значений Last-Modified при отрицательном. Если задана единица измерения, временная метка трактуется как число секунд от начала эпохи при “s” (по умолчанию), миллисекунд при “ms” или микросекунд при “us”. Смещение считается заданным в тех же единицах, что и входная временная метка.

iif(<true>,<false>)

iif(<true>,<false>)

Возвращает строку <true>, если входное значение истинно. В противном случае возвращает строку <false>.

Пример:

http-request set-header x-forwarded-proto %[ssl_fc,iif(https,http)]

in_table([<table>])

in_table([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается логическое значение false. В противном случае — логическое значение true. Может использоваться для проверки наличия определённого ключа в таблице, отслеживающей некоторые элементы (например, был ли уже виден IP-адрес источника или заголовок Authorization).

ip.data

ip.data

Используется с входным образцом, представляющим двоичный кадр Ethernet, который возвращает “fc_saved_syn”, когда параметр “tcp-ss” директивы bind равен “1”, либо с результатом “eth.data”. Пропускает заголовок IP и любые необязательные опции или расширения, и возвращает блок двоичных данных, начинающийся с транспортного протокола (обычно TCP или UDP). См. также “fc_saved_syn”, “tcp-ss” и “eth.data”.

ip.df

ip.df

Используется с входным образцом, представляющим двоичный кадр Ethernet, который возвращает “fc_saved_syn”, когда параметр “tcp-ss” директивы bind равен “1”, либо с результатом “eth.data”. Возвращает целое значение 1, если установлен флаг DF (не фрагментировать) в заголовке IP, иначе — 0. У протокола IPv6 нет флага DF, и он по умолчанию не фрагментирует, поэтому всегда возвращает 1. См. также “fc_saved_syn”, “tcp-ss” и “eth.data”.

ip.dst

ip.dst

Используется с входным образцом, представляющим двоичный кадр Ethernet, который возвращает “fc_saved_syn”, когда параметр “tcp-ss” директивы bind равен “1”, либо с результатом “eth.data”. Возвращает адрес назначения IPv4 или IPv6 из заголовка IPv4/v6. См. также “fc_saved_syn”, “tcp-ss” и “eth.data”.

ip.fp([<mode>])

ip.fp([<mode>])

Используется с входным образцом, представляющим двоичный кадр Ethernet, который возвращает “fc_saved_syn”, когда параметр “tcp-ss” директивы bind равен “1”, либо с результатом “eth.data”. Анализирует различные части заголовков IP и TCP, чтобы построить своего рода отпечаток их неизменных частей. Он позволяет различать несколько внешне одинаковых узлов. На практике это применяется для более точного определения узлов с некорректным поведением за общим IP-адресом, чтобы не блокировать легитимных пользователей, когда некорректно ведёт себя и требует блокировки только один узел. На основе входных данных преобразователь строит двоичный блок размером не менее 8 байт. Байты отпечатка расположены следующим образом: - байт 0: поле IP TOS (см. ip.tos) - байт 1: - бит 7: IPv6 (1) / IPv4 (0) - бит 6: ip.df - биты 5..4: 0:ip.ttl<=32; 1:ip.ttl<=64; 2:ip.ttl<=128; 3:ip.ttl<=255 - бит 3: опции IP присутствуют (1) / отсутствуют (0) - бит 2: данные TCP присутствуют (1) / отсутствуют (0) - бит 1: в TCP.flags установлен CWR (1) / сброшен (0) - бит 0: в TCP.flags установлен ECE (1) / сброшен (0) - байт 2: - биты 7..4: длина заголовка TCP в 4-байтных словах - биты 3..0: масштаб окна TCP + 1 (1..15) / 0 (WS не объявлен) - байты 3..4: tcp.win - байты 5..6: tcp.options.mss или ноль, если отсутствует - байт 7: по 1 биту на каждую присутствующую опцию TCP; опции от 2 до 8 соответствуют битам 0..6, а бит 7 обозначает наличие любой опции от 9 до 255.

Аргумент <mode> позволяет добавить в отпечаток дополнительную информацию. По умолчанию, если <mode> не задан или равен нулю, отпечаток состоит только из описанных выше 8 байт. Если <mode> задан другим значением, оно означает сумму следующих значений; соответствующие компоненты присоединяются к отпечатку в указанном порядке: - 1: к отпечатку добавляется полученное значение TTL (1 байт) - 2: к отпечатку добавляется список видов опций TCP, возвращаемый “tcp.options_list” и занимающий от 0 до 40 дополнительных байт - 4: к отпечатку добавляется IP-адрес источника, что увеличивает его на 4 байта для IPv4 или на 16 для IPv6.

Пример: создать отпечаток размером 13..25 байт, используя базовый FP, TTL и адрес источника (1+4=5):

frontend test
    mode http
    bind :4445 tcp-ss 1
    tcp-request connection set-var(sess.syn) fc_saved_syn
    http-request return status 200 content-type text/plain lf-string &#92;
          "src=%[var(sess.syn),ip.src] fp=%[var(sess.syn),ip.fp(5),hex]&#92;n"

См. также “fc_saved_syn”, “tcp-ss”, “eth.data”, “ip.df”, “ip.ttl”, “tcp.win”, “tcp.options.mss” и “tcp.options_list”.

ip.hdr

ip.hdr

Используется с входным образцом, представляющим двоичный кадр Ethernet, который возвращает “fc_saved_syn”, когда параметр “tcp-ss” директивы bind равен “1”, либо с результатом “eth.data”. Возвращает блок двоичных данных, начинающийся с заголовка IP и заканчивающийся после последней опции или расширения, до начала заголовка транспортного протокола. См. также “fc_saved_syn”, “tcp-ss” и “eth.data”.

ip.proto

ip.proto

Используется с входным образцом, представляющим двоичный кадр Ethernet, который возвращает “fc_saved_syn”, когда параметр “tcp-ss” директивы bind равен “1”, либо с результатом “eth.data”. Возвращает номер транспортного протокола, обычно 6 для TCP или 17 для UDP. См. также “fc_saved_syn”, “tcp-ss” и “eth.data”.

ip.src

ip.src

Используется с входным образцом, представляющим двоичный кадр Ethernet, который возвращает “fc_saved_syn”, когда параметр “tcp-ss” директивы bind равен “1”, либо с результатом “eth.data”. Возвращает адрес источника IPv4 или IPv6 из заголовка IPv4/v6. См. также “fc_saved_syn”, “tcp-ss” и “eth.data”.

ip.tos

ip.tos

Используется с входным образцом, представляющим двоичный кадр Ethernet, который возвращает “fc_saved_syn”, когда параметр “tcp-ss” директивы bind равен “1”, либо с результатом “eth.data”. Возвращает целое число, соответствующее значению поля type-of-service (TOS) в заголовке IPv4 или поля traffic class (TC) в заголовке IPv6. Обратите внимание, что в современной интернет-инфраструктуре это поле чаще всего содержит значение DSCP (Differentiated Services Codepoint) в старших 6 битах, а два младших бита либо не используются, либо используются механизмом IP ECN. См. RFC2474 и RFC8436 для значений DSCP, и RFC3168 для полей IP ECN. См. также “fc_saved_syn”, “tcp-ss” и “eth.data”.

ip.ttl

ip.ttl

Используется с входным образцом, представляющим двоичный кадр Ethernet, который возвращает “fc_saved_syn”, когда параметр “tcp-ss” директивы bind равен “1”, либо с результатом “eth.data”. Возвращает целое число, соответствующее полю TTL (Time To Live) или HL (Hop Limit) в заголовке IPv4/IPv6. Обычно этому полю присваивается фиксированное начальное значение и уменьшается на каждом маршрутизаторе, через который проходит пакет. Если начальное значение известно, это помогает оценить, с какого расстояния подключается клиент. Обратите внимание, что большинство современных операционных систем начинают с начального значения 64. См. также “fc_saved_syn”, “tcp-ss” и “eth.data”.

ip.ver

ip.ver

Используется с входным образцом, представляющим двоичный кадр Ethernet, который возвращает “fc_saved_syn”, когда параметр “tcp-ss” директивы bind равен “1”, либо с результатом “eth.data”. Возвращает версию IP из заголовка IP, обычно 4 или 6. Обратите внимание, что не проверяется соответствие номера протокола в кадре Ethernet вышележащего уровня, но поскольку ожидается использование с корректными пакетами, предполагается, что операционная система уже выполнила эту проверку. См. также “fc_saved_syn”, “tcp-ss” и “eth.data”.

ipmask(<mask4>[,<mask6>])

ipmask(<mask4>[,<mask6>])

Применяет маску к IP-адресу и использует результат для поиска и хранения. Это позволяет всем узлам в пределах заданной маски использовать общие записи таблицы и, следовательно, один сервер. mask4 можно задать в записи с точками, например 255.255.255.0, или в форме CIDR, например 24. mask6 можно задать группами из четырёх шестнадцатеричных цифр, например ffff:ffff::, или в форме CIDR, например 64. Если mask6 не задана, преобразование адресов IPv6 завершается неудачей по соображениям обратной совместимости.

json([<input-code>])

json([<input-code>])

Экранирует входную строку и формирует выходную строку ASCII, готовую к использованию как строка JSON. Преобразователь пытается декодировать входную строку в соответствии с параметром <input-code>. Он может принимать значения “ascii”, “utf8”, “utf8s”, “utf8p” или “utf8ps”. Декодер “ascii” никогда не завершается с ошибкой. Декодер “utf8” обнаруживает 3 типа ошибок:

  • некорректная последовательность UTF-8: одиночный байт продолжения, неверное число байтов продолжения и т. п.;
  • недопустимый диапазон: декодированное значение попадает в запрещённый диапазон UTF-8;
  • избыточное кодирование: значение закодировано большим числом байтов, чем требуется.

Кодирование UTF-8 в JSON может вызвать ошибку “too long value”, если символ UTF-8 имеет значение больше 0xffff: спецификация экранирования строк JSON допускает только 4 шестнадцатеричные цифры для кодирования значения. Декодер UTF-8 существует в 4 вариантах, обозначаемых сочетанием двух буквенных суффиксов: “p” — разрешающий режим, “s” — игнорирование без сообщений. Декодеры ведут себя следующим образом:

  • “ascii”: никогда не завершается с ошибкой;
  • “utf8”: завершается с ошибкой при обнаружении любой ошибки;
  • “utf8s”: никогда не завершается с ошибкой, но удаляет символы, соответствующие ошибкам;
  • “utf8p”: принимает и исправляет ошибки избыточного кодирования, но завершается с ошибкой при любой другой ошибке;
  • “utf8ps”: никогда не завершается с ошибкой, принимает и исправляет ошибки избыточного кодирования, но удаляет символы, соответствующие другим ошибкам.

Этот преобразователь особенно полезен для формирования правильно экранированного JSON при отправке журналов трафика на серверы, принимающие их в формате JSON.

Пример:

capture request header Host len 15
capture request header user-agent len 150
log-format '{"ip":"%[src]","user-agent":"%[capture.req.hdr(1),json(utf8s)]"}'

Входящий запрос от клиента 127.0.0.1:

GET / HTTP/1.0
User-Agent: Very "Ugly" UA 1/2

Полученная запись журнала:

{"ip":"127.0.0.1","user-agent":"Very \"Ugly\" UA 1\/2"}

json_query(<json_path>[,<output_type>])

json_query(<json_path>[,<output_type>])

Преобразователь json_query поддерживает типы JSON string, boolean, number и array. Числа с плавающей точкой возвращаются строкой. Если задать output_type ‘int’, значение преобразуется в целое число. Массивы возвращаются строкой, которая начинается и заканчивается квадратными скобками. Содержимое имеет формат CSV. В зависимости от типа данных значения массива могут заключаться в кавычки. Если значения массива имеют сложные типы, строка содержит полное представление JSON каждого значения через запятую. Пример результата запроса ролей к JWT:

["manage-account","manage-account-links","view-profile"]

Если преобразование невозможно, преобразователь json_query завершается с ошибкой.

<json_path> должен быть корректной строкой JSON Path, определённой в https://datatracker.ietf.org/doc/draft-ietf-jsonpath-base/

Примечание: в зависимости от контекста и реализации результат извлечения повторяющихся ключей JSON не определён: может быть возвращено первое, последнее или любое другое вхождение одного ключа во входном содержимом. Если имена ключей переданы в закодированном виде, они не всегда будут сопоставлены. Таким образом, этот преобразователь не подходит для очистки содержимого.

Пример:

# get a integer value from the request body
# "{"integer":4}" => 5
http-request set-var(txn.pay_int) req.body,json_query('$.integer','int'),add(1)

# get a key with '.' in the name
# {"my.key":"myvalue"} => myvalue
http-request set-var(txn.pay_mykey) req.body,json_query('$.my\\.key')

# {"boolean-false":false} => 0
http-request set-var(txn.pay_boolean_false) req.body,json_query('$.boolean-false')

# get the value of the key 'iss' from a JWT Bearer token
http-request set-var(txn.token_payload) req.hdr(Authorization),word(2,.),ub64dec,json_query('$.iss')

jwt_decrypt_cert(<cert>)

jwt_decrypt_cert(<cert>)

Выполняет проверку подписи веб-токена JSON в формате JSON Web Encryption (см. RFC 7516) на входе и возвращает его содержимое, расшифрованное с помощью предоставленного сертификата. Параметр <cert> должен быть путём к уже загруженному сертификату (который можно выгрузить с помощью команды “dump ssl cert” CLI). Сертификат должен иметь опцию “jwt”, явно установленную в значение “on” (см. опцию crt-list “jwt”). Путь можно указать напрямую или через переменную. На данный момент поддерживаются только токены, использующие формат компактной сериализации (пять строк base64-url, разделённых точками).

Преобразователь можно использовать для токенов с одним из следующих алгоритмов в поле “alg” заголовка JOSE: RSA-OAEP, RSA-OAEP-256, ECDH-ES, ECDH-ES+A128KW, ECDH-ES+A192KW или ECDH-ES+A256KW. Алгоритм RSA1_5 реализован, но по умолчанию отключён согласно рекомендации раздела 3.2 RFC 8725. При необходимости его можно снова включить глобальным параметром ‘jwt.decrypt_alg_list’.

Поддерживаемые алгоритмы и алгоритмы шифрования, задаваемые соответственно полями “alg” и “enc” заголовка JOSE, можно изменить глобальными параметрами ‘jwt.decrypt_alg_list’ и ‘jwt.decrypt_enc_list’.

Токен JWE должен быть предоставлен в кодировке base64url, а результат возвращается в необработанном виде. В случае ошибки при разборе токена, проверке подписи или расшифровке содержимого будет возвращена пустая строка.

Пример:

# Get a JWT from the authorization header, put its decrypted content in an
# HTTP header
http-request set-var(txn.bearer) http_auth_bearer
http-request set-header X-Decrypted %[var(txn.bearer),jwt_decrypt_cert("/foo/bar.pem")]

jwt_decrypt_jwk(<jwk>)

jwt_decrypt_jwk(<jwk>)

Проверяет подпись переданного на вход JSON Web Token в формате JSON Web Encryption (см. RFC 7516) и возвращает его содержимое, расшифрованное предоставленным JSON Web Key (RFC7517). Параметр <jwk> должен быть корректным JWK типа ‘oct’, ‘EC’ или ‘RSA’, указанного полем ‘kty’ ключа JSON. Его можно передать строкой или через переменную.

На данный момент поддерживаются только токены, использующие формат компактной сериализации (пять строк base64-url, разделённых точками).

Этот преобразователь можно использовать для декодирования токенов с одним из следующих симметричных алгоритмов в поле “alg” заголовка JOSE: A128KW, A192KW, A256KW, A128GCMKW, A192GCMKW, A256GCMKW, dir. В этом случае ожидается JWK типа ‘oct’.

Преобразователь также поддерживает токены с алгоритмом семейства RSA (RSA-OAEP или RSA-OAEP-256) в поле “alg” заголовка JOSE при передаче JWK типа ‘RSA’, либо семейства ECDH (ECDH-ES, ECDH-ES+A128KW, ECDH-ES+A192KW или ECDH-ES+A256KW) при передаче JWK типа ‘EC’. Алгоритм RSA1_5 реализован, но по умолчанию отключён согласно рекомендации раздела 3.2 RFC 8725. При необходимости его можно снова включить глобальным параметром ‘jwt.decrypt_alg_list’.

Обратите внимание, что алгоритмы A128KW и A192KW недоступны на AWS-LC, поэтому алгоритмы A128KW, A192KW, ECDH-ES+A128KW и ECDH-ES+A192KW не будут работать.

Поддерживаемые алгоритмы и алгоритмы шифрования, задаваемые соответственно полями “alg” и “enc” заголовка JOSE, можно изменить глобальными параметрами ‘jwt.decrypt_alg_list’ и ‘jwt.decrypt_enc_list’.

Токен JWE должен быть предоставлен в кодировке base64url, а результат возвращается в необработанном виде. В случае ошибки при разборе токена, проверке подписи или расшифровке содержимого будет возвращена пустая строка.

Из-за особенностей обработки кавычек, запятых и двойных кавычек в конфигурации содержимое JWK необходимо правильно экранировать для корректной работы преобразователя. Подробности см. в разделе 2.2 .

Пример:

 # Get a JWT from the authorization header, put its decrypted content in an
 # HTTP header
 http-request set-var(txn.bearer) http_auth_bearer
 http-request set-header X-Decrypted %[var(txn.bearer),jwt_decrypt_jwk(\'{\"kty\":\"oct\",\"k\":\"wAsgsg\"}\')

# or via a variable
 http-request set-var(txn.bearer) http_auth_bearer
 http-request set-var(txn.jwk) str(\'{\"kty\":\"oct\",\"k\":\"Q-NFLlghQ\"}\')
 http-request set-header X-Decrypted %[var(txn.bearer),jwt_decrypt_jwk(txn.jwk)

jwt_decrypt_secret(<secret>)

jwt_decrypt_secret(<secret>)

Выполняет проверку подписи веб-токена JSON в формате JSON Web Encryption (см. RFC 7516) на входе и возвращает его содержимое, расшифрованное с помощью предоставленного секрета, закодированного в base64. Секрет может быть указан как строка или через переменную. На данный момент поддерживаются только токены, использующие формат компактной сериализации (пять строк base64-url, разделённых точками).

Этот преобразователь можно использовать для токенов, алгоритм (“alg” поле заголовка JOSE) которых входит в следующий список: A128KW, A192KW, A256KW, A128GCMKW, A192GCMKW, A256GCMKW, dir. Обратите внимание, что алгоритмы A128KW и A192KW недоступны на AWS-LC, и расшифровка не будет работать.

Токен JWE должен быть предоставлен в кодировке base64url, а результат возвращается в необработанном виде. В случае ошибки при разборе токена, проверке подписи или расшифровке содержимого будет возвращена пустая строка.

Пример:

# Get a JWT from the authorization header, put its decrypted content in an
# HTTP header
http-request set-var(txn.bearer) http_auth_bearer
http-request set-header X-Decrypted %[var(txn.bearer),jwt_decrypt_secret("GawgguFyGrWKav7AX4VKUg")]

jwt_header_query([<json_path>[,<output_type>]])

jwt_header_query([<json_path>[,<output_type>]])

При получении на вход JSON Web Token (JWT) возвращает декодированный заголовок токена, то есть первую часть JWT в кодировке base64-url, если параметр не задан; иначе выполняет json_query для декодированного заголовка. Подробности о допустимых параметрах json_path и output_type см. в описании преобразователя “json_query”. Этот преобразователь можно использовать с токенами JWS и JWE в формате компактной сериализации.

Обратите внимание: этот преобразователь доступен только в том случае, если HAProxy собран с USE_OPENSSL.

jwt_payload_query([<json_path>[,<output_type>]])

jwt_payload_query([<json_path>[,<output_type>]])

При получении на вход JSON Web Token (JWT) в формате JSON Web Signed (JWS) возвращает декодированную полезную нагрузку токена, то есть вторую часть JWT в кодировке base64-url, если параметр не задан; иначе выполняет json_query для декодированной полезной нагрузки. Подробности о допустимых параметрах json_path и output_type см. в описании преобразователя “json_query”.

Обратите внимание: этот преобразователь доступен только в том случае, если HAProxy собран с USE_OPENSSL.

jwt_verify(<alg>,<key>)

Выполняет проверку подписи веб-токена JSON (JWT) на входе с использованием алгоритма <alg> и параметра <key>. На данный момент обрабатываются только токены JWS в формате компактной сериализации (три строки base64-url, разделённые точками). Этот преобразователь проверяет только подпись токена и не выполняет полную проверку JWT, как указано в разделе 7.2 документа RFC7519. Например, не проверяется, являются ли заголовок и полезная нагрузка после декодирования полностью корректными данными JSON; их содержимое также не проверяется.

  • <alg> может быть строкой или именем переменной (см. также “set-var”), содержащей имя алгоритма, используемого для проверки.

    Поддерживаются алгоритмы, перечисленные в разделе 3.1 RFC7518:

   +--------------+---------------------------------------------------------+
   | Значение     | Алгоритм цифровой подписи или MAC                       |
   | парам. "alg" |                                                         |
   +--------------+---------------------------------------------------------+
   | HS256        | HMAC с SHA-256                                          |
   | HS384        | HMAC с SHA-384                                          |
   | HS512        | HMAC с SHA-512                                          |
   | RS256        | RSASSA-PKCS1-v1_5 с SHA-256                             |
   | RS384        | RSASSA-PKCS1-v1_5 с SHA-384                             |
   | RS512        | RSASSA-PKCS1-v1_5 с SHA-512                             |
   | ES256        | ECDSA с P-256 и SHA-256                                 |
   | ES384        | ECDSA с P-384 и SHA-384                                 |
   | ES512        | ECDSA с P-521 и SHA-512                                 |
   | PS256        | RSASSA-PSS с SHA-256 и MGF1 с SHA-256                   |
   | PS384        | RSASSA-PSS с SHA-384 и MGF1 с SHA-384                   |
   | PS512        | RSASSA-PSS с SHA-512 и MGF1 с SHA-512                   |
   | none         | Цифровая подпись и MAC не выполняются (см. примечание ниже) |
   +--------------+---------------------------------------------------------+

Алгоритм “none” по умолчанию не разрешён согласно рекомендациям RFC8725 раздел 3.2 . Чтобы явно разрешить его, задайте глобальную опцию ‘jwt.allow_none_alg’.

  • <key> может быть строкой или именем переменной (см. также “set-var”), содержащей секрет или путь к открытому ключу.

    Секреты применимы только при использовании алгоритмов HMAC.

    Открытые ключи должны быть в формате PKCS#1 для ключей RSA, начинающемся с BEGIN RSA PUBLIC KEY, либо в формате SPKI (Subject Public Key Info), начинающемся с BEGIN PUBLIC KEY. Открытые ключи должны быть доступны при разборе конфигурации; их нельзя обновлять или загружать во время работы. Для проверки токенов JWT по полноценным сертификатам PEM см. преобразователь “jwt_verify_cert”.

    Все открытые ключи, которые могут использоваться для проверки JWT, должны быть известны при инициализации. Тогда они будут добавлены в специальный кэш, и во время работы доступ к диску не потребуется.

Возвращает 1 при успешной проверке, 0 при неуспешной проверке и строго отрицательное значение при любой другой ошибке. Из-за этих ненулевых кодов ошибок результат преобразователя никогда не следует преобразовывать в логическое значение. Полный список возможных возвращаемых значений приведён ниже.

Возможные возвращаемые значения следующие:

  +----+----------------------------------------------------------------------+
  | ID | сообщение                                                            |
  +----+----------------------------------------------------------------------+
  |  1 | "Verification success"                                               |
  |  0 | "Verification failure"                                               |
  | -1 | "Unknown algorithm (not mentioned in RFC7518)"                       |
  | -2 | "Unmanaged algorithm"                                                |
  | -3 | "Invalid token"                                                      |
  | -4 | "Out of memory"                                                      |
  | -5 | "Unknown pubkey/certificate"                                         |
  | -6 | "Internal error"                                                     |
  +----+----------------------------------------------------------------------+

Обратите внимание: этот преобразователь доступен только в том случае, если HAProxy собран с USE_OPENSSL.

Пример:

# Get a JWT from the authorization header, extract the "alg" field of its
# JOSE header and use a public key to verify a signature
http-request set-var(txn.bearer) http_auth_bearer
http-request set-var(txn.jwt_alg) var(txn.bearer),jwt_header_query('$.alg')
http-request deny unless { var(txn.jwt_alg) -m str "RS256" }
http-request deny unless { var(txn.bearer),jwt_verify(txn.jwt_alg,"/path/to/pubkey.pem") 1 }

jwt_verify_cert(<alg>,<cert>)

Выполняет проверку подписи веб-токена JSON (JWT) на входе с использованием алгоритма <alg> и параметра <cert>. На данный момент обрабатываются только токены JWS в формате компактной сериализации (три строки base64-url, разделённые точками). Этот преобразователь проверяет только подпись токена и не выполняет полную проверку JWT, как указано в разделе 7.2 документа RFC7519. Например, не проверяется, являются ли заголовок и полезная нагрузка после декодирования полностью корректными данными JSON; их содержимое также не проверяется.

  • <alg> может быть строкой или именем переменной (см. также “set-var”), содержащей имя алгоритма, используемого для проверки. В отличие от преобразователя “jwt_verify”, этот преобразователь ожидает только сертификат в качестве второго параметра, поэтому его не следует использовать для токенов, использующих алгоритмы HMAC.

    Поддерживаются алгоритмы, перечисленные в разделе 3.1 RFC7518, кроме HMAC:

   +--------------+---------------------------------------------------------+
   | Значение     | Алгоритм цифровой подписи или MAC                       |
   | парам. "alg" |                                                         |
   +--------------+---------------------------------------------------------+
   | RS256        | RSASSA-PKCS1-v1_5 с SHA-256                             |
   | RS384        | RSASSA-PKCS1-v1_5 с SHA-384                             |
   | RS512        | RSASSA-PKCS1-v1_5 с SHA-512                             |
   | ES256        | ECDSA с P-256 и SHA-256                                 |
   | ES384        | ECDSA с P-384 и SHA-384                                 |
   | ES512        | ECDSA с P-521 и SHA-512                                 |
   | PS256        | RSASSA-PSS с SHA-256 и MGF1 с SHA-256                   |
   | PS384        | RSASSA-PSS с SHA-384 и MGF1 с SHA-384                   |
   | PS512        | RSASSA-PSS с SHA-512 и MGF1 с SHA-512                   |
   | none         | Цифровая подпись и MAC не выполняются                   |
   +--------------+---------------------------------------------------------+
  • <key> может быть строкой или именем переменной (см. также “set-var”), содержащей путь к сертификату.

    Сертификаты должны быть стандартными сертификатами PEM, начинающимися с BEGIN CERTIFICATE. Их путь можно передать преобразователю напрямую или через переменную. При использовании переменной соответствующие сертификаты можно объявить в crt-store либо динамически загрузить через сокет статистики. Если путь задан напрямую и соответствующий сертификат ещё не загружен во внутреннее хранилище сертификатов, он будет загружен при разборе конфигурации. Поэтому он уже должен существовать, иначе возникнет ошибка.

    Можно использовать только те сертификаты, которые явно определены как пригодные для проверки JWT. См. опцию “jwt” crt-store.

    Сертификаты можно динамически обновлять и добавлять через сокет статистики. См. также “set ssl cert” и “new ssl cert” в руководстве по управлению.

Возвращает 1 при успешной проверке, 0 при неуспешной проверке и строго отрицательное значение при любой другой ошибке. Из-за этих ненулевых кодов ошибок результат преобразователя никогда не следует преобразовывать в логическое значение. Полный список возможных возвращаемых значений приведён ниже.

Возможные возвращаемые значения следующие:

  +----+----------------------------------------------------------------------+
  | ID | сообщение                                                            |
  +----+----------------------------------------------------------------------+
  |  1 | "Verification success"                                               |
  |  0 | "Verification failure"                                               |
  | -1 | "Unknown algorithm (not mentioned in RFC7518)"                       |
  | -2 | "Unmanaged algorithm"                                                |
  | -3 | "Invalid token"                                                      |
  | -4 | "Out of memory"                                                      |
  | -5 | "Unknown pubkey/certificate"                                         |
  | -6 | "Internal error"                                                     |
  | -7 | "Unavailable certificate" (see "jwt")                                |
  +----+----------------------------------------------------------------------+

Обратите внимание: этот преобразователь доступен только в том случае, если HAProxy собран с USE_OPENSSL.

Пример:

# Get a JWT from the authorization header, extract the "alg" field of its
# JOSE header and use a public certificate to verify a signature
http-request set-var(txn.bearer) http_auth_bearer
http-request set-var(txn.jwt_alg) var(txn.bearer),jwt_header_query('$.alg')
http-request deny unless { var(txn.jwt_alg) -m str "RS256" }
http-request deny unless { var(txn.bearer),jwt_verify_cert(txn.jwt_alg,"/path/to/cert.pem") 1 }

language(<value>[,<default>])

language(<value>[,<default>])

Возвращает значение с наибольшим коэффициентом q из списка, извлечённого из заголовка “accept-language” с помощью “req.fhdr”. Значения без коэффициента q имеют коэффициент q равный 1. Значения с коэффициентом q 0 отбрасываются. Учитываются только значения, входящие в список, разделённый точкой с запятой <values>. Синтаксис аргумента <value> — “lang[;lang[;lang[;…]]]”. Если ни одно значение не соответствует заданному списку и указано значение по умолчанию, оно возвращается. Обратите внимание, что имена языков могут содержать вариант после дефиса (’-’). Если такой вариант присутствует в списке, он будет сопоставлен, но если его нет — проверяется только базовый язык. Сопоставление чувствительно к регистру, а выходная строка всегда является одной из указанных в аргументах. Порядок аргументов не имеет значения, важен только порядок значений в запросе, поскольку при одинаковом коэффициенте q используется первое значение среди совпадающих.

Пример:

# this configuration switches to the backend matching a
# given language based on the request:

acl es req.fhdr(accept-language),language(es;fr;en) -m str es
acl fr req.fhdr(accept-language),language(es;fr;en) -m str fr
acl en req.fhdr(accept-language),language(es;fr;en) -m str en
use_backend spanish if es
use_backend french  if fr
use_backend english if en
default_backend choose_your_language

length

length

Возвращает длину строки. Этот преобразователь можно размещать только после функции извлечения строкового образца или после ключевого слова преобразования, возвращающего строку. Результат имеет целочисленный тип.

lower

lower

Приводит строковый образец к нижнему регистру. Этот преобразователь можно размещать только после функции извлечения строкового образца или после ключевого слова преобразования, возвращающего строку. Результат имеет строковый тип.

ltime(<format>[,<offset>])

ltime(<format>[,<offset>])

Преобразует целое число, рассматриваемое как дата от начала эпохи, в строку с этой датой в местном времени по формату <format> с помощью strftime(3). Это позволяет использовать в журналах любой формат даты. К входной дате можно применить необязательное положительное или отрицательное смещение <offset> в секундах. Поддерживаемый операционной системой формат описан на странице руководства strftime(). См. также преобразователь utime.

Пример:

# Emit two colons, one with the local time and another with ip:port
# e.g.  20140710162350 127.0.0.1:57325
log-format %[date,ltime(%Y%m%d%H%M%S)]\ %ci:%cp

ltrim(<chars>)

ltrim(<chars>)

Пропускает любые символы из <chars> в начале строкового представления входного образца.

map(<map_name>[,<default_value>])

map(<map_name>[,<default_value>])
map_<match_type>(<map_name>[,<default_value>])
map_<match_type>_<output_type>(<map_name>[,<default_value>])

Ищет входное значение в <map_name> с использованием метода сопоставления <match_type> и возвращает соответствующее значение, преобразованное к типу <output_type>. Если входное значение не найдено в <map_name>, преобразователь возвращает <default_value>. Если <default_value> не установлен, преобразователь завершается с ошибкой, как будто входное значение не было получено. Если <match_type> не установлен, он по умолчанию принимает значение “str”. Аналогично, если <output_type> не установлен, он по умолчанию принимает значение “str”. Для удобства ключевое слово “map” является псевдонимом для “map_str” и сопоставляет одной строке другую строку. <map_name> должен соответствовать формату, описанному в 2.7 относительно формата имён для таблиц соответствий и ACL.

Важно избегать пересечений между ключами: IP-адреса и строки хранятся в деревьях, поэтому используется первое совпадение с наибольшей точностью. Другие ключи хранятся в списках, поэтому используется первое совпадающее вхождение.

В следующей таблице перечислены все доступные функции таблиц соответствий с сортировкой по типу входных данных, методу сопоставления и типу результата.

 Входной тип | Метод сравн. | Тип выхода str  | Тип выхода int  | Тип выхода ip  | Тип выхода key
  -----------+--------------+-----------------+-----------------+----------------+----------------
    str      | str          | map_str         | map_str_int     | map_str_ip     | map_str_key
  -----------+--------------+-----------------+-----------------+----------------+----------------
    str      | beg          | map_beg         | map_beg_int     | map_beg_ip     | map_beg_key
  -----------+--------------+-----------------+-----------------+----------------+----------------
    str      | sub          | map_sub         | map_sub_int     | map_sub_ip     | map_sub_key
  -----------+--------------+-----------------+-----------------+----------------+----------------
    str      | dir          | map_dir         | map_dir_int     | map_dir_ip     | map_dir_key
  -----------+--------------+-----------------+-----------------+----------------+----------------
    str      | dom          | map_dom         | map_dom_int     | map_dom_ip     | map_dom_key
  -----------+--------------+-----------------+-----------------+----------------+----------------
    str      | end          | map_end         | map_end_int     | map_end_ip     | map_end_key
  -----------+--------------+-----------------+-----------------+----------------+----------------
    str      | reg          | map_reg         | map_reg_int     | map_reg_ip     | map_reg_key
  -----------+--------------+-----------------+-----------------+----------------+----------------
    str      | reg          | map_regm        | map_reg_int     | map_reg_ip     | map_reg_key
  -----------+--------------+-----------------+-----------------+----------------+----------------
    int      | int          | map_int         | map_int_int     | map_int_ip     | map_int_key
  -----------+--------------+-----------------+-----------------+----------------+----------------
    ip       | ip           | map_ip          | map_ip_int      | map_ip_ip      | map_ip_key
  -----------+--------------+-----------------+-----------------+----------------+----------------

Преобразователь “map_regm” ожидает группы захвата в регулярном выражении и изменяет результат, заменяя обратные ссылки, например “\1”, соответствующим совпавшим текстом.

Тип вывода “key” означает, что будет возвращён ключ найденного элемента (как он указан в файле таблицы соответствий) в виде строки вместо значения. Обратите внимание, что не поддерживается необязательный аргумент <default_value> при использовании типа вывода “key”.

Файлы, указанные в <map_name>, содержат по одной паре ключ + значение в строке. Строки, начинающиеся с ‘#’, игнорируются, как и пустые строки. Начальные табуляции и пробелы удаляются. Ключ — первое «слово», то есть последовательность символов без пробелов и табуляций. Значение — всё после следующей за ключом последовательности пробелов и табуляций до конца строки, без завершающих пробелов и табуляций.

Пример:

     # this is a comment and is ignored
        2.22.246.0/23    United Kingdom      \n
     <-><-----------><--><------------><---->
      |       |       |         |        `- конечные пробелы игнорируются
      |       |       |         `---------- значение
      |       |       `-------------------- пробелы в середине игнорируются
      |       `---------------------------- ключ
      `------------------------------------ начальные пробелы игнорируются

mod(<value>)

mod(<value>)

Делит входное целое число со знаком на <value> и возвращает остаток как целое число со знаком. Если <value> равен нулю, возвращается ноль. <value> может быть числом или именем переменной. Подробности о переменных см. в разделе 2.8 .

mqtt_field_value(<packettype>,<fieldname_or_property_ID>)

mqtt_field_value(<packettype>,<fieldname_or_property_ID>)

Возвращает значение <fieldname>, найденное во входной полезной нагрузке MQTT типа <packettype>. <packettype> может быть строкой (сопоставление без учёта регистра) или числовым значением, соответствующим типу пакета, из которого необходимо извлечь данные. Поддерживаемые строки и целые числа можно найти здесь: https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718021 https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901022

<fieldname> зависит от <packettype> и может быть любым из перечисленных ниже. (Обратите внимание, что сопоставление <fieldname> не чувствительно к регистру). <property id> может быть найден только в потоках MQTT v5.0. Проверьте эту таблицу: https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901029

  • CONNECT (или 1): flags, protocol_name, protocol_version, client_identifier, will_topic, will_payload, username, password, keepalive ИЛИ любой идентификатор свойства в виде числа (только для пакетов MQTT v5.0):
17: Session Expiry Interval
33: Receive Maximum
39: Maximum Packet Size
34: Topic Alias Maximum
25: Request Response Information
23: Request Problem Information
21: Authentication Method
22: Authentication Data
18: Will Delay Interval
 1: Payload Format Indicator
 2: Message Expiry Interval
 3: Content Type
 8: Response Topic
 9: Correlation Data

Ещё не поддерживается:

38: User Property
  • CONNACK (или 2): flags, protocol_version, reason_code ИЛИ любой идентификатор свойства в виде числа (только для пакетов MQTT v5.0):
17: Session Expiry Interval
33: Receive Maximum
36: Maximum QoS
37: Retain Available
39: Maximum Packet Size
18: Assigned Client Identifier
34: Topic Alias Maximum
31: Reason String
40; Wildcard Subscription Available
41: Subscription Identifiers Available
42: Shared Subscription Available
19: Server Keep Alive
26: Response Information
28: Server Reference
21: Authentication Method
22: Authentication Data

Ещё не поддерживается:

38: User Property

Из-за текущей архитектуры HAProxy можно разобрать только первый пакет, отправленный клиентом, и первый ответ, отправленный сервером. Следовательно, этот преобразователь может извлекать данные только из типов пакетов CONNECT и CONNACK. CONNECT — это первый пакет, отправленный клиентом, а CONNACK — первый ответ, отправленный сервером.

Пример:

acl data_in_buffer req.len ge 4
tcp-request content set-var(txn.username) \
        req.payload(0,0),mqtt_field_value(connect,protocol_name) \
        if data_in_buffer
# do the same as above
tcp-request content set-var(txn.username) \
        req.payload(0,0),mqtt_field_value(1,protocol_name) \
        if data_in_buffer

mqtt_is_valid

mqtt_is_valid

Проверяет, представляют ли двоичные входные данные корректный пакет MQTT. Возвращает логическое значение.

Из-за текущей архитектуры HAProxy можно разобрать только первый пакет, отправленный клиентом, и первый ответ, отправленный сервером. Следовательно, этот преобразователь может извлекать данные только из типов пакетов CONNECT и CONNACK. CONNECT — это первый пакет, отправленный клиентом, а CONNACK — первый ответ, отправленный сервером.

Поддерживаются только MQTT 3.1, 3.1.1 и 5.0.

Пример:

acl data_in_buffer req.len ge 4
tcp-request content reject unless { req.payload(0,0),mqtt_is_valid }

ms_ltime(<format>[,<offset>])

ms_ltime(<format>[,<offset>])

Работает как “ltime”, но принимает входное значение в миллисекундах. Также поддерживает спецификатор преобразования %N по образцу date(1). Преобразует целое число, рассматриваемое как дата от начала эпохи, в строку с этой датой в местном времени по формату <format> с помощью strftime(3). Это позволяет использовать в журналах любой формат даты. К входной дате можно применить необязательное положительное или отрицательное смещение <offset> в миллисекундах. Поддерживаемый операционной системой формат описан на странице руководства strftime().

Спецификатор преобразования %N позволяет вывести часть даты в наносекундах, точность ограничена, поскольку входные данные задаются в миллисекундах. (000000000..999000000). %N может принимать аргумент ширины между % и N. Полезно для отображения миллисекунд (%3N) или микросекунд (%6N). Ширина по умолчанию и максимальная — 9 (%N = %9N).

См. также преобразователь utime для UTC, а также преобразователи “ltime” и “us_ltime”.

Пример:

# Emit 3 colons, the local time, the timezone and another with ip:port
# e.g. 2023/07/24/11:53:02.196 +0200 127.0.0.1:41530
log-format %[accept_date(ms),ms_ltime("%Y/%m/%d/%H:%M:%S.%3N %z")]\ %ci:%cp

ms_utime(<format>[,<offset>])

ms_utime(<format>[,<offset>])

Работает как “utime”, но принимает входное значение в миллисекундах. Также поддерживает спецификатор преобразования %N по образцу date(1). Преобразует целое число, рассматриваемое как дата от начала эпохи, в строку с этой датой в UTC по формату <format> с помощью strftime(3). Это позволяет использовать в журналах любой формат даты. К входной дате можно применить необязательное положительное или отрицательное смещение <offset> в миллисекундах. Поддерживаемый операционной системой формат описан на странице руководства strftime().

Спецификатор преобразования %N позволяет вывести часть даты в наносекундах, точность ограничена, поскольку входные данные задаются в миллисекундах. (000000000..999000000). %N может принимать аргумент ширины между % и N. Полезно для отображения миллисекунд (%3N) или микросекунд (%6N). Ширина по умолчанию и максимальная — 9 (%N = %9N).

См. также преобразователь ltime для локального времени, а также преобразователи “utime” и “us_utime”.

Пример:

# Emit 3 colons, the UTC time, the timezone and another with ip:port
# e.g. 2023/07/24/09:53:02.196 +0000 127.0.0.1:41530
log-format %[accept_date(ms),ms_utime("%Y/%m/%d/%H:%M:%S.%3N %z")]\ %ci:%cp

mul(<value>)

mul(<value>)

Умножает входное целое число со знаком на <value> и возвращает произведение как целое число со знаком. При переполнении возвращается предельное значение для соответствующего знака, чтобы избежать циклического перехода при переполнении. <value> может быть числом или именем переменной. Подробности о переменных см. в разделе 2.8 .

nbsrv

nbsrv

Принимает на вход строку, трактует её как имя бэкенда и возвращает число пригодных к использованию серверов в этом бэкенде. Может использоваться там, где требуется найти бэкенд по динамическому имени, например по результату поиска в таблице соответствий.

neg

neg

Принимает входное целое число со знаком, вычисляет противоположное значение и возвращает остаток как целое число со знаком. 0 не изменяется. Оператор предназначен для обратного вычитания: чтобы вычесть входное значение из константы, достаточно выполнить “neg,add(value)”.

not

not

Возвращает логическое FALSE, если входное целое число со знаком ненулевое; иначе возвращает TRUE. Совместно с and() позволяет получить true/false при проверке битов входного значения, например при проверке отсутствия флага.

odd

odd

Возвращает логическое TRUE, если входное целое число со знаком нечётное; иначе возвращает FALSE. Функционально эквивалентен “and(1),bool”.

or(<value>)

or(<value>)

Выполняет побитовое “OR” между <value> и входным целым числом со знаком и возвращает результат как целое число со знаком. <value> может быть числом или именем переменной. Подробности о переменных см. в разделе 2.8 .

param(<name>[,<delim>])

param(<name>[,<delim>])

Извлекает первое вхождение параметра <name> из входной строки, в которой параметры разделены символом <delim> (по умолчанию “&”), а имя и значение параметра — знаком “=”. Если до конца сегмента параметра отсутствуют знак “=” и значение, это считается эквивалентным значению в виде пустой строки.

Это может быть полезно для извлечения параметров из строки запроса или тела в формате x-www-form-urlencoded. В частности, query,param(<name>) можно использовать как альтернативу urlp(<name>): первое выражение использует только “&” как разделитель, тогда как “urlp” также использует “?” и “;”.

Обратите внимание, что этот преобразователь не выполняет специальных действий с закодированными символами URL. Если требуется декодировать значение, можно применить преобразователь url_dec к выходным данным. Если имя параметра во входных данных может содержать закодированные символы, вероятно, стоит нормализовать входные данные перед вызовом “param”. Это можно сделать с помощью “http-request normalize-uri”, в частности, опций percent-decode-unreserved и percent-to-uppercase.

Пример:

str(a=b&c=d&a=r),param(a)   # b
str(a&b=c),param(a)         # ""
str(a=&b&c=a),param(b)      # ""
str(a=1;b=2;c=4),param(b,;) # 2
query,param(redirect_uri),urldec()

port_only

port_only

Преобразует строку со значением заголовка Host в целое число, возвращая указанный в ней порт. Входные данные должны соответствовать формату значения заголовка Host (rfc9110#section-7.2). Поддерживаются следующие варианты: hostname, hostname:80, 127.0.0.1, 127.0.0.1:80, [::1], [::1]:80.

Если во входных данных не указан порт, возвращает 0.

См. также: преобразователь “host_only”, который вернёт хост.

protobuf(<field_number>[,<field_type>])

protobuf(<field_number>[,<field_type>])

Извлекает поле сообщения protocol buffers из входного двоичного образца, представляющего такое сообщение. Номер поля задаётся аргументом <field_number> (в нотации с точками). Если <field_type> отсутствует, поле извлекается в необработанном виде; если указан — в виде целочисленного образца (см. также “ungrpc” ниже). Допустимы следующие типы: “int32”, “int64”, “uint32”, “uint64”, “sint32”, “sint64”, “bool”, “enum” для типа кодирования “varint” 0; “fixed64”, “sfixed64”, “double” для 64-битного типа кодирования 1; “fixed32”, “sfixed32”, “float” для типа кодирования 5. Тип “string” считается типом с явно заданной длиной, поэтому для его извлечения аргумент <field_type> не требуется. Дополнительные сведения о типах полей сообщений protocol buffers: https://developers.google.com/protocol-buffers/docs/encoding

regsub(<regex>,<subst>[,<flags>])

regsub(<regex>,<subst>[,<flags>])

Применяет замену на основе регулярного выражения к входной строке. Выполняет ту же операцию, что и известный инструмент “sed” с “s/<regex>/<subst>/”. По умолчанию заменяет во входной строке первое вхождение наибольшего фрагмента, соответствующего регулярному выражению <regex>, на строку замены <subst>. Возможна замена всех вхождений вместо одного, если добавить флаг “g” в третий аргумент <flags>. Также возможно сделать регулярное выражение нечувствительным к регистру, добавив флаг “i” в <flags>. Поскольку <flags> — это строка, она состоит из конкатенации всех желаемых флагов. Таким образом, если нужны и “i”, и “g”, использование “gi” или “ig” даст одинаковый результат. Первое применение этого преобразователя — замена определённых символов или последовательностей на другие.

Настоятельно рекомендуется заключать регулярное выражение в защищённые кавычки, чтобы улучшить читаемость и не спутать его закрывающую скобку со скобкой функции. Как и в оболочке Bourne, первый уровень кавычек обрабатывается при выделении групп слов в строке, а второй можно использовать для аргументов. Рекомендуется использовать одинарные кавычки снаружи, поскольку они не интерпретируют обратные косые черты и знаки доллара.

Примеры:

# de-duplicate "/" in header "x-path".
# input:  x-path: /////a///b/c/xzxyz/
# output: x-path: /a/b/c/xzxyz/
http-request set-header x-path "%[hdr(x-path),regsub('/+','/','g')]"

# copy query string to x-query and drop all leading '?', ';' and '&'
http-request set-header x-query "%[query,regsub([?;&]*,'')]"

# capture groups and backreferences
# both lines do the same.
http-request redirect location %[url,'regsub("(foo|bar)([0-9]+)?","\2\1",i)']
http-request redirect location %[url,regsub(\"(foo|bar)([0-9]+)?\",\"\2\1\",i)]

reverse

reverse

Переворачивает входную строку байт за байтом.

Этот преобразователь не зависит от кодировки и переворачивает байты, а не символы; он не подходит для переворота текста, закодированного в UTF-8.

Это превращает поиск по суффиксу исходной строки в поиск по префиксу перевёрнутой строки и позволяет использовать в больших таблицах соответствий индексированные методы сопоставления по префиксу, такие как “map_beg”.

Примеры:

"example.com" -> "moc.elpmaxe"
"ab cd" -> "dc ba"

# Given a map file where each key contains a reversed hostname:
#   moc.elpmaxe.ppa app1
#   moc.elpmaxe.bd  dbcluster
# Pick a backend based on the domain suffix of the Host header:
use_backend %[req.hdr(host),lower,reverse,map_beg(/etc/haproxy/hosts.map,default)]

reverse_dom

reverse_dom

Преобразует строку с именем хоста в формате, напоминающем FQDN в представление с обратным порядком меток. Одна конечная точка во входной строке игнорируется. Пустые метки приводят к неудаче преобразования.

Этот преобразователь не приводит входные данные к нижнему регистру и не удаляет порт. Он предназначен для использования в сочетании с существующими преобразователями, такими как “lower” или “host_only”, при необходимости.

Обработка точки в конце намеренно оставлена на усмотрение вызывающей стороны. Это позволяет ей решать, следует ли сопоставлять также корневой домен или только поддомены.

Форма с обратным порядком меток удобна для больших таблиц соответствий доменов: поиск по суффиксу домена превращается в поиск по префиксу, что позволяет использовать индексированные методы сопоставления по префиксу, такие как “map_beg”.

Примеры:

"example.com" -> "com.example"
"mail.example.com" -> "com.example.mail"
"example.com." -> "com.example"

# match only subdomains of example.net, not the apex
acl example_net_sub req.hdr(Host),host_only,reverse_dom -m beg net.example.

# match only the apex
acl example_net_apex req.hdr(Host),host_only,reverse_dom -i net.example

# exact-or-subdomain prefix lookup using an explicit dotted form
http-request set-var(txn.rev_host) req.hdr(Host),host_only,reverse_dom,concat(.)
use_backend %[var(txn.rev_host),map_beg(/etc/haproxy/domains.map)]

rfc7239_field(<field>)

rfc7239_field(<field>)

Извлекает одно поле/параметр из входного значения заголовка, соответствующего формату RFC 7239.

Поддерживаемые поля: - proto: ‘http’ или ‘https’ - host: узел в формате HTTP - for: узел RFC7239 - by: узел RFC7239

Дополнительная информация здесь:

https://www.rfc-editor.org/rfc/rfc7239.html#section-6

Пример:

# extract host field from forwarded header and store it in req.fhost var
http-request set-var(req.fhost) req.hdr(forwarded),rfc7239_field(host)
#input: "proto=https;host=\"haproxy.org:80\""
#  output: "haproxy.org:80"

# extract for field from forwarded header and store it in req.ffor var
http-request set-var(req.ffor) req.hdr(forwarded),rfc7239_field(for)
#input: "proto=https;host=\"haproxy.org:80\";for=\"127.0.0.1:9999\""
#  output: "127.0.0.1:9999"

rfc7239_is_valid

rfc7239_is_valid

Возвращает true, если входное значение заголовка соответствует RFC 7239, и false в противном случае.

Пример:

acl valid req.hdr(forwarded),rfc7239_is_valid
#input: "for=127.0.0.1;proto=http"
#  output: TRUE
#input: "proto=custom"
#  output: FALSE

rfc7239_n2nn

rfc7239_n2nn

Преобразует узел RFC7239, полученный из полей заголовка ‘for’ или ‘by’ 7239, в соответствующее конечное представление nodename: - адрес ipv4 - адрес ipv6 - ‘unknown’ - идентификатор ‘_obfs’

Пример:

# extract 'for' field from forwarded header, extract nodename from
# resulting node identifier and store the result in req.fnn
http-request set-var(req.fnn) req.hdr(forwarded),rfc7239_field(for),rfc7239_n2nn
#input: "127.0.0.1:9999"
#  output: 127.0.0.1 (ipv4)
#input: "[ab:cd:ff:ff:ff:ff:ff:ff]:9998"
#  output: ab:cd:ff:ff:ff:ff:ff:ff (ipv6)
#input: "_name:_port"
#  output: "_name" (string)

rfc7239_n2np

rfc7239_n2np

Преобразует узел RFC7239, полученный из полей заголовка ‘for’ или ‘by’ 7239, в соответствующее конечное представление nodeport: - беззнаковое целое число - идентификатор ‘_obfs’

Пример:

# extract 'by' field from forwarded header, extract node port from
# resulting node identifier and store the result in req.fnp
http-request set-var(req.fnp) req.hdr(forwarded),rfc7239_field(by),rfc7239_n2np
#input: "127.0.0.1:9999"
#  output: 9999 (integer)
#input: "[ab:cd:ff:ff:ff:ff:ff:ff]:9998"
#  output: 9998 (integer)
#input: "_name:_port"
#  output: "_port" (string)

rfc7239_nn

rfc7239_nn

Преобразует переданный адрес или строку в имя узла, соответствующее RFC7239. Можно использовать для ручного формирования полей заголовка ‘for’ или ‘by’ 7239.

Если входные данные — строка, она автоматически будет предварена символом ‘_’ для представления обфусцированного идентификатора. Строка должна соответствовать набору символов RFC7239. Если строка пустая, она преобразуется в идентификатор “unknown”.

Пример:

#input: ipv6(ab:cd:ff:ff:ff:ff:ff:ff)
#  output: "[ab:cd:ff:ff:ff:ff:ff:ff]"
#input: str(test)
#  output: "_test"
#input: str()
#  output: "unknown"

См. также: “rfc7239_np”

rfc7239_np

rfc7239_np

Преобразует переданное беззнаковое целое число или строку в порт узла, соответствующий RFC7239. Можно использовать для ручного формирования полей заголовка ‘for’ или ‘by’ 7239.

Если входные данные — строка, она автоматически будет предварена символом ‘_’ для представления обфусцированного идентификатора. Строка должна соответствовать набору символов RFC7239 и не может быть пустой.

Пример:

#input: int(12)
#  output: "12"
#input: str(test)
#  output: "_test"

# build 'for' forwarded header field
http-request set-var-fmt(txn.test) "for=\"%[ipv6(::1),rfc7239_nn]:%[int(8080),rfc7239_np]\";"
#  output: "for=\"[::1]:8080\";"

# build RFC-compliant 7239 header:
http-request set-var-fmt(txn.forwarded) "for=\"%[ipv6(::1),rfc7239_nn]:%[str(8888),rfc7239_np]\";host=\"haproxy.org\";proto=http"
# check RFC-compliancy:
http-request set-var(txn.test) "var(txn.forwarded),debug(test,stderr),rfc7239_is_valid,debug(test,stderr)"
#  stderr output:
#    [debug] test: type=str <for="[::1]:_8888";host="haproxy.org";proto=http>
#    [debug] test: type=bool <1>

См. также: “rfc7239_nn”

rtrim(<chars>)

rtrim(<chars>)

Пропускает любые символы из <chars> в конце строкового представления входного образца.

sdbm([<avalanche>])

sdbm([<avalanche>])

Хеширует входной двоичный образец в 32-битное беззнаковое значение с помощью хеш-функции SDBM. Если необязательный аргумент <avalanche> равен 1, к результату можно применить хеш-функцию с полным лавинным эффектом. Этот преобразователь использует те же функции, что и различные алгоритмы балансировки нагрузки на основе хеша, поэтому даёт точно такие же результаты. Он предназначен преимущественно для отладки, но может использоваться как запись таблицы привязок для сбора приблизительной статистики. Его нельзя использовать для обеспечения безопасности: 32-битный хеш легко взломать. См. также “crc32”, “djb2”, “wt6”, “crc32c” и директиву “hash-type”.

secure_memcmp(<var>)

secure_memcmp(<var>)

Сравнивает содержимое <var> с входным значением. Оба значения обрабатываются как двоичная строка. Возвращает логическое значение, указывающее на совпадение двух двоичных строк.

Если обе двоичные строки имеют одинаковую длину, сравнение будет выполнено за постоянное время.

Обратите внимание: этот преобразователь доступен только в том случае, если HAProxy собран с USE_OPENSSL.

Пример:

http-request set-var(txn.token) hdr(token)
# Check whether the token sent by the client matches the secret token
# value, without leaking the contents using a timing attack.
acl token_given str(my_secret_token),secure_memcmp(txn.token)

set-var(<var>[,<cond>...])

set-var(<var>[,<cond>...])

Присваивает переменной входное содержимое и возвращает его на выход без изменений, если все указанные условия истинны (список возможных условий приведён ниже). Переменная сохраняет значение и соответствующий входной тип. Подробнее о переменных см. в разделе 2.8 .

Преобразователю можно передать не более четырёх условий из следующего списка:

  • “ifexists”/“ifnotexists”:
Проверяет, существовала ли переменная до текущего вызова set-var.
Обычно переменная создаётся при успешном вызове set-var.
Обратите внимание: переменные с областью действия "proc" создаются при разборе
конфигурации, поэтому условие "ifexists" для них всегда будет истинным.
  • “ifempty”/“ifnotempty”:
Проверяет, пуст ли входной образец.
Скалярные типы никогда не бывают пустыми, поэтому условие ifempty для них
будет ложным независимо от содержимого образца (целые числа, логические значения, IP и т. д.).
  • “ifset”/“ifnotset”:
Проверяет, было ли ранее задано значение переменной или вызван unset-var
для этой переменной.
Переменная, которая ещё не существует, считается не имеющей заданного значения.
Переменная "proc" может существовать без заданного значения, поскольку такие
переменные создаются при разборе конфигурации.
  • “ifgt”/“iflt”:
Проверяет, «больше» или «меньше» содержимое переменной, чем входной образец.
Эта проверка возможна, только если и входной образец, и переменная имеют
целочисленный тип. В противном случае результат проверки по умолчанию
считается истинным.

sha1

sha1

Преобразует двоичный входной образец в дайджест SHA-1. Результат — двоичный образец длиной 20 байт.

sha2([<bits>])

sha2([<bits>])

Преобразует двоичный входной образец в дайджест из семейства SHA-2. Результат — двоичный образец длиной <bits>/8 байт.

Допустимые значения для <bits> — 224, 256, 384, 512, каждое из которых соответствует SHA-<bits>. Значение по умолчанию — 256.

Обратите внимание: этот преобразователь доступен только в том случае, если HAProxy собран с USE_OPENSSL.

srv_is_up

srv_is_up

Принимает входное значение строкового типа, либо имя сервера, либо формат <backend>/<server>, и возвращает true, если указанный сервер в настоящее время находится в состоянии UP. Может использоваться в местах, где необходимо проверить состояние сервера по динамическому имени, например, значению cookie (например, req.cook(SRVID),srv_is_up) и затем принять решение о перенаправлении запроса. Перед использованием имейте в виду, что применение этого преобразователя к неконтролируемым данным может позволить внешнему наблюдателю запросить состояние любого сервера в конфигурации, что может быть недопустимо в некоторых средах.

srv_queue

srv_queue

Принимает входное значение строкового типа, либо имя сервера, либо формат <backend>/<server>, и возвращает число потоков в очереди на этом сервере. Может использоваться в местах, где необходимо проверить число потоков в очереди по динамическому имени, например, значению cookie (например, req.cook(SRVID),srv_queue) и затем принять решение о разрыве привязки или перенаправлении запроса. Перед использованием имейте в виду, что применение этого преобразователя к неконтролируемым данным может позволить внешнему наблюдателю запросить состояние любого сервера в конфигурации, что может быть недопустимо в некоторых средах.

strcmp(<var>)

strcmp(<var>)

Сравнивает содержимое <var> с входным значением типа строка. Возвращает результат как знаковое целое, совместимое с strcmp(3): 0, если обе строки идентичны. Значение меньше 0, если левая строка лексикографически меньше правой или если левая строка короче. Значение больше 0 в остальных случаях (правая строка больше левой или правая строка короче).

См. также преобразователь secure_memcmp, если требуется сравнить две двоичные строки за постоянное время.

Пример:

http-request set-var(txn.host) hdr(host)
# Check whether the client is attempting domain fronting.
acl ssl_sni_http_host_match ssl_fc_sni,strcmp(txn.host) eq 0

sub(<value>)

sub(<value>)

Вычитает <value> из входного значения типа знаковое целое и возвращает результат как знаковое целое. Примечание: чтобы вычесть входное значение из константы, достаточно выполнить “neg,add(value)”. <value> может быть числовым значением или именем переменной. См. раздел 2.8 о переменных для подробностей.

table_bytes_in_rate([<table>])

table_bytes_in_rate([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целое значение ноль. В противном случае преобразователь возвращает среднюю интенсивность передачи данных от клиента к серверу, связанную с входным образцом в указанной таблице, измеряемую в количестве байт за период, настроенный в таблице. См. также ключевое слово извлечения образца sc_bytes_in_rate.

table_bytes_out_rate([<table>])

table_bytes_out_rate([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целое значение ноль. В противном случае преобразователь возвращает среднюю интенсивность передачи данных от сервера к клиенту, связанную с входным образцом в указанной таблице, измеряемую в количестве байт за период, настроенный в таблице. См. также ключевое слово извлечения образца sc_bytes_out_rate.

table_clr_gpc(<idx>[,<table>])

table_clr_gpc(<idx>[,<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Очищает счётчик общего назначения по индексу <idx> массива gpc и возвращает его предыдущее значение. <idx> — целое число от 0 до 99. Если запись не найдена, она создаётся, и возвращается 0. Этот преобразователь применяется только к data_type массива ‘gpc’ (а не к устаревшим data_types ‘gpc0’ или ‘gpc1’). См. также ключевое слово извлечения образца sc_clr_gpc.

table_clr_gpc0([<table>])

table_clr_gpc0([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Очищает первый счётчик общего назначения ‘0’ и возвращает его предыдущее значение. Если запись не найдена, она создаётся, и возвращается 0. Обычно используется как второй ACL в выражении для отметки соединения при истинном результате первого ACL:

Пример:

# block if 5 consecutive requests continue to come faster than 10 sess
# per second, and reset the counter as soon as the traffic slows down.
acl abuse src_http_req_rate gt 10
acl kill  src,table_inc_gpc0 gt 5
acl save  src,table_clr_gpc0 ge 0
tcp-request connection accept if !abuse save
tcp-request connection reject if abuse kill

См. также ключевое слово извлечения образца sc_clr_gpc0.

table_clr_gpc1([<table>])

table_clr_gpc1([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Очищает первый счётчик общего назначения ‘1’ и возвращает его предыдущее значение. Если запись не найдена, она создаётся, и возвращается 0. Обычно используется как второй ACL в выражении для отметки соединения при истинном результате первого ACL. См. также ключевое слово извлечения образца sc_clr_gpc1.

table_conn_cnt([<table>])

table_conn_cnt([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целое значение ноль. В противном случае преобразователь возвращает общее количество входящих соединений, связанных с входным образцом в указанной таблице. См. также ключевое слово извлечения образца sc_conn_cnt.

table_conn_cur([<table>])

table_conn_cur([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целое значение ноль. В противном случае преобразователь возвращает текущее количество одновременных отслеживаемых соединений, связанных с входным образцом в указанной таблице. См. также ключевое слово извлечения образца sc_conn_cur.

table_conn_rate([<table>])

table_conn_rate([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целое значение ноль. В противном случае преобразователь возвращает среднюю интенсивность входящих соединений, связанных с входным образцом в указанной таблице. См. также ключевое слово извлечения образца sc_conn_rate.

table_expire([<table>[,<default_value>]])

table_expire([<table>[,<default_value>]])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, преобразователь завершается с ошибкой, за исключением случая, когда установлено <default_value>: тогда преобразователь успешно выполняется и возвращает <default_value>. Если ключ найден, преобразователь возвращает время до истечения срока действия ключа, связанную с входным образцом в указанной таблице. См. также ключевое слово извлечения образца table_idle.

table_glitch_cnt([<table>])

table_glitch_cnt([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целое значение ноль. В противном случае преобразователь возвращает общее количество сбоев входящих соединений, связанных с входным образцом в указанной таблице. См. также ключевое слово извлечения образца sc_glitch_cnt и fc_glitches для значения, измеренного на текущем входящем соединении.

table_glitch_rate([<table>])

table_glitch_rate([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целое значение ноль. В противном случае преобразователь возвращает среднюю интенсивность сбоев входящих соединений, связанных с входным образцом в указанной таблице. См. также ключевое слово извлечения образца sc_glitch_rate.

table_gpc(<idx>[,<table>])

table_gpc(<idx>[,<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целое значение ноль. В противном случае преобразователь возвращает текущее значение счётчика общего назначения по индексу <idx> массива, связанного с входным образцом в указанной таблице <table>. <idx> — целое число от 0 до 99. Если по этому индексу нет сохранённого GPC, также возвращается целочисленное значение 0. Это относится только к data_type массива ‘gpc’ (а не к устаревшим data_types ‘gpc0’ или ‘gpc1’). См. также ключевое слово извлечения образца sc_get_gpc.

table_gpc0([<table>])

table_gpc0([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целочисленное значение ноль. В противном случае преобразователь возвращает текущее значение первого счётчика общего назначения, связанного с входным образцом в указанной таблице. См. также ключевое слово извлечения образца sc_get_gpc0.

table_gpc0_rate([<table>])

table_gpc0_rate([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целочисленное значение ноль. В противном случае преобразователь возвращает частоту увеличения счётчика gpc0 за настроенный период в таблице, связанную с входным образцом в указанной таблице. См. также ключевое слово извлечения образца sc_get_gpc0_rate.

table_gpc1([<table>])

table_gpc1([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целочисленное значение ноль. В противном случае преобразователь возвращает текущее значение второго счётчика общего назначения, связанного с входным образцом в указанной таблице. См. также ключевое слово извлечения образца sc_get_gpc1.

table_gpc1_rate([<table>])

table_gpc1_rate([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целочисленное значение ноль. В противном случае преобразователь возвращает частоту увеличения счётчика gpc1 за настроенный период в таблице, связанную с входным образцом в указанной таблице. См. также ключевое слово извлечения образца sc_get_gpc1_rate.

table_gpc_rate(<idx>[,<table>])

table_gpc_rate(<idx>[,<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целое значение ноль. В противном случае преобразователь возвращает частоту, с которой счётчик глобального назначения по индексу <idx> массива (связанный с входным образцом в указанной таблице привязок <table>) увеличивался за настроенный период. <idx> — целое число от 0 до 99. Если gpc_rate не хранится по этому индексу, также возвращается целочисленное значение 0. Это относится только к data_type массива ‘gpc_rate’ (а не к устаревшим data_types ‘gpc0_rate’ или ‘gpc1_rate’). См. также sc_gpc_rate — ключевое слово извлечения образца.

table_gpt(<idx>[,<table>])

table_gpt(<idx>[,<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целое значение ноль. В противном случае преобразователь возвращает текущее значение метки общего назначения по индексу <idx> массива, связанного с входным образцом в указанной таблице <table>. <idx> — целое число от 0 до 99. Если по этому индексу нет сохранённого GPT, также возвращается целочисленное значение 0. Это относится только к data_type массива ‘gpt’ (а не к устаревшему типу данных ‘gpt0’). См. также sc_get_gpt — ключевое слово извлечения образца.

table_gpt0([<table>])

table_gpt0([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целочисленное значение ноль. В противном случае преобразователь возвращает текущее значение первой метки общего назначения, связанного с входным образцом в указанной таблице. См. также ключевое слово извлечения образца sc_get_gpt0.

table_http_err_cnt([<table>])

table_http_err_cnt([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целочисленное значение ноль. В противном случае преобразователь возвращает общее количество ошибок типа HTTP, связанных с входным образцом в указанной таблице. См. также ключевое слово извлечения образца sc_http_err_cnt.

table_http_err_rate([<table>])

table_http_err_rate([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целочисленное значение ноль. В противном случае преобразователь возвращает среднюю частоту ошибок типа HTTP, связанных с входным образцом в указанной таблице, измеряемую как количество ошибок за период, настроенный в таблице. См. также ключевое слово извлечения образца sc_http_err_rate.

table_http_fail_cnt([<table>])

table_http_fail_cnt([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целочисленное значение ноль. В противном случае преобразователь возвращает общее количество сбоев типа HTTP, связанных с входным образцом в указанной таблице. См. также ключевое слово извлечения образца sc_http_fail_cnt.

table_http_fail_rate([<table>])

table_http_fail_rate([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целочисленное значение ноль. В противном случае преобразователь возвращает среднюю частоту сбоев типа HTTP, связанных с входным образцом в указанной таблице, измеряемую как количество сбоев за период, настроенный в таблице. См. также ключевое слово извлечения образца sc_http_fail_rate.

table_http_req_cnt([<table>])

table_http_req_cnt([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целочисленное значение ноль. В противном случае преобразователь возвращает общее количество запросов типа HTTP, связанных с входным образцом в указанной таблице. См. также ключевое слово извлечения образца sc_http_req_cnt.

table_http_req_rate([<table>])

table_http_req_rate([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целочисленное значение ноль. В противном случае преобразователь возвращает среднюю частоту запросов типа HTTP, связанных с входным образцом в указанной таблице, измеряемую как количество запросов за период, настроенный в таблице. См. также ключевое слово извлечения образца sc_http_req_rate.

table_idle([<table>[,<default_value>]])

table_idle([<table>[,<default_value>]])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, преобразователь завершается с ошибкой, за исключением случая, когда установлено <default_value>: это делает преобразователь успешным и возвращает значение <default_value>. Если ключ найден, преобразователь возвращает время, в течение которого запись, связанная с входным образцом в указанной таблице, оставалась неактивной с момента последнего обновления. См. также ключевое слово извлечения образца table_expire.

table_inc_gpc(<idx>[,<table>])

table_inc_gpc(<idx>[,<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Увеличивает значение счётчика общего назначения по индексу <idx> массива и возвращает его новое значение. <idx> — целое число от 0 до 99. Если запись не найдена, она создаётся, и возвращается значение 1. Этот преобразователь применяется только к data_type массива ‘gpc’ (а не к устаревшим data_types ‘gpc0’ или ‘gpc1’). См. также sc_inc_gpc.

table_inc_gpc0([<table>])

table_inc_gpc0([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Увеличивает счётчик общего назначения ‘0’ и возвращает его новое значение. Если запись не найдена, она создаётся, и возвращается 1. См. также sc0/sc2/sc2_inc_gpc0. Обычно используется как второй ACL в выражении, чтобы отметить соединение при истинном результате первого ACL:

Пример:

acl abuse src,table_req_rate gt 10
acl kill  src,table_inc_gpc0 gt 0
tcp-request connection reject if abuse kill

table_inc_gpc1([<table>])

table_inc_gpc1([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Увеличивает счётчик общего назначения ‘1’ и возвращает его новое значение. Если запись не найдена, она создаётся, и возвращается 1. См. также sc0/sc2/sc2_inc_gpc1. Обычно используется как второй ACL в выражении, чтобы отметить соединение при истинном результате первого ACL.

table_kbytes_in([<table>])

table_kbytes_in([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целочисленное значение ноль. В противном случае преобразователь возвращает общее количество данных от клиента к серверу, связанных с входным образцом в указанной таблице, измеряемое в килобайтах. Тест в настоящее время выполняется на 32-битных целых числах, что ограничивает значения до 4 терабайт. См. также ключевое слово извлечения образца sc_kbytes_in.

table_kbytes_out([<table>])

table_kbytes_out([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целочисленное значение ноль. В противном случае преобразователь возвращает общее количество данных от сервера к клиенту, связанных с входным образцом в указанной таблице, измеряемое в килобайтах. Тест в настоящее время выполняется на 32-битных целых числах, что ограничивает значения до 4 терабайт. См. также ключевое слово извлечения образца sc_kbytes_out.

table_server_id([<table>])

table_server_id([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целочисленное значение ноль. В противном случае преобразователь возвращает идентификатор сервера, связанный с входным образцом в указанной таблице. Идентификатор сервера привязывается к образцу правилом “stick” при успешном подключении к серверу. Идентификатор сервера ноль означает, что ключу не присвоен никакой сервер.

table_sess_cnt([<table>])

table_sess_cnt([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целочисленное значение ноль. В противном случае преобразователь возвращает общее количество входящих сеансов, связанных с входным образцом в указанной таблице. Примечание: под сеансом здесь понимается входящее соединение, принятое правилами набора “tcp-request connection”. См. также ключевое слово извлечения образца sc_sess_cnt.

table_sess_rate([<table>])

table_sess_rate([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целочисленное значение ноль. В противном случае преобразователь возвращает среднюю частоту входящих сеансов, связанных с входным образцом в указанной таблице. Примечание: под сеансом здесь понимается входящее соединение, принятое правилами набора “tcp-request connection”. См. также ключевое слово извлечения образца sc_sess_rate.

table_trackers([<table>])

table_trackers([<table>])

Использует входной образец для поиска в таблице привязок текущего прокси или в указанной таблице привязок. Если ключ не найден в таблице, возвращается целочисленное значение ноль. В противном случае преобразователь возвращает текущее количество одновременных соединений, отслеживающих тот же ключ, что и входной образец, в указанной таблице. Отличается от table_conn_cur тем, что не полагается на хранящуюся информацию, а использует счётчик ссылок таблицы (значение “use”, возвращаемое командой “show table” на CLI). Это может быть более подходящим для отслеживания layer7. Например, позволяет сообщить серверу число одновременных соединений от заданного адреса. См. также ключевое слово извлечения образца sc_trackers.

tcp.dst

tcp.dst

Используется со входным образцом, представляющим двоичный заголовок TCP, возвращаемый “ip.data”. Возвращает целое число, представляющее порт назначения, содержащийся в заголовке TCP. См. также “fc_saved_syn”, “tcp-ss” и “ip.data”.

tcp.flags

tcp.flags

Используется со входным образцом, представляющим двоичный заголовок TCP, возвращаемый “ip.data”. Возвращает целое число, представляющее флаги TCP из этого заголовка TCP. Извлекаются все 8 флагов от FIN до CWR. Каждый флаг может быть проверен с помощью преобразователя “and()”. См. RFC9293 для значений каждого флага. Также см. “fc_saved_syn”, “tcp-ss” и “ip.data”.

tcp.options.mss

tcp.options.mss

Используется со входным образцом, представляющим двоичный заголовок TCP, возвращаемый “ip.data”. Ищет опцию TCP типа “MSS”, и если найдена, возвращает целое значение, соответствующее объявленному значению в этой опции, в противном случае — ноль. Значение MSS — это максимальный размер сегмента и указывает наибольший размер сегмента, который может принять другая сторона, в байтах. См. также “fc_saved_syn”, “tcp-ss” и “ip.data”.

tcp.options.sack

tcp.options.sack

Используется со входным образцом, представляющим двоичный заголовок TCP, возвращаемый “ip.data”. Ищет опцию TCP типа “Sack-Permitted”, и если найдена, возвращает 1, в противном случае — ноль. См. также “fc_saved_syn”, “tcp-ss” и “ip.data”.

tcp.options.tsopt

tcp.options.tsopt

Используется со входным образцом, представляющим двоичный заголовок TCP, возвращаемый “ip.data”. Ищет опцию TCP типа “Timestamp”, и если найдена, возвращает 1, в противном случае — ноль. См. также “fc_saved_syn”, “tcp-ss” и “ip.data”.

tcp.options.tsval

tcp.options.tsval

Используется со входным образцом, представляющим двоичный заголовок TCP, возвращаемый “ip.data”. Ищет опцию TCP типа “Timestamp”, и если найдена, возвращает значение временной метки, переданное другой стороной, в противном случае не возвращает ничего. Обратите внимание, что временные метки — это беззнаковые значения длиной 32 бит без определённой единицы измерения, выбираемой только другой стороной, и временные метки предполагаются независимыми между различными соединениями. См. также “fc_saved_syn”, “tcp-ss” и “ip.data”.

tcp.options.wscale

tcp.options.wscale

Используется со входным образцом, представляющим двоичный заголовок TCP, возвращаемый “ip.data”. Ищет опцию TCP типа “Window Scale”, и если найдена, возвращает значение масштабирования окна, переданное другой стороной, в противном случае — ноль. Обратите внимание, что предполагается, что значения не превышают 14, хотя технически ограничений на их отправку нет. Чтобы определить, использовалась ли опция масштабирования окна, используйте “tcp.options.wsopt”. См. также “tcp-ss”, “fc_saved_syn”, “ip.data” и “tcp.options.wsopt”.

tcp.options.wsopt

tcp.options.wsopt

Используется со входным образцом, представляющим двоичный заголовок TCP, возвращаемый “ip.data”. Ищет опцию TCP типа “Window Scale”, и если найдена, возвращает 1, в противном случае — 0. См. также “fc_saved_syn”, “tcp-ss”, “ip.data”, “tcp.options.wscale”.

tcp.options_list

tcp.options_list

Используется со входным образцом, представляющим двоичный заголовок TCP, возвращаемый “ip.data”. Строит двоичную последовательность всех видов опций TCP в том же порядке, в каком они появляются в заголовке TCP. Может выдать от 0 до 60 байт (в худшем случае). Маркер конца опций не включается в результат. См. также “fc_saved_syn”, “tcp-ss” и “ip.data”.

tcp.seq

tcp.seq

Используется со входным образцом, представляющим двоичный заголовок TCP, возвращаемый “ip.data”. Возвращает целое число, представляющее номер последовательности, используемый удалённым узлом в заголовке TCP. Номера последовательности являются беззнаковыми значениями размером 32 бит. См. также “fc_saved_syn”, “tcp-ss” и “ip.data”.

tcp.src

tcp.src

Используется со входным образцом, представляющим двоичный заголовок TCP, возвращаемый “ip.data”. Возвращает целое число, представляющее номер порта источника, содержащийся в заголовке TCP. См. также “fc_saved_syn”, “tcp-ss” и “ip.data”.

tcp.win

tcp.win

Используется со входным образцом, представляющим двоичный заголовок TCP, возвращаемый “ip.data”. Возвращает целое число, представляющее размер окна, объявленный удалённым узлом в заголовке TCP. Значение предоставляется без изменений, как 16-битное беззнаковое значение, без применения коэффициента масштабирования окна. См. также “fc_saved_syn”, “tcp-ss” и “ip.data”.

ub64dec

ub64dec

Этот преобразователь — вариант преобразователя b64dec для base64url. Кодирование base64url — вариант кодирования base64 с алфавитом, безопасным для URL и имён файлов. Оно также используется в стандарте JWT (JSON Web Token).

Пример:

# Decoding a JWT payload:
http-request set-var(txn.token_payload) req.hdr(Authorization),word(2,.),ub64dec

ub64enc

ub64enc

Этот преобразователь — вариант base64url преобразователя base64.

ungrpc(<field_number>[,<field_type>])

ungrpc(<field_number>[,<field_type>])

Извлекает поле сообщения protocol buffers из входного двоичного образца, представляющего сообщение gRPC. Номер поля задаётся аргументом <field_number> (в нотации с точками). Если <field_type> отсутствует, поле извлекается в необработанном виде; если указан — в виде целочисленного образца. Допустимы следующие типы: “int32”, “int64”, “uint32”, “uint64”, “sint32”, “sint64”, “bool”, “enum” для типа кодирования “varint” 0; “fixed64”, “sfixed64”, “double” для 64-битного типа кодирования 1; “fixed32”, “sfixed32”, “float” для типа кодирования 5. Тип “string” считается типом с явно заданной длиной, поэтому для его извлечения аргумент <field_type> не требуется. Дополнительные сведения о типах полей сообщений protocol buffers: https://developers.google.com/protocol-buffers/docs/encoding

Пример:

// with such a protocol buffer .proto file content adapted from
// https://github.com/grpc/grpc/blob/master/examples/protos/route_guide.proto

message Point {
  int32 latitude = 1;
  int32 longitude = 2;
}

message PPoint {
  Point point = 59;
}

message Rectangle {
  // One corner of the rectangle.
  PPoint lo = 48;
  // The other corner of the rectangle.
  PPoint hi = 49;
}

Например, если тело запроса состоит из значения объекта “Rectangle” (два сообщения protocol buffers PPoint), четыре поля protocol buffers можно извлечь с помощью следующих директив “ungrpc”:

req.body,ungrpc(48.59.1,int32) # "latitude" of "lo" first PPoint
req.body,ungrpc(48.59.2,int32) # "longitude" of "lo" first PPoint
req.body,ungrpc(49.59.1,int32) # "latitude" of "hi" second PPoint
req.body,ungrpc(49.59.2,int32) # "longitude" of "hi" second PPoint

Можно также извлечь промежуточное поле 48.59 как двоичный образец следующим образом:

req.body,ungrpc(48.59)

Поскольку сообщение gRPC всегда состоит из заголовка gRPC, за которым следуют сообщения protocol buffers, в предыдущем примере поле “latitude” первого PPoint “lo” можно извлечь следующими эквивалентными директивами:

req.body,ungrpc(48.59),protobuf(1,int32)
req.body,ungrpc(48),protobuf(59.1,int32)
req.body,ungrpc(48),protobuf(59),protobuf(1,int32)

Обратите внимание, что первый преобразователь должен быть “ungrpc”, остальные должны быть “protobuf”, и только последний может иметь или не иметь второй аргумент для интерпретации предыдущего двоичного образца.

unset-var(<var>)

unset-var(<var>)

Сбрасывает переменную, если входные данные определены. Имя переменной начинается с обозначения её области действия. Подробнее о переменных см. в разделе 2.8 .

upper

upper

Преобразует строковый образец в верхний регистр. Может использоваться только после функции извлечения строкового образца или после ключевого слова преобразования, возвращающего тип строки. Результат имеет тип string.

url_dec([<in_form>])

url_dec([<in_form>])

Принимает URL-кодированную строку в качестве входных данных и возвращает декодированную версию в качестве выходных данных. Входные и выходные данные имеют тип string. Если аргумент <in_form> установлен в ненулевое целочисленное значение, входная строка считается частью формы или строки запроса, и символ ‘+’ будет заменён на пробел (’ ‘). В противном случае это произойдёт только после знака вопроса, указывающего на строку запроса (’?’).

url_enc([<enc_type>])

url_enc([<enc_type>])

Принимает строку в качестве входных данных и возвращает закодированную версию в качестве выходных данных. Входные и выходные данные имеют тип string. По умолчанию тип кодирования предназначен для типа query. В настоящее время другие типы не поддерживаются, но опциональный аргумент предусмотрен для будущих изменений.

us_ltime(<format>[,<offset>])

us_ltime(<format>[,<offset>])

Работает аналогично “ltime”, но принимает входные данные в микросекундах. Также поддерживает спецификатор преобразования %N по образцу date(1). Преобразует целое число, которое предполагается датой, отсчитанной от начала эпохи, в строку с этой датой в местном времени. Формат задаётся строкой <format> с помощью strftime(3). Это позволяет использовать в журналах произвольный формат даты. К входной дате можно применить необязательное смещение <offset> в микросекундах (положительное или отрицательное). Поддерживаемые операционной системой форматы описаны на странице руководства strftime().

Спецификатор преобразования %N позволяет вывести часть даты в наносекундах, точность ограничена тем, что входные данные заданы в микросекундах. (000000000..999999000). %N может принимать аргумент ширины между % и N. Полезно для отображения миллисекунд (%3N) или микросекунд (%6N). Ширина по умолчанию и максимальная ширина — 9 (%N = %9N).

См. также преобразователь “utime” для UTC, а также преобразователи “ltime” и “ms_ltime”.

Пример:

# Emit 3 colons, the local time, the timezone and another with ip:port
# e.g. 2023/07/24/09:53:02.196234 +0000 127.0.0.1:41530
log-format %[accept_date(us),us_ltime("%Y/%m/%d/%H:%M:%S.%6N %z")]\ %ci:%cp

us_utime(<format>[,<offset>])

us_utime(<format>[,<offset>])

Работает аналогично “utime”, но принимает входные данные в микросекундах. Также поддерживает спецификатор преобразования %N по образцу date(1). Преобразует целое число, которое предполагается датой, отсчитанной от начала эпохи, в строку с этой датой в UTC. Формат задаётся строкой <format> с помощью strftime(3). Это позволяет использовать в журналах произвольный формат даты. К входной дате можно применить необязательное смещение <offset> в микросекундах (положительное или отрицательное). Поддерживаемые операционной системой форматы описаны на странице руководства strftime().

Спецификатор преобразования %N позволяет вывести часть даты в наносекундах, точность ограничена тем, что входные данные заданы в микросекундах. (000000000..999999000). %N может принимать аргумент ширины между % и N. Полезно для отображения миллисекунд (%3N) или микросекунд (%6N). Ширина по умолчанию и максимальная ширина — 9 (%N = %9N).

См. также преобразователь “ltime” для локального времени, а также преобразователи “utime” и “ms_utime”.

Пример:

# Emit 3 colons, the UTC time, the timezone and another with ip:port
# e.g. 2023/07/24/09:53:02.196234 +0000 127.0.0.1:41530
log-format %[accept_date(us),us_utime("%Y/%m/%d/%H:%M:%S.%6N %z")]\ %ci:%cp

utime(<format>[,<offset>])

utime(<format>[,<offset>])

Преобразует целое число, которое предполагается датой, отсчитанной от начала эпохи, в строку с этой датой в UTC. Формат задаётся строкой <format> с помощью strftime(3). Это позволяет использовать в журналах произвольный формат даты. К входной дате можно применить необязательное смещение <offset> в секундах (положительное или отрицательное). Поддерживаемые операционной системой форматы описаны на странице руководства strftime(). См. также преобразователь “ltime”, а также “ms_utime” и “us_utime”.

Пример:

# Emit two colons, one with the UTC time and another with ip:port
# e.g.  20140710162350 127.0.0.1:57325
log-format %[date,utime(%Y%m%d%H%M%S)]\ %ci:%cp

when(<condition>[,<args>...])

when(<condition>[,<args>...])

Оценивает условие и, если оно истинно, передаёт входной образец без изменений на выход, в противном случае — ничего не возвращает. Предназначен специально для получения редко необходимых данных, которые следует выводить только при определённых условиях, например отладочной информации при возникновении ошибки.

Условие состоит из ключевого слова из приведённого ниже списка, необязательно предваряемого восклицательным знаком (’!’) для отрицания, и необязательно сопровождаемого аргументами, специфичными для этого условия:

- "error" возвращает true, когда во время обработки запроса или потока возникла ошибка. Используются те же правила, что и для "dontlog-normal" (например, успешное повторное распределение считается ошибкой).

- "forwarded" возвращает true, если запрос был перенаправлен на сервер бэкенда

- "normal" возвращает true, если ошибка не произошла (что эквивалентно "!error").

- "processed" возвращает true, если запрос был либо перенаправлен на сервер бэкенда, либо обработан апплетом.

- "stopping" возвращает true, если во время вычисления правила процесс
  сейчас останавливается

- "toapplet" возвращает true, если запрос был обработан апплетом.

- "acl" возвращает true, если ACL, указанный следующим аргументом,
  даёт результат true. ACL вычисляется непосредственно преобразователем,
  поэтому то, к чему он обращается, должно быть допустимым в этом контексте.
  Один из вариантов использования — проверить, слишком ли велико общее
  время передачи, прежде чем записывать в журнал подробности
  аномально долгих передач.

Обратите внимание, что содержимое всегда оценивается, поэтому такое действие не предотвращает генерацию этой информации. Оно предназначено только для предотвращения её вывода.

Например, можно добавлять отладочную информацию по потоку бэкенда в журнал только при возникновении ошибки во время обработки, или записывать дополнительные данные в журнал при остановке и т. д.

Пример:

# log "dbg={-}" when fine, or "dbg={... debug info ...}" on error:
log-format "$HAPROXY_HTTP_LOG_FMT dbg={%[bs.debug_str,when(!normal)]}"

Здесь поле "dbg" в журнале содержит только дефис ('-'), указывающий на
отсутствие содержимого, если условие правила не выполнено; когда оно выполнено,
выводится целый блок отладочной информации.

Пример

# log "dbg={-}" when fine, or "dbg={... debug info ...}" on slow transfers
acl slow_xfer res.timer.data ge 10000   # more than 10s is slow
log-format "$HAPROXY_HTTP_LOG_FMT                                         \
            fsdbg={%[fs.debug_str,when(acl,slow_xfer)]}                   \
            bsdbg={%[bs.debug_str,when(acl,slow_xfer)]}"

Пример

# only emit the backend src/port when a real connection was issued:
log-format "$HAPROXY_HTTP_LOG_FMT \
           src=[%[bc_src,when(forwarded)]:%[bc_src_port,when(forwarded)]]"

Поскольку он прерывает оценку выражения, если условие не выполняется, его также можно использовать для предотвращения вызова последующего преобразователя. Например, это может быть использовано для вызова преобразователя debug() только при возникновении ошибки, чтобы логировать элемент только в случае необходимости.

Пример:

# emit the whole response headers list to stderr only on error and only
# when the output is a connection. We abuse a dummy variable here.
http-after-response set-var(res.test) \
              res.hdrs,when(error),when(forwarded),debug(hdrs,stderr)

См. также: преобразователь отладки

word(<index>,<delimiters>[,<count>])

word(<index>,<delimiters>[,<count>])

Извлекает n-е слово, считая с начала (положительный индекс) или с конца (отрицательный индекс), из входной строки с учётом заданных разделителей. Индексы начинаются с 1 или -1, разделители — это строка, содержащая список символов. Пустые слова пропускаются. Это означает, что разделители в начале или конце входной строки игнорируются, а последовательные разделители внутри строки считаются одним разделителем. Необязательно можно указать <count> извлекаемых слов (по умолчанию: 1). Значение 0 означает извлечение всех оставшихся слов.

Пример:

str(f1_f2_f3__f5),word(4,_)    # f5
str(f1_f2_f3__f5),word(5,_)    # <not found>
str(f1_f2_f3__f5),word(2,_,0)  # f2_f3__f5
str(f1_f2_f3__f5),word(3,_,2)  # f3__f5
str(f1_f2_f3__f5),word(-2,_,3) # f1_f2_f3
str(f1_f2_f3__f5),word(-3,_,0) # f1_f2
str(/f1/f2/f3/f4),word(1,/)    # f1
str(/f1////f2/f3/f4),word(1,/) # f2

wt6([<avalanche>])

wt6([<avalanche>])

Хэширует двоичный входной образец в беззнаковое 32-битное значение с использованием хэш-функции WT6. К результату можно дополнительно применить хеш-функцию с полным лавинным эффектом, если необязательный аргумент <avalanche> равен 1. Этот преобразователь использует те же функции, что и различные алгоритмы балансировки нагрузки на основе хэширования, поэтому обеспечивает точно такие же результаты. В основном предназначен для отладки, но может использоваться как запись в таблице привязок для сбора приблизительной статистики. Не должен использоваться в целях безопасности, так как хэш размером 32 бит легко взломать. См. также “crc32”, “djb2”, “sdbm”, “crc32c” и директиву “hash-type”.

x509_v_err_str

x509_v_err_str

Преобразует числовое значение в соответствующее ему имя константы X509_V_ERR. Полезно при ACL для создания конфигурации, совместимой с несколькими версиями OpenSSL, поскольку некоторые коды могут меняться при переходе на другую версию.

При отсутствии соответствующего имени константы выводит числовое значение в виде строки.

Список констант, предоставляемых OpenSSL, можно найти на https://www.openssl.org/docs/manmaster/man3/X509_STORE_CTX_get_error.html#ERROR-CODES . Будьте внимательны: убедитесь, что читаете страницу для правильной версии OpenSSL.

Пример:

bind :443 ssl crt common.pem ca-file ca-auth.crt verify optional crt-ignore-err X509_V_ERR_CERT_REVOKED,X509_V_ERR_CERT_HAS_EXPIRED

acl cert_expired ssl_c_verify,x509_v_err_str -m str X509_V_ERR_CERT_HAS_EXPIRED
acl cert_revoked ssl_c_verify,x509_v_err_str -m str X509_V_ERR_CERT_REVOKED
acl cert_ok      ssl_c_verify,x509_v_err_str -m str X509_V_OK

http-response add-header X-SSL Ok if cert_ok
http-response add-header X-SSL Expired if cert_expired
http-response add-header X-SSL Revoked if cert_revoked

http-response add-header X-SSL-verify %[ssl_c_verify,x509_v_err_str]

xor(<value>)

xor(<value>)

Выполняет побитовую операцию “XOR” (исключающее ИЛИ) между <value> и входным значением типа знаковое целое и возвращает результат как знаковое целое. <value> может быть числом или именем переменной. Подробнее о переменных см. в разделе 2.8 .

xxh3([<seed>])

xxh3([<seed>])

Хеширует входной двоичный образец в 64-битное знаковое значение с помощью 64-битного варианта XXH3 хеш-функции XXhash. Хеш поддерживает начальное значение, по умолчанию равное нулю; другое значение можно передать аргументом <seed>. Эта хеш-функция известна хорошими свойствами и высокой скоростью, поэтому её можно использовать для хеширования URLs и/или параметров URL в качестве ключей таблиц привязок, собирающих статистику с низкой частотой коллизий. Однако следует соблюдать осторожность: алгоритм не считается криптографически безопасным.

xxh32([<seed>])

xxh32([<seed>])

Хэширует двоичный входной образец в беззнаковое количество 32 бит с использованием варианта XXHash хэш-функции размером 32 бит. Этот хэш поддерживает начальное значение (seed), по умолчанию равное нулю, но может быть задано другое значение через аргумент <seed>. Этот хэш известен своей высокой эффективностью и скоростью, поэтому его можно использовать для хэширования URL и/или параметров URL в качестве ключей таблицы привязок для сбора статистики с низкой вероятностью коллизий, хотя следует помнить, что алгоритм не считается криптографически безопасным.

xxh64([<seed>])

xxh64([<seed>])

Хэширует двоичный входной образец в знаковое количество 64 бит с использованием варианта XXHash хэш-функции размером 64 бит. Этот хэш поддерживает начальное значение (seed), по умолчанию равное нулю, но может быть задано другое значение через аргумент <seed>. Этот хэш известен своей высокой эффективностью и скоростью, поэтому его можно использовать для хэширования URL и/или параметров URL в качестве ключей таблицы привязок для сбора статистики с низкой вероятностью коллизий, хотя следует помнить, что алгоритм не считается криптографически безопасным.

7.3.2. Извлечение образцов из внутренних состояний

Первый набор методов извлечения образцов применяется к внутренней информации, не связанной даже с какими-либо данными клиента. Эти методы иногда используются с директивами “monitor fail” для передачи внутреннего состояния внешним наблюдателям. Методы извлечения образцов, описанные в этом разделе, могут использоваться в любом месте.

Сводка методов извлечения образцов в этом разделе и их соответствующие типы:

  Ключевое слово                                   Выходной тип
-------------------------------------------------+-------------
acl([!]<name>[,...])                               boolean
act_conn                                           integer
always_false                                       boolean
always_true                                        boolean
avg_queue([<backend>])                             integer
be_conn([<backend>])                               integer
be_conn_free([<backend>])                          integer
be_sess_rate([<backend>])                          integer
bin(<hex>)                                         bin
bool(<bool>)                                       bool
connslots([<backend>])                             integer
cpu_calls                                          integer
cpu_ns_avg                                         integer
cpu_ns_tot                                         integer
date([<offset>[,<unit>]])                          integer
date_us                                            integer
env(<name>)                                        string
fe_conn([<frontend>])                              integer
fe_req_rate([<frontend>])                          integer
fe_sess_rate([<frontend>])                         integer
hostname                                           string
int(<integer>)                                     signed
ipv4(<ipv4>)                                       ipv4
ipv6(<ipv6>)                                       ipv6
last_entity                                        string
last_rule_file                                     string
last_rule_line                                     integer
lat_ns_avg                                         integer
lat_ns_tot                                         integer
meth(<method>)                                     method
nbsrv([<backend>])                                 integer
pid                                                integer
prio_class                                         integer
prio_offset                                        integer
proc                                               integer
queue([<backend>])                                 integer
quic_enabled                                       boolean
rand([<range>])                                    integer
srv_conn([<backend>/]<server>)                     integer
srv_conn_free([<backend>/]<server>)                integer
srv_is_up([<backend>/]<server>)                    boolean
srv_iweight([<backend>/]<server>)                  integer
srv_queue([<backend>/]<server>)                    integer
srv_sess_rate([<backend>/]<server>)                integer
srv_uweight([<backend>/]<server>)                  integer
srv_weight([<backend>/]<server>)                   integer
stopping                                           boolean
str(<string>)                                      string
table_avl([<table>])                               integer
table_cnt([<table>])                               integer
term_events                                        string
thread                                             integer
txn.id32                                           integer
txn.sess_term_state                                string
uptime                                             integer
uuid([<version>])                                  string
var(<var-name>[,<default>])                        undefined
wait_end                                           boolean
waiting_entity                                     string
-------------------------------------------------+-------------

Подробный список:

acl([!]<name>[,...]): boolean

acl([!]<name>[,...]): boolean

Возвращает true, если оценка всех указанных ACL(ов) является истинной, в противном случае — false. Можно указать до 12 ACL, разделённых запятыми. Каждый указанный ACL может быть предварён знаком “!” для инвертирования результата. Если какая-либо оценка приводит к ошибке, то образец также возвращает ошибку. Обратите внимание, что HAProxy не выполняет проверки на корректность ссылок на ACL, например, на то, используется ли ACL, использующий извлечение образца запроса HTTP, в контексте ответа. Это поведение может измениться в будущем.

act_conn: integer Возвращает общее количество активных одновременных соединений на процессе.

always_false: boolean Всегда возвращает логическое значение “false”. Может использоваться с ACL как временная замена другому, при настройке конфигурации.

always_true: boolean Всегда возвращает логическое значение “true”. Может использоваться с ACL как временная замена другому, при настройке конфигурации.

avg_queue([<backend>]): integer

avg_queue([<backend>]): integer

Возвращает общее количество соединений в очереди в указанном бэкенде, делённое на количество активных серверов. Если бэкенд не указан, используется текущий. Это очень похоже на “queue”, за исключением того, что учитывается размер фермы, чтобы получить более точную оценку времени обработки нового соединения. Основное применение — с ACL для возврата страницы с извинением новым пользователям, когда становится очевидным, что они получат обслуживание ухудшенного качества, или для передачи бэкенд-серверам в заголовке, чтобы те решили работать в ухудшённом режиме или отключить некоторые функции для ускорения обработки. Обратите внимание, что в случае, если больше не останется активных серверов, будет считаться удвоенное количество соединений в очереди. Это разумная оценка, поскольку мы ожидаем, что один из серверов скоро вернётся, но всё же предпочтительнее направлять новую нагрузку на другой бэкенд, если он в лучшем состоянии. См. также методы извлечения образцов “queue”, “be_conn” и “be_sess_rate”.

be_conn([<backend>]): integer

be_conn([<backend>]): integer

Применяется к количеству установленных соединений в бэкенде, возможно, включая соединение, которое оценивается. Если имя бэкенда не указано, используется текущий. Также возможно проверить другой бэкенд. Может использоваться для выбора конкретной фермы, когда основная заполнена. См. также критерии “fe_conn”, “queue”, “be_conn_free” и “be_sess_rate”.

be_conn_free([<backend>]): integer

be_conn_free([<backend>]): integer

Возвращает целое значение, соответствующее количеству доступных соединений на доступных серверах в бэкенде. Места в очереди не учитываются. Резервные серверы также не учитываются, кроме случая, когда все остальные серверы недоступны. Если имя бэкенда не указано, используется текущий. Также возможно проверить другой бэкенд. Может использоваться для выбора конкретной фермы, когда основная заполнена. См. также критерии “be_conn”, “connslots” и “srv_conn_free”.

ДРУГИЕ ОГОВОРКИ И ПРИМЕЧАНИЯ: если любое из значений maxconn или maxqueue сервера равно 0 (то есть неограничено), то это извлечение образца не имеет смысла, в таком случае возвращаемое значение будет -1.

be_sess_rate([<backend>]): integer

be_sess_rate([<backend>]): integer

Возвращает целочисленное значение, соответствующее скорости создания сессий в бэкенде, в количестве новых сессий в секунду. Используется с ACL для переключения на альтернативный бэкенд, когда дорогой или уязвимый бэкенд достигает слишком высокой скорости сессий, либо для ограничения злоупотребления сервисом (например, предотвращение массового скачивания онлайн-словаря). Также может быть полезно добавить этот элемент в логи с помощью директивы log-format.

Пример:

# Redirect to an error page if the dictionary is requested too often
backend dynamic
    mode http
    acl being_scanned be_sess_rate gt 100
    redirect location /denied.html if being_scanned

bin(<hex>): bin

bin(<hex>): bin

Возвращает двоичную цепочку. Входные данные — шестнадцатеричное представление строки.

bool(<bool>): bool

bool(<bool>): bool

Возвращает логическое значение. <bool> может быть ’true’, ‘false’, ‘1’ или ‘0’. Значения ‘false’ и ‘0’ эквивалентны. Значения ’true’ и ‘1’ эквивалентны.

connslots([<backend>]): integer

connslots([<backend>]): integer

Возвращает целочисленное значение, соответствующее количеству доступных мест для соединений в бэкенде, путём суммирования максимального количества соединений на всех серверах и максимального размера очереди. Вероятно, используется только с ACL.

Основная идея заключается в возможности измерения количества “свободных слотов” для соединений (соединение + очередь), чтобы всё, что превышает это количество (предполагаемое применение; см. ключевое слово “use_backend”), могло быть перенаправлено на другой бэкенд.

‘connslots’ = количество доступных слотов соединений на серверах + количество доступных слотов очереди на серверах.

Обратите внимание, что хотя “fe_conn” может использоваться, “connslots” особенно полезен в случае, когда трафик направляется на один IP-адрес, разделяясь между несколькими бэкендами (возможно, с использованием ACL для балансировки по имени) и вы хотите различать различные бэкенды и их доступные “connslots”. Кроме того, в отличие от “nbsrv”, который измеряет только серверы, которые фактически недоступны, этот метод более детализирован и учитывает количество доступных слотов соединений. См. также “queue” и “avg_queue”.

ДРУГИЕ ОГОВОРКИ И ПРИМЕЧАНИЯ: на данный момент код не учитывает динамические соединения. Кроме того, если любое из значений maxconn или maxqueue сервера равно 0, то это извлечение образца не имеет смысла, в таком случае возвращаемое значение будет -1.

cpu_calls: integer Возвращает количество вызовов задачи, обрабатывающей поток или текущий запрос, с момента её выделения. Это число сбрасывается при каждом новом запросе на том же соединении при HTTP keep-alive. Обычно это значение низкое и стабильное (около 2 вызовов для типичного простого запроса), но может стать высоким, если выполняется какая-либо обработка (сжатие, кэширование или анализ). Используется исключительно для мониторинга производительности.

cpu_ns_avg: integer Возвращает среднее количество наносекунд, затраченных на каждый вызов задачи, обрабатывающей поток или текущий запрос. Это число сбрасывается при каждом новом запросе на том же соединении при HTTP keep-alive. Это значение указывает на общую стоимость обработки запроса или соединения на каждый вызов. Нет хорошего или плохого значения, но время, затраченное на вызов, автоматически увеличивает задержку для других операций (см. lat_ns_avg ниже), и может влиять на кажущееся время ответа других соединений. Операции, такие как сжатие, сложное сопоставление по регулярным выражениям или тяжёлые операции Lua, могут напрямую влиять на это значение, и наличие его в логах облегчит выявление неисправной обработки, требующей исправления для восстановления приемлемой производительности. Примечание: это значение точно равно cpu_ns_tot делённому на cpu_calls.

cpu_ns_tot: integer Возвращает общее количество наносекунд, затраченных на каждый вызов задачи, обрабатывающей поток или текущий запрос. Это число сбрасывается при каждом новом запросе на том же соединении при HTTP keep-alive. Это значение указывает на общую стоимость обработки запроса или соединения на каждый вызов. Нет хорошего или плохого значения, но время, затраченное на вызов, автоматически увеличивает задержку для других операций (см. lat_ns_avg ниже), вызывает дополнительные затраты на машине (CPU), и может влиять на кажущееся время ответа других соединений. Операции, такие как сжатие, сложное сопоставление по регулярным выражениям или тяжёлые операции Lua, могут напрямую влиять на это значение, и наличие его в логах облегчит выявление неисправной обработки, требующей исправления для восстановления приемлемой производительности. Значение может быть искусственно высоким из-за большого количества cpu_calls при обработке множества фрагментов HTTP, поэтому зачастую предпочтительнее логировать cpu_ns_avg.

cpu_usage_grp: integer Возвращает измерённое использование CPU за последний цикл опроса, между 0 и 100, усреднённое по всем потокам текущей группы потоков. Это может использоваться для устранения неполадок и ведения журнала. Измерение чрезвычайно нестабильно, но остаётся точным при длительной нагрузке, поскольку каждый поток измеряет его на нескольких десятках до сотен запросов.

cpu_usage_proc: integer Возвращает измерённое использование CPU за последний цикл опроса, между 0 и 100, усреднённое по всем работающим потокам. Это может использоваться для устранения неполадок и ведения журнала. Измерение чрезвычайно нестабильно, но остаётся точным при длительной нагрузке, поскольку каждый поток измеряет его на нескольких десятках до сотен запросов. Это значение равно 100 минус значение, указанное в доле простоя на странице статистики и в команде “show info”.

cpu_usage_thr: integer Возвращает измерённое использование CPU за последний цикл опроса, между 0 и 100, для вызывающего потока. Это может использоваться для устранения неполадок и ведения журнала. Измерение чрезвычайно нестабильно, но остаётся точным при длительной нагрузке, поскольку измеряется на нескольких десятках до сотен запросов. Это то же самое значение, которое используется для принятия решения о принудительном закрытии соединений при чрезмерном уровне сбоев или отключении сжатия. См. также “tune.glitches.kill.cpu-usage” и “maxcompcpuusage”.

date([<offset>[,<unit>]]): integer

date([<offset>[,<unit>]]): integer

Возвращает текущую дату как число секунд с начала эпохи (с 01/01/1970).

Если указано смещение, то оно добавляется к текущей дате перед возвратом значения. Это особенно полезно для вычисления относительных дат, так как допускаются как положительные, так и отрицательные смещения. Полезно использовать вместе с преобразователем http_date.

Параметр <unit> необязателен и может быть установлен в “s” для секунд (поведение по умолчанию), “ms” для миллисекунд или “us” для микросекунд. Если указана единица измерения, возвращаемое значение — целое число, отражающее количество секунд, миллисекунд или микросекунд с эпохи, плюс смещение. Полезно, когда требуется разрешение времени менее одной секунды.

Пример:

# set an expires header to now+1 hour in every response
http-response set-header Expires %[date(3600),http_date]

# set an expires header to now+1 hour in every response, with
# millisecond granularity
http-response set-header Expires %[date(3600000,ms),http_date(0,ms)]

date_us: integer Возвращает микросекунды даты (часть “секунды” возвращается образцом date). Этот образец согласован с образцом date, поскольку берётся из той же структуры timeval.

env(<name>): string

env(<name>): string

Возвращает строку, содержащую значение переменной среды <name>. Напоминаем, что переменные среды являются специфичными для процесса и извлекаются при запуске процесса. Это может быть полезно для передачи некоторой информации следующему узлу или с использованием ACL для выполнения определённых действий при запуске процесса определённым образом.

Примеры:

# Pass the Via header to next hop with the local hostname in it
http-request add-header Via 1.1\ %[env(HOSTNAME)]

# reject cookie-less requests when the STOP environment variable is set
http-request deny if !{ req.cook(SESSIONID) -m found } { env(STOP) -m found }

fe_conn([<frontend>]): integer

fe_conn([<frontend>]): integer

Возвращает количество текущих установленных соединений на фронтенде, возможно, включая соединение, которое оценивается. Если имя фронтенда не указано, используется текущий. Также возможно проверить другой фронтенд. Может использоваться для возврата страницы с извинением перед жёсткой блокировкой или для использования определённого бэкенда для отвода новых запросов, когда ферма считается перегруженной. В основном используется с ACL, но также может применяться для передачи некоторых статистических данных серверам в заголовках HTTP. См. также извлечения образцов “dst_conn”, “be_conn”, “fe_sess_rate”.

fe_req_rate([<frontend>]): integer

fe_req_rate([<frontend>]): integer

Возвращает целое значение, соответствующее количеству запросов HTTP в секунду, отправленных на фронтенд. Это число может отличаться от “fe_sess_rate” в ситуациях, когда включено keep-alive на стороне клиента.

fe_sess_rate([<frontend>]): integer

fe_sess_rate([<frontend>]): integer

Возвращает целое значение, соответствующее скорости создания сессий на фронтенде, в количестве новых сессий в секунду. Используется с ACL для ограничения скорости входящих сессий до приемлемого диапазона, чтобы предотвратить злоупотребление сервисом на ранней стадии, например, в сочетании с другими ACL уровня 4 для вынуждения клиентов немного подождать, пока скорость не упадёт ниже порога. Также может быть полезно добавить этот элемент в журналы с помощью директивы log-format. См. также директиву “rate-limit sessions” для использования на фронтендах.

Пример:

# This frontend limits incoming mails to 10/s with a max of 100
# concurrent connections. We accept any connection below 10/s, and
# force excess clients to wait for 100 ms. Since clients are limited to
# 100 max, there cannot be more than 10 incoming mails per second.
frontend mail
    bind :25
    mode tcp
    maxconn 100
    acl too_fast fe_sess_rate ge 10
    tcp-request inspect-delay 100ms
    tcp-request content accept if ! too_fast
    tcp-request content accept if WAIT_END

hostname: string Возвращает имя хоста системы.

int(<integer>): signed integer

int(<integer>): signed integer

Возвращает знаковое целое число.

ipv4(<ipv4>): ipv4

ipv4(<ipv4>): ipv4

Возвращает IPv4.

ipv6(<ipv6>): ipv6

ipv6(<ipv6>): ipv6

Возвращает IPv6.

last_entity: string Возвращает идентификатор последней сущности, которая была оценена во время анализа потока. Это может быть завершающее правило, которое совпало, или фильтр, прервавший обработку.

Завершающее правило — это правило, завершающее оценку набора правил (например, “accept”, “deny” или “redirect”). Работает для правил запроса и ответа TCP, действующих на наборах правил “content”, а также для правил HTTP из наборов правил “http-request”, “http-response” и “http-after-response”. Устаревшие наборы правил “redirect” не поддерживаются (такая информация там не хранится), а также не поддерживаются наборы правил “tcp-request connection” и “tcp-request session”, поскольку информация хранится на уровне потока, а потоки ещё не существуют во время выполнения этих правил. В этом случае возвращаемое значение эквивалентно “last_rule_file:last_rule_line”. См. также “last_rule_file”, “last_rule_line”.

Для фильтра возвращается его идентификатор, определённый разработчиками. Если идентификатор не определён, возвращается шестнадцатеричное значение, соответствующее уникальному внутреннему идентификатору.

Основная цель этой функции — возможность указывать в журналах последнюю сущность, прервавшую обработку, для упрощения отладки проблем. Информация о сущностях может меняться со временем и не должна использоваться для других целей, кроме отладки.

Пример:

# Log the last entity, if any, and only if an error is reported
log-format "$HAPROXY_HTTP_LOG_FMT %{Q}[last_entity,when(error)]

last_rule_file: string Возвращает имя конфигурационного файла, содержащего последнее завершающее правило, сработавшее при анализе потока. Завершающее правило — это правило, завершающее оценку набора правил (например, “accept”, “deny” или “redirect”). Работает для правил запроса и ответа TCP, действующих на наборах правил “content”, а также для правил HTTP из наборов правил “http-request”, “http-response” и “http-after-response”. Устаревшие наборы правил “redirect” не поддерживаются (такая информация там не хранится), а также не поддерживаются наборы правил “tcp-request connection” и “tcp-request session”, поскольку информация хранится на уровне потока, а потоки ещё не существуют во время выполнения этих правил. Основная цель этой функции — возможность указывать в журналах, где находилось правило, вынесшее окончательное решение, чтобы помочь понять, почему запрос был отклонён, например. См. также “last_rule_line”.

last_rule_line: integer Возвращает номер строки в конфигурационном файле, где находится последнее завершающее правило, сработавшее при анализе потока. Завершающее правило — это правило, завершающее оценку набора правил (например, “accept”, “deny” или “redirect”). Работает для правил запроса и ответа TCP, действующих на наборах правил “content”, а также для правил HTTP из наборов правил “http-request”, “http-response” и “http-after-response”. Устаревшие наборы правил “redirect” не поддерживаются (такая информация там не хранится), а также не поддерживаются наборы правил “tcp-request connection” и “tcp-request session”, поскольку информация хранится на уровне потока, а потоки ещё не существуют во время выполнения этих правил. Основная цель этой функции — возможность указывать в журналах, где находилось правило, вынесшее окончательное решение, чтобы помочь понять, почему запрос был отклонён, например. См. также “last_rule_file”.

lat_ns_avg: integer Возвращает среднее количество наносекунд, затраченных между моментом пробуждения задачи, обрабатывающей поток, и моментом её фактического вызова. Это значение сбрасывается для каждого нового запроса на одном и том же соединении при HTTP keep-alive. Это значение указывает общую задержку, накладываемую на текущий запрос всеми другими запросами, обрабатываемыми параллельно, и является прямым индикатором воспринимаемой производительности из-за “шумных соседей”. Чтобы сохранить значение низким, можно уменьшить глубину очереди выполнения планировщика с помощью “tune.runqueue-depth”, сократить количество одновременно обрабатываемых событий с помощью “tune.maxpollevents”, уменьшить значение nice потока с помощью опции “nice” в строках bind или в фронтенде, включить планирование с низкой задержкой с помощью “tune.sched.low-latency” или искать другие тяжёлые запросы в журналах (те, у которых большое значение “cpu_ns_avg”), обработку которых необходимо скорректировать или исправить. Сжатие больших буферов может быть причиной, как и сложные регулярные выражения или длинные списки регулярных выражений. Примечание: это значение точно равно lat_ns_tot делённому на cpu_calls.

lat_ns_tot: integer Возвращает общее количество наносекунд, затраченных между моментом пробуждения задачи, обрабатывающей поток, и моментом её фактического вызова. Это значение сбрасывается для каждого нового запроса на одном и том же соединении при HTTP keep-alive. Это значение указывает общую задержку, накладываемую на текущий запрос всеми другими запросами, обрабатываемыми параллельно, и является прямым индикатором воспринимаемой производительности из-за “шумных соседей”. Чтобы сохранить значение низким, можно уменьшить глубину очереди выполнения планировщика с помощью “tune.runqueue-depth”, сократить количество одновременно обрабатываемых событий с помощью “tune.maxpollevents”, уменьшить значение nice потока с помощью опции “nice” в строках bind или в фронтенде, включить планирование с низкой задержкой с помощью “tune.sched.low-latency” или искать другие тяжёлые запросы в журналах (те, у которых большое значение “cpu_ns_avg”), обработку которых необходимо скорректировать или исправить. Сжатие больших буферов может быть причиной, как и сложные регулярные выражения или длинные списки регулярных выражений. Примечание: хотя может показаться интуитивно, что общая задержка складывается с временем передачи, это почти никогда не так, потому что пока задача ждёт CPU, сетевые буферы продолжают заполняться, и следующий вызов будет обрабатывать больше данных сразу. Значение может быть искусственно высоким из-за большого количества cpu_calls, например, при обработке множества фрагментов HTTP, поэтому часто предпочтительнее логировать lat_ns_avg, который является более релевантным показателем производительности.

meth(<method>): method

meth(<method>): method

Возвращает метод.

nbsrv([<backend>]): integer

nbsrv([<backend>]): integer

Возвращает целое значение, соответствующее количеству доступных серверов либо текущего бэкенда, либо указанного бэкенда. В основном используется с ACL, но также может быть полезно при добавлении в журналы. Обычно используется для переключения на альтернативный бэкенд, когда количество серверов слишком мало для обработки нагрузки. Полезно использовать для сообщения об ошибке в сочетании с “monitor fail”.

pid: integer Возвращает PID текущего процесса. В большинстве случаев это PID рабочего процесса.

prio_class: integer Возвращает класс приоритета текущего потока в режиме HTTP или соединения в режиме TCP. Значение будет тем, что установлено последним вызовом “http-request set-priority-class” или “tcp-request content set-priority-class”.

prio_offset: integer Возвращает смещение приоритета текущего потока в режиме HTTP или соединения в режиме TCP. Значение будет тем, что установлено последним вызовом “http-request set-priority-offset” или “tcp-request content set-priority-offset”.

proc: integer Всегда возвращает значение 1 (исторически оно возвращало номер вызывающего процесса).

queue([<backend>]): integer

queue([<backend>]): integer

Возвращает общее количество соединений в очередях указанного бэкенда, включая все соединения в очередях серверов. Если имя бэкенда не указано, используется текущий, но также возможно проверить другой. Полезно с ACL или для передачи статистики серверам бэкенда. Может использоваться для принятия действий при превышении известного уровня очереди, как правило, указывающего на всплеск трафика или значительное замедление на серверах. Одним из возможных действий может быть отклонение новых пользователей, но при этом принимаются старые. См. также извлечения образцов “avg_queue”, “be_conn” и “be_sess_rate”.

quic_enabled: boolean Возвращает true, если поддержка транспортного протокола QUIC была скомпилирована и если слушатели QUIC не отключены глобальным параметром “tune.quic.listen”. См. также глобальный параметр “tune.quic.listen”.

rand([<range>]): integer

rand([<range>]): integer

Возвращает случайное целое число в диапазоне из <range> возможных значений, начиная с нуля. Если диапазон не указан, по умолчанию используется 2^32, что даёт числа от 0 до 4294967295. Может быть полезно для передачи некоторых значений, необходимых для принятия решений о маршрутизации, например, или просто для отладки. Этот случайный выбор не должен использоваться в целях безопасности.

srv_conn([<backend>/]<server>): integer

srv_conn([<backend>/]<server>): integer

Возвращает целое значение, соответствующее количеству установленных соединений на указанном сервере, включая, возможно, оцениваемое соединение. Если <backend> опущен, сервер ищется в текущем бэкенде. Может использоваться для выбора конкретной фермы при заполнении одного сервера или для информирования сервера о нашем представлении количества активных соединений с ним. См. также методы извлечения “fe_conn”, “be_conn”, “queue” и “srv_conn_free”.

srv_conn_free([<backend>/]<server>): integer

srv_conn_free([<backend>/]<server>): integer

Возвращает целое значение, соответствующее количеству доступных соединений на указанном сервере, включая, возможно, оцениваемое соединение. Значение не включает места в очереди. Если <backend> опущен, сервер ищется в текущем бэкенде. Может использоваться для выбора конкретной фермы при заполнении одного сервера или для информирования сервера о нашем представлении количества активных соединений с ним. См. также методы извлечения “be_conn_free” и “srv_conn”.

ДРУГИЕ ОГОВОРКИ И ПРИМЕЧАНИЯ: если maxconn сервера равно 0, то данное извлечение образца явно не имеет смысла, в таком случае возвращаемое значение будет -1.

srv_is_up([<backend>/]<server>): boolean

srv_is_up([<backend>/]<server>): boolean

Возвращает true, если указанный сервер находится в состоянии UP, и false — если он находится в состоянии DOWN или в режиме обслуживания. Если <backend> опущен, сервер ищется в текущем бэкенде. Используется в основном для принятия решений на основе внешнего статуса, сообщённого через проверку работоспособности (например, доступность географического сайта). Другое возможное применение, которое скорее является обходным приёмом, заключается в использовании фиктивных серверов как логических переменных, которые могут быть включены или выключены через CLI, чтобы правила, зависящие от таких ACL, можно было настраивать в реальном времени.

srv_iweight([<backend>/]<server>): integer

srv_iweight([<backend>/]<server>): integer

Возвращает целое значение, соответствующее начальному весу сервера. Если <backend> опущен, сервер ищется в текущем бэкенде. См. также “srv_weight” и “srv_uweight”.

srv_queue([<backend>/]<server>): integer

srv_queue([<backend>/]<server>): integer

Возвращает целое значение, соответствующее количеству соединений, ожидающих в очереди на указанном сервере. Если <backend> опущен, сервер ищется в текущем бэкенде. Иногда может использоваться совместно с директивой “use-server” для принудительного использования заведомо более быстрого сервера при небольшой загрузке. См. также методы извлечения образца “srv_conn”, “avg_queue” и “queue”.

srv_sess_rate([<backend>/]<server>): integer

srv_sess_rate([<backend>/]<server>): integer

Возвращает целое значение, соответствующее интенсивности создания сессий на указанном сервере, в количестве новых сессий в секунду. Если <backend> опущен, сервер ищется в текущем бэкенде. В основном используется с ACL, но может быть полезно и при ведении журнала. Используется для переключения на альтернативный бэкенд когда дорогостоящий или уязвимый бэкенд достигает слишком высокой интенсивности создания сессий, либо для ограничения злоупотребления сервисом (например, предотвращение перегрузки серверов из-за латентных запросов).

Пример:

# Redirect to a separate back
acl srv1_full srv_sess_rate(be1/srv1) gt 50
acl srv2_full srv_sess_rate(be1/srv2) gt 50
use_backend be2 if srv1_full or srv2_full

srv_uweight([<backend>/]<server>): integer

srv_uweight([<backend>/]<server>): integer

Возвращает целое значение, соответствующее видимому пользователю весу сервера. Если <backend> опущен, сервер ищется в текущем бэкенде. См. также “srv_weight” и “srv_iweight”.

srv_weight([<backend>/]<server>): integer

srv_weight([<backend>/]<server>): integer

Возвращает целое значение, соответствующее текущему (или эффективному) весу сервера. Если <backend> опущен, сервер ищется в текущем бэкенде. См. также “srv_iweight” и “srv_uweight”.

stopping: boolean Возвращает TRUE, если процесс, вызывающий функцию, в настоящее время останавливается. Это может быть полезно для ведения журнала или для смягчения определённых проверок или помощи при закрытии соединений во время мягкой остановки.

str(<string>): string

str(<string>): string

Возвращает строку.

table_avl([<table>]): integer

table_avl([<table>]): integer

Возвращает общее количество доступных записей в таблице привязок текущего прокси или в указанной таблице привязок. См. также “table_cnt”.

table_cnt([<table>]): integer

table_cnt([<table>]): integer

Возвращает общее количество записей, используемых в настоящий момент в таблице привязок текущего прокси или в указанной таблице привязок. См. также “table_conn_cnt” и table_avl для других методов подсчёта записей.

term_events: string Возвращает все известные события завершения для всех сущностей, привязанных к потоку, на стороне клиента и сервера. Возвращается кортеж из семи элементов со следующей информацией:

- события завершения соединения фронтенда
- события завершения соединения мультиплексора фронтенда
- события завершения дескриптора конечной точки потока фронтенда
  (поток мультиплексора или апплет)
- события завершения потока
- события завершения дескриптора конечной точки потока бэкенда
  (поток мультиплексора или апплет)
- события завершения соединения мультиплексора бэкенда
- события завершения соединения бэкенда

На каждом уровне возвращаются первые четыре события. Если событие ещё не было зарегистрировано для конкретного уровня, возвращается пустая строка. Если события завершения не поддерживаются, возвращается “-”.

Должно использоваться только в целях отладки. Точный формат не документирован, так как может меняться в зависимости от требований разработчиков.

tgroup: integer Возвращает целое значение, соответствующее позиции группы потоков, вызывающего функцию, в диапазоне от 0 до (global.thread-groups - 1). Полезно для ведения журнала и отладки.

thread: integer Возвращает целое значение, соответствующее позиции потока, вызывающего функцию, в диапазоне от 0 до (global.nbthread-1). Полезно для ведения журнала и отладки.

txn.id32: integer Возвращает внутренний идентификатор транзакции. Это 32-битное целое число. Таким образом, его значение не абсолютно уникально, идентификаторы транзакций могут переполняться. Период переполнения зависит от интенсивности запросов. На практике это обычно не должно создавать проблем. Для получения истинно уникального идентификатора см. директиву “unique-id-format”.

txn.sess_term_state: string Возвращает состояние завершения потока TCP или HTTP, указанное в журнале. Это строка из 2 символов: конечное состояние потока, за которым следует событие, вызвавшее его завершение. Список возможных событий при разрыве соединения приведён в разделе 8.5 . Возвращается текущее значение на момент извлечения образца; оно может измениться. Кроме случаев использования с ACL в наборах правил “http-after-response” или в сообщениях журнала, значение всегда равно “–”.

Пример:

# Return a 429-Too-Many-Requests if stream timed out in queue
http-after-response set-status 429 if { txn.sess_term_state  "sQ" }

uptime: integer Возвращает время работы текущего рабочего процесса HAProxy в секундах.

uuid([<version>]): string

uuid([<version>]): string

Возвращает UUID в соответствии со стандартом RFC 9562. Если версия не указана, возвращается UUID версии 4 (полностью случайный).

Поддерживаются версии 4 и 7.

var(<var-name>[,<default>]): undefined

var(<var-name>[,<default>]): undefined

Возвращает переменную с сохранённым типом. Если переменная не задана, извлечение образца завершается неудачей, кроме случая, когда указано значение по умолчанию: тогда оно возвращается как строка. Допускаются пустые строки. Подробнее о переменных см. в разделе 2.8 .

dump_all_vars([<scope>][,<prefix>][,<delimiter>]): string

dump_all_vars([<scope>][,<prefix>][,<delimiter>]): string

Возвращает список всех переменных в указанной области видимости, с необязательной фильтрацией по префиксу имени и настраиваемым разделителем.

Формат вывода: var1=value1<delim>var2=value2<delim>…

Кодирование значений по типу:

  • Строки: заключаются в кавычки и экранируются (", \, \r, \n, \b, \0) Пример: txn.name=“John \“Doe\””
  • Бинарные данные: закодированы в шестнадцатеричном виде с префиксом ‘x’, без кавычек. Пример: txn.data=x48656c6c6f
  • Целые числа: без кавычек, десятичные. Пример: txn.count=42
  • Логические значения: без кавычек, “true” или “false”. Пример: txn.active=true
  • Адреса: без кавычек, строка IP-адреса. Пример: txn.client=192.168.1.1
  • Методы HTTP: заключённая в кавычки строка. Пример: req.method=“GET”

Аргументы:

  • <scope> (необязательно): sess, txn, req, res или proc. Если опущено, все эти области просматриваются в том же порядке, что и здесь.

  • <prefix> (необязательно): фильтрует переменные, имена которых начинаются с указанного префикса (после удаления префикса области). Примечание по производительности: при использовании фильтрации по префиксу все переменные в области всё равно просматриваются. Не следует использовать с конфигурациями, содержащими тысячи переменных.

  • <delimiter> (необязательно): строка-разделитель переменных. По умолчанию — “, " (запятая с пробелом). Может быть настроена на любую строку. Напоминание: для передачи запятых или пробелов в аргументе функции их необходимо заключить в одинарные или двойные кавычки (если выражение уже находится в кавычках, используйте другие).

Возвращаемое значение:

  • При успехе: строка, содержащая все подходящие переменные
  • При неудаче: пусто (извлечение образца завершается неудачей), если буфер вывода слишком мал. Функция не усекает вывод; она целиком завершается неудачей, чтобы не возвращать неполные данные.

Это особенно полезно для отладки, ведения журнала или экспорта состояний переменных.

Примеры:

# Dump all transaction variables
http-request return string %[dump_all_vars(txn)]

# Dump only variables starting with "user"
http-request set-header X-User-Vars "%[dump_all_vars(txn,user)]"

# Dump all process variables
http-request return string %[dump_all_vars(proc)]

# Custom delimiter (semicolon)
http-request set-header X-Vars "%[dump_all_vars(txn,,; )]"

# Force the default delimiter (comma space)
http-request set-header X-Vars "%[dump_all_vars(txn,,', ')]"

# Prefix filter with custom delimiter
http-request set-header X-Session "%[dump_all_vars(sess,user,|)]"

wait_end: boolean Это извлечение либо возвращает true, когда период проверки завершён, либо не возвращает образец. Используется только в ACL, в сочетании с анализом содержимого для предотвращения преждевременного принятия неверного решения. Может также использоваться для откладывания некоторых действий, например, задержанного отказа для определённых адресов. Поскольку оно либо останавливает оценку правил, либо немедленно возвращает true, рекомендуется использовать этот ACL последним в правиле. Обратите внимание, что предопределённый ACL “WAIT_END” всегда доступно без предварительного объявления. Этот тест был разработан для использования с анализом содержимого запроса TCP.

Примеры:

# delay every incoming request by 2 seconds
tcp-request inspect-delay 2s
tcp-request content accept if WAIT_END

# don't immediately tell bad guys they are rejected
tcp-request inspect-delay 10s
acl goodguys src 10.0.0.0/24
acl badguys  src 10.0.1.0/24
tcp-request content accept if goodguys
tcp-request content reject if badguys WAIT_END
tcp-request content reject

waiting_entity: string Возвращает идентификатор сущности, которая ожидала продолжения обработки при возникновении ошибки или тайм-аута. Это может быть правило или фильтр, например. Однако этот список не является исчерпывающим, и формат всех возможных сущностей не обязательно документирован.

Когда сущность — правило, возвращается её расположение. Это имя конфигурационного файла, содержащего правило, за которым следует номер строки, где определено это правило, разделённые двоеточием.

Для фильтра возвращается его идентификатор, определённый разработчиками. Если идентификатор не определён, возвращается шестнадцатеричное значение, соответствующее уникальному внутреннему идентификатору.

Основная цель этой функции — возможность указать в журнале сущность, блокирующую анализ потока при возникновении ошибки или тайм-аута, прервавших обработку, для упрощения отладки. Информация о сущностях может изменяться со временем и не должна использоваться для других целей, кроме отладки.

Пример:

# Log the waiting entity, if any, and only if an error is reported
log-format "$HAPROXY_HTTP_LOG_FMT %{Q}[waiting_entity,when(error)]

7.3.3. Извлечение образцов на уровне 4

Уровень 4 обычно описывает только транспортный уровень, который в HAProxy ближе всего к соединению, где ещё не доступны данные содержимого. Методы извлечения образцов, описанные здесь, применимы на уровне “tcp-request connection”, если они не требуют будущей информации. Обычно это TCP/IP-адреса и порты, а также элементы таблицы привязок, связанные с входящим соединением. Для получения значения из счётчика привязки номер счётчика может быть явно задан как 0, 1 или 2 с использованием предопределённых префиксов “sc0_”, “sc1_” или “sc2_”. Эти три предопределённых префикса можно использовать только при условии, что глобальное значение “tune.stick-counters” не превышает 3; в противном случае номер счётчика может быть указан как первый целочисленный аргумент при использовании префикса “sc_” от “sc_0” до “sc_N”, где N — (tune.stick-counters-1). Необязательно можно указать таблицу в формате “sc*”, в этом случае ключ, отслеживаемый в данный момент, будет искаться в альтернативной таблице вместо текущей отслеживаемой таблицы.

Сводка методов извлечения образцов в этом разделе и их соответствующие типы:

  Ключевое слово                                   Выходной тип
-------------------------------------------------+-------------
accept_date([<unit>])                              integer
bc.timer.connect                                   integer
bc_be_queue                                        integer
bc_dst                                             ip
bc_dst_port                                        integer
bc_err                                             integer
bc_err_name                                        string
bc_err_str                                         string
bc_glitches                                        integer
bc_http_major                                      integer
bc_nb_streams                                      integer
bc_reused                                          boolean
bc_rtt(<unit>)                                     integer
bc_rttvar(<unit>)                                  integer
bc_settings_streams_limit                          integer
bc_src                                             ip
bc_src_port                                        integer
bc_srv_queue                                       integer
be_id                                              integer
be_name                                            string
be_connect_timeout                                 integer
be_queue_timeout                                   integer
be_server_timeout                                  integer
be_tarpit_timeout                                  integer
be_tunnel_timeout                                  integer
bytes_in                                           integer
bytes_out                                          integer
cur_connect_timeout                                integer
cur_client_timeout                                 integer
cur_queue_timeout                                  integer
cur_server_timeout                                 integer
cur_tarpit_timeout                                 integer
cur_tunnel_timeout                                 integer
dst                                                ip
dst_conn                                           integer
dst_is_local                                       boolean
dst_port                                           integer
fc.timer.handshake                                 integer
fc.timer.total                                     integer
fc_dst                                             ip
fc_dst_is_local                                    boolean
fc_dst_port                                        integer
fc_err                                             integer
fc_err_name                                        string
fc_err_str                                         string
fc_fackets                                         integer
fc_glitches                                        integer
fc_http_major                                      integer
fc_lost                                            integer
fc_nb_streams                                      integer
fc_pp_authority                                    string
fc_pp_tlv(<id>)                                    string
fc_pp_unique_id                                    string
fc_rcvd_proxy                                      boolean
fc_reordering                                      integer
fc_retrans                                         integer
fc_rtt(<unit>)                                     integer
fc_rttvar(<unit>)                                  integer
fc_sacked                                          integer
fc_saved_syn                                       binary
fc_settings_streams_limit                          integer
fc_src                                             ip
fc_src_is_local                                    boolean
fc_src_port                                        integer
fc_unacked                                         integer
fe_tarpit_timeout                                  integer
fe_client_timeout                                  integer
fe_defbe                                           string
fe_id                                              integer
fe_name                                            string
req.bytes_in                                       integer
req.bytes_out                                      integer
res.bytes_in                                       integer
res.bytes_out                                      integer
res.timer.data                                     integer
sc0_bytes_in_rate([<table>])                       integer
sc0_bytes_out_rate([<table>])                      integer
sc0_clr_gpc0([<table>])                            integer
sc0_clr_gpc1([<table>])                            integer
sc0_conn_cnt([<table>])                            integer
sc0_conn_cur([<table>])                            integer
sc0_conn_rate([<table>])                           integer
sc0_get_gpc0([<table>])                            integer
sc0_get_gpc1([<table>])                            integer
sc0_get_gpt0([<table>])                            integer
sc0_glitch_cnt([<table>])                          integer
sc0_glitch_rate([<table>])                         integer
sc0_gpc0_rate([<table>])                           integer
sc0_gpc1_rate([<table>])                           integer
sc0_http_err_cnt([<table>])                        integer
sc0_http_err_rate([<table>])                       integer
sc0_http_fail_cnt([<table>])                       integer
sc0_http_fail_rate([<table>])                      integer
sc0_http_req_cnt([<table>])                        integer
sc0_http_req_rate([<table>])                       integer
sc0_inc_gpc0([<table>])                            integer
sc0_inc_gpc1([<table>])                            integer
sc0_kbytes_in([<table>])                           integer
sc0_kbytes_out([<table>])                          integer
sc0_key                                            any
sc0_sess_cnt([<table>])                            integer
sc0_sess_rate([<table>])                           integer
sc0_tracked([<table>])                             boolean
sc0_trackers([<table>])                            integer
sc1_bytes_in_rate([<table>])                       integer
sc1_bytes_out_rate([<table>])                      integer
sc1_clr_gpc0([<table>])                            integer
sc1_clr_gpc1([<table>])                            integer
sc1_conn_cnt([<table>])                            integer
sc1_conn_cur([<table>])                            integer
sc1_conn_rate([<table>])                           integer
sc1_get_gpc0([<table>])                            integer
sc1_get_gpc1([<table>])                            integer
sc1_get_gpt0([<table>])                            integer
sc1_glitch_cnt([<table>])                          integer
sc1_glitch_rate([<table>])                         integer
sc1_gpc0_rate([<table>])                           integer
sc1_gpc1_rate([<table>])                           integer
sc1_http_err_cnt([<table>])                        integer
sc1_http_err_rate([<table>])                       integer
sc1_http_fail_cnt([<table>])                       integer
sc1_http_fail_rate([<table>])                      integer
sc1_http_req_cnt([<table>])                        integer
sc1_http_req_rate([<table>])                       integer
sc1_inc_gpc0([<table>])                            integer
sc1_inc_gpc1([<table>])                            integer
sc1_kbytes_in([<table>])                           integer
sc1_kbytes_out([<table>])                          integer
sc1_key                                            any
sc1_sess_cnt([<table>])                            integer
sc1_sess_rate([<table>])                           integer
sc1_tracked([<table>])                             boolean
sc1_trackers([<table>])                            integer
sc2_bytes_in_rate([<table>])                       integer
sc2_bytes_out_rate([<table>])                      integer
sc2_clr_gpc0([<table>])                            integer
sc2_clr_gpc1([<table>])                            integer
sc2_conn_cnt([<table>])                            integer
sc2_conn_cur([<table>])                            integer
sc2_conn_rate([<table>])                           integer
sc2_get_gpc0([<table>])                            integer
sc2_get_gpc1([<table>])                            integer
sc2_get_gpt0([<table>])                            integer
sc2_glitch_cnt([<table>])                          integer
sc2_glitch_rate([<table>])                         integer
sc2_gpc0_rate([<table>])                           integer
sc2_gpc1_rate([<table>])                           integer
sc2_http_err_cnt([<table>])                        integer
sc2_http_err_rate([<table>])                       integer
sc2_http_fail_cnt([<table>])                       integer
sc2_http_fail_rate([<table>])                      integer
sc2_http_req_cnt([<table>])                        integer
sc2_http_req_rate([<table>])                       integer
sc2_inc_gpc0([<table>])                            integer
sc2_inc_gpc1([<table>])                            integer
sc2_kbytes_in([<table>])                           integer
sc2_kbytes_out([<table>])                          integer
sc2_key                                            any
sc2_sess_cnt([<table>])                            integer
sc2_sess_rate([<table>])                           integer
sc2_tracked([<table>])                             boolean
sc2_trackers([<table>])                            integer
sc_bytes_in_rate(<ctr>[,<table>])                  integer
sc_bytes_out_rate(<ctr>[,<table>])                 integer
sc_clr_gpc(<idx>,<ctr>[,<table>])                  integer
sc_clr_gpc0(<ctr>[,<table>])                       integer
sc_clr_gpc1(<ctr>[,<table>])                       integer
sc_conn_cnt(<ctr>[,<table>])                       integer
sc_conn_cur(<ctr>[,<table>])                       integer
sc_conn_rate(<ctr>[,<table>])                      integer
sc_get_gpc(<idx>,<ctr>[,<table>])                  integer
sc_get_gpc0(<ctr>[,<table>])                       integer
sc_get_gpc1(<ctr>[,<table>])                       integer
sc_get_gpt(<idx>,<ctr>[,<table>])                  integer
sc_get_gpt0(<ctr>[,<table>])                       integer
sc_glitch_cnt(<ctr>[,<table>])                     integer
sc_glitch_rate(<ctr>[,<table>])                    integer
sc_gpc0_rate(<ctr>[,<table>])                      integer
sc_gpc1_rate(<ctr>[,<table>])                      integer
sc_gpc_rate(<idx>,<ctr>[,<table>])                 integer
sc_http_err_cnt(<ctr>[,<table>])                   integer
sc_http_err_rate(<ctr>[,<table>])                  integer
sc_http_fail_cnt(<ctr>[,<table>])                  integer
sc_http_fail_rate(<ctr>[,<table>])                 integer
sc_http_req_cnt(<ctr>[,<table>])                   integer
sc_http_req_rate(<ctr>[,<table>])                  integer
sc_inc_gpc(<idx>,<ctr>[,<table>])                  integer
sc_inc_gpc0(<ctr>[,<table>])                       integer
sc_inc_gpc1(<ctr>[,<table>])                       integer
sc_kbytes_in(<ctr>[,<table>])                      integer
sc_kbytes_out(<ctr>[,<table>])                     integer
sc_key(<ctr>)                                      any
sc_sess_cnt(<ctr>[,<table>])                       integer
sc_sess_rate(<ctr>[,<table>])                      integer
sc_tracked(<ctr>[,<table>])                        boolean
sc_trackers(<ctr>[,<table>])                       integer
so_id                                              integer
so_name                                            string
src                                                ip
src_bytes_in_rate([<table>])                       integer
src_bytes_out_rate([<table>])                      integer
src_clr_gpc(<idx>[,<table>])                       integer
src_clr_gpc0([<table>])                            integer
src_clr_gpc1([<table>])                            integer
src_conn_cnt([<table>])                            integer
src_conn_cur([<table>])                            integer
src_conn_rate([<table>])                           integer
src_get_gpc(<idx>[,<table>])                       integer
src_get_gpc0([<table>])                            integer
src_get_gpc1([<table>])                            integer
src_get_gpt(<idx>[,<table>])                       integer
src_get_gpt0([<table>])                            integer
src_glitch_cnt([<table>])                          integer
src_glitch_rate([<table>])                         integer
src_gpc0_rate([<table>])                           integer
src_gpc1_rate([<table>])                           integer
src_gpc_rate(<idx>[,<table>])                      integer
src_http_err_cnt([<table>])                        integer
src_http_err_rate([<table>])                       integer
src_http_fail_cnt([<table>])                       integer
src_http_fail_rate([<table>])                      integer
src_http_req_cnt([<table>])                        integer
src_http_req_rate([<table>])                       integer
src_inc_gpc(<idx>[,<table>])                       integer
src_inc_gpc0([<table>])                            integer
src_inc_gpc1([<table>])                            integer
src_is_local                                       boolean
src_kbytes_in([<table>])                           integer
src_kbytes_out([<table>])                          integer
src_port                                           integer
src_sess_cnt([<table>])                            integer
src_sess_rate([<table>])                           integer
src_updt_conn_cnt([<table>])                       integer
srv_id                                             integer
srv_name                                           string
txn.conn_retries                                   integer
txn.redispatched                                   boolean
-------------------------------------------------+-------------

Подробный список:

accept_date([<unit>]): integer

accept_date([<unit>]): integer

Точная дата получения соединения HAProxy (которая может незначительно отличаться от даты, зафиксированной на сетевом уровне, если соединение ожидало в очереди входящих соединений системы). Обычно это та же дата, которая может появляться в журнале любого промежуточного брандмауэра. При использовании в режиме HTTP поле accept_date будет сброшено на первый момент готовности соединения к получению нового запроса (конец предыдущего ответа для HTTP/1, сразу после предыдущего запроса для HTTP/2).

Возвращает значение в секундах с эпохи.

<unit> необязателен и может быть установлен в “s” для секунд (поведение по умолчанию), “ms” для миллисекунд или “us” для микросекунд. Если указана единица измерения, возвращаемое значение — целое число, отражающее количество секунд, миллисекунд или микросекунд с эпохи. Полезно, когда требуется разрешение времени менее одной секунды.

bc.timer.connect: integer Полное время установления соединения TCP с сервером. Соответствует %Tc в log-format и выражается в миллисекундах (ms). Подробнее см. раздел 8.4 «Временные события».

bc_be_queue: integer Число потоков, извлечённых из очереди, пока поток ожидал свободного места для соединения с целевым бэкендом. Эквивалентно %bq в log-format.

bc_dst: ip IP-адрес назначения соединения на стороне сервера: адрес сервера, к которому подключился HAProxy. Имеет тип IP и работает с таблицами IPv4 и IPv6. В таблицах IPv6 адрес IPv4 отображается в соответствующий адрес IPv6 согласно RFC 4291.

bc_dst_port: integer Возвращает целочисленное значение порта назначения TCP для соединения на стороне сервера: порта, к которому подключился HAProxy.

bc_err: integer Возвращает ID ошибки, которая могла возникнуть в текущем соединении с бэкендом. Полный список кодов ошибок и соответствующих сообщений приведён в описании метода извлечения “fc_err_str”.

bc_err_name: string Возвращает внутреннее имя ошибки, описывающей проблему в соединении с бэкендом, которая привела к сбою соединения. Строка состоит из одного слова и пуста, если ошибки нет. Соответствует столбцу “name” таблицы в описании ключевого слова “fc_err_str”.

bc_err_str: string Возвращает сообщение об ошибке, описывающее проблему в текущем соединении с бэкендом, которая привела к сбою соединения. Полный список кодов ошибок и соответствующих сообщений приведён в описании метода извлечения “fc_err_str”.

bc_glitches: integer Возвращает число протокольных сбоев, зарегистрированных в соединении с бэкендом. Обычно это нарушения протокола и мелкие аномалии, указывающие на неисправный сервер или сервер с некорректным поведением, который может создавать проблемы в инфраструктуре (например, вызывать преждевременное прекращение соединений или частые повторные согласования TLS). Причиной также могут быть слишком большие ответы, не помещающиеся в одном буфере, что объясняет ошибки HTTP 502. В идеале следует поддерживать это число равным нулю, но обычно допустимо очень малое значение по сравнению с общим числом запросов. Как правило, эти значения не следует считать тревожными (особенно небольшие), хотя резкий скачок может указывать на аномалию. Эту метрику измеряют не все мультиплексоры протоколов; единственный способ получить подробности о событиях — включить трассировку для записи всех обменов.

bc_http_major: integer Возвращает основной номер версии кодирования HTTP в соединении с бэкендом: 1 для HTTP/0.9 — HTTP/1.1 или 2 для HTTP/2. Значение определяется кодированием на линии, а не версией, указанной в заголовке запроса.

bc_nb_streams: integer Возвращает число потоков, открытых в соединении с бэкендом.

bc_reused: boolean Возвращает true, если передача выполнялась через повторно использованное соединение с бэкендом.

bc_rtt(<unit>): integer

bc_rtt(<unit>): integer

Возвращает время приёма-передачи (RTT), измеренное ядром для соединения с бэкендом. Аргумент <unit> необязателен; единица измерения по умолчанию — миллисекунды. <unit> может принимать значение “ms” для миллисекунд или “us” для микросекунд. Если соединение с сервером не установлено, не использует TCP или операционная система не поддерживает TCP_INFO (например, ядра Linux до 2.4), извлечение образца завершается неудачей.

bc_rttvar(<unit>): integer

bc_rttvar(<unit>): integer

Возвращает вариацию времени приёма-передачи (RTT), измеренную ядром для соединения с бэкендом. Аргумент <unit> необязателен; единица измерения по умолчанию — миллисекунды. <unit> может принимать значение “ms” для миллисекунд или “us” для микросекунд. Если соединение с сервером не установлено, не использует TCP или операционная система не поддерживает TCP_INFO (например, ядра Linux до 2.4), извлечение образца завершается неудачей.

bc_settings_streams_limit: integer Возвращает максимальное число потоков, разрешённых в соединении с бэкендом. Для соединений TCP и HTTP/1.1 оно всегда равно 1. Для других протоколов зависит от параметров, согласованных с сервером.

bc_src: ip IP-адрес источника соединения на стороне сервера: адрес, с которого HAProxy подключился к серверу. Имеет тип IP и работает с таблицами IPv4 и IPv6. В таблицах IPv6 адреса IPv4 отображаются в соответствующие адреса IPv6 согласно RFC 4291.

bc_src_port: integer Возвращает целочисленное значение исходного порта TCP для соединения на стороне сервера: порта, с которого подключился HAProxy.

bc_srv_queue: integer Число потоков, извлечённых из очереди, пока поток ожидал свободного места для соединения с целевым сервером. Эквивалентно %sq в log-format.

be_id: integer Возвращает целое число с id текущего бэкенда. Можно использовать во фронтендах при обработке ответов, чтобы определить, какой бэкенд обработал запрос. При использовании во фронтенде, если бэкенд не использовался, возвращает id текущего фронтенда. Также можно использовать в наборе правил tcp-check или http-check.

be_connect_timeout: integer Возвращает настроенное значение тайм-аута подключения для текущего бэкенда в миллисекундах. Этот тайм-аут может быть переопределён правилом “set-timeout”. См. также “cur_connect_timeout”.

be_name: string Возвращает строку с именем текущего бэкенда. Можно использовать во фронтендах при обработке ответов, чтобы определить, какой бэкенд обработал запрос. При использовании во фронтенде, если бэкенд не использовался, возвращает имя текущего фронтенда. Также можно использовать в наборе правил tcp-check или http-check.

be_queue_timeout: integer Возвращает настроенное значение тайм-аута ожидания в очереди для текущего бэкенда в миллисекундах. Этот тайм-аут может быть переопределён правилом “set-timeout”. См. также “cur_queue_timeout”.

be_server_timeout: integer Возвращает настроенное значение тайм-аута сервера для текущего бэкенда в миллисекундах. Этот тайм-аут может быть переопределён правилом “set-timeout”. См. также “cur_server_timeout”.

be_tarpit_timeout: integer Возвращает настроенное значение тайм-аута ожидания в очереди для текущего бэкенда в миллисекундах. Этот тайм-аут может быть переопределён правилом “set-timeout”. См. также “cur_tarpit_timeout”.

be_tunnel_timeout: integer Возвращает настроенное значение тайм-аута туннеля для текущего бэкенда в миллисекундах. Этот тайм-аут может быть переопределён правилом “set-timeout”. См. также “cur_tunnel_timeout”.

bytes_in: integer См. “req.bytes_in”.

bytes_out: integer См. “res.bytes_in”.

cur_connect_timeout: integer Возвращает текущий тайм-аут подключения для потока в миллисекундах. По умолчанию он равен be_connect_timeout, если не применено правило “set-timeout”. См. также “be_connect_timeout”.

cur_client_timeout: integer Возвращает текущий тайм-аут клиента для потока в миллисекундах. По умолчанию он равен fe_client_timeout, если не применено правило “set-timeout”. См. также “fe_client_timeout”.

cur_queue_timeout: integer Возвращает текущий тайм-аут ожидания в очереди для потока в миллисекундах. По умолчанию он равен be_queue_timeout, если не применено правило “set-timeout”. См. также “be_queue_timeout”.

cur_server_timeout: integer Возвращает текущий тайм-аут сервера для потока в миллисекундах. По умолчанию он равен be_server_timeout, если не применено правило “set-timeout”. См. также “be_server_timeout”.

cur_tarpit_timeout: integer Возвращает текущий тайм-аут ловушки соединений (tarpit) для потока в миллисекундах. По умолчанию он равен fe_tarpit_timeout/be_tarpit_timeout, если не применено правило “set-timeout”. См. также “fe_tarpit_timeout” и “be_tarpit_timeout”.

cur_tunnel_timeout: integer Возвращает текущий тайм-аут туннеля для потока в миллисекундах. По умолчанию он равен be_tunnel_timeout, если не применено правило “set-timeout”. См. также “be_tunnel_timeout”.

dst: ip IP-адрес назначения соединения на стороне клиента: адрес, к которому подключился клиент. Этот адрес может изменяться любыми правилами tcp/http. Может быть полезен в прозрачном режиме. Имеет тип IP и работает с таблицами IPv4 и IPv6. В таблицах IPv6 адрес IPv4 отображается в соответствующий адрес IPv6 согласно RFC 4291. Если входящее соединение прошло через преобразование адресов или перенаправление с отслеживанием соединений, возвращается исходный адрес назначения до перенаправления. В системах Linux источник и назначение иногда могут поменяться местами, если задан sysctl nf_conntrack_tcp_loose: запоздалый ответ может вновь открыть соединение, закрытое по тайм-ауту, и поменять представление о том, какая сторона является источником, а какая — назначением.

dst_conn: integer Возвращает целочисленное значение числа установленных соединений на том же сокете, включая проверяемое соединение. Обычно используется с ACL, но может также передаваться серверам в заголовке HTTP или в журналах. Позволяет вернуть страницу с сообщением о недоступности перед жёсткой блокировкой либо использовать определённый бэкенд для обработки новых запросов, когда сокет считается насыщенным. Это позволяет назначать разные пределы разным портам или адресам прослушивания. См. также методы извлечения “fe_conn” и “be_conn”.

dst_is_local: boolean Возвращает true, если адрес назначения входящего соединения принадлежит локальной системе, или false, если адреса в системе нет, то есть соединение перехвачено в прозрачном режиме. Может быть полезен для применения одних правил по умолчанию к пересылаемому трафику, а других — к трафику, направленному на действительный адрес машины. Например, страницу статистики можно выдавать только по этому адресу или локально перенаправлять доступ SSH. Проверка требует нескольких системных вызовов, поэтому лучше выполнять её только один раз на соединение.

dst_port: integer Возвращает целочисленное значение порта назначения TCP для соединения на стороне клиента: порта, к которому подключился клиент. Этот адрес может изменяться любыми правилами tcp/http. Это может использоваться в прозрачном режиме, при назначении динамических портов некоторым клиентам на весь сеанс приложения, для привязки всех пользователей к одному серверу или для передачи серверу порта назначения в заголовке HTTP.

fc.timer.handshake: integer Общее время приёма соединения tcp и выполнения рукопожатий низкоуровневых протоколов. Сейчас это proxy-protocol и SSL. Эквивалентно %Th в log-format. Значение указывается в миллисекундах (ms). Подробнее см. раздел 8.4 «Времена событий».

fc.timer.total: integer Общая длительность потока: от момента его приёма прокси до закрытия обоих концов. Эквивалентно %Tt в log-format. Значение указывается в миллисекундах (ms). Подробнее см. раздел 8.4 «Времена событий».

fc_dst: ip Исходный IP-адрес назначения соединения на стороне клиента. Этот адрес могут изменять только правила “tcp-request connection”. Подробнее см. “dst”.

fc_dst_is_local: boolean Возвращает true, если исходный адрес назначения входящего соединения принадлежит локальной системе, или false, если адреса в системе нет. Подробнее см. “dst_is_local”.

fc_dst_port: integer Возвращает целочисленное значение исходного порта назначения TCP для соединения на стороне клиента. Этот адрес могут изменять только правила “tcp-request connection”. Подробнее см. “dst-port”.

fc_err: integer Возвращает ID ошибки, которая могла возникнуть в текущем соединении. Любое строго положительное значение этого метода извлечения означает, что соединение не удалось и будет выведена запись об ошибке в журнал (см. раздел 8.2.5 ). Полный список кодов ошибок и соответствующих сообщений приведён в описании метода извлечения “fc_err_str”.

fc_err_name: string Возвращает внутреннее имя ошибки, описывающей проблему в соединении с фронтендом, которая привела к сбою соединения. Строка состоит из одного слова и пуста, если ошибки нет. Соответствует столбцу “name” таблицы в описании ключевого слова “fc_err_str”.

fc_err_str: string Возвращает сообщение об ошибке, описывающее проблему в текущем соединении, которая привела к сбою соединения. Эта строка соответствует части “message” формата записи ошибки в журнале (см. раздел 8.2.5 ). Полный список кодов ошибок и соответствующих сообщений приведён ниже:

  +----+------------------+-------------------------------------------------------------------------+
  | ID | имя              | сообщение                                                               |
  +----+------------------+-------------------------------------------------------------------------+
  | 0  | -                | "Success"                                                               |
  | 1  | CONF_FDLIM       | "Reached configured maxconn value"                                      |
  | 2  | PROC_FDLIM       | "Too many sockets on the process"                                       |
  | 3  | SYS_FDLIM        | "Too many sockets on the system"                                        |
  | 4  | SYS_MEMLIM       | "Out of system buffers"                                                 |
  | 5  | NOPROTO          | "Protocol or address family not supported"                              |
  | 6  | SOCK_ERR         | "General socket error"                                                  |
  | 7  | PORT_RANGE       | "Source port range exhausted"                                           |
  | 8  | CANT_BIND        | "Can't bind to source address"                                          |
  | 9  | FREE_PORTS       | "Out of local source ports on the system"                               |
  | 10 | ADDR_INUSE       | "Local source address already in use"                                   |
  | 11 | PRX_EMPTY        | "Connection closed while waiting for PROXY protocol header"             |
  | 12 | PRX_ABORT        | "Connection error while waiting for PROXY protocol header"              |
  | 13 | PRX_TIMEOUT      | "Timeout while waiting for PROXY protocol header"                       |
  | 14 | PRX_TRUNCATED    | "Truncated PROXY protocol header received"                              |
  | 15 | PRX_NOT_HDR      | "Received something which does not look like a PROXY protocol header"   |
  | 16 | PRX_BAD_HDR      | "Received an invalid PROXY protocol header"                             |
  | 17 | PRX_BAD_PROTO    | "Received an unhandled protocol in the PROXY protocol header"           |
  | 18 | CIP_EMPTY        | "Connection closed while waiting for NetScaler Client IP header"        |
  | 19 | CIP_ABORT        | "Connection error while waiting for NetScaler Client IP header"         |
  | 20 | CIP_TIMEOUT      | "Timeout while waiting for a NetScaler Client IP header"                |
  | 21 | CIP_TRUNCATED    | "Truncated NetScaler Client IP header received"                         |
  | 22 | CIP_BAD_MAGIC    | "Received an invalid NetScaler Client IP magic number"                  |
  | 23 | CIP_BAD_PROTO    | "Received an unhandled protocol in the NetScaler Client IP header"      |
  | 24 | SSL_EMPTY        | "Connection closed during SSL handshake"                                |
  | 25 | SSL_ABORT        | "Connection error during SSL handshake"                                 |
  | 26 | SSL_TIMEOUT      | "Timeout during SSL handshake"                                          |
  | 27 | SSL_TOO_MANY     | "Too many SSL connections"                                              |
  | 28 | SSL_NO_MEM       | "Out of memory when initializing an SSL connection"                     |
  | 29 | SSL_RENEG        | "Rejected a client-initiated SSL renegotiation attempt"                 |
  | 30 | SSL_CA_FAIL      | "SSL client CA chain cannot be verified"                                |
  | 31 | SSL_CRT_FAIL     | "SSL client certificate not trusted"                                    |
  | 32 | SSL_MISMATCH     | "Server presented an SSL certificate different from the configured one" |
  | 33 | SSL_MISMATCH_SNI | "Server presented an SSL certificate different from the expected one"   |
  | 34 | SSL_HANDSHAKE    | "SSL handshake failure"                                                 |
  | 35 | SSL_HANDSHAKE_HB | "SSL handshake failure after heartbeat"                                 |
  | 36 | SSL_KILLED_HB    | "Stopped a TLSv1 heartbeat attack (CVE-2014-0160)"                      |
  | 37 | SSL_NO_TARGET    | "Attempt to use SSL on an unknown target (internal error)"              |
  | 38 | SSL_EARLY_FAILED | "Server refused early data"                                             |
  | 39 | SOCKS4_SEND      | "SOCKS4 Proxy write error during handshake"                             |
  | 40 | SOCKS4_RECV      | "SOCKS4 Proxy read error during handshake"                              |
  | 41 | SOCKS4_DENY      | "SOCKS4 Proxy deny the request"                                         |
  | 42 | SOCKS4_ABORT     | "SOCKS4 Proxy handshake aborted by server"                              |
  | 43 | SSL_FATAL        | "SSL fatal error"                                                       |
  | 44 | REVERSE          | "Reverse connect failure"                                               |
  | 45 | POLLERR          | "Poller reported POLLERR"                                               |
  | 46 | EREFUSED         | "ECONNREFUSED returned by OS"                                           |
  | 47 | ERESET           | "ECONNRESET returned by OS"                                             |
  | 48 | EUNREACH         | "ENETUNREACH returned by OS"                                            |
  | 49 | ENOMEM           | "ENOMEM returned by OS"                                                 |
  | 50 | EBADF            | "EBADF returned by OS"                                                  |
  | 51 | EFAULT           | "EFAULT returned by OS"                                                 |
  | 52 | EINVAL           | "EINVAL returned by OS"                                                 |
  | 53 | ENCONN           | "ENCONN returned by OS"                                                 |
  | 54 | ENSOCK           | "ENSOCK returned by OS"                                                 |
  | 55 | ENOBUFS          | "ENOBUFS returned by OS"                                                |
  | 56 | EPIPE            | "EPIPE returned by OS"                                                  |
  +----+------------------+-------------------------------------------------------------------------+

fc_fackets: integer Возвращает счётчик fack, измеренный ядром для соединения с клиентом. Если соединение с сервером не установлено, соединение не использует TCP или операционная система не поддерживает TCP_INFO (например, ядра Linux до 2.4), извлечение образца завершается неудачей.

fc_glitches: integer Возвращает число протокольных сбоев, зарегистрированных в соединении с фронтендом. Обычно это нарушения протокола и мелкие аномалии, указывающие на неисправный клиент или клиент с некорректным поведением, который может создавать проблемы в инфраструктуре: например, излишние ошибки в журналах или множество преждевременно прекращённых соединений, вызывающих частые повторные согласования TLS. Причиной также могут быть слишком большие запросы, не помещающиеся в одном буфере, что объясняет ошибки HTTP 400. В идеале следует поддерживать это число равным нулю, хотя некоторые браузеры, проверяющие границы допустимого поведения протокола, могут время от времени увеличивать его. Как правило, эти значения не следует считать тревожными (особенно небольшие), хотя резкий скачок может указывать на аномалию. Большие значения (сотни или тысячи на соединение либо столько же, сколько запросов) могут указывать на специально созданный клиент, который пытается идентифицировать стек протоколов или атаковать его. Эту метрику измеряют не все мультиплексоры протоколов; единственный способ получить подробности о событиях — включить трассировку для записи всех обменов.

fc_http_major: integer Показывает основной номер версии кодирования HTTP в клиентском соединении: 1 для HTTP/0.9 — HTTP/1.1 или 2 для HTTP/2. Значение определяется кодированием на линии, а не версией, указанной в заголовке запроса.

fc_lost: integer Если соединение не использует ни TCP, ни QUIC, извлечение образца завершается неудачей. Для QUIC возвращает число потерянных пакетов QUIC в соединении с клиентом. Для TCP возвращает счётчик lost, измеренный ядром для соединения с клиентом. Если соединение с сервером не установлено или операционная система не поддерживает TCP_INFO (например, ядра Linux до 2.4), извлечение образца завершается неудачей.

fc_nb_streams: integer Возвращает число потоков, открытых в соединении с фронтендом.

fc_pp_authority: string Возвращает первый TLV authority, отправленный клиентом в заголовке протокола PROXY, если он есть.

fc_pp_tlv(<id>): string

fc_pp_tlv(<id>): string

Возвращает значение TLV для указанного ID TLV. ID должен быть числом от 0 до 255 либо одним из следующих поддерживаемых символьных имён, соответствующих суффиксам констант TLV в спецификации PPv2: “ALPN”: PP2_TYPE_ALPN, “AUTHORITY”: PP2_TYPE_AUTHORITY, “CRC32”: PP2_TYPE_CRC32C, “NETNS”: PP2_TYPE_NETNS, “NOOP: PP2_TYPE_NOOP”, “SSL”: PP2_TYPE_SSL, “SSL_CIPHER”: PP2_SUBTYPE_SSL_CIPHER, “SSL_CN”: PP2_SUBTYPE_SSL_CN, “SSL_KEY_ALG”: PP2_SUBTYPE_SSL_KEY_ALG, “SSL_SIG_ALG”: PP2_SUBTYPE_SSL_SIG_ALG, “SSL_VERSION”: PP2_SUBTYPE_SSL_VERSION, “UNIQUE_ID”: PP2_TYPE_UNIQUE_ID.

Полученное значение должно быть не длиннее 1024 байт. Это ограничение предотвращает потенциальные атаки DoS. Для значений длиной не более 256 байт можно использовать пул памяти. Поэтому для оптимальной производительности следует ограничивать длину отправляемых значений 256 байтами.

В отличие от fc_pp_authority и fc_pp_unique_id, fc_pp_tlv может перебирать все вхождения запрошенного TLV при наличии повторяющихся ID TLV. Порядок перебора соответствует расположению в заголовке протокола PROXY. Однако, как правило, следует избегать опоры на повторяющиеся значения, поскольку TLV обычно считаются уникальными. Повторяющиеся ID TLV обычно указывают на ошибку у отправителя заголовка протокола PROXY.

fc_pp_unique_id: string Возвращает первый TLV unique ID, отправленный клиентом в заголовке протокола PROXY, если он есть.

fc_rcvd_proxy: boolean Возвращает true, если клиент начал соединение с заголовка протокола PROXY.

fc_reordering: integer Если соединение не использует ни TCP, ни QUIC, извлечение образца завершается неудачей. Для QUIC возвращает число пакетов QUIC, пришедших не по порядку, в соединении с клиентом. Для TCP возвращает счётчик reordering, измеренный ядром для соединения с клиентом. Если соединение с сервером не установлено или операционная система не поддерживает TCP_INFO (например, ядра Linux до 2.4), извлечение образца завершается неудачей.

fc_retrans: integer Возвращает счётчик retransmits, измеренный ядром для соединения с клиентом. Если соединение с сервером не установлено, соединение не использует TCP или операционная система не поддерживает TCP_INFO (например, ядра Linux до 2.4), извлечение образца завершается неудачей.

fc_rtt(<unit>): integer

fc_rtt(<unit>): integer

Если соединение не использует ни TCP, ни QUIC, извлечение образца завершается неудачей. Для QUIC возвращает сглаженное время приёма-передачи для соединения с клиентом. Для TCP возвращает время приёма-передачи (RTT), измеренное ядром для соединения с клиентом. Аргумент <unit> необязателен; единица измерения по умолчанию — миллисекунды. <unit> может принимать значение “ms” для миллисекунд или “us” для микросекунд. Если соединение с сервером не установлено или операционная система не поддерживает TCP_INFO (например, ядра Linux до 2.4), извлечение образца завершается неудачей.

fc_rttvar(<unit>): integer

fc_rttvar(<unit>): integer

Если соединение не использует ни TCP, ни QUIC, извлечение образца завершается неудачей. Для QUIC возвращает вариацию сглаженного времени приёма-передачи для соединения с клиентом. Для TCP возвращает вариацию времени приёма-передачи (RTT), измеренную ядром для соединения с клиентом. Аргумент <unit> необязателен; единица измерения по умолчанию — миллисекунды. <unit> может принимать значение “ms” для миллисекунд или “us” для микросекунд. Если соединение с сервером не установлено или операционная система не поддерживает TCP_INFO (например, ядра Linux до 2.4), извлечение образца завершается неудачей.

fc_sacked: integer Возвращает счётчик sacked, измеренный ядром для соединения с клиентом. Если соединение с сервером не установлено, соединение не использует TCP или операционная система не поддерживает TCP_INFO (например, ядра Linux до 2.4), извлечение образца завершается неудачей.

fc_saved_syn: binary Возвращает копию пакета SYN, сохранённого системой во время установления входящего соединения. Требуется параметр “tcp-ss” в строке “bind” и ядро Linux версии не ниже 4.3. При “tcp-ss”, равном 1, присутствуют только заголовки IP и TCP. При “tcp-ss”, равном 2, перед заголовком IP также присутствует заголовок Ethernet; его можно использовать, например, для контроля или записи в журнал адреса MAC источника или VLAN. Сохранение SYN не гарантируется. Например, при использовании SYN cookies пакет SYN не сохраняется, а соединение устанавливается по соответствующему пакету ACK. Кроме того, система не гарантирует сохранение копии после первого чтения. Поэтому настоятельно рекомендуется скопировать её в переменную с областью действия “sess” из правила “tcp-request connection” и для дальнейших операций использовать только эту переменную. На интерфейсе обратной петли система создаёт фиктивный 14-байтовый заголовок ethernet: и адрес источника, и адрес назначения равны нулю, задан только протокол. При отладке удобно преобразовать такие образцы в шестнадцатеричную форму преобразователем “hex”. Пример (ниже поля вручную разделены и снабжены комментариями):

frontend test
    mode http
    bind :::4445 tcp-ss 2
    tcp-request connection set-var(sess.syn) fc_saved_syn
    http-request return status 200 content-type text/plain \
                 lf-string "%[var(sess.syn),hex]\n"

$ curl '0:4445'
000000000000 000000000000 0800 \  # MAC_DST MAC_SRC PROTO=IPv4
4500003C0A65400040063255       \  # IPv4 header, proto=6 (TCP)
7F000001 7F000001              \  # IP_SRC=127.0.0.1 IP_DST=127.0.0.1
E1F2 115D 01AF4E3E 00000000    \  # TCP_SPORT=57842 TCP_DPORT=4445, SEQ
A0 02 FFD7 FE300000            \  # OPT_LEN=20 TCP_FLAGS=SYN WIN=65495
0204FFD70402080A01C2A71A0000000001030307 # MSS=65495, TS, SACK, WSCALE 7

$ curl '[::1]:4445'
000000000000 000000000000 86DD   \ # MAC_DST MAC_SRC PROTO=IPv6
6008018F00280640                 \ # IPv6 header, proto=6 (TCP)
00000000000000000000000000000001 \ # SRC=::1
00000000000000000000000000000001 \ # DST=::1
9758 115D B5511F5D 00000000      \ # TCP_SPORT=38744 TCP_DPORT=4445, SEQ
A0 02 FFC4 00300000              \  # OPT_LEN=20 TCP_FLAGS=SYN WIN=65476
0204FFC40402080A9C231D680000000001030307 # MSS=65476, TS, SACK, WSCALE 7

Преобразователь “bytes()” помогает извлечь из пакета отдельные поля. be2dec() также позволяет читать фрагменты и выводить их как целые числа. Для более точного извлечения см. преобразователи “eth.XXX”.

Пример со входными данными IPv4:

frontend test
    mode http
    bind :4445 tcp-ss 2
    tcp-request connection set-var(sess.syn) fc_saved_syn
    http-request return status 200 content-type text/plain lf-string \
                 "mac_dst=%[var(sess.syn),eth.dst,hex] \
                  mac_src=%[var(sess.syn),eth.src,hex] \
                  proto=%[var(sess.syn),eth.proto,bytes(6),be2hex(,2)] \
                  ipv4h=%[var(sess.syn),eth.data,bytes(0,12),hex] \
                  ipv4_src=%[var(sess.syn),eth.data,ip.src] \
                  ipv4_dst=%[var(sess.syn),eth.data,ip.dst] \
                  tcp_spt=%[var(sess.syn),eth.data,ip.data,tcp.src] \
                  tcp_dpt=%[var(sess.syn),eth.data,ip.data,tcp.dst] \
                  tcp_win=%[var(sess.syn),eth.data,ip.data,tcp.win] \
                  tcp_opt=%[var(sess.syn),eth.data,ip.data,bytes(20),hex]\n"

$ curl '0:4445'
mac_dst=000000000000 mac_src=000000000000 proto=0800 \
ipv4h=4500003CC9B7400040067302 ipv4_src=127.0.0.1 ipv4_dst=127.0.0.1 \
tcp_spt=43970 tcp_dpt=4445 tcp_win=65495 \
tcp_opt=0204FFD70402080A01DC0D410000000001030307

См. также действие “set-var” и преобразователи “be2dec”, “bytes”, “hex”, “eth.XXX”, “ip.XXX” и “tcp.XXX”.

fc_settings_streams_limit: integer Возвращает максимальное число потоков, разрешённых в соединении с фронтендом. Для соединений TCP и HTTP/1.1 оно всегда равно 1. Для других протоколов зависит от параметров, согласованных с клиентом.

fc_src: ip Исходный IP-адрес источника соединения на стороне клиента. Этот адрес могут изменять только правила “tcp-request connection”. Подробнее см. “src”.

fc_src_is_local: boolean Возвращает true, если адрес источника входящего соединения принадлежит локальной системе, или false, если адреса в системе нет. Подробнее см. “src_is_local”.

fc_src_port: integer Возвращает целочисленное значение исходного порта TCP для соединения на стороне клиента. Этот адрес могут изменять только правила “tcp-request connection”. Подробнее см. “src-port”.

fc_unacked: integer Возвращает счётчик unacked, измеренный ядром для соединения с клиентом. Если соединение с сервером не установлено, соединение не использует TCP или операционная система не поддерживает TCP_INFO (например, ядра Linux до 2.4), извлечение образца завершается неудачей.

fe_client_timeout: integer Возвращает настроенное значение тайм-аута клиента для текущего фронтенда в миллисекундах. Этот тайм-аут может быть переопределён правилом “set-timeout”.

fe_defbe: string Возвращает строку с именем бэкенда по умолчанию для фронтенда. Можно использовать во фронтендах, чтобы определить, какой бэкенд будет обрабатывать запросы по умолчанию.

fe_id: integer Возвращает целое число с id текущего фронтенда. Можно использовать в бэкендах, чтобы определить, из какого фронтенда они вызваны, или привязать всех пользователей, пришедших через один фронтенд, к одному серверу.

fe_name: string Возвращает строку с именем текущего фронтенда. Можно использовать в бэкендах, чтобы определить, из какого фронтенда они вызваны, или привязать всех пользователей, пришедших через один фронтенд, к одному серверу.

fe_tarpit_timeout: integer Возвращает настроенное значение тайм-аута ловушки соединений (tarpit) для текущего фронтенда в миллисекундах. Этот тайм-аут может быть переопределён правилом “set-timeout”.

req.bytes_in: integer Возвращает число байт, полученных от клиента. Значение соответствует данным, полученным HAProxy, включая некоторые заголовки и служебные данные внутреннего кодирования. Сжатие запроса не влияет на это значение.

req.bytes_out: integer Возвращает число байт, отправленных серверу. Значение соответствует данным, отправленным HAProxy, включая некоторые заголовки и служебные данные внутреннего кодирования. Сжатие запроса влияет на это значение.

res.bytes_in: integer Возвращает число байт, полученных от сервера. Значение соответствует данным, полученным HAProxy, включая некоторые заголовки и служебные данные внутреннего кодирования. Сжатие ответа не влияет на это значение.

res.bytes_out: integer Возвращает число байт, отправленных клиенту. Значение соответствует данным, отправленным HAProxy, включая некоторые заголовки и служебные данные внутреннего кодирования. Сжатие ответа влияет на это значение.

res.timer.data: integer Общее время передачи тела ответа до отправки клиенту последнего байта. В HTTP отсчёт начинается после последнего заголовка ответа (после Tr). Эквивалентно %Td в log-format; значение указывается в миллисекундах (ms). Подробнее см. раздел 8.4 «Времена событий».

sc_bytes_in_rate(<ctr>[,<table>]): integer

sc_bytes_in_rate(<ctr>[,<table>]): integer
sc0_bytes_in_rate([<table>]): integer
sc1_bytes_in_rate([<table>]): integer
sc2_bytes_in_rate([<table>]): integer

Возвращает среднюю интенсивность передачи байт от клиента к серверу из текущих отслеживаемых счётчиков, измеряемую числом байт за период, настроенный в таблице. См. также “table_bytes_in_rate”.

sc_bytes_out_rate(<ctr>[,<table>]): integer

sc_bytes_out_rate(<ctr>[,<table>]): integer
sc0_bytes_out_rate([<table>]): integer
sc1_bytes_out_rate([<table>]): integer
sc2_bytes_out_rate([<table>]): integer

Возвращает среднюю интенсивность передачи байт от сервера к клиенту из текущих отслеживаемых счётчиков, измеряемую числом байт за период, настроенный в таблице. См. также “table_bytes_out_rate”.

sc_clr_gpc(<idx>,<ctr>[,<table>]): integer

sc_clr_gpc(<idx>,<ctr>[,<table>]): integer

Обнуляет счётчик общего назначения по индексу <idx> массива, связанного с указанным отслеживаемым счётчиком с ID <ctr> из таблицы привязок текущего прокси или указанной таблицы привязок <table>, и возвращает его предыдущее значение. <idx> — целое число от 0 до 99, а <ctr> — целое число от 0 до 2. До первого вызова сохранённое значение равно нулю, поэтому первый вызов всегда возвращает ноль. Этот метод извлечения применяется только к data_type массива ‘gpc’ (а не к устаревшим data_types ‘gpc0’ или ‘gpc1’).

sc_clr_gpc0(<ctr>[,<table>]): integer

sc_clr_gpc0(<ctr>[,<table>]): integer
sc0_clr_gpc0([<table>]): integer
sc1_clr_gpc0([<table>]): integer
sc2_clr_gpc0([<table>]): integer

Обнуляет первый счётчик общего назначения, связанный с текущими отслеживаемыми счётчиками, и возвращает его предыдущее значение. До первого вызова сохранённое значение равно нулю, поэтому первый вызов всегда возвращает ноль. Обычно используется как второй ACL в выражении, чтобы отметить соединение при истинном результате первого ACL:

Пример:

# block if 5 consecutive requests continue to come faster than 10 sess
# per second, and reset the counter as soon as the traffic slows down.
acl abuse sc0_http_req_rate gt 10
acl kill  sc0_inc_gpc0 gt 5
acl save  sc0_clr_gpc0 ge 0
tcp-request connection accept if !abuse save
tcp-request connection reject if abuse kill

sc_clr_gpc1(<ctr>[,<table>]): integer

sc_clr_gpc1(<ctr>[,<table>]): integer
sc0_clr_gpc1([<table>]): integer
sc1_clr_gpc1([<table>]): integer
sc2_clr_gpc1([<table>]): integer

Обнуляет второй счётчик общего назначения, связанный с текущими отслеживаемыми счётчиками, и возвращает его предыдущее значение. До первого вызова сохранённое значение равно нулю, поэтому первый вызов всегда возвращает ноль. Обычно используется как второй ACL в выражении, чтобы отметить соединение при истинном результате первого ACL.

sc_conn_cnt(<ctr>[,<table>]): integer

sc_conn_cnt(<ctr>[,<table>]): integer
sc0_conn_cnt([<table>]): integer
sc1_conn_cnt([<table>]): integer
sc2_conn_cnt([<table>]): integer

Возвращает суммарное число входящих соединений из текущих отслеживаемых счётчиков. См. также “table_conn_cnt”.

sc_conn_cur(<ctr>[,<table>]): integer

sc_conn_cur(<ctr>[,<table>]): integer
sc0_conn_cur([<table>]): integer
sc1_conn_cur([<table>]): integer
sc2_conn_cur([<table>]): integer

Возвращает текущее число одновременных соединений, отслеживающих те же счётчики. Это число автоматически увеличивается при начале отслеживания и уменьшается при его прекращении. См. также “table_conn_cur”.

sc_conn_rate(<ctr>[,<table>]): integer

sc_conn_rate(<ctr>[,<table>]): integer
sc0_conn_rate([<table>]): integer
sc1_conn_rate([<table>]): integer
sc2_conn_rate([<table>]): integer

Возвращает среднюю интенсивность соединений из текущих отслеживаемых счётчиков, измеряемую числом соединений за период, настроенный в таблице. См. также “table_conn_rate”.

sc_get_gpc(<idx>,<ctr>[,<table>]): integer

sc_get_gpc(<idx>,<ctr>[,<table>]): integer

Возвращает значение счётчика общего назначения по индексу <idx> в массиве GPC, связанном с текущим отслеживаемым счётчиком с ID <ctr> из таблицы привязок текущего прокси или указанной таблицы привязок <table>. <idx> — целое число от 0 до 99, а <ctr> — целое число от 0 до 2. Если по этому индексу нет сохранённого gpc, возвращается ноль. Этот метод извлечения применяется только к data_type массива ‘gpc’ (а не к устаревшим data_types ‘gpc0’ или ‘gpc1’). См. также “table_gpc” и “sc_inc_gpc”.

sc_get_gpc0(<ctr>[,<table>]): integer

sc_get_gpc0(<ctr>[,<table>]): integer
sc0_get_gpc0([<table>]): integer
sc1_get_gpc0([<table>]): integer
sc2_get_gpc0([<table>]): integer

Возвращает значение первого счётчика общего назначения, связанного с текущими отслеживаемыми счётчиками. См. также “table_gpc0” и sc/sc0/sc1/sc2_inc_gpc0.

sc_get_gpc1(<ctr>[,<table>]): integer

sc_get_gpc1(<ctr>[,<table>]): integer
sc0_get_gpc1([<table>]): integer
sc1_get_gpc1([<table>]): integer
sc2_get_gpc1([<table>]): integer

Возвращает значение второго счётчика общего назначения, связанного с текущими отслеживаемыми счётчиками. См. также “table_gpc1” и sc/sc0/sc1/sc2_inc_gpc1.

sc_get_gpt(<idx>,<ctr>[,<table>]): integer

sc_get_gpt(<idx>,<ctr>[,<table>]): integer

Возвращает значение первой метки общего назначения по индексу <idx> массива, связанного с отслеживаемым счётчиком с ID <ctr> и взятого из таблицы привязок текущего прокси или указанной таблицы привязок <table>. <idx> — целое число от 0 до 99, а <ctr> — целое число от 0 до 2. Если по этому индексу нет сохранённого GPT, возвращается ноль. Этот метод извлечения применяется только к массиву ‘gpt’ data_type (а не к устаревшему data-type ‘gpt0’). См. также “table_gpt”.

sc_get_gpt0(<ctr>[,<table>]): integer

sc_get_gpt0(<ctr>[,<table>]): integer
sc0_get_gpt0([<table>]): integer
sc1_get_gpt0([<table>]): integer
sc2_get_gpt0([<table>]): integer

Возвращает значение первой метки общего назначения, связанной с текущими отслеживаемыми счётчиками. См. также “table_gpt0”.

sc_glitch_cnt(<ctr>[,<table>]): integer

sc_glitch_cnt(<ctr>[,<table>]): integer
sc0_glitch_cnt([<table>]): integer
sc1_glitch_cnt([<table>]): integer
sc2_glitch_cnt([<table>]): integer

Возвращает суммарное число протокольных сбоев, наблюдавшихся в клиентских соединениях, связанных с текущими отслеживаемыми счётчиками. Обычно эти сбои приводят к прекращению запросов или соединений, поэтому возвращаемое значение часто относится к прежним соединениям. Хорошего или плохого значения нет, но некачественный клиент может иногда вызывать несколько сбоев на соединение, а очень некорректный или злонамеренный клиент — быстро добавлять тысячи событий в одном соединении. См. также fc_glitches для числа сбоев в текущем соединении, src_glitch_cnt для поиска по источнику и sc_glitch_rate для измерения интенсивности событий.

sc_glitch_rate(<ctr>[,<table>]): integer

sc_glitch_rate(<ctr>[,<table>]): integer
sc0_glitch_rate([<table>]): integer
sc1_glitch_rate([<table>]): integer
sc2_glitch_rate([<table>]): integer

Возвращает среднюю интенсивность протокольных сбоев в клиентских соединениях для текущих отслеживаемых счётчиков, измеряемую числом событий за период, настроенный в таблице. Обычно эти сбои приводят к прекращению запросов или соединений, поэтому возвращаемое значение часто относится к прежним соединениям. Хорошего или плохого значения нет, но некачественный клиент может иногда вызывать несколько сбоев на соединение, поэтому обычно ожидается низкая интенсивность. Однако очень некорректный или злонамеренный клиент может быстро добавлять тысячи событий на соединение и поддерживать здесь высокую интенсивность. См. также “table_glitch_rate” и “sc_glitch_cnt”.

sc_gpc_rate(<idx>,<ctr>[,<table>]): integer

sc_gpc_rate(<idx>,<ctr>[,<table>]): integer

Возвращает среднюю интенсивность увеличения счётчика общего назначения по индексу <idx> массива, связанного с отслеживаемым счётчиком с ID <ctr> из таблицы текущего прокси или указанной таблицы привязок <table>. Показывает частоту, с которой счётчик gpc увеличивался за настроенный период. <idx> — целое число от 0 до 99, а <ctr> — целое число от 0 до 2. Чтобы получить значение, в таблице привязок должен храниться массив счётчиков ‘gpc_rate’, поскольку ‘gpc’ содержит только число событий. Этот метод извлечения применяется только к массиву ‘gpc_rate’ data_type (а не к устаревшим data_types ‘gpc0_rate’ или ‘gpc1_rate’). См. также “table_gpc_rate”, “sc_get_gpc” и “sc_inc_gpc”.

sc_gpc0_rate(<ctr>[,<table>]): integer

sc_gpc0_rate(<ctr>[,<table>]): integer
sc0_gpc0_rate([<table>]): integer
sc1_gpc0_rate([<table>]): integer
sc2_gpc0_rate([<table>]): integer

Возвращает среднюю интенсивность увеличения первого счётчика общего назначения, связанного с текущими отслеживаемыми счётчиками. Показывает частоту увеличения счётчика gpc0 за настроенный период. См. также src_gpc0_rate, sc/sc0/sc1/sc2_get_gpc0 и sc/sc0/sc1/sc2_inc_gpc0. Чтобы получить значение, в таблице привязок должен храниться счётчик “gpc0_rate”, поскольку “gpc0” содержит только число событий.

sc_gpc1_rate(<ctr>[,<table>]): integer

sc_gpc1_rate(<ctr>[,<table>]): integer
sc0_gpc1_rate([<table>]): integer
sc1_gpc1_rate([<table>]): integer
sc2_gpc1_rate([<table>]): integer

Возвращает среднюю интенсивность увеличения второго счётчика общего назначения, связанного с текущими отслеживаемыми счётчиками. Показывает частоту увеличения счётчика gpc1 за настроенный период. См. также src_gpc1_rate, sc/sc0/sc1/sc2_get_gpc1 и sc/sc0/sc1/sc2_inc_gpc1. Чтобы получить значение, в таблице привязок должен храниться счётчик “gpc1_rate”, поскольку “gpc1” содержит только число событий.

sc_http_err_cnt(<ctr>[,<table>]): integer

sc_http_err_cnt(<ctr>[,<table>]): integer
sc0_http_err_cnt([<table>]): integer
sc1_http_err_cnt([<table>]): integer
sc2_http_err_cnt([<table>]): integer

Возвращает суммарное число ошибок HTTP из текущих отслеживаемых счётчиков. Включает как ошибки запросов, так и ответы с ошибками 4xx. См. также “table_http_err_cnt”.

sc_http_err_rate(<ctr>[,<table>]): integer

sc_http_err_rate(<ctr>[,<table>]): integer
sc0_http_err_rate([<table>]): integer
sc1_http_err_rate([<table>]): integer
sc2_http_err_rate([<table>]): integer

Возвращает среднюю интенсивность ошибок HTTP из текущих отслеживаемых счётчиков, измеряемую числом ошибок за период, настроенный в таблице. Включает как ошибки запросов, так и ответы с ошибками 4xx. См. также src_http_err_rate.

sc_http_fail_cnt(<ctr>[,<table>]): integer

sc_http_fail_cnt(<ctr>[,<table>]): integer
sc0_http_fail_cnt([<table>]): integer
sc1_http_fail_cnt([<table>]): integer
sc2_http_fail_cnt([<table>]): integer

Возвращает суммарное число сбоев ответов HTTP из текущих отслеживаемых счётчиков. Включает как ошибки ответов, так и коды состояния 5xx, кроме 501 и 505. См. также “table_http_fail_cnt”.

sc_http_fail_rate(<ctr>[,<table>]): integer

sc_http_fail_rate(<ctr>[,<table>]): integer
sc0_http_fail_rate([<table>]): integer
sc1_http_fail_rate([<table>]): integer
sc2_http_fail_rate([<table>]): integer

Возвращает среднюю интенсивность сбоев ответов HTTP из текущих отслеживаемых счётчиков, измеряемую числом сбоев за период, настроенный в таблице. Включает как ошибки ответов, так и коды состояния 5xx, кроме 501 и 505. См. также “table_http_fail_rate”.

sc_http_req_cnt(<ctr>[,<table>]): integer

sc_http_req_cnt(<ctr>[,<table>]): integer
sc0_http_req_cnt([<table>]): integer
sc1_http_req_cnt([<table>]): integer
sc2_http_req_cnt([<table>]): integer

Возвращает суммарное число запросов HTTP из текущих отслеживаемых счётчиков. Включает все начатые запросы, корректные и некорректные. См. также src_http_req_cnt.

sc_http_req_rate(<ctr>[,<table>]): integer

sc_http_req_rate(<ctr>[,<table>]): integer
sc0_http_req_rate([<table>]): integer
sc1_http_req_rate([<table>]): integer
sc2_http_req_rate([<table>]): integer

Возвращает среднюю интенсивность запросов HTTP из текущих отслеживаемых счётчиков, измеряемую числом запросов за период, настроенный в таблице. Включает все начатые запросы, корректные и некорректные. См. также src_http_req_rate.

sc_inc_gpc(<idx>,<ctr>[,<table>]): integer

sc_inc_gpc(<idx>,<ctr>[,<table>]): integer

Увеличивает счётчик общего назначения по индексу <idx> массива, связанного с указанным отслеживаемым счётчиком с ID <ctr> из таблицы привязок текущего прокси или указанной таблицы привязок <table>, и возвращает новое значение. <idx> — целое число от 0 до 99, а <ctr> — целое число от 0 до 2. До первого вызова сохранённое значение равно нулю, поэтому первый вызов увеличивает его до 1 и возвращает 1. Этот метод извлечения применяется только к массиву ‘gpc’ data_type (а не к устаревшим data_types ‘gpc0’ или ‘gpc1’).

sc_inc_gpc0(<ctr>[,<table>]): integer

sc_inc_gpc0(<ctr>[,<table>]): integer
sc0_inc_gpc0([<table>]): integer
sc1_inc_gpc0([<table>]): integer
sc2_inc_gpc0([<table>]): integer

Увеличивает первый счётчик общего назначения, связанный с текущими отслеживаемыми счётчиками, и возвращает его новое значение. До первого вызова сохранённое значение равно нулю, поэтому первый вызов увеличивает его до 1 и возвращает 1. Обычно используется как второй ACL в выражении, чтобы отметить соединение при истинном результате первого ACL:

Пример:

acl abuse sc0_http_req_rate gt 10
acl kill  sc0_inc_gpc0 gt 0
tcp-request connection reject if abuse kill

sc_inc_gpc1(<ctr>[,<table>]): integer

sc_inc_gpc1(<ctr>[,<table>]): integer
sc0_inc_gpc1([<table>]): integer
sc1_inc_gpc1([<table>]): integer
sc2_inc_gpc1([<table>]): integer

Увеличивает второй счётчик общего назначения, связанный с текущими отслеживаемыми счётчиками, и возвращает его новое значение. До первого вызова сохранённое значение равно нулю, поэтому первый вызов увеличивает его до 1 и возвращает 1. Обычно используется как второй ACL в выражении, чтобы отметить соединение при истинном результате первого ACL.

sc_kbytes_in(<ctr>[,<table>]): integer

sc_kbytes_in(<ctr>[,<table>]): integer
sc0_kbytes_in([<table>]): integer
sc1_kbytes_in([<table>]): integer
sc2_kbytes_in([<table>]): integer

Возвращает общий объём данных от клиента к серверу из текущих отслеживаемых счётчиков в килобайтах. Сейчас проверка выполняется с 32-битными целыми числами, что ограничивает значения 4 терабайтами. См. также “table_kbytes_in”.

sc_kbytes_out(<ctr>[,<table>]): integer

sc_kbytes_out(<ctr>[,<table>]): integer
sc0_kbytes_out([<table>]): integer
sc1_kbytes_out([<table>]): integer
sc2_kbytes_out([<table>]): integer

Возвращает общий объём данных от сервера к клиенту из текущих отслеживаемых счётчиков в килобайтах. Сейчас проверка выполняется с 32-битными целыми числами, что ограничивает значения 4 терабайтами. См. также “table_kbytes_out”.

sc_key(<ctr>): any sc0_key: any sc1_key: any sc2_key: any Возвращает ключ, используемый для сопоставления текущего отслеживаемого счётчика.

sc_sess_cnt(<ctr>[,<table>]): integer

sc_sess_cnt(<ctr>[,<table>]): integer
sc0_sess_cnt([<table>]): integer
sc1_sess_cnt([<table>]): integer
sc2_sess_cnt([<table>]): integer

Возвращает суммарное число входящих соединений, преобразованных в сеансы, то есть принятых правилом “tcp-request connection”, из текущих отслеживаемых счётчиков. Бэкенд может насчитать больше сеансов, чем соединений: каждое соединение может породить множество сеансов бэкенда, если соединение с клиентом использует постоянные соединения HTTP keep-alive. См. также “table_sess_cnt”.

sc_sess_rate(<ctr>[,<table>]): integer

sc_sess_rate(<ctr>[,<table>]): integer
sc0_sess_rate([<table>]): integer
sc1_sess_rate([<table>]): integer
sc2_sess_rate([<table>]): integer

Возвращает среднюю интенсивность сеансов из текущих отслеживаемых счётчиков, измеряемую числом сеансов за период, настроенный в таблице. Сеанс — это соединение, прошедшее ранние правила “tcp-request connection”. Бэкенд может насчитать больше сеансов, чем соединений: каждое соединение может породить множество сеансов бэкенда, если соединение с клиентом использует постоянные соединения HTTP keep-alive. См. также “table_sess_rate”.

sc_tracked(<ctr>[,<table>]): boolean

sc_tracked(<ctr>[,<table>]): boolean
sc0_tracked([<table>]): boolean
sc1_tracked([<table>]): boolean
sc2_tracked([<table>]): boolean

Возвращает true, если указанный счётчик сеанса сейчас отслеживается текущим сеансом. Может быть полезен при решении, следует ли задавать определённые значения в заголовке, передаваемом серверу.

sc_trackers(<ctr>[,<table>]): integer

sc_trackers(<ctr>[,<table>]): integer
sc0_trackers([<table>]): integer
sc1_trackers([<table>]): integer
sc2_trackers([<table>]): integer

Возвращает текущее число одновременных соединений, отслеживающих те же счётчики. Это число автоматически увеличивается при начале отслеживания и уменьшается при его прекращении. Отличается от sc0_conn_cur тем, что использует счётчик ссылок таблицы, а не сохранённые данные (значение “use”, возвращаемое командой “show table” в CLI). Иногда это больше подходит для отслеживания на уровне 7. Например, позволяет сообщить серверу число одновременных соединений от заданного адреса.

so_id: integer Возвращает целое число с id текущего слушающего сокета. Полезен во фронтендах с множеством строк “bind” или для привязки всех пользователей, пришедших через один сокет, к одному серверу.

so_name: string Возвращает строку с именем текущего слушающего сокета, заданным с помощью name в строке “bind”. Служит тем же целям, что и so_id, но использует строки вместо целых чисел.

src: ip IP-адрес источника клиента текущего сеанса. Этот адрес может изменяться любыми правилами tcp/http. Имеет тип IP и работает с таблицами IPv4 и IPv6. В таблицах IPv6 адреса IPv4 отображаются в соответствующие адреса IPv6 согласно RFC 4291. Используется адрес источника на уровне TCP, а не адрес клиента за прокси. Однако при использовании директивы bind “accept-proxy” или “accept-netscaler-cip” это может быть адрес клиента за другим компонентом, совместимым с PROXY-protocol, во всех наборах правил, кроме “tcp-request connection”, который видит настоящий адрес. Если входящее соединение прошло через преобразование адресов или перенаправление с отслеживанием соединений, возвращается исходный адрес назначения до перенаправления. В системах Linux источник и назначение иногда могут поменяться местами, если задан sysctl nf_conntrack_tcp_loose: запоздалый ответ может вновь открыть соединение, закрытое по тайм-ауту, и поменять представление о том, какая сторона является источником, а какая — назначением.

Пример:

# add an HTTP header in requests with the originating address' country
http-request set-header X-Country %[src,map_ip(geoip.lst)]

src_bytes_in_rate([<table>]): integer

src_bytes_in_rate([<table>]): integer

Работает как преобразователь “table_bytes_in_rate”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_bytes_in_rate([<table>])

src_bytes_out_rate([<table>]): integer

src_bytes_out_rate([<table>]): integer

Работает как преобразователь “table_bytes_out_rate”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_bytes_out_rate([<table>])

src_clr_gpc(<idx>[,<table>]): integer

src_clr_gpc(<idx>[,<table>]): integer

Работает как преобразователь “table_clr_gpc”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_clr_gpc(<idx>[,<table>])

src_clr_gpc0([<table>]): integer

src_clr_gpc0([<table>]): integer

Работает как преобразователь “table_clr_gpc0”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_clr_gpc0([<table>])

src_clr_gpc1([<table>]): integer

src_clr_gpc1([<table>]): integer

Работает как преобразователь “table_clr_gpc1”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_clr_gpc1([<table>])

src_conn_cnt([<table>]): integer

src_conn_cnt([<table>]): integer

Работает как преобразователь “table_conn_cnt”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_conn_cnt([<table>])

src_conn_cur([<table>]): integer

src_conn_cur([<table>]): integer

Работает как преобразователь “table_conn_cur”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_conn_cur([<table>])

src_conn_rate([<table>]): integer

src_conn_rate([<table>]): integer

Работает как преобразователь “table_conn_rate”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_conn_rate([<table>])

src_get_gpc(<idx>[,<table>]): integer

src_get_gpc(<idx>[,<table>]): integer

Работает как преобразователь “table_gpc”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_gpc(<idx>[,<table>])

src_get_gpc0([<table>]): integer

src_get_gpc0([<table>]): integer

Работает как преобразователь “table_gpc0”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_gpc0([<table>])

src_get_gpc1([<table>]): integer

src_get_gpc1([<table>]): integer

Работает как преобразователь “table_gpc1”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_gpc1([<table>])

src_get_gpt(<idx>[,<table>]): integer

src_get_gpt(<idx>[,<table>]): integer

Работает как преобразователь “table_gpt”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_gpt(<idx>[,<table>])

src_get_gpt0([<table>]): integer

src_get_gpt0([<table>]): integer

Работает как преобразователь “table_gpt0”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_gpt0([<table>])

src_glitch_cnt([<table>]): integer

src_glitch_cnt([<table>]): integer

Работает как преобразователь “table_glitch_cnt”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_glitch_cnt([<table>])

src_glitch_rate([<table>]): integer

src_glitch_rate([<table>]): integer

Работает как преобразователь “table_glitch_rate”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_glitch_rate([<table>])

src_gpc_rate(<idx>[,<table>]): integer

src_gpc_rate(<idx>[,<table>]): integer

Работает как преобразователь “table_gpc_rate”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_gpc_rate(<idx>[,<table>])

src_gpc0_rate([<table>]): integer

src_gpc0_rate([<table>]): integer

Работает как преобразователь “table_gpc0_rate”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_gpc0_rate([<table>])

src_gpc1_rate([<table>]): integer

src_gpc1_rate([<table>]): integer

Работает как преобразователь “table_gpc1_rate”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_gpc1_rate([<table>])

src_http_err_cnt([<table>]): integer

src_http_err_cnt([<table>]): integer

Работает как преобразователь “table_http_err_cnt”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_http_err_cnt([<table>])

src_http_err_rate([<table>]): integer

src_http_err_rate([<table>]): integer

Работает как преобразователь “table_http_err_rate”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_http_err_rate([<table>])

src_http_fail_cnt([<table>]): integer

src_http_fail_cnt([<table>]): integer

Работает как преобразователь “table_http_fail_cnt”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_http_fail_cnt([<table>])

src_http_fail_rate([<table>]): integer

src_http_fail_rate([<table>]): integer

Работает как преобразователь “table_http_fail_rate”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_http_fail_rate([<table>])

src_http_req_cnt([<table>]): integer

src_http_req_cnt([<table>]): integer

Работает как преобразователь “table_http_req_cnt”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_http_req_cnt([<table>])

src_http_req_rate([<table>]): integer

src_http_req_rate([<table>]): integer

Работает как преобразователь “table_http_req_rate”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_http_req_rate([<table>])

src_inc_gpc(<idx>[,<table>]): integer

src_inc_gpc(<idx>[,<table>]): integer

Работает как преобразователь “src_inc_gpc”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_inc_gpc(<idx>[,<table>])

src_inc_gpc0([<table>]): integer

src_inc_gpc0([<table>]): integer

Работает как преобразователь “src_inc_gpc0”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_inc_gpc0([<table>])

src_inc_gpc1([<table>]): integer

src_inc_gpc1([<table>]): integer

Работает как преобразователь “src_inc_gpc1”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_inc_gpc1([<table>])

src_is_local: boolean Возвращает true, если адрес источника входящего соединения локален для системы, или false, если адрес отсутствует в системе, то есть пришёл с удалённой машины. Обратите внимание, что адреса UNIX считаются локальными. Это может быть полезно для применения определённых ограничений доступа в зависимости от источника клиента (например, требовать аутентификацию или HTTPS для удалённых машин). Обратите внимание, что проверка требует нескольких системных вызовов, поэтому лучше выполнять её только один раз за соединение.

src_kbytes_in([<table>]): integer

src_kbytes_in([<table>]): integer

Работает как преобразователь “table_kbytes_in”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_kbytes_in([<table>])

src_kbytes_out([<table>]): integer

src_kbytes_out([<table>]): integer

Работает как преобразователь “table_kbytes_out”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_kbytes_out([<table>])

src_port: integer Возвращает целочисленное значение, соответствующее исходному порту TCP соединения на стороне клиента, то есть порту, с которого подключился клиент. Любые правила tcp/http могут изменить этот адрес. Использование этой функции ограничено, поскольку современные протоколы в настоящее время не уделяют большого внимания исходным портам.

src_sess_cnt([<table>]): integer

src_sess_cnt([<table>]): integer

Работает как преобразователь “table_sess_cnt”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_sess_cnt([<table>])

src_sess_rate([<table>]): integer

src_sess_rate([<table>]): integer

Работает как преобразователь “table_sess_rate”, при этом ключом служит адрес источника входящего соединения.

Эквивалентно: src,table_sess_rate([<table>])

src_updt_conn_cnt([<table>]): integer

src_updt_conn_cnt([<table>]): integer

Создаёт или обновляет запись, связанную с адресом источника входящего соединения в таблице привязок текущего прокси или в указанной таблице привязок. Эта таблица должна быть настроена для хранения типа данных “conn_cnt”, иначе сопоставление будет проигнорировано. Текущее значение счётчика увеличивается на единицу, и таймер истечения обновляется. Возвращается обновлённое значение счётчика, поэтому результат не может быть нулевым. Использовалось для блокировки злоупотребляющих сервисом по их адресу источника. Примечание: рекомендуется использовать более полные действия “track-sc*” в правилах “tcp-request” вместо этого.

Пример:

# This frontend limits incoming SSH connections to 3 per 10 second for
# each source address, and rejects excess connections until a 10 second
# silence is observed. At most 20 addresses are tracked.
listen ssh
    bind :22
    mode tcp
    maxconn 100
    stick-table type ip size 20 expire 10s store conn_cnt
    tcp-request content reject if { src_updt_conn_cnt gt 3 }
    server local 127.0.0.1:22

srv_id: integer Возвращает целое число, содержащее идентификатор сервера при обработке ответа. Хотя используется почти исключительно в правилах ACL, может применяться для ведения журнала или отладки. Также может использоваться в правилах tcp-check или http-check.

srv_name: string Возвращает строку, содержащую имя сервера при обработке ответа. Хотя используется почти исключительно в правилах ACL, может применяться для ведения журнала или отладки. Также может использоваться в правилах tcp-check или http-check.

txn.conn_retries: integer Возвращает число повторных попыток соединения этого потока с сервером. Это значение может меняться, пока соединение не будет полностью установлено. Для соединений HTTP на значение могут влиять повторные попытки L7.

txn.redispatched: boolean Возвращает true, если соединение было перераспределено при повторной попытке в соответствии с конфигурацией “option redispatch”. Это значение может изменяться до полной установки соединения. Для соединений HTTP значение может быть затронуто повторными попытками L7.

7.3.4. Извлечение образцов на уровне 5

Уровень 5 обычно описывает только сеансовый уровень, который в HAProxy находится ближе всего к сеансу после завершения всех рукопожатий соединения, но когда ещё не доступны данные. Методы извлечения, описанные здесь, могут использоваться уже на уровне “tcp-request content”, если они не требуют будущей информации. К ним обычно относятся результаты согласования SSL.

Сводка методов извлечения образцов в этом разделе и их соответствующие типы:

  Ключевое слово                                   Выходной тип
-------------------------------------------------+-------------
51d.all(<prop>[,<prop>*])                          string
bs.aborted                                         boolean
bs.debug_str([<bitmap>])                           string
bs.id                                              integer
bs.rst_code                                        integer
fs.aborted                                         boolean
fs.debug_str([<bitmap>])                           string
fs.id                                              integer
fs.rst_code                                        integer
ssl_bc                                             boolean
ssl_bc_alg_keysize                                 integer
ssl_bc_alpn                                        string
ssl_bc_cipher                                      string
ssl_bc_client_early_traffic_secret                 string
ssl_bc_client_handshake_traffic_secret             string
ssl_bc_client_random                               binary
ssl_bc_client_traffic_secret_0                     string
ssl_bc_curve                                       string
ssl_bc_early_exporter_secret                       string
ssl_bc_err                                         integer
ssl_bc_err_str                                     string
ssl_bc_exporter_secret                             string
ssl_bc_is_resumed                                  boolean
ssl_bc_npn                                         string
ssl_bc_protocol                                    string
ssl_bc_server_handshake_traffic_secret             string
ssl_bc_server_random                               binary
ssl_bc_server_traffic_secret_0                     string
ssl_bc_session_id                                  binary
ssl_bc_session_key                                 binary
ssl_bc_sni                                         string
ssl_bc_unique_id                                   binary
ssl_bc_use_keysize                                 integer
ssl_c_ca_err                                       integer
ssl_c_ca_err_depth                                 integer
ssl_c_chain_der                                    binary
ssl_c_der                                          binary
ssl_c_err                                          integer
ssl_c_i_dn([<entry>[,<occ>[,<format>]]])           string
ssl_c_key_alg                                      string
ssl_c_notafter                                     string
ssl_c_notbefore                                    string
ssl_c_r_dn([<entry>[,<occ>[,<format>]]])           string
ssl_c_s_dn([<entry>[,<occ>[,<format>]]])           string
ssl_c_san                                          string
ssl_c_serial                                       binary
ssl_c_sha1                                         binary
ssl_c_sig_alg                                      string
ssl_c_used                                         boolean
ssl_c_verify                                       integer
ssl_c_version                                      integer
ssl_f_der                                          binary
ssl_f_i_dn([<entry>[,<occ>[,<format>]]])           string
ssl_f_key_alg                                      string
ssl_f_notafter                                     string
ssl_f_notbefore                                    string
ssl_f_s_dn([<entry>[,<occ>[,<format>]]])           string
ssl_f_serial                                       binary
ssl_f_sha1                                         binary
ssl_f_sig_alg                                      string
ssl_f_version                                      integer
ssl_fc                                             boolean
ssl_fc_alg_keysize                                 integer
ssl_fc_alpn                                        string
ssl_fc_cipher                                      string
ssl_fc_cipherlist_bin([<filter_option>])           binary
ssl_fc_cipherlist_hex([<filter_option>])           string
ssl_fc_cipherlist_str([<filter_option>])           string
ssl_fc_cipherlist_xxh                              integer
ssl_fc_client_early_traffic_secret                 string
ssl_fc_client_handshake_traffic_secret             string
ssl_fc_client_random                               binary
ssl_fc_client_traffic_secret_0                     string
ssl_fc_crtname                                     string
ssl_fc_curve                                       string
ssl_fc_early_exporter_secret                       string
ssl_fc_ecformats_bin                               binary
ssl_fc_eclist_bin([<filter_option>])               binary
ssl_fc_err                                         integer
ssl_fc_err_str                                     string
ssl_fc_exporter_secret                             string
ssl_fc_extlist_bin([<filter_option>])              binary
ssl_fc_has_crt                                     boolean
ssl_fc_has_early                                   boolean
ssl_fc_has_sni                                     boolean
ssl_fc_is_resumed                                  boolean
ssl_fc_npn                                         string
ssl_fc_protocol                                    string
ssl_fc_protocol_hello_id                           integer
ssl_fc_server_handshake_traffic_secret             string
ssl_fc_server_random                               binary
ssl_fc_server_traffic_secret_0                     string
ssl_fc_session_id                                  binary
ssl_fc_session_key                                 binary
ssl_fc_sigalgs_bin([<filter_option>])              binary
ssl_fc_sni                                         string
ssl_fc_supported_versions_bin([<filter_option>])   binary
ssl_fc_unique_id                                   binary
ssl_fc_use_keysize                                 integer
ssl_s_chain_der                                    binary
ssl_s_der                                          binary
ssl_s_i_dn([<entry>[,<occ>[,<format>]]])           string
ssl_s_key_alg                                      string
ssl_s_notafter                                     string
ssl_s_notbefore                                    string
ssl_s_s_dn([<entry>[,<occ>[,<format>]]])           string
ssl_s_serial                                       binary
ssl_s_sha1                                         binary
ssl_s_sig_alg                                      string
ssl_s_version                                      integer
txn.timer.user                                     integer
-------------------------------------------------+-------------

Подробный список:

51d.all(<prop>[,<prop>*]): string

51d.all(<prop>[,<prop>*]): string

Возвращает значения запрошенных свойств в виде строки, где значения разделены разделителем, указанным с помощью “51degrees-property-separator”. Устройство идентифицируется с использованием всех важных заголовков HTTP из запроса. Функция может принимать до пяти имён свойств, и если имя свойства не найдено, возвращается значение “NoData”.

Пример:

# Here the header "X-51D-DeviceTypeMobileTablet" is added to the request
# containing the three properties requested using all relevant headers from
# the request.
frontend http-in
  bind *:8081
  default_backend servers
  http-request set-header X-51D-DeviceTypeMobileTablet \
    %[51d.all(DeviceType,IsMobile,IsTablet)]

bs.aborted: boolean Возвращает true, если для текущего потока от сервера получено прерывание. В противном случае возвращает false.

bs.debug_str([<bitmap>]): string

bs.debug_str([<bitmap>]): string

Эта функция предназначена для использования разработчиками в ходе сложных сессий устранения неполадок. Она извлекает некоторые внутренние состояния из нижних уровней потока и соединения бэкенда и упорядочивает их в виде строки, обычно в форме последовательности “name=value”, разделённых пробелами. Необязательный аргумент <bitmap> указывает, из каких уровней извлекать информацию, и представляет собой арифметическую операцию ИЛИ (или сумму) следующих значений: - уровень сокета: 16 - уровень соединения: 8 - транспортный уровень (например SSL): 4 - соединение мультиплексора: 2 - поток мультиплексора: 1

Эти значения могут меняться между версиями. Значение по умолчанию ноль является особым и включает все уровни. Не следует полагаться на вывод этой функции для долгосрочного мониторинга рабочей системы. Она предназначена для эволюции даже в стабильной ветке по мере роста потребности в детализации. Одним из типичных применений является объединение этой информации в конце log-format вместе с fs.debug_str(). Пример:

log-format "$HAPROXY_HTTP_LOG_FMT fs=<%[fs.debug_str]> bs=<%[bs.debug_str]>"

bs.id: integer Возвращает ID потока мультиплексора на стороне сервера. За возврат соответствующих сведений отвечает мультиплексор.

bs.rst_code: integer Возвращает код сброса, полученный от сервера для текущего потока. Возвращается код кадра H2 RST_STREAM или кадра QUIC STOP_SENDING, полученного от сервера. Извлечение образца завершается неудачей, если не было получено прерывание или если поток сервера не является потоком H2/QUIC.

fs.aborted: boolean Возвращает true, если для текущего потока от клиента получено прерывание. В противном случае возвращает false.

fs.debug_str([<bitmap>]): string

fs.debug_str([<bitmap>]): string

Эта функция предназначена для использования разработчиками в ходе сложных сессий устранения неполадок. Она извлекает некоторые внутренние состояния из нижних уровней потока и соединения фронтенда и упорядочивает их в виде строки, обычно в форме последовательности “name=value”, разделённых пробелами. Необязательный аргумент <bitmap> указывает, из каких уровней извлекать информацию, и представляет собой арифметическую операцию ИЛИ (или сумму) следующих значений: - уровень сокета: 16 - уровень соединения: 8 - транспортный уровень (например SSL): 4 - соединение мультиплексора: 2 - поток мультиплексора: 1

Эти значения могут меняться между версиями. Значение по умолчанию ноль является особым и включает все уровни. Не следует полагаться на вывод этой функции для долгосрочного мониторинга рабочей системы. Она предназначена для эволюции даже в стабильной ветке по мере роста потребности в детализации. Одним из типичных применений является объединение этой информации в конце log-format вместе с bs.debug_str(). Пример:

log-format "$HAPROXY_HTTP_LOG_FMT fs=<%[fs.debug_str]> bs=<%[bs.debug_str]>"

fs.id: integer Возвращает идентификатор потока мультиплексора на стороне клиента. Ответственность за возврат соответствующей информации лежит на мультиплексоре. Например, при использовании обычного TCP, всегда возвращается 0, поскольку поток отсутствует.

fs.rst_code: integer Возвращает код сброса, полученный от клиента для текущего потока. Возвращается код кадра H2 RST_STREAM или кадра QUIC STOP_SENDING, полученного от клиента. Извлечение образца завершается неудачей, если не было получено прерывание или если поток клиента не является потоком H2/QUIC.

ssl_bc: boolean Возвращает true, когда соединение с сервером было установлено через транспортный уровень SSL/TLS и локально расшифровано. Это означает, что исходящее соединение было установлено с сервером, для которого включена опция “ssl”. Может использоваться в правилах tcp-check или http-check.

ssl_bc_alg_keysize: integer Возвращает поддерживаемую длину ключа симметричного шифра в битах, когда исходящее соединение установлено по транспортному протоколу SSL/TLS. Можно использовать в наборе правил tcp-check либо http-check.

ssl_bc_alpn: string Извлекает поле согласования протокола прикладного уровня из исходящего соединения, установленного через транспортный уровень TLS. Результат — строка, содержащая имя протокола, согласованного с сервером. Библиотека SSL должна быть скомпилирована с поддержкой расширений TLS (проверьте haproxy -vv). Обратите внимание, что расширение TLS ALPN не объявляется, если на строке “server” не указан список протоколов с ключевым словом “alpn”. Также ничто не заставляет сервер выбирать протокол из этого списка — может быть использован любой другой. Расширение TLS ALPN предназначено для замены расширения TLS NPN. См. также “ssl_bc_npn”. Может использоваться в правилах tcp-check или http-check.

ssl_bc_cipher: string Возвращает имя используемого шифра при установке исходящего соединения через транспортный уровень SSL/TLS. Может использоваться в правилах tcp-check или http-check.

ssl_bc_client_early_traffic_secret: string Возвращает CLIENT_EARLY_TRAFFIC_SECRET в виде шестнадцатеричной строки для соединения с сервером, если исходящее соединение установлено по транспортному протоколу TLS 1.3. Требуется OpenSSL >= 1.1.1. Это один из ключей, выгружаемых обратным вызовом keylog OpenSSL для формирования SSLKEYLOGFILE. Журналирование ключей SSL необходимо включить директивой “tune.ssl.keylog on” в секции global. См. также “tune.ssl.keylog”.

ssl_bc_client_handshake_traffic_secret: string Возвращает CLIENT_HANDSHAKE_TRAFFIC_SECRET в виде шестнадцатеричной строки для соединения с сервером, если исходящее соединение установлено по транспортному протоколу TLS 1.3. Требуется OpenSSL >= 1.1.1. Это один из ключей, выгружаемых обратным вызовом keylog OpenSSL для формирования SSLKEYLOGFILE. Журналирование ключей SSL необходимо включить директивой “tune.ssl.keylog on” в секции global. См. также “tune.ssl.keylog”.

ssl_bc_client_random: binary Возвращает случайное значение клиента для соединения с сервером, когда входящее соединение было установлено через транспортный уровень SSL/TLS. Полезно для расшифровки трафика, отправленного с использованием эфемерных шифров. Требуется OpenSSL >= 1.1.0 или BoringSSL. Может использоваться в правилах tcp-check или http-check.

ssl_bc_client_traffic_secret_0: string Возвращает CLIENT_TRAFFIC_SECRET_0 в виде шестнадцатеричной строки для соединения с сервером, если исходящее соединение установлено по транспортному протоколу TLS 1.3. Требуется OpenSSL >= 1.1.1. Это один из ключей, выгружаемых обратным вызовом keylog OpenSSL для формирования SSLKEYLOGFILE. Журналирование ключей SSL необходимо включить директивой “tune.ssl.keylog on” в секции global. См. также “tune.ssl.keylog”.

ssl_bc_curve: string Возвращает имя кривой, используемой при согласовании ключей, когда исходящее соединение было установлено через транспортный уровень SSL/TLS. Требуется OpenSSL >= 3.0.0 или AWS-LC >= 1.57.0.

ssl_bc_early_exporter_secret: string Возвращает EARLY_EXPORTER_SECRET в виде шестнадцатеричной строки для соединения с сервером, если исходящее соединение установлено по транспортному протоколу TLS 1.3. Требуется OpenSSL >= 1.1.1. Это один из ключей, выгружаемых обратным вызовом keylog OpenSSL для формирования SSLKEYLOGFILE. Журналирование ключей SSL необходимо включить директивой “tune.ssl.keylog on” в секции global. См. также “tune.ssl.keylog”.

ssl_bc_err: integer При установке исходящего соединения через транспортный уровень SSL/TLS возвращает идентификатор последней ошибки из первого стека ошибок, возникшего на стороне бэкенда. Может включать ошибки рукопожатия, а также другие ошибки чтения или записи, возникшие в течение срока жизни соединения. Чтобы получить текстовое описание этого кода ошибки, можно использовать либо извлечение образца “ssl_bc_err_str”, либо команду “openssl errstr” (которая принимает код ошибки в шестнадцатеричном представлении в качестве параметра). Обратитесь к документации вашей библиотеки SSL для получения полного списка кодов ошибок.

ssl_bc_err_str: string При установке исходящего соединения через транспортный уровень SSL/TLS возвращает строковое представление последней ошибки из первого стека ошибок, возникшего с точки зрения бэкенда. См. также “ssl_fc_err”.

ssl_bc_exporter_secret: string Возвращает EXPORTER_SECRET в виде шестнадцатеричной строки для соединения с сервером, если исходящее соединение установлено по транспортному протоколу TLS 1.3. Требуется OpenSSL >= 1.1.1. Это один из ключей, выгружаемых обратным вызовом keylog OpenSSL для формирования SSLKEYLOGFILE. Журналирование ключей SSL необходимо включить директивой “tune.ssl.keylog on” в секции global. См. также “tune.ssl.keylog”.

ssl_bc_is_resumed: boolean Возвращает true, когда соединение с сервером было установлено через транспортный уровень SSL/TLS и новая сессия SSL была возобновлена с использованием кэшированной сессии или билета TLS. Может использоваться в правилах tcp-check или http-check.

ssl_bc_npn: string Извлекает поле согласования следующего протокола из исходящего соединения, установленного через транспортный уровень TLS. Результат — строка, содержащая имя протокола, согласованного с сервером. Библиотека SSL должна быть скомпилирована с поддержкой расширений TLS (проверьте haproxy -vv). Обратите внимание, что расширение TLS NPN не объявляется, если на строке “server” не указан список протоколов с ключевым словом “npn”. Также ничто не заставляет сервер выбирать протокол из этого списка — может быть использован любой другой. Обратите внимание, что расширение TLS NPN было заменено на ALPN. Может использоваться в правилах tcp-check или http-check.

ssl_bc_protocol: string Возвращает имя используемого протокола при установке исходящего соединения через транспортный уровень SSL/TLS. Может использоваться в правилах tcp-check или http-check.

ssl_bc_server_handshake_traffic_secret: string Возвращает SERVER_HANDSHAKE_TRAFFIC_SECRET в виде шестнадцатеричной строки для соединения с сервером, если исходящее соединение установлено по транспортному протоколу TLS 1.3. Требуется OpenSSL >= 1.1.1. Это один из ключей, выгружаемых обратным вызовом keylog OpenSSL для формирования SSLKEYLOGFILE. Журналирование ключей SSL необходимо включить директивой “tune.ssl.keylog on” в секции global. См. также “tune.ssl.keylog”.

ssl_bc_server_random: binary Возвращает случайное значение сервера для соединения с сервером, когда входящее соединение было установлено через транспортный уровень SSL/TLS. Полезно для расшифровки трафика, отправленного с использованием эфемерных шифров. Требуется OpenSSL >= 1.1.0 или BoringSSL. Может использоваться в правилах tcp-check или http-check.

ssl_bc_server_traffic_secret_0: string Возвращает SERVER_TRAFFIC_SECRET_0 в виде шестнадцатеричной строки для соединения с сервером, если исходящее соединение установлено по транспортному протоколу TLS 1.3. Требуется OpenSSL >= 1.1.1. Это один из ключей, выгружаемых обратным вызовом keylog OpenSSL для формирования SSLKEYLOGFILE. Журналирование ключей SSL необходимо включить директивой “tune.ssl.keylog on” в секции global. См. также “tune.ssl.keylog”.

ssl_bc_session_id: binary Возвращает идентификатор SSL соединения с сервером, когда исходящее соединение было установлено через транспортный уровень SSL/TLS. Полезно для ведения журнала, если необходимо узнать, была ли сессия использована повторно. Может использоваться в правилах tcp-check или http-check.

ssl_bc_session_key: binary Возвращает главный ключ сессии SSL соединения с сервером, когда исходящее соединение было установлено через транспортный уровень SSL/TLS. Полезно для расшифровки трафика, отправленного с использованием эфемерных шифров. Требуется OpenSSL >= 1.1.0 или BoringSSL. Может использоваться в правилах tcp-check или http-check.

ssl_bc_sni: string Извлекает поле расширения TLS для указания имени сервера (SNI), использованное при подключении к серверу. Результат (при наличии) обычно представляет собой строку, соответствующую имени хоста HTTPS (не более 253 символов). Основное применение — ведение журнала и отладка (например, определение, какой SNI был использован при установлении соединения, для сопоставления с тем, что видел сервер).

ssl_bc_unique_id: binary Если исходящее соединение установлено по транспортному протоколу SSL/TLS, возвращает уникальный идентификатор TLS, определённый в RFC5929 раздел 3 . Этот идентификатор можно кодировать в base64 преобразователем “ssl_bc_unique_id,base64”. Можно использовать в наборе правил tcp-check либо http-check.

ssl_bc_use_keysize: integer Возвращает размер симметричного ключа шифрования в битах, использованный при установке исходящего соединения через транспортный уровень SSL/TLS. Может использоваться в правилах tcp-check или http-check.

ssl_c_ca_err: integer Когда входящее соединение было установлено через транспортный уровень SSL/TLS, возвращает идентификатор первой обнаруженной ошибки при проверке сертификата клиента на глубине > 0, или 0, если при этой проверке не было обнаружено ошибок. См. документацию вашей библиотеки SSL для получения полного списка кодов ошибок.

ssl_c_ca_err_depth: integer Когда входящее соединение было установлено через транспортный уровень SSL/TLS, возвращает глубину в цепочке CA первой обнаруженной ошибки при проверке сертификата клиента. Если ошибок не обнаружено, возвращается 0.

ssl_c_chain_der: binary Возвращает цепочку сертификатов в формате DER, представленную клиентом, когда входящее соединение было установлено через транспортный уровень SSL/TLS. При использовании для ACL значения для сравнения могут передаваться в шестнадцатеричном виде. Результат можно разобрать с помощью любой библиотеки, поддерживающей данные ASN.1 DER. В настоящее время не поддерживает возобновлённые сессии.

ssl_c_der: binary Возвращает сертификат, представленный клиентом, в формате DER, когда входящее соединение было установлено через транспортный уровень SSL/TLS. При использовании для ACL значения для сравнения могут передаваться в шестнадцатеричном виде.

ssl_c_err: integer Когда входящее соединение было установлено через транспортный уровень SSL/TLS, возвращает идентификатор первой обнаруженной ошибки при проверке на глубине 0, или 0, если при этой проверке не было обнаружено ошибок. См. документацию вашей библиотеки SSL для получения полного списка кодов ошибок.

ssl_c_i_dn([<entry>[,<occ>[,<format>]]]): string

ssl_c_i_dn([<entry>[,<occ>[,<format>]]]): string

Когда входящее соединение установлено по транспортному протоколу SSL/TLS, возвращает полное различимое имя (DN) издателя сертификата, представленного клиентом, если <entry> не указан, либо значение первого вхождения указанного элемента, найденного с начала DN. Если необязательным вторым аргументом задан положительный/отрицательный номер вхождения, возвращается значение n-го вхождения указанного элемента с начала/конца DN. Например, “ssl_c_i_dn(OU,2)” возвращает второе подразделение организации, а “ssl_c_i_dn(CN)” — общее имя. Параметр <format> позволяет получить DN, пригодный для использования различными протоколами. Сейчас поддерживается rfc2253 для LDAP v3. Если требуется изменить только формат, первыми двумя параметрами можно указать пустую строку и ноль. Пример: ssl_c_i_dn(,0,rfc2253). Если значение ASN.1 запрашиваемого элемента (либо, когда <entry> не указан, любого элемента в DN) содержит встроенный байт NUL, за которым следуют другие данные, это значение считается некорректным и данные не возвращаются.

ssl_c_key_alg: string Возвращает имя алгоритма, использованного для генерации ключа сертификата, представленного клиентом, когда входящее соединение было установлено через транспортный уровень SSL/TLS.

ssl_c_notafter: string Возвращает дату окончания, представленную клиентом, в виде отформатированной строки YYMMDDhhmmss[Z], когда входящее соединение было установлено через транспортный уровень SSL/TLS.

ssl_c_notbefore: string Возвращает дату начала, представленную клиентом, в виде отформатированной строки YYMMDDhhmmss[Z], когда входящее соединение было установлено через транспортный уровень SSL/TLS.

ssl_c_r_dn([<entry>[,<occ>[,<format>]]]): string

ssl_c_r_dn([<entry>[,<occ>[,<format>]]]): string

Когда входящее соединение установлено по транспортному протоколу SSL/TLS и успешно проверено с использованием заданного ca-file, возвращает полное различимое имя (DN) корневого CA сертификата, представленного клиентом, если <entry> не указан, либо значение первого вхождения указанного элемента, найденного с начала DN. Если необязательным вторым аргументом задан положительный/отрицательный номер вхождения, возвращается значение n-го вхождения указанного элемента с начала/конца DN. Например, “ssl_c_r_dn(OU,2)” возвращает второе подразделение организации, а “ssl_c_r_dn(CN)” — общее имя. Параметр <format> позволяет получить DN, пригодный для использования различными протоколами. Сейчас поддерживается rfc2253 для LDAP v3. Если требуется изменить только формат, первыми двумя параметрами можно указать пустую строку и ноль. Пример: ssl_c_r_dn(,0,rfc2253). Если значение ASN.1 запрашиваемого элемента (либо, когда <entry> не указан, любого элемента в DN) содержит встроенный байт NUL, за которым следуют другие данные, это значение считается некорректным и данные не возвращаются.

ssl_c_s_dn([<entry>[,<occ>[,<format>]]]): string

ssl_c_s_dn([<entry>[,<occ>[,<format>]]]): string

Когда входящее соединение установлено по транспортному протоколу SSL/TLS, возвращает полное различимое имя (DN) субъекта сертификата, представленного клиентом, если <entry> не указан, либо значение первого вхождения указанного элемента, найденного с начала DN. Если необязательным вторым аргументом задан положительный/отрицательный номер вхождения, возвращается значение n-го вхождения указанного элемента с начала/конца DN. Например, “ssl_c_s_dn(OU,2)” возвращает второе подразделение организации, а “ssl_c_s_dn(CN)” — общее имя. Параметр <format> позволяет получить DN, пригодный для использования различными протоколами. Сейчас поддерживается rfc2253 для LDAP v3. Если требуется изменить только формат, первыми двумя параметрами можно указать пустую строку и ноль. Пример: ssl_c_s_dn(,0,rfc2253). Если значение ASN.1 запрашиваемого элемента (либо, когда <entry> не указан, любого элемента в DN) содержит встроенный байт NUL, за которым следуют другие данные, это значение считается некорректным и данные не возвращаются.

ssl_c_san: string Когда входящее соединение было установлено через транспортный уровень SSL/TLS, и предоставлен сертификат клиента, возвращает строку с перечислением полей альтернативных имён субъекта (Subject Alt Name), содержащихся в данном сертификате, разделённых запятыми.

Можно использовать для проверки сертификата клиента.

Пример:

acl is_valid_client_cert ssl_c_used && ! ssl_c_verify
http-request set-header X-SSL-Client-SAN %[ssl_c_san] if is_valid_client_cert

Результат:

X-SSL-Client-SAN: IP Address:127.0.0.1, IP Address:127.0.0.2, IP Address:127.0.0.3, URI:http://docs.haproxy.org/2.7/, DNS:ca.tests.haproxy.com

ssl_c_serial: binary Возвращает серийный номер сертификата, представленного клиентом, когда входящее соединение было установлено через транспортный уровень SSL/TLS. При использовании для ACL значения для сравнения могут передаваться в шестнадцатеричном виде.

ssl_c_sha1: binary Возвращает отпечаток SHA-1 сертификата, представленного клиентом, если входящее соединение установлено по транспортному протоколу SSL/TLS. Можно использовать для привязки клиента к серверу либо передачи этой информации серверу. Выходные данные двоичные, поэтому для передачи этого отпечатка серверу его нужно кодировать в hex либо base64, как в примере ниже:

Пример:

http-request set-header X-SSL-Client-SHA1 %[ssl_c_sha1,hex]

ssl_c_sig_alg: string Возвращает имя алгоритма, использованного для подписи сертификата, представленного клиентом, когда входящее соединение было установлено через транспортный уровень SSL/TLS.

ssl_c_used: boolean Возвращает true, если текущий сеанс SSL использует сертификат клиента, даже если текущее соединение использует возобновление сеанса SSL. См. также “ssl_fc_has_crt”.

ssl_c_verify: integer Возвращает идентификатор ошибки проверки при входящем соединении, установленном через транспортный уровень SSL/TLS, в противном случае — ноль, если ошибок не обнаружено. См. документацию вашей библиотеки SSL для получения полного списка кодов ошибок.

ssl_c_version: integer Возвращает версию сертификата, предоставленного клиентом, если входящее соединение установлено через транспортный уровень SSL/TLS.

ssl_f_der: binary Возвращает сертификат, представленный фронтендом, в формате DER, когда входящее соединение было установлено через транспортный уровень SSL/TLS. При использовании для ACL значения для сравнения могут передаваться в шестнадцатеричном виде.

ssl_f_i_dn([<entry>[,<occ>[,<format>]]]): string

ssl_f_i_dn([<entry>[,<occ>[,<format>]]]): string

Когда входящее соединение установлено по транспортному протоколу SSL/TLS, возвращает полное различимое имя (DN) издателя сертификата, представленного фронтендом, если <entry> не указан, либо значение первого вхождения указанного элемента, найденного с начала DN. Если необязательным вторым аргументом задан положительный/отрицательный номер вхождения, возвращается значение n-го вхождения указанного элемента с начала/конца DN. Например, “ssl_f_i_dn(OU,2)” возвращает второе подразделение организации, а “ssl_f_i_dn(CN)” — общее имя. Параметр <format> позволяет получить DN, пригодный для использования различными протоколами. Сейчас поддерживается rfc2253 для LDAP v3. Если требуется изменить только формат, первыми двумя параметрами можно указать пустую строку и ноль. Пример: ssl_f_i_dn(,0,rfc2253). Если значение ASN.1 запрашиваемого элемента (либо, когда <entry> не указан, любого элемента в DN) содержит встроенный байт NUL, за которым следуют другие данные, это значение считается некорректным и данные не возвращаются.

ssl_f_key_alg: string Возвращает имя алгоритма, использованного для генерации ключа сертификата, представленного фронтендом, когда входящее соединение было установлено через транспортный уровень SSL/TLS.

ssl_f_notafter: string Возвращает дату окончания, представленную фронтендом, в виде отформатированной строки YYMMDDhhmmss[Z], когда входящее соединение было установлено через транспортный уровень SSL/TLS.

ssl_f_notbefore: string Возвращает дату начала, представленную фронтендом, в виде отформатированной строки YYMMDDhhmmss[Z], когда входящее соединение было установлено через транспортный уровень SSL/TLS.

ssl_f_s_dn([<entry>[,<occ>[,<format>]]]): string

ssl_f_s_dn([<entry>[,<occ>[,<format>]]]): string

Когда входящее соединение установлено по транспортному протоколу SSL/TLS, возвращает полное различимое имя (DN) субъекта сертификата, представленного фронтендом, если <entry> не указан, либо значение первого вхождения указанного элемента, найденного с начала DN. Если необязательным вторым аргументом задан положительный/отрицательный номер вхождения, возвращается значение n-го вхождения указанного элемента с начала/конца DN. Например, “ssl_f_s_dn(OU,2)” возвращает второе подразделение организации, а “ssl_f_s_dn(CN)” — общее имя. Параметр <format> позволяет получить DN, пригодный для использования различными протоколами. Сейчас поддерживается rfc2253 для LDAP v3. Если требуется изменить только формат, первыми двумя параметрами можно указать пустую строку и ноль. Пример: ssl_f_s_dn(,0,rfc2253). Если значение ASN.1 запрашиваемого элемента (либо, когда <entry> не указан, любого элемента в DN) содержит встроенный байт NUL, за которым следуют другие данные, это значение считается некорректным и данные не возвращаются.

ssl_f_serial: binary Возвращает серийный номер сертификата, представленного фронтендом, когда входящее соединение было установлено через транспортный уровень SSL/TLS. При использовании для ACL значения для сравнения могут передаваться в шестнадцатеричном виде.

ssl_f_sha1: binary Возвращает отпечаток SHA-1 сертификата, представленного фронтендом, если входящее соединение установлено по транспортному протоколу SSL/TLS. Можно использовать, чтобы узнать, какой сертификат был выбран с помощью SNI.

ssl_f_sig_alg: string Возвращает имя алгоритма, использованного для подписи сертификата, представленного фронтендом, когда входящее соединение было установлено через транспортный уровень SSL/TLS.

ssl_f_version: integer Возвращает версию сертификата, предоставленного фронтендом, если входящее соединение установлено через транспортный уровень SSL/TLS.

ssl_fc: boolean Возвращает true, когда соединение с клиентом было установлено через транспортный уровень SSL/TLS и расшифровано локально. Это означает, что оно соответствует сокету, объявленному с помощью строки “bind” с опцией “ssl”.

Пример:

# This passes "X-Proto: https" to servers when client connects over SSL
listen http-https
    bind :80
    bind :443 ssl crt /etc/haproxy.pem
    http-request add-header X-Proto https if { ssl_fc }

ssl_fc_alg_keysize: integer Возвращает поддерживаемую длину ключа симметричного шифра в битах, если входящее соединение установлено через транспортный уровень SSL/TLS.

ssl_fc_alpn: string Извлекает поле согласования протокола прикладного уровня из входящего соединения, установленного через транспортный уровень TLS и расшифрованного локально HAProxy. Результат — строка, содержащая имя протокола, объявленное клиентом. Библиотека SSL должна быть собрана с поддержкой расширений TLS (проверьте haproxy -vv). Обратите внимание, что расширение TLS ALPN не объявляется, если ключевое слово “alpn” в строке “bind” не указывает список протоколов. Также ничто не заставляет клиента выбирать протокол из этого списка — может быть запрошен любой другой. Расширение TLS ALPN предназначено для замены расширения TLS NPN. См. также “ssl_fc_npn”.

ssl_fc_cipher: string Возвращает имя используемого шифра, если входящее соединение установлено через транспортный уровень SSL/TLS.

ssl_fc_cipherlist_bin([<filter_option>]): binary

ssl_fc_cipherlist_bin([<filter_option>]): binary

Возвращает двоичную форму списка шифров сообщения ClientHello. Максимальная длина возвращаемого значения ограничена размером общего буфера захвата, управляемым параметром “tune.ssl.capture-buffer-size”. Аргумент <filter_option> позволяет фильтровать возвращаемые данные. Допустимые значения:

0: вернуть полный список шифров (по умолчанию)
1: исключить значения GREASE (RFC8701) из результата

Пример:

http-request set-header X-SSL-JA3 %[ssl_fc_protocol_hello_id],\
    %[ssl_fc_cipherlist_bin(1),be2dec(-,2)],\
    %[ssl_fc_extlist_bin(1),be2dec(-,2)],\
    %[ssl_fc_eclist_bin(1),be2dec(-,2)],\
    %[ssl_fc_ecformats_bin,be2dec(-,1)]
acl is_malware req.fhdr(x-ssl-ja3),digest(md5),hex \
    -f /path/to/file/with/malware-ja3.lst
http-request set-header X-Malware True if is_malware
http-request set-header X-Malware False if !is_malware

ssl_fc_cipherlist_hex([<filter_option>]): string

ssl_fc_cipherlist_hex([<filter_option>]): string

Возвращает двоичную форму списка шифров сообщения ClientHello в шестнадцатеричной кодировке. Максимальная длина возвращаемого значения ограничена размером общего буфера захвата, управляемым параметром “tune.ssl.capture-buffer-size”. Аргумент <filter_option> позволяет фильтровать возвращаемые данные. Допустимые значения:

0: вернуть полный список шифров (по умолчанию)
1: исключить значения GREASE (RFC8701) из результата

ssl_fc_cipherlist_str([<filter_option>]): string

ssl_fc_cipherlist_str([<filter_option>]): string

Возвращает декодированную текстовую форму списка шифров сообщения ClientHello. Максимальная длина возвращаемого значения ограничена размером общего буфера захвата, управляемым параметром “tune.ssl.capture-buffer-size”. Аргумент <filter_option> позволяет фильтровать возвращаемые данные. Допустимые значения:

0: вернуть полный список шифров (по умолчанию)
1: исключить значения GREASE (RFC8701) из результата

Этот метод извлечения образца доступен только с OpenSSL >= 1.0.2. Если функция не включена, он возвращает хеш, как “ssl_fc_cipherlist_xxh”.

ssl_fc_cipherlist_xxh: integer Возвращает xxh64 списка шифров. Этот хеш возвращается только при значении “tune.ssl.capture-buffer-size” больше 0, однако при вычислении хеша учитываются все данные списка шифров.

ssl_fc_client_early_traffic_secret: string Возвращает CLIENT_EARLY_TRAFFIC_SECRET в виде шестнадцатеричной строки для соединения с клиентом, если входящее соединение установлено по транспортному протоколу TLS 1.3. Требуется OpenSSL >= 1.1.1. Это один из ключей, выгружаемых обратным вызовом keylog OpenSSL для формирования SSLKEYLOGFILE. Журналирование ключей SSL необходимо включить директивой “tune.ssl.keylog on” в секции global. См. также “tune.ssl.keylog”.

ssl_fc_client_handshake_traffic_secret: string Возвращает CLIENT_HANDSHAKE_TRAFFIC_SECRET в виде шестнадцатеричной строки для соединения с клиентом, если входящее соединение установлено по транспортному протоколу TLS 1.3. Требуется OpenSSL >= 1.1.1. Это один из ключей, выгружаемых обратным вызовом keylog OpenSSL для формирования SSLKEYLOGFILE. Журналирование ключей SSL необходимо включить директивой “tune.ssl.keylog on” в секции global. См. также “tune.ssl.keylog”.

ssl_fc_client_random: binary Возвращает случайное значение клиента для соединения с клиентом, когда входящее соединение было установлено через транспортный уровень SSL/TLS. Полезно для расшифровки трафика, отправленного с использованием эфемерных шифров. Требуется OpenSSL >= 1.1.0 или BoringSSL.

ssl_fc_client_traffic_secret_0: string Возвращает CLIENT_TRAFFIC_SECRET_0 в виде шестнадцатеричной строки для соединения с клиентом, если входящее соединение установлено по транспортному протоколу TLS 1.3. Требуется OpenSSL >= 1.1.1. Это один из ключей, выгружаемых обратным вызовом keylog OpenSSL для формирования SSLKEYLOGFILE. Журналирование ключей SSL необходимо включить директивой “tune.ssl.keylog on” в секции global. См. также “tune.ssl.keylog”.

ssl_fc_crtname: string Возвращает имя сертификата, выбранного для входящего соединения SSL/TLS. Это имя соответствует тому, что отображается в команде “show ssl cert”: может быть именем файла с относительным или абсолютным путём, либо псевдонимом, в зависимости от способа объявления сертификата в конфигурации.

Пример:

crt-store example
    load crt "example.com.pem"

frontend www
    bind *:443 ssl crt "@example/example.com.pem"
    acl match_certificate ssl_fc_crtname -m beg -i "@example/"
    http-request set-header X-Cert-Name %[ssl_fc_crtname] if match_certificate

ssl_fc_curve: string Возвращает имя кривой, используемой при согласовании ключей, когда входящее соединение было установлено через транспортный уровень SSL/TLS. Требуется OpenSSL >= 3.0.0.

ssl_fc_early_rcvd: boolean Возвращает true, если на этом соединении были получены данные до завершения рукопожатия, независимо от того, завершено ли оно. У него нет практических применений при обработке трафика, однако это практически единственный способ “увидеть”, что клиент использовал 0-RTT для отправки данных до завершения рукопожатия, и иногда полезен при отладке, поскольку альтернативы — захват сетевого трафика или логирование флагов соединения с клиентом с последующим сопоставлением в коде. Может также быть полезен для сбора статистики по возможностям клиентов. См. также “ssl_fc_has_early”.

ssl_fc_early_exporter_secret: string Возвращает EARLY_EXPORTER_SECRET в виде шестнадцатеричной строки для соединения с клиентом, если входящее соединение установлено по транспортному протоколу TLS 1.3. Требуется OpenSSL >= 1.1.1. Это один из ключей, выгружаемых обратным вызовом keylog OpenSSL для формирования SSLKEYLOGFILE. Журналирование ключей SSL необходимо включить директивой “tune.ssl.keylog on” в секции global. См. также “tune.ssl.keylog”.

ssl_fc_ecformats_bin: binary Возвращает двоичную форму списка форматов точек эллиптических кривых, поддерживаемых в сообщении ClientHello. Максимальная длина возвращаемого значения ограничена размером общей буферной области захвата, управляемой параметром “tune.ssl.capture-buffer-size”.

Пример:

http-request set-header X-SSL-JA3 %[ssl_fc_protocol_hello_id],\
    %[ssl_fc_cipherlist_bin(1),be2dec(-,2)],\
    %[ssl_fc_extlist_bin(1),be2dec(-,2)],\
    %[ssl_fc_eclist_bin(1),be2dec(-,2)],\
    %[ssl_fc_ecformats_bin,be2dec(-,1)]
acl is_malware req.fhdr(x-ssl-ja3),digest(md5),hex \
    -f /path/to/file/with/malware-ja3.lst
http-request set-header X-Malware True if is_malware
http-request set-header X-Malware False if !is_malware

ssl_fc_eclist_bin([<filter_option>]): binary

ssl_fc_eclist_bin([<filter_option>]): binary

Возвращает двоичную форму списка поддерживаемых эллиптических кривых в сообщении ClientHello. Максимальная длина возвращаемого значения ограничена размером общей буферной области захвата, управляемой параметром “tune.ssl.capture-buffer-size”. Параметр <filter_option> позволяет фильтровать возвращаемые данные. Допустимые значения:

0: вернуть полный список поддерживаемых эллиптических кривых (по умолчанию)
1: исключить значения GREASE (RFC8701) из результата

Пример:

http-request set-header X-SSL-JA3 %[ssl_fc_protocol_hello_id],\
    %[ssl_fc_cipherlist_bin(1),be2dec(-,2)],\
    %[ssl_fc_extlist_bin(1),be2dec(-,2)],\
    %[ssl_fc_eclist_bin(1),be2dec(-,2)],\
    %[ssl_fc_ecformats_bin,be2dec(-,1)]
acl is_malware req.fhdr(x-ssl-ja3),digest(md5),hex \
    -f /path/to/file/with/malware-ja3.lst
http-request set-header X-Malware True if is_malware
http-request set-header X-Malware False if !is_malware

ssl_fc_err: integer При входящем соединении, установленном через транспортный уровень SSL/TLS, возвращает идентификатор последней ошибки из первого стека ошибок, возникшего на стороне фронтенда, или 0, если ошибка не была обнаружена. Может использоваться для выявления ошибок, связанных с рукопожатием, кроме ошибок проверки (например, несоответствие шифров), а также других ошибок чтения или записи, возникших в течение жизненного цикла соединения. Любые ошибки, возникающие при процессе проверки сертификата клиента, не будут переданы через это извлечение, а будут переданы через существующие извлечения “ssl_c_err”, “ssl_c_ca_err” и “ssl_c_ca_err_depth”. Чтобы получить текстовое описание этого кода ошибки, можно использовать извлечение образца “ssl_fc_err_str” или команду “openssl errstr” (принимает код ошибки в шестнадцатеричном виде). Обратитесь к документации вашей библиотеки SSL для получения полного списка кодов ошибок.

ssl_fc_err_str: string При входящем соединении, установленном через транспортный уровень SSL/TLS, возвращает строковое представление последней ошибки из первого стека ошибок, возникшего на стороне фронтенда. Любые ошибки, возникающие при проверке сертификата клиента, не будут переданы через это извлечение. См. также “ssl_fc_err”.

ssl_fc_exporter_secret: string Возвращает EXPORTER_SECRET в виде шестнадцатеричной строки для соединения с клиентом, если входящее соединение установлено по транспортному протоколу TLS 1.3. Требуется OpenSSL >= 1.1.1. Это один из ключей, выгружаемых обратным вызовом keylog OpenSSL для формирования SSLKEYLOGFILE. Журналирование ключей SSL необходимо включить директивой “tune.ssl.keylog on” в секции global. См. также “tune.ssl.keylog”.

ssl_fc_extlist_bin([<filter_option>]): binary

ssl_fc_extlist_bin([<filter_option>]): binary

Возвращает двоичную форму списка расширений сообщения ClientHello. Максимальная длина возвращаемого значения ограничена размером общей буферной области захвата, управляемой параметром “tune.ssl.capture-buffer-size”. Параметр <filter_option> позволяет фильтровать возвращаемые данные. Допустимые значения:

0: вернуть полный список расширений (по умолчанию)
1: исключить значения GREASE (RFC8701) из результата

Пример:

http-request set-header X-SSL-JA3 %[ssl_fc_protocol_hello_id],\
    %[ssl_fc_cipherlist_bin(1),be2dec(-,2)],\
    %[ssl_fc_extlist_bin(1),be2dec(-,2)],\
    %[ssl_fc_eclist_bin(1),be2dec(-,2)],\
    %[ssl_fc_ecformats_bin,be2dec(-,1)]
acl is_malware req.fhdr(x-ssl-ja3),digest(md5),hex \
    -f /path/to/file/with/malware-ja3.lst
http-request set-header X-Malware True if is_malware
http-request set-header X-Malware False if !is_malware

ssl_fc_has_crt: boolean Возвращает true, если во входящем соединении по транспортному протоколу SSL/TLS присутствует сертификат клиента. Полезно, когда ‘verify’ задан как ‘optional’. Примечание: при возобновлении сессии SSL через Session ID или билет TLS сертификат клиента отсутствует в текущем соединении, но может быть извлечён из кеша либо билета. Поэтому для проверки того, использует ли текущая сессия SSL сертификат клиента, предпочтительнее “ssl_c_used”.

ssl_fc_has_early: boolean Возвращает true, если были отправлены данные до завершения рукопожатия, и рукопожатие ещё не завершено. Поскольку это имеет последствия для безопасности, полезно иметь возможность отклонять такие соединения или ждать завершения рукопожатия (с помощью действия “wait-for-handshake”). См. также “ssl_fc_early_rcvd”.

ssl_fc_has_sni: boolean Проверяет наличие расширения TLS для указания имени сервера (SNI) во входящем соединении, установленном через транспортный уровень SSL/TLS. Возвращает true, если входящее соединение содержит поле TLS SNI. Требуется, чтобы библиотека SSL была скомпилирована с поддержкой расширений TLS (проверьте haproxy -vv).

ssl_fc_is_resumed: boolean Возвращает true, если сессия SSL/TLS была восстановлена с использованием кэша сессий SSL или билетов TLS при входящем соединении через транспортный уровень SSL/TLS.

ssl_fc_npn: string Извлекает поле согласования следующего протокола из входящего соединения, установленного через транспортный уровень TLS и локально расшифрованного HAProxy. Результат — строка, содержащая имя протокола, объявленное клиентом. Библиотека SSL должна быть скомпилирована с поддержкой расширений TLS (проверьте haproxy -vv). Обратите внимание, что расширение TLS NPN не объявляется, если ключевое слово “npn” в строке “bind” не указывает список протоколов. Кроме того, клиент может выбрать любой другой протокол, не входящий в этот список. Обратите внимание, что расширение TLS NPN было заменено на ALPN.

ssl_fc_protocol: string Возвращает имя используемого протокола, если входящее соединение установлено через транспортный уровень SSL/TLS.

ssl_fc_protocol_hello_id: integer Версия протокола TLS, по которому клиент желает общаться в течение сессии, как указано в сообщении ClientHello. Значение может быть возвращено только при условии, что значение “tune.ssl.capture-buffer-size” установлено выше 0.

Пример:

http-request set-header X-SSL-JA3 %[ssl_fc_protocol_hello_id],\
    %[ssl_fc_cipherlist_bin(1),be2dec(-,2)],\
    %[ssl_fc_extlist_bin(1),be2dec(-,2)],\
    %[ssl_fc_eclist_bin(1),be2dec(-,2)],\
    %[ssl_fc_ecformats_bin,be2dec(-,1)]
acl is_malware req.fhdr(x-ssl-ja3),digest(md5),hex \
    -f /path/to/file/with/malware-ja3.lst
http-request set-header X-Malware True if is_malware
http-request set-header X-Malware False if !is_malware

ssl_fc_server_handshake_traffic_secret: string Возвращает SERVER_HANDSHAKE_TRAFFIC_SECRET в виде шестнадцатеричной строки для соединения с клиентом, если входящее соединение установлено по транспортному протоколу TLS 1.3. Требуется OpenSSL >= 1.1.1. Это один из ключей, выгружаемых обратным вызовом keylog OpenSSL для формирования SSLKEYLOGFILE. Журналирование ключей SSL необходимо включить директивой “tune.ssl.keylog on” в секции global. См. также “tune.ssl.keylog”.

ssl_fc_server_random: binary Возвращает случайное значение сервера для соединения с клиентом, когда входящее соединение было установлено через транспортный уровень SSL/TLS. Полезно для расшифровки трафика, отправленного с использованием эфемерных шифров. Требуется OpenSSL >= 1.1.0, или BoringSSL.

ssl_fc_server_traffic_secret_0: string Возвращает SERVER_TRAFFIC_SECRET_0 в виде шестнадцатеричной строки для соединения с клиентом, если входящее соединение установлено по транспортному протоколу TLS 1.3. Требуется OpenSSL >= 1.1.1. Это один из ключей, выгружаемых обратным вызовом keylog OpenSSL для формирования SSLKEYLOGFILE. Журналирование ключей SSL необходимо включить директивой “tune.ssl.keylog on” в секции global. См. также “tune.ssl.keylog”.

ssl_fc_session_id: binary Возвращает идентификатор SSL соединения с клиентом, когда входящее соединение было установлено через транспортный уровень SSL/TLS. Полезно для привязки определённого клиента к серверу. Важно отметить, что некоторые браузеры обновляют свой идентификатор сессии каждые несколько минут.

ssl_fc_session_key: binary Возвращает главный ключ сессии SSL соединения с клиентом, когда входящее соединение было установлено через транспортный уровень SSL/TLS. Полезно для расшифровки трафика, отправленного с использованием эфемерных шифров. Требуется OpenSSL >= 1.1.0, или BoringSSL.

ssl_fc_sigalgs_bin([<filter_option>]): binary

ssl_fc_sigalgs_bin([<filter_option>]): binary

Возвращает содержимое расширения signatures_algorithms (13) TLS, представленного в сообщении ClientHello. Предоставляет двоичный список алгоритмов, представленных 2 байтами, определённых в TLS RFC: https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.3 .

Значение может быть возвращено только при условии, что значение “tune.ssl.capture-buffer-size” установлено выше 0. Параметр <filter_option> позволяет фильтровать возвращаемые данные. Допустимые значения: 0: возвращает полный список шифров (по умолчанию) 1: исключает значения GREASE (RFC8701) из вывода

ssl_fc_sni: string Извлекает поле расширения TLS для указания имени сервера (SNI) из входящего соединения, установленного через транспортный уровень SSL/TLS и локально расшифрованного HAProxy. Результат (при наличии) обычно представляет собой строку, соответствующую имени хоста HTTPS (не более 253 символов). Библиотека SSL должна быть скомпилирована с поддержкой расширений TLS (проверьте haproxy -vv).

В отличие от “req.ssl_sni” выше, это извлечение применяется к соединению, расшифровываемому HAProxy, а не к содержимому SSL, пересылаемому без анализа. См. также “ssl_fc_sni_end” и “ssl_fc_sni_reg” ниже. Требуется библиотека SSL, собранная с включённой поддержкой расширений TLS (проверьте haproxy -vv).

ОСТОРОЖНО! За исключением весьма специфических условий, использовать это поле вместо поля заголовка HTTP “Host” обычно некорректно. Например, при пересылке соединения HTTPS серверу поле SNI необходимо задавать по заголовку HTTP Host с помощью “req.hdr(host)”, а не по значению SNI со стороны клиента. Причина в том, что SNI используется исключительно для выбора сертификата, который представит сторона сервера, после чего клиентам разрешается отправлять запросы с различными значениями Host, если они соответствуют именам в сертификате. Поэтому “ssl_fc_sni” обычно не следует использовать как аргумент ключевого слова “sni” сервера, кроме случая, когда бэкенд работает в режиме TCP.

Производные ACL:

ssl_fc_sni_end: сопоставление по суффиксу
ssl_fc_sni_reg: сопоставление по регулярному выражению

ssl_fc_supported_versions_bin([<filter_option>]): binary

ssl_fc_supported_versions_bin([<filter_option>]): binary

Возвращает содержимое расширения TLS supported_versions (43), представленного в сообщении ClientHello. Это двоичный список версий по 2 байта каждая: TLSv1.3 (0x0304), TLSv1.2 (0x0303).

Значение может быть возвращено только при условии, что значение “tune.ssl.capture-buffer-size” установлено выше 0. Параметр <filter_option> позволяет фильтровать возвращаемые данные. Допустимые значения: 0: возвращает полный список шифров (по умолчанию) 1: исключает значения GREASE (RFC8701) из вывода

ssl_fc_unique_id: binary Если входящее соединение установлено по транспортному протоколу SSL/TLS, возвращает уникальный идентификатор TLS, определённый в RFC5929 раздел 3 . Этот идентификатор можно кодировать в base64 преобразователем “ssl_fc_unique_id,base64”.

ssl_fc_use_keysize: integer Возвращает используемую длину ключа симметричного шифра в битах, если входящее соединение установлено через транспортный уровень SSL/TLS.

ssl_s_chain_der: binary Возвращает цепочку сертификатов в формате DER, представленную сервером при установке исходящего соединения через транспортный уровень SSL/TLS. При использовании для ACL значения, с которыми нужно сравнивать, могут передаваться в шестнадцатеричном виде. Результат можно разобрать любой библиотекой, поддерживающим данные ASN.1 DER. Это извлечение пока не поддерживает возобновлённые сессии.

ssl_s_der: binary Возвращает сертификат в формате DER, представленный сервером при установке исходящего соединения через транспортный уровень SSL/TLS. При использовании для ACL значения, с которыми нужно сравнивать, могут передаваться в шестнадцатеричном виде.

ssl_s_i_dn([<entry>[,<occ>[,<format>]]]): string

ssl_s_i_dn([<entry>[,<occ>[,<format>]]]): string

Когда исходящее соединение установлено по транспортному протоколу SSL/TLS, возвращает полное различимое имя (DN) издателя сертификата, представленного сервером, если <entry> не указан, либо значение первого вхождения указанного элемента, найденного с начала DN. Если необязательным вторым аргументом задан положительный/отрицательный номер вхождения, возвращается значение n-го вхождения указанного элемента с начала/конца DN. Например, “ssl_s_i_dn(OU,2)” возвращает второе подразделение организации, а “ssl_s_i_dn(CN)” — общее имя. Параметр <format> позволяет получить DN, пригодный для использования различными протоколами. Сейчас поддерживается rfc2253 для LDAP v3. Если требуется изменить только формат, первыми двумя параметрами можно указать пустую строку и ноль. Пример: ssl_s_i_dn(,0,rfc2253). Если значение ASN.1 запрашиваемого элемента (либо, когда <entry> не указан, любого элемента в DN) содержит встроенный байт NUL, за которым следуют другие данные, это значение считается некорректным и данные не возвращаются.

ssl_s_key_alg: string Возвращает имя алгоритма, использованного для генерации ключа сертификата, представленного сервером при установке исходящего соединения через транспортный уровень SSL/TLS.

ssl_s_notafter: string Возвращает дату окончания, представленную сервером в виде отформатированной строки YYMMDDhhmmss[Z] при установке исходящего соединения через транспортный уровень SSL/TLS.

ssl_s_notbefore: string Возвращает дату начала, представленную сервером в виде отформатированной строки YYMMDDhhmmss[Z] при установке исходящего соединения через транспортный уровень SSL/TLS.

ssl_s_s_dn([<entry>[,<occ>[,<format>]]]): string

ssl_s_s_dn([<entry>[,<occ>[,<format>]]]): string

Когда исходящее соединение установлено по транспортному протоколу SSL/TLS, возвращает полное различимое имя (DN) субъекта сертификата, представленного сервером, если <entry> не указан, либо значение первого вхождения указанного элемента, найденного с начала DN. Если необязательным вторым аргументом задан положительный/отрицательный номер вхождения, возвращается значение n-го вхождения указанного элемента с начала/конца DN. Например, “ssl_s_s_dn(OU,2)” возвращает второе подразделение организации, а “ssl_s_s_dn(CN)” — общее имя. Параметр <format> позволяет получить DN, пригодный для использования различными протоколами. Сейчас поддерживается rfc2253 для LDAP v3. Если требуется изменить только формат, первыми двумя параметрами можно указать пустую строку и ноль. Пример: ssl_s_s_dn(,0,rfc2253). Если значение ASN.1 запрашиваемого элемента (либо, когда <entry> не указан, любого элемента в DN) содержит встроенный байт NUL, за которым следуют другие данные, это значение считается некорректным и данные не возвращаются.

ssl_s_serial: binary Возвращает серийный номер сертификата, представленного сервером при установке исходящего соединения через транспортный уровень SSL/TLS. При использовании для ACL значения, с которыми нужно сравнивать, могут передаваться в шестнадцатеричном виде.

ssl_s_sha1: binary Возвращает отпечаток SHA-1 сертификата, представленного сервером при установке исходящего соединения через транспортный уровень SSL/TLS. Это может использоваться для определения, какой сертификат был выбран с помощью SNI.

ssl_s_sig_alg: string Возвращает имя алгоритма, использованного для подписи сертификата, представленного сервером при установке исходящего соединения через транспортный уровень SSL/TLS.

ssl_s_version: integer Возвращает версию сертификата, предоставленного сервером, если исходящее соединение установлено через транспортный уровень SSL/TLS.

txn.timer.user: integer Полное оценочное время с точки зрения клиента от момента принятия соединения прокси до закрытия обоих концов, без времени простоя. Соответствует %Tu в log-format и выражается в миллисекундах (ms). Подробнее см. раздел 8.4 «Временные события».

7.3.5. Извлечение образцов из содержимого буферов (уровень 6)

Извлечение образцов из содержимого буфера отличается от предыдущих извлечений образцов тем, что извлекаемые данные являются временными. Эти данные можно использовать только тогда, когда они доступны, и будут потеряны при передаче. В связи с этим образцы, извлечённые из содержимого буфера во время запроса, не могут быть использованы в ответе, например. Даже во время извлечения данные могут изменяться. Иногда необходимо установить задержки или объединить несколько методов извлечения образцов, чтобы гарантировать, что ожидаемые данные будут полными и пригодными к использованию, например, с помощью проверки содержимого запроса TCP. Подробнее см. ключевое слово “tcp-request content”.

Предупреждение: следующие извлечения образцов игнорируются, если используются в прокси HTTP. Они работают только с сырыми данными, найденными в буферах. С другой стороны, прокси HTTP используют структурированные данные. Таким образом, сырое представление этих данных не имеет смысла. При использовании ACL, зависящего от одного из следующих извлечений образцов, выдаётся предупреждение. Однако невозможно обнаружить все некорректные случаи использования (например, внутри пользовательского формата журнала или выражения образца). Будьте осторожны.

Сводка методов извлечения образцов в этом разделе и их соответствующие типы:

  Ключевое слово                                      Выходной тип
----------------------------------------------------+-------------
distcc_body(<token>[,<occ>])                          binary
distcc_param(<token>[,<occ>])                         integer
payload(<offset>,<length>)                            binary
payload_lv(<offset1>,<length>[,<offset2>])            binary
rdp_cookie([<name>])                                  string
rdp_cookie_cnt([name])                                integer
rep_ssl_hello_type                                    integer
req.len                                               integer
req.payload(<offset>,<length>)                        binary
req.payload_lv(<offset1>,<length>[,<offset2>])        binary
req.proto_http                                        boolean
req.rdp_cookie([<name>])                              string
req.rdp_cookie_cnt([name])                            integer
req.ssl_alpn                                          string
req.ssl_cipherlist                                    binary
req.ssl_ec_ext                                        boolean
req.ssl_hello_type                                    integer
req.ssl_keyshare_groups                               binary
req.ssl_sigalgs                                       binary
req.ssl_sni                                           string
req.ssl_st_ext                                        integer
req.ssl_supported_groups                              binary
req.ssl_ver                                           integer
req_len                                               integer
req_proto_http                                        boolean
req_ssl_hello_type                                    integer
req_ssl_sni                                           string
req_ssl_ver                                           integer
res.len                                               integer
res.payload(<offset>,<length>)                        binary
res.payload_lv(<offset1>,<length>[,<offset2>])        binary
res.ssl_hello_type                                    integer
----------------------------------------------------+-------------

Подробный список:

distcc_body(<token>[,<occ>]): binary

distcc_body(<token>[,<occ>]): binary

Анализирует сообщение distcc и возвращает тело, соответствующее вхождению #<occ> токена <token>. Вхождения начинаются с 1, и если номер не указан, может совпадать любое, хотя на практике пока проверяется только первое. Это можно использовать для извлечения имён файлов или аргументов в файлах, собранных с помощью distcc через HAProxy. См. документацию протокола distcc для полного списка поддерживаемых токенов.

distcc_param(<token>[,<occ>]): integer

distcc_param(<token>[,<occ>]): integer

Анализирует сообщение distcc и возвращает параметр, соответствующий вхождению #<occ> токена <token>. Вхождения начинаются с 1, и если номер не указан, может совпадать любое, хотя на практике пока проверяется только первое. Это можно использовать для извлечения определённой информации, такой как версия протокола, размер файла или аргумент в файлах, собранных с помощью distcc через HAProxy. Другой пример использования — ожидание начала содержимого предварительно обработанного файла перед подключением к серверу, чтобы избежать неактивных соединений. См. документацию протокола distcc для полного списка поддерживаемых токенов.

Пример:

# wait up to 20s for the pre-processed file to be uploaded
tcp-request inspect-delay 20s
tcp-request content accept if { distcc_param(DOTI) -m found }
# send large files to the big farm
use_backend big_farm if { distcc_param(DOTI) gt 1000000 }

payload(<offset>,<length>): binary (deprecated)

payload(<offset>,<length>): binary (deprecated)

Это псевдоним для “req.payload” при использовании в контексте запроса (например, “stick on”, “stick match”) и для “res.payload” при использовании в контексте ответа, например, в “stick store response”.

payload_lv(<offset1>,<length>[,<offset2>]): binary (deprecated)

payload_lv(<offset1>,<length>[,<offset2>]): binary (deprecated)

Это псевдоним для “req.payload_lv” при использовании в контексте запроса (например, “stick on”, “stick match”) и для “res.payload_lv” при использовании в контексте ответа, например, в “stick store response”.

req.len: integer req_len: integer (устарело) Возвращает целочисленное значение, соответствующее количеству байтов в буфере запроса. Используется в основном в ACL. Важно понимать, что этот тест не возвращает false, пока буфер изменяется. Это означает, что проверка на равенство нулю почти всегда немедленно совпадает в начале сессии, тогда как проверка наличия дополнительных данных будет ждать поступления данных и вернёт false только тогда, когда HAProxy уверен, что больше данных не поступит. Этот тест был разработан для использования с анализом содержимого запроса TCP.

req.payload(<offset>,<length>): binary

req.payload(<offset>,<length>): binary

Извлекает двоичный блок из <length> байтов, начиная с байта <offset> в буфере запроса. В качестве особого случая, если аргумент <length> равен нулю, извлекается весь буфер от <offset> до конца. Это можно использовать с ACL для проверки наличия определённого содержимого в буфере в любом месте.

Производные ACL:

req.payload(<offset>,<length>): двоичное сопоставление в шестнадцатеричном виде

req.payload_lv(<offset1>,<length>[,<offset2>]): binary

req.payload_lv(<offset1>,<length>[,<offset2>]): binary

Извлекает двоичный блок, размер которого записан в поле длиной <length> байтов по смещению <offset1>, а начало находится по смещению <offset2>, если оно указано, либо сразу после поля длины в буфере запроса. Параметр <offset2> также поддерживает относительные смещения, если перед ним стоит знак ‘+’ либо ‘-’.

Производные ACL:

req.payload_lv(<offset1>,<length>[,<offset2>]): двоичное сопоставление в шестнадцатеричном виде

Пример: см. пример для ключевого слова “stick store-response”.

req.proto_http: boolean req_proto_http: boolean (устарело) Возвращает true, когда данные в буфере запроса похожи на HTTP и правильно разбираются как HTTP. Используется тот же анализатор, что и для обычных запросов HTTP, поэтому неожиданностей быть не должно. Тест не даёт совпадения до завершения разбора запроса, ошибки или истечения тайм-аута. Можно использовать для указания протокола в журналах TCP, но основное применение — задерживать анализ запроса TCP до появления полного запроса HTTP в буфере, например для отслеживания заголовка.

Пример:

# track request counts per "base" (concatenation of Host+URL)
tcp-request inspect-delay 10s
tcp-request content reject if !HTTP
tcp-request content track-sc0 base table req-rate

req.rdp_cookie([<name>]): string

req.rdp_cookie([<name>]): string
rdp_cookie([<name>]): string (deprecated)

Когда буфер запроса похож на протокол RDP, извлекает cookie RDP <name> либо любой cookie, если имя не задано. Разбор проверяет только первый cookie, как показано в спецификации протокола RDP. Имя cookie нечувствительно к регистру. Обычно используется имя cookie “MSTS”, поскольку при надлежащей настройке клиента он может содержать имя пользователя клиента, подключающегося к серверу. Для привязки сеансов к серверам также часто используется cookie “MSTSHASH”.

Отличается от “balance rdp-cookie” тем, что может использоваться любой алгоритм балансировки, и поэтому распределение клиентов между серверами бэкенда не связано с хешем cookie RDP. Предполагается, что использование алгоритма балансировки, такого как “balance roundrobin” или “balance leastconn”, приведёт к более равномерному распределению клиентов между серверами бэкенда по сравнению с хешем, используемым в “balance rdp-cookie”.

Производные ACL:

req.rdp_cookie([<name>]): точное сопоставление строки

Пример:

listen tse-farm
    bind 0.0.0.0:3389
    # wait up to 5s for an RDP cookie in the request
    tcp-request inspect-delay 5s
    tcp-request content accept if RDP_COOKIE
    # apply RDP cookie persistence
    persist rdp-cookie
    # Persist based on the mstshash cookie
    # This is only useful makes sense if
    # balance rdp-cookie is not used
    stick-table type string size 204800
    stick on req.rdp_cookie(mstshash)
    server srv1 1.1.1.1:3389
    server srv1 1.1.1.2:3389

См. также “balance rdp-cookie”, “persist rdp-cookie”, “tcp-request” и ACL “req.rdp_cookie”.

req.rdp_cookie_cnt([name]): integer

req.rdp_cookie_cnt([name]): integer
rdp_cookie_cnt([name]): integer (deprecated)

Пытается разобрать буфер запроса как протокол RDP, затем возвращает целое число, соответствующее количеству найденных cookie RDP. Если указано необязательное имя cookie, учитываются только совпадающие по имени. Используется в основном в ACL.

Производные ACL:

req.rdp_cookie_cnt([<name>]): целочисленное сопоставление

req.ssl_alpn: string Возвращает строку со значениями расширения TLS согласования протокола прикладного уровня (ALPN, RFC7301), отправленного клиентом в сообщении SSL ClientHello. Обратите внимание, что это применяется только к необработанному содержимому буфера запроса, а не к содержимому, расшифрованному через слой данных SSL, поэтому не работает со строками “bind”, имеющими опцию “ssl”. Это полезно в ACL для принятия решения о маршрутизации на основе предпочтений ALPN клиента TLS, как в примере ниже. См. также “ssl_fc_alpn”. Это извлечение анализирует только первое сообщение ClientHello в буфере запроса; подробнее о последствиях этого ограничения (HelloRetryRequest, повторное согласование, Encrypted Client Hello) см. в документации ключевого слова “req.ssl_sni”.

Примеры:

# Wait for a client hello for at most 5 seconds
tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }
use_backend bk_acme if { req.ssl_alpn acme-tls/1 }
default_backend bk_default

req.ssl_cipherlist binary

req.ssl_cipherlist binary

Возвращает двоичную форму списка поддерживаемых клиентом вариантов симметричных шифров, указанных в содержимом сообщения ClientHello TLS. Обратите внимание, что это применяется только к сырым данным, найденным в буфере запроса, а не к данным, расшифрованным через уровень данных SSL, поэтому это не будет работать со строками “bind”, имеющими опцию “ssl”. См. “ssl_fc_cipherlist_bin”, который является эквивалентом для SSL bind, используемым при указании опции “ssl”. Это извлечение анализирует только первое сообщение ClientHello, найденное в буфере запроса, см. документацию ключевого слова “req.ssl_sni” для более подробной информации об ограничениях (HelloRetryRequest, повторное согласование, Encrypted Client Hello).

Примеры:

# Wait for a client hello for at most 5 seconds
tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }
use-server fe3 if { req.ssl_cipherlist,be2hex(:,2),lower -m sub 1302:009f }
server fe3  ${htst_fe3_addr}:${htst_fe3_port}

req.ssl_ec_ext: boolean Возвращает логическое значение, указывающее, отправил ли клиент расширение поддерживаемых эллиптических кривых, определённое в RFC4492, раздел 5.1 , в сообщении SSL ClientHello. Это позволяет предоставлять совместимым с ECC клиентам сертификат EC, а для всех остальных использовать RSA на том же адресе IP. Обратите внимание, что это применяется только к необработанному содержимому буфера запроса, а не к содержимому, расшифрованному через слой данных SSL, поэтому не работает со строками “bind”, имеющими опцию “ssl”. Это извлечение анализирует только первое сообщение ClientHello в буфере запроса; подробнее о последствиях этого ограничения (HelloRetryRequest, повторное согласование, Encrypted Client Hello) см. в документации ключевого слова “req.ssl_sni”.

req.ssl_hello_type: integer req_ssl_hello_type: integer (устарело) Возвращает целое число с типом сообщения приветствия SSL, найденного в буфере запроса, если данные буфера разбираются как полное сообщение приветствия клиента SSL (v3 или выше). Обратите внимание, что это применяется только к необработанному содержимому буфера запроса, а не к содержимому, расшифрованному через слой данных SSL, поэтому не работает со строками “bind”, имеющими опцию “ssl”. В основном используется в ACL для обнаружения сообщения приветствия SSL, которое предположительно содержит идентификатор сессии SSL, пригодный для привязки. Это извлечение анализирует только первое сообщение ClientHello в буфере запроса; подробнее о последствиях этого ограничения (HelloRetryRequest, повторное согласование, Encrypted Client Hello) см. в документации ключевого слова “req.ssl_sni”.

req.ssl_keyshare_groups binary

req.ssl_keyshare_groups binary

Возвращает двоичную форму списка криптографических параметров обмена ключами, поддерживаемых клиентом и указанных в TLS ClientHello. В TLS v1.3 keyshare входит в сообщение ClientHello и является последним расширением приветствия клиента. Обратите внимание, что это применяется только к необработанному содержимому буфера запроса, а не к содержимому, расшифрованному через слой данных SSL, поэтому не работает со строками “bind”, имеющими опцию “ssl”. Это извлечение анализирует только первое сообщение ClientHello в буфере запроса; подробнее о последствиях этого ограничения (HelloRetryRequest, повторное согласование, Encrypted Client Hello) см. в документации ключевого слова “req.ssl_sni”.

Примеры:

# Wait for a client hello for at most 5 seconds
tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }
use-server fe3 if { req.ssl_keyshare_groups,be2hex(:,2),lower -m sub 001d  }
server fe3  ${htst_fe3_addr}:${htst_fe3_port}

req.ssl_sigalgs binary

req.ssl_sigalgs binary

Возвращает двоичную форму списка алгоритмов подписи, поддерживаемых клиентом и указанных в TLS ClientHello. Он доступен как расширение приветствия клиента. Обратите внимание, что это применяется только к необработанному содержимому буфера запроса, а не к содержимому, расшифрованному через слой данных SSL, поэтому не работает со строками “bind”, имеющими опцию “ssl”. См. “ssl_fc_sigalgs_bin” — эквивалент для SSL bind, который можно использовать при указанной опции “ssl”. Это извлечение анализирует только первое сообщение ClientHello в буфере запроса; подробнее о последствиях этого ограничения (HelloRetryRequest, повторное согласование, Encrypted Client Hello) см. в документации ключевого слова “req.ssl_sni”.

Примеры:

# Wait for a client hello for at most 5 seconds
tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }
use-server fe4 if { req.ssl_sigalgs,be2hex(:,2),lower -m sub 0403:0805 }
server fe4  ${htst_fe4_addr}:${htst_fe4_port}

req.ssl_sni: string req_ssl_sni: string (устарело) Возвращает строку со значением расширения TLS имени сервера, отправленного клиентом в потоке TLS, проходящем через буфер запроса, если данные буфера разбираются как полное сообщение приветствия клиента SSL (v3 или выше). Обратите внимание, что это применяется только к необработанному содержимому буфера запроса, а не к содержимому, расшифрованному через слой данных SSL, поэтому не работает со строками “bind”, имеющими опцию “ssl”. Работает только с протоколами, использующими неявный TLS, такими как HTTPS (443), IMAPS (993), SMTPS (465), но не с протоколами с явным TLS, такими как SMTP (25/587) либо IMAP (143). SNI обычно содержит имя хоста, к которому клиент пытается подключиться (для современных браузеров). Этот тест предназначен для анализа содержимого запроса TCP. Если нужно переключение по содержимому, рекомендуется сначала дождаться полного приветствия клиента (тип 1), как в примере ниже. См. также “ssl_fc_sni”. Учитывайте, что по причинам, подробно описанным ниже (HelloRetryRequest, повторное согласование, Encrypted Client Hello), значение этого извлечения недостаточно надёжно для самостоятельного разрешения или запрета доступа к определённым хостам.

Это извлечение разбирает только первое сообщение ClientHello, найденное в буфере запроса. Если клиент отправляет несколько сообщений ClientHello в одном потоке TCP, например потому, что сервер запросил HelloRetryRequest (HRR) в рамках TLS 1.3, либо клиент начинает повторное согласование TLS (позже в том же потоке TCP отправляется новое ClientHello, возможно с другим SNI), возвращается только SNI самого первого ClientHello; содержимое любых последующих ClientHello игнорируется.

При использовании Encrypted Client Hello (ECH) в сети видно только “Outer” ClientHello, содержащее настоящее зашифрованное “Inner” ClientHello. В этом случае извлечение получает SNI из Outer ClientHello — подставной SNI, а не настоящий хост, к которому намерен обратиться клиент. Сейчас это извлечение не умеет расшифровывать или анализировать Inner ClientHello, поэтому при использовании ECH на него нельзя полагаться для решений о маршрутизации или контроле доступа.

Производные ACL:

req.ssl_sni: точное сопоставление строки

Примеры:

# Wait for a client hello for at most 5 seconds
tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }
use_backend bk_allow if { req.ssl_sni -f allowed_sites }
default_backend bk_sorry_page

req.ssl_st_ext: integer Возвращает 0, если клиент не отправил расширение TLS SessionTicket (RFC5077). Возвращает 1, если клиент отправил расширение TLS SessionTicket. Возвращает 2, если клиент также отправил TLS SessionTicket ненулевой длины. Обратите внимание, что это применяется только к необработанному содержимому буфера запроса, а не к содержимому, расшифрованному через слой данных SSL, поэтому не работает со строками “bind”, имеющими опцию “ssl”. Например, это позволяет обнаружить, отправил ли клиент SessionTicket, и выбрать привязку соответственно: при отсутствии SessionTicket использовать привязку по SessionID либо не применять привязку, поскольку при использовании SessionTickets состояние на стороне сервера отсутствует. Это извлечение анализирует только первое сообщение ClientHello в буфере запроса; подробнее о последствиях этого ограничения (HelloRetryRequest, повторное согласование, Encrypted Client Hello) см. в документации ключевого слова “req.ssl_sni”.

req.ssl_supported_groups binary

req.ssl_supported_groups binary

Возвращает двоичную форму списка поддерживаемых клиентом групп, указанных в TLS ClientHello и используемых для обмена ключами; они могут включать обмен как на эллиптических кривых, так и без EC. Обратите внимание, что это применяется только к необработанному содержимому буфера запроса, а не к содержимому, расшифрованному через слой данных SSL, поэтому не работает со строками “bind”, имеющими опцию “ssl”. См. “ssl_fc_eclist_bin” — эквивалент для SSL bind, который можно использовать при указанной опции “ssl”. Это извлечение анализирует только первое сообщение ClientHello в буфере запроса; подробнее о последствиях этого ограничения (HelloRetryRequest, повторное согласование, Encrypted Client Hello) см. в документации ключевого слова “req.ssl_sni”.

Примеры:

# Wait for a client hello for at most 5 seconds
tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }
use-server fe3 if { req.ssl_supported_groups, be2hex(:,2),lower -m sub 0017 }
server fe3  ${htst_fe3_addr}:${htst_fe3_port}

req.ssl_ver: integer req_ssl_ver: integer (устарело) Возвращает целое число с версией протокола SSL/TLS потока, присутствующего в буфере запроса. Поддерживаются сообщения приветствия SSLv2 и сообщения SSLv3. TLSv1 объявляется как версия SSL 3.1. Значение складывается из старшей версии, умноженной на 65536, и младшей версии. Обратите внимание, что это применяется только к необработанному содержимому буфера запроса, а не к содержимому, расшифрованному через слой данных SSL, поэтому не работает со строками “bind”, имеющими опцию “ssl”. Версия теста для ACL сопоставляет десятичную запись вида MAJOR.MINOR (например, 3.1). В основном это извлечение используется в ACL. Это извлечение анализирует только первое сообщение ClientHello в буфере запроса; подробнее о последствиях этого ограничения (HelloRetryRequest, повторное согласование, Encrypted Client Hello) см. в документации ключевого слова “req.ssl_sni”.

Производные ACL:

req.ssl_ver: сопоставление десятичных чисел

res.len: integer Возвращает целое число байтов, присутствующих в буфере ответа. В основном используется в ACL. Важно понимать, что этот тест не возвращает false, пока буфер меняется. Поэтому проверка равенства нулю почти всегда немедленно совпадёт в начале потока, тогда как проверка наличия большего объёма данных будет ждать их поступления и вернёт false только тогда, когда HAProxy уверен, что данные больше не поступят. Этот тест предназначен для анализа содержимого ответа TCP, но также может использоваться в правилах expect на основе tcp-check.

res.payload(<offset>,<length>): binary

res.payload(<offset>,<length>): binary

Извлекает двоичный блок длиной <length> байтов, начиная с байта <offset> в буфере ответа. Особый случай: если аргумент <length> равен нулю, извлекается весь буфер от <offset> до конца. Можно использовать с ACL для проверки наличия определённого содержимого в любом месте буфера. Также может использоваться в правилах expect на основе tcp-check.

res.payload_lv(<offset1>,<length>[,<offset2>]): binary

res.payload_lv(<offset1>,<length>[,<offset2>]): binary

Извлекает двоичный блок, размер которого записан в поле длиной <length> байтов по смещению <offset1>, а начало находится по смещению <offset2>, если оно указано, либо сразу после поля длины в буфере ответа. Параметр <offset2> также поддерживает относительные смещения, если перед ним стоит знак ‘+’ либо ‘-’. Также может использоваться в правилах expect на основе tcp-check.

Пример: см. пример для ключевого слова “stick store-response”.

res.ssl_hello_type: integer rep_ssl_hello_type: integer (устарело) Возвращает целое число с типом сообщения приветствия SSL, найденного в буфере ответа, если данные буфера разбираются как полное сообщение приветствия SSL (v3 или выше). Это применяется только к необработанному содержимому буфера ответа, а не к содержимому, расшифрованному через слой данных SSL, поэтому не работает со строками “server”, имеющими опцию “ssl”. В основном используется в ACL для обнаружения сообщения приветствия SSL, которое предположительно содержит идентификатор сессии SSL, пригодный для привязки.

7.3.6. Извлечение образцов HTTP (уровень 7)

Можно извлекать образцы из содержимого HTTP, запросов и ответов. Этот прикладной уровень также называют уровнем 7. Данные из этого раздела можно извлечь только после разбора полного запроса или ответа HTTP из соответствующего буфера запроса или ответа. Это всегда выполняется для всех правил, специфичных для HTTP, и секций с “mode http”. При анализе содержимого TCP может потребоваться задержка анализа, чтобы сначала дождаться запроса или ответа. Эти извлечения могут требовать несколько больше ресурсов CPU, чем извлечения уровня 4, но ненамного, поскольку запросы и ответы индексируются.

Примечание: обработка HTTP в правилах tcp-request content в прокси HTTP работает ожидаемым образом. Однако в прокси TCP без переключения на HTTP она работает только для содержимого HTTP/1. В содержимом HTTP/2 видна только начальная последовательность. Поэтому можно использовать только извлечения образцов “req.proto_http”, “req.ver” и, возможно, “method”. Все остальные извлечения образцов L7 завершаются неудачей. После переключения на HTTP они работают так же, как в прокси HTTP.

Сводка методов извлечения образцов в этом разделе и их соответствующие типы:

  Ключевое слово                                   Выходной тип
-------------------------------------------------+-------------
base                                               string
base32                                             integer
base32+src                                         binary
baseq                                              string
capture.req.hdr(<idx>)                             string
capture.req.method                                 string
capture.req.uri                                    string
capture.req.ver                                    string
capture.res.hdr(<idx>)                             string
capture.res.ver                                    string
cook([<name>])                                     string
cook_cnt([<name>])                                 integer
cook_val([<name>])                                 integer
cookie([<name>])                                   string
hdr([<name>[,<occ>]])                              string
hdr_cnt([<header>])                                integer
hdr_ip([<name>[,<occ>]])                           ip
hdr_val([<name>[,<occ>]])                          integer
http_auth(<userlist>)                              boolean
http_auth_bearer([<header>])                       string
http_auth_group(<userlist>)                        string
http_auth_pass                                     string
http_auth_type                                     string
http_auth_user                                     string
http_first_req                                     boolean
method                                             integer
path                                               string
pathq                                              string
query([<options>])                                 string
req.body                                           binary
req.body_len                                       integer
req.body_param([<name>[,i]])                       string
req.body_size                                      integer
req.cook([<name>])                                 string
req.cook_cnt([<name>])                             integer
req.cook_names([<delim>])                          string
req.cook_val([<name>])                             integer
req.fhdr(<name>[,<occ>])                           string
req.fhdr_cnt([<name>])                             integer
req.hdr([<name>[,<occ>]])                          string
req.hdr_cnt([<name>])                              integer
req.hdr_ip([<name>[,<occ>]])                       ip
req.hdr_names([<delim>])                           string
req.hdr_val([<name>[,<occ>]])                      integer
req.hdrs                                           string
req.hdrs_bin                                       binary
req.timer.hdr                                      integer
req.timer.idle                                     integer
req.timer.queue                                    integer
req.timer.tq                                       integer
req.ver                                            string
req_ver                                            string
request_date([<unit>])                             integer
res.body                                           binary
res.body_len                                       integer
res.body_size                                      integer
res.cache_hit                                      boolean
res.cache_name                                     string
res.comp                                           boolean
res.comp_algo                                      string
res.cook([<name>])                                 string
res.cook_cnt([<name>])                             integer
res.cook_names([<delim>])                          string
res.cook_val([<name>])                             integer
res.fhdr([<name>[,<occ>]])                         string
res.fhdr_cnt([<name>])                             integer
res.hdr([<name>[,<occ>]])                          string
res.hdr_cnt([<name>])                              integer
res.hdr_ip([<name>[,<occ>]])                       ip
res.hdr_names([<delim>])                           string
res.hdr_val([<name>[,<occ>]])                      integer
res.hdrs                                           string
res.hdrs_bin                                       binary
res.timer.hdr                                      integer
res.ver                                            string
resp_ver                                           string
scook([<name>])                                    string
scook_cnt([<name>])                                integer
scook_val([<name>])                                integer
server_status                                      integer
set-cookie([<name>])                               string
shdr([<name>[,<occ>]])                             string
shdr_cnt([<name>])                                 integer
shdr_ip([<name>[,<occ>]])                          ip
shdr_val([<name>[,<occ>]])                         integer
status                                             integer
txn.status                                         integer
txn.timer.total                                    integer
unique-id                                          string
url                                                string
url32                                              integer
url32+src                                          binary
url_ip                                             ip
url_param([<name>[,<delim>[,i]]])                  string
url_port                                           integer
urlp([<name>[,<delim>[,i]]])                       string
urlp_val([<name>[,<delim>[,i]]])                   integer
-------------------------------------------------+-------------

Подробный список:

base: string Возвращает объединение первого заголовка Host и части пути запроса, которая начинается с первой косой черты и заканчивается перед вопросительным знаком. В средах с виртуальным хостингом это полезно для обнаружения злоупотреблений URL и повышения эффективности общих кешей. Использование с таблицей привязок ограниченного размера также позволяет собирать статистику по наиболее часто запрашиваемым объектам для каждой пары хост/путь. В ACL это позволяет задавать простые правила переключения по содержимому, одновременно учитывающие хост и путь, например “www.example.com/favicon.ico ”. См. также “path” и “uri”.

Производные ACL:

base    : точное сопоставление строки
base_beg: сопоставление по префиксу
base_dir: сопоставление по подкаталогу
base_dom: сопоставление по домену
base_end: сопоставление по суффиксу
base_len: сопоставление по длине
base_reg: сопоставление по регулярному выражению
base_sub: сопоставление по подстроке

Примечание: производные ACL нельзя использовать с последующим преобразователем или в ACL с методом сопоставления шаблонов “-m”.

base32: integer Возвращает 32-битный хеш значения, возвращаемого описанным выше извлечением “base”. Это полезно для отслеживания активности по отдельным URL на сайтах с высоким трафиком без хранения всех URL. Вместо них сохраняется более короткий хеш, что существенно экономит память. Выходной тип — беззнаковое целое число. Используется хеш-функция SDBM с полным лавинным преобразованием результата. Технически base32 в точности равен “base,sdbm(1)”.

base32+src: binary Возвращает объединение результатов извлечения base32 выше и src ниже. Результат имеет двоичный тип и размер 8 или 20 байтов в зависимости от семейства исходного адреса. Можно использовать для отслеживания счётчиков по отдельным IP и URL.

baseq: string Возвращает объединение первого заголовка Host и части пути запроса вместе со строкой запроса, начиная с первой косой черты. Использование вместо “base” позволяет правильно определить целевой ресурс для статистики или кеширования. См. также “path”, “pathq” и “base”.

capture.req.hdr(<idx>): string

capture.req.hdr(<idx>): string

Извлекает содержимое заголовка, захваченного директивой “capture request header”; idx — позиция ключевого слова capture в конфигурации. Первая запись имеет индекс 0. См. также “capture request header”.

capture.req.method: string Извлекает метод (METHOD) запроса HTTP. Можно использовать как в запросе, так и в ответе. В отличие от “method”, доступно и в запросе, и в ответе, поскольку для этого значения выделяется память.

capture.req.uri: string Извлекает URI запроса, который начинается с первой косой черты и заканчивается перед первым пробелом в запросе (без части с хостом). В отличие от “path” и “url”, доступно и в запросе, и в ответе, поскольку для этого значения выделяется память.

capture.req.ver: string Извлекает версию HTTP из запроса и возвращает её в формате “HTTP/<major>.<minor>”. Можно использовать в запросах, ответах и журналах, поскольку используется сохраняемая информация. Если версия запроса недопустима, извлечение образца завершается неудачей.

capture.res.hdr(<idx>): string

capture.res.hdr(<idx>): string

Извлекает содержимое заголовка, захваченного директивой “capture response header”; idx — позиция ключевого слова capture в конфигурации. Первая запись имеет индекс 0. См. также “capture response header”.

capture.res.ver: string Извлекает версию HTTP из ответа и возвращает её в формате “HTTP/<major>.<minor>”. Можно использовать в журналах, поскольку используется сохраняемая информация. Если версия ответа недопустима, извлечение образца завершается неудачей.

cookie([<name>]): string (deprecated)

cookie([<name>]): string (deprecated)

Извлекает последнее вхождение cookie с именем <name> из строки заголовка “Cookie” в запросе либо заголовка “Set-Cookie” в ответе и возвращает его значение в виде строки. Обычно применяется, чтобы несколько клиентов с общим профилем использовали один сервер. Это похоже на поведение “appsession” с “request-learn”, но поддерживает синхронизацию между несколькими узлами и сохранение состояния при перезапусках. Если имя не задано, возвращается значение первого cookie. Это извлечение больше не следует использовать: его следует заменить на req.cook() либо res.cook(), поскольку направление неоднозначно определяется контекстом использования.

hdr([<name>[,<occ>]]): string

hdr([<name>[,<occ>]]): string

При использовании с запросами эквивалентно req.hdr(), а с ответами — res.hdr(). Подробности см. в описаниях этих извлечений. Если направление извлечения вызывает сомнения, используйте явные варианты. Обратите внимание, что в отличие от метода извлечения образцов hdr(), ключевые слова ACL hdr_* однозначно применяются к заголовкам запроса.

http_auth(<userlist>): boolean

http_auth(<userlist>): boolean

Возвращает логическое значение, указывающее, соответствуют ли полученные от клиента данные аутентификации имени пользователя и паролю, сохранённым в указанном userlist. Эта функция извлечения практически бесполезна вне ACL. Сейчас поддерживается только базовая аутентификация HTTP.

http_auth_bearer([<header>]): string

http_auth_bearer([<header>]): string

Возвращает предоставленный клиентом токен из данных авторизации при использовании схемы Bearer (например, для передачи JSON Web Tokens). Данные, отправленные клиентом, не проверяются. Если указан конкретный <header>, разбирается этот заголовок вместо Authorization.

http_auth_group(<userlist>): string

http_auth_group(<userlist>): string

Возвращает строку с именем пользователя из полученных от клиента данных аутентификации, если и имя пользователя, и пароль действительны согласно указанному userlist. Основное назначение — использование в ACL, где затем проверяется принадлежность пользователя к какой-либо группе из списка. Эта функция извлечения практически бесполезна вне ACL. Сейчас поддерживается только базовая аутентификация HTTP.

Производные ACL:

http_auth_group(<userlist>): group ...
Возвращает true, если пользователь, извлечённый из запроса, чей пароль
прошёл проверку по указанному userlist, принадлежит хотя бы одной
из групп.

http_auth_pass: string Возвращает пароль пользователя из данных аутентификации, полученных от клиента в заголовке Authorization. Это извлечение образца не выполняет проверок. Поддерживается только аутентификация Basic.

http_auth_type: string Возвращает метод аутентификации из данных аутентификации, полученных от клиента в заголовке Authorization. Это извлечение образца не выполняет проверок. Поддерживается только аутентификация Basic.

http_auth_user: string Возвращает имя пользователя из данных аутентификации, полученных от клиента в заголовке Authorization. Это извлечение образца не выполняет проверок. Поддерживается только аутентификация Basic.

http_first_req: boolean Возвращает true, когда обрабатываемый запрос является первым в соединении. Можно использовать для добавления или удаления заголовков, которые могут отсутствовать в некоторых запросах, если запрос не первый, либо для группировки запросов в журналах.

method: integer + string Возвращает целое число, соответствующее методу в запросе HTTP. Например, “GET” соответствует 1 (соответствие определяется по исходному коду). Значение 9 означает «другой метод» и может быть преобразовано в строку, извлечённую из потока. Это не следует использовать напрямую как образец: предназначено только для ACL, которые прозрачно преобразуют методы из шаблонов в эти значения integer + string. Некоторые предопределённые ACL уже проверяют наиболее распространённые методы.

Производные ACL:

method: сопоставление метода без учёта регистра

Пример:

# only accept GET and HEAD requests
acl valid_method method GET HEAD
http-request deny if ! valid_method

path: string Извлекает путь URL запроса, который начинается с первой косой черты и заканчивается перед вопросительным знаком (без части с хостом). Обычно используется с кешами, поддерживающими предварительное получение, и порталами, которым нужно объединять сведения из баз данных и хранить их в кешах. Для исходящих кешей разумнее использовать “url”. В ACL обычно применяется для сопоставления точных имён файлов (например, “/login.php”) либо частей каталогов с помощью производных форм. См. также методы извлечения “url” и “base”. Обратите внимание, что любая ссылка на фрагмент в URI (’#’ после пути) строго запрещена стандартом HTTP и будет отклонена. Однако, если во фронтенде, принимающем запрос, включена “option accept-unsafe-violations-in-http-request”, часть с фрагментом будет принята и также появится в path.

Производные ACL:

path    : точное сопоставление строки
path_beg: сопоставление по префиксу
path_dir: сопоставление по подкаталогу
path_dom: сопоставление по домену
path_end: сопоставление по суффиксу
path_len: сопоставление по длине
path_reg: сопоставление по регулярному выражению
path_sub: сопоставление по подстроке

Примечание: производные ACL нельзя использовать с последующим преобразователем или в ACL с методом сопоставления шаблонов “-m”.

pathq: string Извлекает путь URL запроса со строкой запроса, начиная с первой косой черты. Это извлечение образца удобно для получения относительного URI без схемы и части полномочий (authority), если они присутствуют. Именно так обычно представлена цель запроса HTTP/1.1, тогда как в HTTP/2 часто используется абсолютный URI. В обоих случаях это извлечение образца вернёт одинаковый результат. Обратите внимание, что любая ссылка на фрагмент в URI (’#’ после пути) строго запрещена стандартом HTTP и будет отклонена. Однако, если во фронтенде, принимающем запрос, включена “option accept-unsafe-violations-in-http-request”, часть с фрагментом будет принята и также появится в path.

query([<options>]): string

query([<options>]): string

Извлекает строку запроса, начинающуюся после первого вопросительного знака. Если вопросительного знака нет, извлечение ничего не возвращает. Если вопросительный знак есть, но после него ничего нет, возвращается пустая строка. Поэтому наличие строки запроса легко проверить методом сопоставления “found”. Это извлечение дополняет “path”, который заканчивается перед вопросительным знаком, и “query_string”, который включает вопросительный знак.

Необязательный параметр позволяет изменить возвращаемое значение. Поддерживаются следующие варианты:

- with_qm: добавить вопросительный знак в начало строки запроса,
            если она не пуста.

req.body: binary Возвращает доступное тело запроса HTTP в виде блока данных. Рекомендуется использовать “option http-buffer-request”, чтобы по возможности дождаться тела запроса.

req.body_len: integer Возвращает длину доступного тела запроса HTTP в байтах. Она может быть меньше объявленной длины, если тело больше буфера. Рекомендуется использовать “option http-buffer-request”, чтобы по возможности дождаться тела запроса.

req.body_param([<name>[,i]]): string

req.body_param([<name>[,i]]): string

Это извлечение предполагает, что тело запроса POST имеет кодировку URL. Пользователь может проверить, содержит ли “content-type” значение “application/x-www-form-urlencoded”. Извлекает первое вхождение параметра <name> в теле, которое заканчивается перед ‘&’. Имя параметра чувствительно к регистру, если вторым аргументом не добавлено “i”. Если имя не задано, подходит любой параметр и возвращается первый. Результат — строка со значением параметра <name> в том виде, в котором оно указано в теле запроса (декодирование URL не выполняется). Обратите внимание, что версия этого извлечения для ACL перебирает несколько параметров и последовательно возвращает значения всех параметров, если имя не задано.

req.body_size: integer Возвращает объявленную длину тела запроса HTTP в байтах. Это объявленное значение заголовка Content-Length либо размер доступных данных при передаче блоками.

req.cook([<name>]): string

req.cook([<name>]): string
cook([<name>]): string (deprecated)

Извлекает последнее вхождение cookie с именем <name> из строки заголовка “Cookie” в запросе и возвращает его значение в виде строки. Если имя не задано, возвращается значение первого cookie. В ACL вычисляются все подходящие cookie. Пробелы вокруг имени и значения игнорируются согласно спецификации заголовка Cookie (RFC6265). Имя cookie чувствительно к регистру. Пустые cookie допустимы, поэтому присутствующий пустой cookie может возвращать пустое значение. Для обнаружения присутствия используйте сопоставление “found”. Для cookie ответа, отправленных сервером, используйте вариант res.cook().

Производные ACL:

req.cook([<name>])    : точное сопоставление строки
req.cook_beg([<name>]): сопоставление по префиксу
req.cook_dir([<name>]): сопоставление по подкаталогу
req.cook_dom([<name>]): сопоставление по домену
req.cook_end([<name>]): сопоставление по суффиксу
req.cook_len([<name>]): сопоставление по длине
req.cook_reg([<name>]): сопоставление по регулярному выражению
req.cook_sub([<name>]): сопоставление по подстроке

Примечание: производные ACL нельзя использовать с последующим преобразователем или в ACL с методом сопоставления шаблонов “-m”.

req.cook_cnt([<name>]): integer

req.cook_cnt([<name>]): integer
cook_cnt([<name>]): integer (deprecated)

Возвращает целочисленное значение числа вхождений cookie <name> в запросе либо всех cookie, если <name> не указан.

req.cook_names([<delim>]): string

req.cook_names([<delim>]): string

Формирует строку путём объединения всех имён cookie в порядке их появления в запросе (заголовок Cookie) на момент вычисления правила. Разделитель по умолчанию — запятая (’,’), но его можно переопределить необязательным аргументом <delim>. В этом случае учитывается только первый символ <delim>.

req.cook_val([<name>]): integer

req.cook_val([<name>]): integer
cook_val([<name>]): integer (deprecated)

Извлекает последнее вхождение cookie с именем <name> из строки заголовка “Cookie” в запросе и преобразует его значение в возвращаемое целое число. Если имя не задано, возвращается значение первого cookie. В ACL перебираются все подходящие имена, пока не будет найдено совпадающее значение.

req.fhdr(<name>[,<occ>]): string

req.fhdr(<name>[,<occ>]): string

Возвращает полное значение последнего вхождения заголовка <name> в запросе HTTP. В отличие от req.hdr(), запятые в значении возвращаются как есть и не используются как разделители. Иногда это полезно для таких заголовков, как User-Agent.

При использовании в ACL все вхождения перебираются до нахождения совпадения.

Необязательно можно указать конкретное вхождение числом позиции. Положительные значения задают позицию от первого вхождения, где 1 — первое. Отрицательные значения задают позицию относительно последнего, где -1 — последнее.

req.fhdr_cnt([<name>]): integer

req.fhdr_cnt([<name>]): integer

Возвращает целое число вхождений поля заголовка запроса с именем <name> либо общее число полей заголовков, если <name> не указан. Как и req.fhdr(), отличается от res.hdr_cnt() тем, что не разделяет заголовки по запятым.

req.hdr([<name>[,<occ>]]): string

req.hdr([<name>[,<occ>]]): string

Возвращает последнее разделённое запятой значение заголовка <name> в запросе HTTP. Любая запятая считается разделителем отдельных значений. Это полезно для обработки заголовков, которые определены как списки значений, например Accept или X-Forwarded-For. Если нужны заголовки целиком, используйте req.fhdr(). Внимательно изучите RFC 7231, чтобы узнать, как следует разбирать конкретные заголовки. Кроме того, некоторые из них нечувствительны к регистру (например, Connection).

При использовании в ACL все вхождения перебираются до нахождения совпадения.

Необязательно можно указать конкретное вхождение числом позиции. Положительные значения задают позицию от первого вхождения, где 1 — первое. Отрицательные значения задают позицию относительно последнего, где -1 — последнее.

Обычно используется с заголовком X-Forwarded-For после преобразования в IP и с таблицей привязок IP.

Производные ACL:

hdr([<name>[,<occ>]])    : точное сопоставление строки
hdr_beg([<name>[,<occ>]]): сопоставление по префиксу
hdr_dir([<name>[,<occ>]]): сопоставление по подкаталогу
hdr_dom([<name>[,<occ>]]): сопоставление по домену
hdr_end([<name>[,<occ>]]): сопоставление по суффиксу
hdr_len([<name>[,<occ>]]): сопоставление по длине
hdr_reg([<name>[,<occ>]]): сопоставление по регулярному выражению
hdr_sub([<name>[,<occ>]]): сопоставление по подстроке

Примечание: производные ACL нельзя использовать с последующим преобразователем или в ACL с методом сопоставления шаблонов “-m”.

req.hdr_cnt([<name>]): integer

req.hdr_cnt([<name>]): integer
hdr_cnt([<header>]): integer (deprecated)

Возвращает целое число вхождений поля заголовка запроса с именем <name> либо общее число значений полей заголовков, если <name> не указан. Как и req.hdr(), считает каждую часть значения заголовка, отделённую запятой. Если нужно считать заголовки целиком, следует использовать req.fhdr_cnt().

В ACL можно использовать для обнаружения наличия, отсутствия или злоупотребления конкретным заголовком, а также для блокировки атак контрабанды запросов путём отклонения запросов, содержащих более одного экземпляра определённых заголовков.

Дополнительные сведения о сопоставлении заголовков см. в req.hdr().

req.hdr_ip([<name>[,<occ>]]): ip

req.hdr_ip([<name>[,<occ>]]): ip
hdr_ip([<name>[,<occ>]]): ip (deprecated)

Извлекает последнее вхождение заголовка <name> в запросе HTTP, преобразует его в адрес IPv4 или IPv6 и возвращает этот адрес. В ACL проверяются все вхождения; если <name> опущен, проверяется каждое значение каждого заголовка. Разбор строго следует формату RFC7239 с расширением: за адресом IPv4 необязательно могут следовать двоеточие (’:’) и допустимый десятичный номер порта (от 0 до 65535), который будет молча отброшен. Все остальные формы не совпадают и приводят к игнорированию адреса.

Параметр <occ> обрабатывается так же, как в req.hdr().

Обычно используется с заголовками X-Forwarded-For и X-Client-IP.

req.hdr_names([<delim>]): string

req.hdr_names([<delim>]): string

Формирует строку путём объединения всех имён заголовков в порядке их появления в запросе на момент вычисления правила. Разделитель по умолчанию — запятая (’,’), но его можно переопределить необязательным аргументом <delim>. В этом случае учитывается только первый символ <delim>.

req.hdr_val([<name>[,<occ>]]): integer

req.hdr_val([<name>[,<occ>]]): integer
hdr_val([<name>[,<occ>]]): integer (deprecated)

Извлекает последнее вхождение заголовка <name> в запросе HTTP и преобразует его в целое число. В ACL проверяются все вхождения; если <name> опущен, проверяется каждое значение каждого заголовка.

Параметр <occ> обрабатывается так же, как в req.hdr().

Обычно используется с заголовком X-Forwarded-For.

req.hdrs: string Возвращает текущие заголовки запроса в виде строки, включая завершающую пустую строку, отделяющую заголовки от тела запроса. По завершающей пустой строке можно обнаружить усечённый блок заголовков. Это извлечение образца полезно для некоторых анализаторов заголовков SPOE и расширенного журналирования.

req.hdrs_bin: binary Возвращает текущие заголовки запроса в предварительно разобранной двоичной форме. Это полезно для передачи части обработки через SPOE. Каждая строка описывается длиной, за которой следует указанное этой длиной число байтов. Длина представлена целым числом переменной длины в кодировке, подробно описанной в документации SPOE. Конец списка обозначается парой пустых имени и значения заголовка (оба имеют длину 0).

*(<str:header-name>``<str:header-value>)<empty string>``<empty string>

int: сведения о кодировании см. в документации SPOE str: <int:length>``<bytes>

req.timer.hdr: integer Полное время получения клиентского запроса (только в режиме HTTP). Это время от получения первых байтов до момента, когда прокси получил пустую строку, обозначающую конец заголовков HTTP. Выражается в миллисекундах (ms) и соответствует %TR в log-format. Подробнее см. раздел 8.4 «Временные события».

req.timer.idle: integer Время простоя перед запросом HTTP (только в режиме HTTP). Таймер отсчитывает время от завершения рукопожатий до первого байта запроса HTTP. Выражается в миллисекундах и соответствует %Ti в log-format. Подробнее см. раздел 8.4 «Временные события».

req.timer.queue: integer Полное время, проведённое в очередях в ожидании свободного места для соединения. Выражается в миллисекундах и соответствует %Tw в log-format. Подробнее см. раздел 8.4 «Временные события».

req.timer.tq: integer Полное время получения клиентского запроса с момента принятия соединения либо отправки последнего байта предыдущего ответа. Выражается в миллисекундах и соответствует %Tq в log-format. Подробнее см. раздел 8.4 «Временные события».

req.ver: string req_ver: string (устарело) Возвращает строку версии из запроса HTTP в формате “<major>.<minor>”. Это может быть полезно для ACL. Некоторые предопределённые ACL уже проверяют распространённые версии. Можно использовать в запросах, ответах и журналах, поскольку используется сохраняемая информация. Если версия запроса недопустима, извлечение образца завершается неудачей.

Обычные значения: “1.0”, “1.1”, “2.0” или “3.0”.

Производные ACL:

req.ver: точное сопоставление строки

request_date([<unit>]): integer

request_date([<unit>]): integer

Точная дата получения HAProxy первого байта запроса HTTP (псевдоним %tr в log-format). Вычисляется как accept_date + время рукопожатия (%Th) + время простоя (%Ti).

Возвращает значение в секундах с эпохи.

<unit> необязателен и может быть установлен в “s” для секунд (поведение по умолчанию), “ms” для миллисекунд или “us” для микросекунд. Если указана единица измерения, возвращаемое значение — целое число, отражающее количество секунд, миллисекунд или микросекунд с эпохи. Полезно, когда требуется разрешение времени менее одной секунды.

res.body: binary Возвращает доступное тело ответа HTTP в виде блока данных. В отличие от обработки запросов, директивы для ожидания тела ответа нет. Это извлечение образца особенно полезно (и применимо) в контексте проверок работоспособности.

Можно использовать в правилах expect на основе tcp-check.

res.body_len: integer Возвращает длину доступного тела ответа HTTP в байтах. В отличие от обработки запросов, директивы для ожидания тела ответа нет. Это извлечение образца особенно полезно (и применимо) в контексте проверок работоспособности.

Можно использовать в правилах expect на основе tcp-check.

res.body_size: integer Возвращает объявленную длину тела ответа HTTP в байтах. Это объявленное значение заголовка Content-Length либо размер доступных данных при передаче блоками. В отличие от обработки запросов, директивы для ожидания тела ответа нет. Это извлечение образца особенно полезно (и применимо) в контексте проверок работоспособности.

Можно использовать в правилах expect на основе tcp-check.

res.cache_hit: boolean Возвращает логическое значение “true”, если ответ сформирован из записи кеша HTTP; в противном случае возвращает логическое значение “false”.

res.cache_name: string Возвращает строку с именем кеша HTTP, использованного для формирования ответа HTTP, если res.cache_hit имеет значение true; иначе возвращает пустую строку.

res.comp: boolean Возвращает логическое значение “true”, если ответ был сжат HAProxy, иначе возвращает логическое значение “false”. Это можно использовать для добавления информации в журналы.

res.comp_algo: string Возвращает строку с именем алгоритма, использованного для сжатия ответа HAProxy, например “deflate”. Это можно использовать для добавления информации в журналы.

res.cook([<name>]): string

res.cook([<name>]): string
scook([<name>]): string (deprecated)

Извлекает последнее вхождение cookie с именем <name> из строки заголовка “Set-Cookie” в ответе и возвращает его значение в виде строки. Если имя не указано, возвращается значение первого cookie.

Можно использовать в правилах expect на основе tcp-check.

Производные ACL:

res.scook([<name>]: точное сопоставление строки

res.cook_cnt([<name>]): integer

res.cook_cnt([<name>]): integer
scook_cnt([<name>]): integer (deprecated)

Возвращает целое число вхождений cookie <name> в ответе либо всех cookie, если <name> не указан. В основном это полезно вместе с ACL для обнаружения подозрительных ответов.

Можно использовать в правилах expect на основе tcp-check.

res.cook_names([<delim>]): string

res.cook_names([<delim>]): string

Формирует строку путём объединения всех имён cookie в порядке их появления в ответе (заголовки Set-Cookie) на момент вычисления правила. Разделитель по умолчанию — запятая (’,’), но его можно переопределить необязательным аргументом <delim>. В этом случае учитывается только первый символ <delim>.

Можно использовать в правилах expect на основе tcp-check.

res.cook_val([<name>]): integer

res.cook_val([<name>]): integer
scook_val([<name>]): integer (deprecated)

Извлекает последнее вхождение cookie с именем <name> из строки заголовка “Set-Cookie” в ответе, преобразует его значение в целое число и возвращает результат. Если имя не указано, возвращается значение первого cookie.

Можно использовать в правилах expect на основе tcp-check.

res.fhdr([<name>[,<occ>]]): string

res.fhdr([<name>[,<occ>]]): string

Работает так же, как метод извлечения req.fhdr(), но действует на заголовки ответа HTTP.

Как и req.fhdr(), метод извлечения res.fhdr() возвращает полные значения. Если заголовок определён как список, следует использовать res.hdr().

Этот метод извлечения иногда полезен с такими заголовками, как Date или Expires.

Можно использовать в правилах expect на основе tcp-check.

res.fhdr_cnt([<name>]): integer

res.fhdr_cnt([<name>]): integer

Работает так же, как метод извлечения req.fhdr_cnt(), но действует на заголовки ответа HTTP.

Как и req.fhdr_cnt(), метод извлечения res.fhdr_cnt() обрабатывает полные значения. Если заголовок определён как список, следует использовать res.hdr_cnt().

Можно использовать в правилах expect на основе tcp-check.

res.hdr([<name>[,<occ>]]): string

res.hdr([<name>[,<occ>]]): string
shdr([<name>[,<occ>]]): string (deprecated)

Работает так же, как метод извлечения req.hdr(), но действует на заголовки ответа HTTP.

Как и req.hdr(), метод извлечения res.hdr() считает запятую разделителем. Если это нежелательно, следует использовать res.fhdr().

Можно использовать в правилах expect на основе tcp-check.

Производные ACL:

res.hdr([<name>[,<occ>]])    : точное сопоставление строки
res.hdr_beg([<name>[,<occ>]]): сопоставление по префиксу
res.hdr_dir([<name>[,<occ>]]): сопоставление по подкаталогу
res.hdr_dom([<name>[,<occ>]]): сопоставление по домену
res.hdr_end([<name>[,<occ>]]): сопоставление по суффиксу
res.hdr_len([<name>[,<occ>]]): сопоставление по длине
res.hdr_reg([<name>[,<occ>]]): сопоставление по регулярному выражению
res.hdr_sub([<name>[,<occ>]]): сопоставление по подстроке

Примечание: производные ACL нельзя использовать с последующим преобразователем или в ACL с методом сопоставления шаблонов “-m”.

res.hdr_cnt([<name>]): integer

res.hdr_cnt([<name>]): integer
shdr_cnt([<name>]): integer (deprecated)

Работает так же, как метод извлечения req.hdr_cnt(), но действует на заголовки ответа HTTP.

Как и req.hdr_cnt(), метод извлечения res.hdr_cnt() считает запятую разделителем. Если это нежелательно, следует использовать res.fhdr_cnt().

Можно использовать в правилах expect на основе tcp-check.

res.hdr_ip([<name>[,<occ>]]): ip

res.hdr_ip([<name>[,<occ>]]): ip
shdr_ip([<name>[,<occ>]]): ip (deprecated)

Работает так же, как метод извлечения req.hdr_ip(), но действует на заголовки ответа HTTP.

Можно использовать для сохранения некоторых данных в таблице привязок.

Можно использовать в правилах expect на основе tcp-check.

res.hdr_names([<delim>]): string

res.hdr_names([<delim>]): string

Формирует строку путём объединения всех имён заголовков в порядке их появления в ответе на момент вычисления правила. Разделитель по умолчанию — запятая (’,’), но его можно переопределить необязательным аргументом <delim>. В этом случае учитывается только первый символ <delim>.

Можно использовать в правилах expect на основе tcp-check.

res.hdr_val([<name>[,<occ>]]): integer

res.hdr_val([<name>[,<occ>]]): integer
shdr_val([<name>[,<occ>]]): integer (deprecated)

Работает так же, как метод извлечения req.hdr_val(), но действует на заголовки ответа HTTP.

Можно использовать для сохранения некоторых данных в таблице привязок.

Можно использовать в правилах expect на основе tcp-check.

res.hdrs: string Возвращает текущие заголовки ответа в виде строки, включая завершающую пустую строку, отделяющую заголовки от тела запроса. По завершающей пустой строке можно обнаружить усечённый блок заголовков. Это извлечение образца полезно для некоторых анализаторов заголовков SPOE и расширенного журналирования.

Также можно использовать в правилах expect на основе tcp-check.

res.hdrs_bin: binary Возвращает текущие заголовки ответа в предварительно разобранной двоичной форме. Это полезно для передачи части обработки через SPOE. Можно использовать в правилах expect, основанных на tcp-check. Каждая строка описывается длиной, за которой следует указанное этой длиной число байтов. Длина представлена целым числом переменной длины в кодировке, подробно описанной в документации SPOE. Конец списка обозначается парой пустых имени и значения заголовка (оба имеют длину 0).

*(<str:header-name>``<str:header-value>)<empty string>``<empty string>

int: сведения о кодировании см. в документации SPOE str: <int:length>``<bytes>

res.timer.hdr: integer Время от установления соединения TCP с сервером до момента, когда сервер отправил все заголовки ответа. Выражается в миллисекундах и соответствует %Tr в log-format. Подробнее см. раздел 8.4 «Временные события».

res.ver: string resp_ver: string (устарело) Возвращает строку версии из ответа HTTP в формате “<major>.<minor>”. Это может быть полезно для журналов, но главным образом предназначено для ACL. Если версия ответа недопустима, извлечение образца завершается неудачей.

Можно использовать в правилах expect на основе tcp-check.

Производные ACL:

resp.ver: точное сопоставление строки

server_status: integer Возвращает целое число, содержащее код состояния HTTP, полученный от сервера. Если ответ от сервера не получен, извлечение образца завершается неудачей.

set-cookie([<name>]): string (deprecated)

set-cookie([<name>]): string (deprecated)

Извлекает последнее вхождение cookie с именем <name> из строки заголовка “Set-Cookie” в ответе и использует соответствующее значение для сопоставления. Это сопоставимо с поведением “appsession” при параметрах по умолчанию, но с поддержкой синхронизации между несколькими узлами и сохранения состояния при перезапусках.

Этот метод извлечения устарел; его заменил метод “res.cook”. Это ключевое слово вскоре исчезнет.

status: integer Возвращает целое число, содержащее код состояния HTTP в ответе HTTP, например 302. В основном используется в ACL и с диапазонами целых чисел, например для удаления любого заголовка Location, если ответ не относится к 3xx. Клиент получит этот код состояния, если его не изменить, например действием ‘set-status’.

Можно использовать в правилах expect на основе tcp-check.

txn.status: integer Возвращает целое число с кодом состояния HTTP транзакции, указанным в журнале.

txn.timer.total: integer Полное время активной обработки запроса HTTP от момента получения прокси первого байта заголовка запроса до отправки последнего байта тела ответа. Соответствует %Ta в log-format и выражается в миллисекундах (ms). Подробнее см. раздел 8.4 «Временные события».

unique-id: string Возвращает unique-id, связанный с запросом. Директива “unique-id-format” должна быть задана. Если она не задана, извлечение образца unique-id завершается неудачей. Хотя unique-id обычно используется с запросами HTTP, это извлечение образца можно использовать и с другими протоколами. Разумеется, при использовании с протоколами, отличными от HTTP, директива unique-id-format не должна содержать части, относящиеся к HTTP. См.: unique-id-format и unique-id-header

url: string Извлекает URL запроса в том виде, в котором он указан в запросе. Обычно используется с кешами, поддерживающими предварительное получение, и с порталами, которым нужно объединять сведения из баз данных и сохранять их в кешах. В ACL предпочтительнее использовать “path”, чем “url”, поскольку клиенты могут отправлять полный URL, как обычно делают при работе с прокси. Единственный реальный вариант применения — сопоставление “*”, которое не выполняется в “path” и для которого уже есть предопределённый ACL. См. также “path” и “base”. Обратите внимание, что любая ссылка на фрагмент в URI (’#’ после пути) строго запрещена стандартом HTTP и будет отклонена. Однако, если во фронтенде, принимающем запрос, включена “option accept-unsafe-violations-in-http-request”, часть с фрагментом будет принята и также появится в url.

Производные ACL:

url    : точное сопоставление строки
url_beg: сопоставление по префиксу
url_dir: сопоставление по подкаталогу
url_dom: сопоставление по домену
url_end: сопоставление по суффиксу
url_len: сопоставление по длине
url_reg: сопоставление по регулярному выражению
url_sub: сопоставление по подстроке

Примечание: производные ACL нельзя использовать с последующим преобразователем или в ACL с методом сопоставления шаблонов “-m”.

url32: integer Возвращает 32-битный хеш значения, полученного объединением первого заголовка Host и всего URL, включая параметры (а не только часть пути запроса, как в извлечении “base32” выше). Это полезно для отслеживания активности по отдельным URL. Сохраняется более короткий хеш, что существенно экономит память. Выходной тип — беззнаковое целое число.

url32+src: binary Возвращает объединение результатов извлечения “url32” и “src”. Результат имеет двоичный тип и размер 8 или 20 байтов в зависимости от семейства исходного адреса. Можно использовать для отслеживания счётчиков по отдельным адресам IP и URL.

url_ip: ip Извлекает адрес IP из URL запроса, когда часть с хостом представлена адресом IP. Если в ней указано имя, извлечение завершается неуспешно, поскольку разрешение имён не выполняется. Применение весьма ограничено. Например, система мониторинга может использовать это поле вместо исходного адреса IP, чтобы проверить, какой путь прошёл бы заданный исходный адрес, либо принудительно создать запись в таблице для заданного исходного адреса. Можно использовать вместе с ‘http-request set-dst’ для воспроизведения прежнего поведения ‘option http_proxy’.

url_port: integer Извлекает порт из URL запроса. Если порт в запросе не указан, предполагается порт 80. Как и “url_ip”, это работает только тогда, когда часть authority в URL представлена адресом. При имени хоста извлечение завершается неуспешно, поскольку разрешение имён здесь не выполняется.

urlp([<name>[,<delim>[,i]]]): string

urlp([<name>[,<delim>[,i]]]): string
url_param([<name>[,<delim>[,i]]]): string

Извлекает первое вхождение параметра <name> в строке запроса, которая начинается после ‘?’ либо <delim> и заканчивается перед ‘&’, ‘;’ либо <delim>. Имя параметра чувствительно к регистру, если третьим аргументом не добавлено “i”. Если имя не задано, подходит любой параметр и возвращается первый. Результат — строка со значением параметра <name> в том виде, в котором оно указано в запросе (декодирование URL не выполняется). Это можно использовать для привязки сеанса по идентификатору клиента, извлечения cookie приложения, переданного параметром URL, либо для проверок в ACL. Обратите внимание, что версия этого извлечения для ACL перебирает несколько параметров и последовательно возвращает значения всех параметров, если имя не задано.

Производные ACL:

urlp(<name>[,<delim>])    : точное сопоставление строки
urlp_beg(<name>[,<delim>]): сопоставление по префиксу
urlp_dir(<name>[,<delim>]): сопоставление по подкаталогу
urlp_dom(<name>[,<delim>]): сопоставление по домену
urlp_end(<name>[,<delim>]): сопоставление по суффиксу
urlp_len(<name>[,<delim>]): сопоставление по длине
urlp_reg(<name>[,<delim>]): сопоставление по регулярному выражению
urlp_sub(<name>[,<delim>]): сопоставление по подстроке

Примечание: производные ACL нельзя использовать с последующим преобразователем или в ACL с методом сопоставления шаблонов “-m”.

Пример:

# match http://example.com/foo?PHPSESSIONID=some_id
stick on urlp(PHPSESSIONID)
# match http://example.com/foo;JSESSIONID=some_id
stick on urlp(JSESSIONID,;)

urlp_val([<name>[,<delim>[,i]]]): integer

urlp_val([<name>[,<delim>[,i]]]): integer

См. “urlp” выше. Извлекает параметр URL <name> в запросе и преобразует его в целое число. Это можно использовать, например, для привязки сеанса по идентификатору пользователя либо с ACL для сопоставления номера страницы или цены.

7.3.7. Извлечение образцов для разработчиков

Этот набор методов извлечения образцов предназначен для разработчиков; его никогда нельзя использовать в рабочей среде, кроме случаев, когда разработчик требует этого для отладки. Кроме того, особое внимание обратной совместимости уделяться не будет. Нет гарантии, что перечисленные ниже методы извлечения образцов не изменятся, не будут переименованы или просто удалены. Поэтому при необходимости использовать их следует соблюдать особую осторожность. Во избежание неоднозначности они помещены в отдельную область “internal”, например “internal.strm.is_htx”.

Сводка методов извлечения образцов в этом разделе и их соответствующие типы:

  Ключевое слово                                   Выходной тип
-------------------------------------------------+-------------
internal.htx.data                                  integer
internal.htx.free                                  integer
internal.htx.free_data                             integer
internal.htx.has_eom                               boolean
internal.htx.nbblks                                integer
internal.htx.size                                  integer
internal.htx.used                                  integer
internal.htx_blk.size(<idx>)                       integer
internal.htx_blk.type(<idx>)                       string
internal.htx_blk.data(<idx>)                       binary
internal.htx_blk.hdrname(<idx>)                    string
internal.htx_blk.hdrval(<idx>)                     string
internal.htx_blk.start_line(<idx>)                 string
internal.strm.is_htx                               boolean
-------------------------------------------------+-------------

Подробный список:

internal.htx.data: integer Возвращает размер в байтах, занимаемый данными в сообщении HTX, связанном с каналом. Канал выбирается в зависимости от направления образца.

internal.htx.free: integer Возвращает свободное место (size - used) в байтах в сообщении HTX, связанном с каналом. Канал выбирается в зависимости от направления образца.

internal.htx.free_data: integer Возвращает свободное место для данных в байтах в сообщении HTX, связанном с каналом. Канал выбирается в зависимости от направления образца.

internal.htx.has_eom: boolean Возвращает true, если сообщение HTX, связанное с каналом, содержит флаг конца сообщения (EOM). В противном случае возвращает false. Канал выбирается в зависимости от направления образца.

internal.htx.nbblks: integer Возвращает число блоков в сообщении HTX, связанном с каналом. Канал выбирается в зависимости от направления образца.

internal.htx.size: integer Возвращает полный размер в байтах сообщения HTX, связанного с каналом. Канал выбирается в зависимости от направления образца.

internal.htx.used: integer Возвращает общий занятый размер в байтах (данные + метаданные) в сообщении HTX, связанном с каналом. Канал выбирается в зависимости от направления образца.

internal.htx_blk.size(<idx>): integer

internal.htx_blk.size(<idx>): integer

Возвращает размер блока в позиции <idx> в сообщении HTX, связанном с каналом, либо 0, если блока нет. Канал выбирается в зависимости от направления образца. <idx> может быть любым положительным целым числом или одним из специальных значений: * head : наиболее давно добавленный блок * tail : последний добавленный блок * first: первый блок, с которого следует (пере)начать анализ.

internal.htx_blk.type(<idx>): string

internal.htx_blk.type(<idx>): string

Возвращает тип блока в позиции <idx> в сообщении HTX, связанном с каналом, либо “HTX_BLK_UNUSED”, если блока нет. Канал выбирается в зависимости от направления образца. <idx> может быть любым положительным целым числом или одним из специальных значений: * head : наиболее давно добавленный блок * tail : последний добавленный блок * first: первый блок, с которого следует (пере)начать анализ.

internal.htx_blk.data(<idx>): binary

internal.htx_blk.data(<idx>): binary

Возвращает значение блока DATA в позиции <idx> в сообщении HTX, связанном с каналом, либо пустую строку, если блока нет или это не блок DATA. Канал выбирается в зависимости от направления образца. <idx> может быть любым положительным целым числом или одним из специальных значений:

* head : наиболее давно добавленный блок
* tail : последний добавленный блок
* first: первый блок, с которого следует (пере)начать анализ

internal.htx_blk.hdrname(<idx>): string

internal.htx_blk.hdrname(<idx>): string

Возвращает имя заголовка блока HEADER в позиции <idx> в сообщении HTX, связанном с каналом, либо пустую строку, если блока нет или это не блок HEADER. Канал выбирается в зависимости от направления образца. <idx> может быть любым положительным целым числом или одним из специальных значений:

* head : наиболее давно добавленный блок
* tail : последний добавленный блок
* first: первый блок, с которого следует (пере)начать анализ

internal.htx_blk.hdrval(<idx>): string

internal.htx_blk.hdrval(<idx>): string

Возвращает значение заголовка блока HEADER в позиции <idx> в сообщении HTX, связанном с каналом, либо пустую строку, если блока нет или это не блок HEADER. Канал выбирается в зависимости от направления образца. <idx> может быть любым положительным целым числом или одним из специальных значений:

* head : наиболее давно добавленный блок
* tail : последний добавленный блок
* first: первый блок, с которого следует (пере)начать анализ

internal.htx_blk.start_line(<idx>): string

internal.htx_blk.start_line(<idx>): string

Возвращает значение блока REQ_SL или RES_SL в позиции <idx> в сообщении HTX, связанном с каналом, либо пустую строку, если блока нет или это не блок SL. Канал выбирается в зависимости от направления образца. <idx> может быть любым положительным целым числом или одним из специальных значений:

* head : наиболее давно добавленный блок
* tail : последний добавленный блок
* first: первый блок, с которого следует (пере)начать анализ

internal.strm.is_htx: boolean Возвращает true, если текущий поток является потоком HTX: данные в буферах каналов хранятся во внутреннем представлении HTX. В противном случае возвращает false.

7.4. Предопределённые ACL

Некоторые предопределённые ACL встроены в код, поэтому их не нужно объявлять в каждом фронтенде, которому они нужны. Во избежание путаницы все их имена записаны в верхнем регистре. Их эквивалентные выражения приведены ниже.

Имя ACL           Эквивалентное выражение      Назначение
---------------+----------------------------------+------------------------------------------------------
FALSE            always_false                       никогда не совпадает
HTTP             req.proto_http                     совпадает, если протокол запроса — корректный HTTP
HTTP_1.0         req.ver 1.0                        совпадает, если версия запроса HTTP — 1.0
HTTP_1.1         req.ver 1.1                        совпадает, если версия запроса HTTP — 1.1
HTTP_2.0         req.ver 2.0                        совпадает, если версия запроса HTTP — 2.0
HTTP_3.0         req.ver 3.0                        совпадает, если версия запроса HTTP — 3.0
HTTP_CONTENT     req.hdr_val(content-length) gt 0   совпадает при наличии content-length в запросе HTTP
HTTP_URL_ABS     url_reg ^[^/:]*://                 совпадает с абсолютным URL со схемой
HTTP_URL_SLASH   url_beg /                          совпадает с URL, начинающимся с "/"
HTTP_URL_STAR    url     *                          совпадает с URL, равным "*"
LOCALHOST        src 127.0.0.1/8::1                совпадает с соединением с локального узла
METH_CONNECT     method  CONNECT                    совпадает с методом HTTP CONNECT
METH_DELETE      method  DELETE                     совпадает с методом HTTP DELETE
METH_GET         method  GET HEAD                   совпадает с методом HTTP GET или HEAD
METH_HEAD        method  HEAD                       совпадает с методом HTTP HEAD
METH_OPTIONS     method  OPTIONS                    совпадает с методом HTTP OPTIONS
METH_POST        method  POST                       совпадает с методом HTTP POST
METH_PUT         method  PUT                        совпадает с методом HTTP PUT
METH_TRACE       method  TRACE                      совпадает с методом HTTP TRACE
RDP_COOKIE       req.rdp_cookie_cnt gt 0            совпадает при наличии RDP cookie в буфере запроса
REQ_CONTENT      req.len gt 0                       совпадает при наличии данных в буфере запроса
TRUE             always_true                        всегда совпадает
WAIT_END         wait_end                           ожидает окончания анализа содержимого
---------------+----------------------------------+------------------------------------------------------

17 - 8. Ведение журнала

Уровни, форматы и профили журналов, временные показатели, захват данных, состояния и примеры

Одна из сильных сторон HAProxy — точность его журналов. Вероятно, они предоставляют наиболее подробную информацию среди продуктов такого рода, что очень важно для устранения неполадок в сложных средах. Стандартные сведения в журналах включают порты клиентов, временные показатели состояний TCP/HTTP, точное состояние потока и причину его завершения, информацию о решениях по направлению трафика на сервер и, конечно, возможность захвата произвольных заголовков.

Чтобы администраторы могли быстрее реагировать, HAProxy подробно сообщает о возникающих внутренних и внешних проблемах и позволяет одновременно отправлять журналы нескольким получателям с разными фильтрами уровней:

  • глобальные журналы уровня процесса (системные ошибки, запуск/остановка и т. д.)
  • системные и внутренние ошибки отдельных экземпляров (нехватка ресурсов, ошибки в программе и т. д.)
  • внешние проблемы отдельных экземпляров (переходы серверов в доступное/недоступное состояние, максимальное число соединений)
  • активность отдельных экземпляров (клиентские соединения), при установлении или завершении соединения.
  • управление уровнем ведения журнала для отдельных запросов, например http-request set-log-level silent if sensitive_request

Возможность распределять журналы разных уровней между разными серверами журналирования позволяет нескольким эксплуатационным командам взаимодействовать и как можно быстрее решать свои проблемы. Например, системные администраторы могут отслеживать общесистемные ошибки, команда приложений — доступность своих серверов в реальном времени, а команда безопасности — анализировать журналы активности с задержкой в один час.

8.1. Уровни ведения журнала

Для соединений TCP и HTTP в журнал можно записывать дату, время, адрес IP источника и адрес назначения, длительность соединения, время ответа, запрос HTTP, код ответа HTTP, число переданных байтов, условия завершения потока и даже значения переданных cookie. Это позволяет, например, отслеживать проблемы конкретного пользователя. Все сообщения могут отправляться не более чем на два сервера syslog. Дополнительные сведения о средствах ведения журнала см. в описании ключевого слова “log” в разделе 4.2 .

8.2. Форматы журналов

HAProxy поддерживает 5 форматов журналов. Несколько полей являются общими для этих форматов и будут подробно описаны в следующих разделах. Некоторые из них могут немного различаться в зависимости от конфигурации из-за индикаторов, относящихся к определённым опциям. Поддерживаются следующие форматы:

  • формат по умолчанию — очень простой и крайне редко используемый. Он предоставляет лишь основные сведения о входящем соединении в момент его принятия: IP:port источника, IP:port назначения и frontend-name. Со временем этот режим исчезнет, поэтому подробно он не рассматривается.

  • формат TCP — более развитый. Он включается, если во фронтенде задана “option tcplog”. В этом случае HAProxy обычно ожидает завершения соединения перед записью в журнал. Формат предоставляет значительно больше сведений: временные показатели, число соединений, размер очереди и т. д. Он рекомендуется для прокси, работающих только с TCP.

  • формат HTTP — наиболее развитый для проксирования HTTP. Он включается, если во фронтенде задана “option httplog”. Он предоставляет те же сведения, что и формат TCP, с дополнительными HTTP-полями: запросом, кодом состояния, захваченными заголовками и cookie. Этот формат рекомендуется для прокси HTTP.

  • формат CLF HTTP — эквивалент формата HTTP, но с полями в порядке формата CLF. В этом режиме все временные показатели, захваты, флаги и т. д. располагаются по одному в поле после общих полей, в том же порядке, что и в стандартном формате HTTP.

  • пользовательский формат журнала позволяет задать собственную строку журнала.

В следующих разделах каждый из этих форматов рассматривается подробнее. Формат описывается по полям. Если не указано иное, поле — это фрагмент текста, отделённый произвольным числом пробелов. Поскольку серверы syslog могут вставлять поля в начало строки, первым всегда считается поле с именем и идентификатором процесса.

Примечание: строки журнала могут быть довольно длинными, поэтому примеры в следующих разделах иногда разбиты на несколько строк. Строки примеров начинаются с 3 закрывающих угловых скобок (’>>>’). При переносе каждая строка, кроме последней, заканчивается обратной косой чертой (’\’), а следующая начинается с отступом в два символа.

8.2.1. Формат журнала по умолчанию

Этот формат используется, если не задана специальная опция. Запись журнала выдаётся сразу после принятия соединения. Следует учитывать, что сейчас это единственный формат, в котором записываются IP и порты назначения запроса.

Пример:

    listen www
        mode http
        log global
        server srv1 127.0.0.1:8000

>>> Feb  6 12:12:09 localhost \
      haproxy[14385]: Connect from 10.0.1.2:33312 to 10.0.3.31:8012 \
      (www/HTTP)

Поле Формат Фрагмент приведённого выше примера

    1   process_name '[' pid ']:'                            haproxy[14385]:
    2   'Connect from'                                          Connect from
    3   source_ip ':' source_port                             10.0.1.2:33312
    4   'to'                                                              to
    5   destination_ip ':' destination_port                   10.0.3.31:8012
    6   '(' frontend_name '/' mode ')'                            (www/HTTP)

Подробное описание полей:

  • “source_ip” — адрес IP клиента, инициировавшего соединение.
  • “source_port” — порт TCP клиента, инициировавшего соединение.
  • “destination_ip” — адрес IP, к которому подключился клиент.
  • “destination_port” — порт TCP, к которому подключился клиент.
  • “frontend_name” — имя фронтенда (или слушателя), который принял и обработал соединение.
  • “mode” — режим работы фронтенда (TCP или HTTP).

Для сокета UNIX адреса источника и назначения помечаются как “unix:”, а порты отражают внутренний ID сокета, принявшего соединение (тот же ID, что и в статистике).

Рекомендуется не использовать этот устаревший формат в новых установках, поскольку со временем он исчезнет.

8.2.2. Формат журнала TCP

Формат TCP используется, когда во фронтенде задана “option tcplog”, и рекомендуется для прокси, работающих только с TCP. Он предоставляет много полезной информации для устранения неполадок. Поскольку этот формат содержит временные показатели и счётчики байтов, запись журнала обычно выдаётся в конце сеанса. Её можно выдать раньше, указав “option logasap”, что имеет смысл в большинстве сред с длительными сеансами, например для удалённых терминалов. Сеансы, соответствующие правилам “monitor”, никогда не записываются в журнал. Кроме того, можно отключить записи для сеансов, в которых клиент и сервер не обменялись данными, задав во фронтенде “option dontlognull”. Успешные соединения не записываются в журнал, если во фронтенде задана “option dontlog-normal”.

Внутри HAProxy формат журнала TCP объявлен как пользовательский формат на основе следующей точной строки. При необходимости её можно использовать как основу для расширения формата. Вместо неё также можно использовать переменную HAPROXY_TCP_LOG_FMT. Порядок использования описан в разделе 8.2.6 «Пользовательский формат журнала»:

# strict equivalent of "option tcplog"
log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts \
            %ac/%fc/%bc/%sc/%rc %sq/%bq"
# or using the HAPROXY_TCP_LOG_FMT variable
log-format "${HAPROXY_TCP_LOG_FMT}"

Формат журнала CLF также объявлен внутри HAProxy как пользовательский формат на основе следующей точной строки:

# strict equivalent of "option tcplog clf"
log-format "%{Q}o %{-Q}ci - - [%T] \"TCP \" 000 %B \"\" \"\" %cp \
            %ms %ft %b %s %Th %Tw %Tc %Tt %U %ts-- %ac %fc %bc \
            %sc %rc %sq %bq \"\" \"\" "

Значения некоторых полей могут немного различаться в зависимости от параметров конфигурации. Такие поля отмечены ниже звёздочкой (’*’) после имени.

Пример:

    frontend fnt
        mode tcp
        option tcplog
        log global
        default_backend bck

    backend bck
        server srv1 127.0.0.1:8000

>>> Feb  6 12:12:56 localhost \
      haproxy[14387]: 10.0.1.2:33313 [06/Feb/2009:12:12:51.443] fnt \
      bck/srv1 0/0/5007 212 -- 0/0/0/0/3 0/0

Поле Формат Фрагмент приведённого выше примера

    1   process_name '[' pid ']:'                            haproxy[14387]:
    2   client_ip ':' client_port                             10.0.1.2:33313
    3   '[' accept_date ']'                       [06/Feb/2009:12:12:51.443]
    4   frontend_name                                                    fnt
    5   backend_name '/' server_name                                bck/srv1
    6   Tw '/' Tc '/' Tt*                                           0/0/5007
    7   bytes_read*                                                      212
    8   termination_state                                                 --
    9   actconn '/' feconn '/' beconn '/' srv_conn '/' retries*    0/0/0/0/3
   10   srv_queue '/' backend_queue                                      0/0

Подробное описание полей:

  • “client_ip” — адрес IP клиента, инициировавшего соединение TCP с HAProxy. Если соединение принято через сокет UNIX, вместо адреса IP указывается слово “unix”. Если соединение принято через сокет с настройкой “accept-proxy” и протокол PROXY используется корректно либо через сокет с настройкой “accept-netscaler-cip” и корректным использованием протокола передачи IP клиента NetScaler, в журнале отражаются сведения о переданном соединении.

  • “client_port” — порт TCP клиента, инициировавшего соединение. Если соединение принято через сокет UNIX, вместо порта указывается ID принимающего сокета, который также отображается в интерфейсе статистики.

  • “accept_date” — точные дата и время получения соединения HAProxy. Они могут совсем немного отличаться от времени, наблюдаемого в сети, если соединение ожидало в системной очереди входящих соединений. Обычно это то же время, которое может появляться в журнале межсетевого экрана перед HAProxy. В режиме HTTP значение accept_date устанавливается заново в первый момент готовности соединения к приёму нового запроса: после завершения предыдущего ответа для HTTP/1 или сразу после предыдущего запроса для HTTP/2.

  • “frontend_name” — имя фронтенда (или слушателя), который принял и обработал соединение.

  • “backend_name” — имя бэкенда (или слушателя), выбранного для управления соединением с сервером. Оно будет таким же, как и у фронтенда, если не применялись правила переключения, что типично для приложений TCP.

  • “server_name” — имя последнего сервера, на который направлялось соединение. Этот сервер может отличаться от первоначального, если из-за ошибок соединения произошло перенаправление. Сервер принадлежит бэкенду, обработавшему запрос. Если соединение прервалось, не достигнув сервера, вместо имени сервера указывается “<NOSRV>”.

  • “Tw” — общее время в миллисекундах, потраченное на ожидание в различных очередях. Может быть “-1”, если соединение было прервано до попадания в очередь. Подробности см. в разделе «Таймеры» ниже.

  • “Tc” — общее время в миллисекундах, потраченное на установление соединения с конечным сервером, включая повторные попытки. Может быть “-1”, если соединение было прервано до установления соединения. Подробности см. в разделе «Таймеры» ниже.

  • “Tt” — общее время в миллисекундах, прошедшее между принятием и последним закрытием соединения. Охватывает все возможные этапы обработки. Исключение — если указано “option logasap”, то подсчёт времени останавливается в момент выдачи записи журнала. В этом случае перед значением добавляется знак ‘+’, указывающий, что окончательное значение будет больше. Подробности см. в разделе «Таймеры» ниже.

  • “bytes_read” — общее количество байт, переданных с сервера клиенту в момент выдачи записи журнала. Если указано “option logasap”, это значение будет предваряться знаком ‘+’, указывающим, что окончательное значение может быть больше. Обратите внимание, что это 64-битный счётчик, поэтому инструменты анализа журналов должны быть способны обрабатывать его без переполнения.

  • “termination_state” — состояние сеанса в момент её завершения. Указывает состояние сеанса, сторону, вызвавшую завершение, и причину (тайм-аут, ошибка и т.д.). Обычные флаги — “–”, что означает, что сеанс была закрыта одной из сторон без остатка данных в буферах. Подробности см. в разделе «Состояние потока при отключении» ниже.

  • “actconn” — общее число одновременных соединений процесса на момент записи сеанса в журнал. Оно помогает определить, достигнуты ли системные ограничения для отдельного процесса. Например, если при многочисленных ошибках соединения actconn близко к 512, весьма вероятно, что система ограничивает процесс 1024 файловыми дескрипторами и все они заняты. Порядок настройки системы описан в разделе 3 «Глобальная секция».

  • “feconn” — общее количество одновременных соединений на фронтенде в момент записи сеанса в журнал. Полезно для оценки объёма ресурсов, необходимых для поддержки высокой нагрузки, и для выявления достижения лимита “maxconn” фронтенда. Часто резкий рост этого значения указывает на перегрузку серверов бэкенда, но иногда может быть вызван атакой типа «отказ в обслуживании».

  • “beconn” — общее количество одновременных соединений, обрабатываемых бэкендом в момент записи сеанса в журнал. Включает общее количество одновременных соединений на серверах, а также количество соединений, ожидающих в очередях. Полезно для оценки количества дополнительных серверов, необходимых для поддержки высокой нагрузки для данного приложения. Часто резкий рост этого значения указывает на перегрузку серверов бэкенда, но иногда может быть вызван атакой типа «отказ в обслуживании».

  • “srv_conn” — общее число одновременных соединений, которые ещё активны на сервере на момент записи сеанса в журнал. Оно никогда не может превышать настроенный для сервера параметр “maxconn”. Если значение очень часто близко к “maxconn” сервера или равно ему, это означает, что часто задействуется регулирование трафика: либо значение maxconn сервера слишком мало, либо серверов недостаточно, чтобы обрабатывать нагрузку с оптимальным временем ответа. Если высокое значение “srv_conn” наблюдается только у одного сервера, обычно у него есть проблема, из-за которой обработка соединений занимает больше времени, чем на остальных серверах.

  • “retries” — число повторных попыток установить соединение с сервером в этом сеансе. Обычно оно должно быть равно нулю, кроме случая, когда сервер останавливается одновременно с попыткой подключения. Частые повторы обычно указывают либо на сетевую проблему между HAProxy и сервером, либо на неверную настройку системной очереди входящих соединений на сервере, из-за которой новые соединения не могут попасть в очередь. Поле может начинаться со знака ‘+’: это означает, что после достижения максимального числа повторных попыток на первоначальном сервере сеанс был перенаправлен. Тогда в журнале указывается имя сервера, на который перенаправлено соединение, а не первоначального; однако иногда, например при хешировании, они могут совпадать. Поэтому, как правило, при наличии ‘+’ перед числом повторных попыток это число не следует относить к серверу, указанному в журнале.

  • “srv_queue” — общее число запросов, обработанных перед данным запросом в очереди сервера. Оно равно нулю, если запрос не проходил через очередь сервера. Разделив время ожидания в очереди на число запросов в ней, можно приблизительно оценить время ответа сервера. Если сеанс перенаправляется и проходит через очереди двух серверов, позиции в них суммируются. Запрос не должен проходить и через очередь сервера, и через очередь бэкенда, кроме случая перенаправления.

  • “backend_queue” — общее число запросов, обработанных перед данным запросом в общей очереди бэкенда. Оно равно нулю, если запрос не проходил через общую очередь. Поле позволяет оценить среднюю длину очереди; разделив её на параметр “maxconn” сервера, легко получить число недостающих серверов. При перенаправлении сеанс может дважды пройти через очередь бэкенда, и тогда обе позиции суммируются. Запрос не должен проходить и через очередь сервера, и через очередь бэкенда, кроме случая перенаправления.

8.2.3. Формат журнала HTTP

Формат HTTP — наиболее полный и лучше всего подходит для прокси HTTP. Он включается, если во фронтенде задана “option httplog”. Он предоставляет те же сведения, что и формат TCP, с дополнительными возможностями, относящимися к протоколу HTTP. Как и в формате TCP, запись журнала обычно выдаётся в конце потока, если не задана “option logasap”; эта опция обычно имеет смысл только для сайтов скачивания файлов. Поток, соответствующий правилам “monitor”, никогда не записывается в журнал. Также можно отключить записи для потоков, в которых клиент не отправил никаких данных, задав во фронтенде “option dontlognull”. Успешные соединения не записываются в журнал, если во фронтенде задана “option dontlog-normal”.

Внутри HAProxy формат журнала HTTP объявлен как пользовательский формат на основе следующей точной строки. При необходимости её можно использовать как основу для расширения формата. Вместо неё также можно использовать переменную HAPROXY_HTTP_LOG_FMT. Порядок использования описан в разделе 8.2.6 «Пользовательский формат журнала»:

# strict equivalent of "option httplog"
log-format "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC \
            %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r"
# or using the HAPROXY_HTTP_LOG_FMT variable
log-format "${HAPROXY_HTTP_LOG_FMT}"

Формат журнала CLF также объявлен внутри HAProxy как пользовательский формат на основе следующей точной строки:

# strict equivalent of "option httplog clf"
log-format "%{+Q}o %{-Q}ci - - [%trg] %r %ST %B \"\" \"\" %cp \
            %ms %ft %b %s %TR %Tw %Tc %Tr %Ta %tsc %ac %fc \
            %bc %sc %rc %sq %bq %CC %CS %hrl %hsl"

Большинство полей совпадают с форматом TCP, некоторые различаются. Некоторые поля могут незначительно отличаться в зависимости от опций конфигурации. Такие поля помечены звёздочкой (’*’) после названия поля ниже.

Пример:

    frontend http-in
        mode http
        option httplog
        log global
        default_backend bck

    backend static
        server srv1 127.0.0.1:8000

>>> Feb  6 12:14:14 localhost \
      haproxy[14389]: 10.0.1.2:33317 [06/Feb/2009:12:14:14.655] http-in \
      static/srv1 10/0/30/69/109 200 2750 - - ---- 1/1/1/1/0 0/0 {1wt.eu} \
      {} "GET /index.html HTTP/1.1"

Поле Формат Фрагмент приведённого выше примера

    1   process_name '[' pid ']:'                            haproxy[14389]:
    2   client_ip ':' client_port                             10.0.1.2:33317
    3   '[' request_date ']'                      [06/Feb/2009:12:14:14.655]
    4   frontend_name                                                http-in
    5   backend_name '/' server_name                             static/srv1
    6   TR '/' Tw '/' Tc '/' Tr '/' Ta*                       10/0/30/69/109
    7   status_code                                                      200
    8   bytes_read*                                                     2750
    9   captured_request_cookie                                            -
   10   captured_response_cookie                                           -
   11   termination_state                                               ----
   12   actconn '/' feconn '/' beconn '/' srv_conn '/' retries*    1/1/1/1/0
   13   srv_queue '/' backend_queue                                      0/0
   14   '{' captured_request_headers* '}'                   {haproxy.1wt.eu}
   15   '{' captured_response_headers* '}'                                {}
   16   '"' http_request '"'                      "GET /index.html HTTP/1.1"

Подробное описание полей:

  • “client_ip” — адрес IP клиента, инициировавшего соединение TCP с HAProxy. Если соединение принято через сокет UNIX, вместо адреса IP указывается слово “unix”. Если соединение принято через сокет с настройкой “accept-proxy” и протокол PROXY используется корректно либо через сокет с настройкой “accept-netscaler-cip” и корректным использованием протокола передачи IP клиента NetScaler, в журнале отражаются сведения о переданном соединении.

  • “client_port” — порт TCP клиента, инициировавшего соединение. Если соединение принято через сокет UNIX, вместо порта указывается ID принимающего сокета, который также отображается в интерфейсе статистики.

  • “request_date” — точные дата и время получения HAProxy первого байта запроса HTTP (поле журнала %tr).

  • “frontend_name” — имя фронтенда (или слушателя), который принял и обработал соединение.

  • “backend_name” — имя бэкенда (или слушателя), выбранного для управления соединением с сервером. Будет совпадать с именем фронтенда, если не применялись правила переключения.

  • “server_name” — имя последнего сервера, на который направлялось соединение. Этот сервер может отличаться от первоначального, если из-за ошибок соединения произошло перенаправление. Сервер принадлежит бэкенду, обработавшему запрос. Если запрос прервался, не достигнув сервера, вместо имени сервера указывается “<NOSRV>”. Если запрос перехватила подсистема статистики, вместо него указывается “<STATS>”.

  • “TR” — общее время в миллисекундах, затраченное на ожидание полного запроса HTTP от клиента (без тела) после получения первого байта. Оно может быть равно “-1”, если соединение прервалось до получения полного запроса или был получен некорректный запрос. Это время всегда должно быть очень малым, поскольку запрос обычно помещается в один пакет. Большие значения обычно указывают на сетевые проблемы между клиентом и HAProxy или на ввод запросов вручную. Подробнее см. раздел 8.4 «Временные показатели событий».

  • “Tw” — общее время в миллисекундах, затраченное на ожидание в различных очередях. Может быть равным “-1”, если соединение было прервано до достижения очереди. Подробнее см. раздел 8.4 «Временные показатели событий».

  • “Tc” — общее время в миллисекундах, затраченное на установление соединения с конечным сервером, включая повторные попытки. Может быть равным “-1”, если запрос был прерван до установления соединения. Подробнее см. раздел 8.4 «Временные показатели событий».

  • “Tr” — общее время в миллисекундах, затраченное на ожидание полного ответа HTTP от сервера, без учёта данных. Может быть равным “-1”, если запрос был прерван до получения полного ответа. Обычно соответствует времени обработки запроса сервером, хотя может изменяться в зависимости от объёма данных, отправленных клиентом серверу. Большое время в случае запросов “GET” обычно указывает на перегруженность сервера. Подробнее см. раздел 8.4 «Временные показатели событий».

  • “Ta” — время активности запроса в HAProxy, то есть общее время в миллисекундах от получения первого байта запроса до отправки последнего байта ответа. Оно охватывает всю обработку, кроме согласования соединения (см. Th) и времени простоя (см. Ti). Есть одно исключение: если задана “option logasap”, отсчёт останавливается в момент выдачи записи журнала. Тогда перед значением ставится знак ‘+’, указывающий, что окончательное значение будет больше. Подробнее см. раздел 8.4 «Временные показатели событий».

  • “status_code” — код состояния HTTP, возвращённый клиенту. Этот код обычно устанавливается сервером, но может быть установлен и HAProxy, если сервер недоступен или если ответ был заблокирован HAProxy.

  • “bytes_read” — общее число байтов, переданных клиенту на момент выдачи записи журнала, включая заголовки HTTP. Если задана “option logasap”, перед значением ставится знак ‘+’, указывающий, что окончательное значение может быть больше. Это 64-битный счётчик, поэтому инструменты анализа журналов должны обрабатывать его без переполнения.

  • “captured_request_cookie” — необязательная запись “name=value”, указывающая, что клиент передал этот cookie в запросе. Имя cookie и его максимальная длина задаются директивой “capture cookie” в конфигурации фронтенда. Если опция не задана, поле содержит один дефис (’-’). Захватить можно только один cookie; обычно он используется для отслеживания обмена ID сеансов между клиентом и сервером, чтобы выявлять смешение сеансов разных клиентов из-за ошибок приложения. Подробнее см. раздел «Захват заголовков HTTP и cookie» ниже.

  • “captured_response_cookie” — необязательная запись “name=value”, указывающая, что сервер вернул cookie в ответе. Имя cookie и его максимальная длина задаются директивой “capture cookie” в конфигурации фронтенда. Если опция не задана, поле содержит один дефис (’-’). Захватить можно только один cookie; обычно он используется для отслеживания обмена ID сеансов между клиентом и сервером, чтобы выявлять смешение сеансов разных клиентов из-за ошибок приложения. Подробнее см. раздел «Захват заголовков HTTP и cookie» ниже.

  • “termination_state” — состояние потока в момент его завершения. Как и в журналах TCP, оно указывает состояние потока, сторону, вызвавшую завершение, и причину (тайм-аут, ошибка и т. д.), а последние два символа содержат информацию об операциях привязки с помощью cookie. Нормальные флаги должны начинаться с “–”: это означает, что поток закрыла одна из сторон, а в буферах не осталось данных. Подробнее см. раздел «Состояние потока при разрыве соединения» ниже.

  • “actconn” — общее число одновременных соединений процесса на момент записи потока в журнал. Оно помогает определить, достигнуты ли системные ограничения для отдельного процесса. Например, если при многочисленных ошибках соединения actconn близко к 512 или 1024, весьма вероятно, что система ограничивает процесс 1024 файловыми дескрипторами и все они заняты. Порядок настройки системы описан в разделе 3 «Глобальная секция».

  • “feconn” — общее количество одновременных соединений на фронтенде на момент записи потока в журнал. Полезно для оценки объёма ресурсов, необходимых для поддержки высокой нагрузки, и для выявления достижения лимита “maxconn” фронтенда. Часто резкий рост этого значения указывает на перегрузку серверов бэкенда, хотя иногда может быть вызван атакой типа “отказ в обслуживании”.

  • “beconn” — общее количество одновременных соединений, обрабатываемых бэкендом на момент записи потока в журнал. Включает общее количество одновременных соединений на серверах, а также количество соединений, ожидающих в очередях. Полезно для оценки количества дополнительных серверов, необходимых для поддержки высокой нагрузки приложения. Часто резкий рост этого значения указывает на перегрузку серверов бэкенда, хотя иногда может быть вызван атакой типа “отказ в обслуживании”.

  • “srv_conn” — общее число одновременных соединений, которые ещё активны на сервере на момент записи потока в журнал. Оно никогда не может превышать настроенный для сервера параметр “maxconn”. Если значение очень часто близко к “maxconn” сервера или равно ему, это означает, что часто задействуется регулирование трафика: либо значение maxconn сервера слишком мало, либо серверов недостаточно, чтобы обрабатывать нагрузку с оптимальным временем ответа. Если высокое значение “srv_conn” наблюдается только у одного сервера, обычно у него есть проблема, из-за которой обработка запросов занимает больше времени, чем на остальных серверах.

  • “retries” — число повторных попыток установить соединение с сервером для этого потока. Обычно оно должно быть равно нулю, кроме случая, когда сервер останавливается одновременно с попыткой подключения. Частые повторы обычно указывают либо на сетевую проблему между HAProxy и сервером, либо на неверную настройку системной очереди входящих соединений на сервере, из-за которой новые соединения не могут попасть в очередь. Поле может начинаться со знака ‘+’: это означает, что после достижения максимального числа повторных попыток на первоначальном сервере поток был перенаправлен. Тогда в журнале указывается имя сервера, на который перенаправлено соединение, а не первоначального; однако иногда, например при хешировании, они могут совпадать. Поэтому, как правило, при наличии ‘+’ перед числом повторных попыток это число не следует относить к серверу, указанному в журнале.

  • “srv_queue” — общее число запросов, обработанных перед данным запросом в очереди сервера. Оно равно нулю, если запрос не проходил через очередь сервера. Разделив время ожидания в очереди на число запросов в ней, можно приблизительно оценить время ответа сервера. Если поток перенаправляется и проходит через очереди двух серверов, позиции в них суммируются. Запрос не должен проходить и через очередь сервера, и через очередь бэкенда, кроме случая перенаправления.

  • “backend_queue” — общее число запросов, обработанных перед данным запросом в общей очереди бэкенда. Оно равно нулю, если запрос не проходил через общую очередь. Поле позволяет оценить среднюю длину очереди; разделив её на параметр “maxconn” сервера, легко получить число недостающих серверов. При перенаправлении поток может дважды пройти через очередь бэкенда, и тогда обе позиции суммируются. Запрос не должен проходить и через очередь сервера, и через очередь бэкенда, кроме случая перенаправления.

  • “captured_request_headers” — список заголовков, захваченных из запроса благодаря директиве “capture request header” во фронтенде. Можно захватывать несколько заголовков; они разделяются вертикальной чертой (’|’). Если захват не включён, фигурные скобки не выводятся и оставшиеся поля сдвигаются. Поле может содержать пробелы, поэтому при его использовании нужен более сложный анализатор журналов. Подробнее см. раздел «Захват заголовков HTTP и cookie» ниже.

  • “captured_response_headers” — список заголовков, захваченных из ответа благодаря директиве “capture response header” во фронтенде. Можно захватывать несколько заголовков; они разделяются вертикальной чертой (’|’). Если захват не включён, фигурные скобки не выводятся и оставшиеся поля сдвигаются. Поле может содержать пробелы, поэтому при его использовании нужен более сложный анализатор журналов. Подробнее см. раздел «Захват заголовков HTTP и cookie» ниже.

  • “http_request” — полная строка запроса HTTP, включая метод, сам запрос и строку версии HTTP. Непечатаемые символы кодируются (см. раздел «Непечатаемые символы» ниже). Это поле всегда последнее, всегда заключено в кавычки и только оно может содержать кавычки. Новые поля формата журнала добавляются перед ним. Поле может быть обрезано, если запрос настолько велик, что не помещается в стандартный буфер syslog (1024 символа). Именно поэтому оно всегда должно оставаться последним.

8.2.4. Формат журнала HTTPS

Формат HTTPS лучше всего подходит для соединений HTTP через SSL. Он расширяет формат HTTP (см. раздел 8.2.3 ) сведениями, связанными с SSL. Он включается, если во фронтенде задана “option httpslog”. Как и в форматах TCP и HTTP, запись журнала обычно выдаётся в конце потока, если не задана “option logasap”. Поток, соответствующий правилам “monitor”, никогда не записывается в журнал. Также можно отключить записи для потоков, в которых клиент не отправил никаких данных, задав во фронтенде “option dontlognull”. Успешные соединения не записываются в журнал, если во фронтенде задана “option dontlog-normal”.

Внутри HAProxy формат журнала HTTPS объявлен как пользовательский формат на основе следующей точной строки. При необходимости её можно использовать как основу для расширения формата. Вместо неё также можно использовать переменную HAPROXY_HTTPS_LOG_FMT. Порядок использования описан в разделе 8.2.6 «Пользовательский формат журнала»:

# strict equivalent of "option httpslog"
log-format "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC \
           %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r \
           %[fc_err]/%[ssl_fc_err,hex]/%[ssl_c_err]/\
           %[ssl_c_ca_err]/%[ssl_fc_is_resumed] %[ssl_fc_sni]/%sslv/%sslc"
# or using the HAPROXY_HTTPS_LOG_FMT variable
log-format "${HAPROXY_HTTPS_LOG_FMT}"

По сути, это формат HTTP (см. раздел 8.2.3 ) с добавленными полями. Здесь подробно описываются новые поля (строки 17 и 18). Описание полей HTTP см. в разделе о формате HTTP.

Пример:

    frontend https-in
        mode http
        option httpslog
        log global
        bind *:443 ssl crt mycerts/srv.pem ...
        default_backend bck

    backend static
        server srv1 127.0.0.1:8000 ssl crt mycerts/clt.pem ...

>>> Feb  6 12:14:14 localhost \
      haproxy[14389]: 10.0.1.2:33317 [06/Feb/2009:12:14:14.655] https-in \
      static/srv1 10/0/30/69/109 200 2750 - - ---- 1/1/1/1/0 0/0 {1wt.eu} \
      {} "GET /index.html HTTP/1.1" 0/0/0/0/0 \
      1wt.eu/TLSv1.3/TLS_AES_256_GCM_SHA384

Поле Формат Фрагмент приведённого выше примера

    1   process_name '[' pid ']:'                              haproxy[14389]:
    2   client_ip ':' client_port                               10.0.1.2:33317
    3   '[' request_date ']'                        [06/Feb/2009:12:14:14.655]
    4   frontend_name                                                 https-in
    5   backend_name '/' server_name                               static/srv1
    6   TR '/' Tw '/' Tc '/' Tr '/' Ta*                         10/0/30/69/109
    7   status_code                                                        200
    8   bytes_read*                                                       2750
    9   captured_request_cookie                                              -
   10   captured_response_cookie                                             -
   11   termination_state                                                 ----
   12   actconn '/' feconn '/' beconn '/' srv_conn '/' retries*      1/1/1/1/0
   13   srv_queue '/' backend_queue                                        0/0
   14   '{' captured_request_headers* '}'                     {haproxy.1wt.eu}
   15   '{' captured_response_headers* '}'                                  {}
   16   '"' http_request '"'                        "GET /index.html HTTP/1.1"
   17   fc_err '/' ssl_fc_err '/' ssl_c_err
        '/' ssl_c_ca_err '/' ssl_fc_is_resumed                       0/0/0/0/0
   18   ssl_fc_sni '/' ssl_version
        '/' ssl_ciphers                  1wt.eu/TLSv1.3/TLS_AES_256_GCM_SHA384

Подробное описание полей:

  • “fc_err” — состояние соединения со стороны фронтенда. Соответствует извлечению образца “fc_err”. См. функции извлечения образца “fc_err” и “fc_err_str” для получения дополнительной информации.

  • “ssl_fc_err” — последняя ошибка в первом стеке ошибок SSL, возникшем на соединении со стороны фронтенда. Например, это поле позволяет выявлять ошибки согласования SSL. Если всё прошло успешно, значение равно 0. Подробнее см. описание функции извлечения образца “ssl_fc_err”.

  • “ssl_c_err” — состояние проверки сертификата клиента. Согласование может завершиться успешно даже при ненулевом коде ошибки проверки, если эта ошибка игнорируется. См. функцию извлечения образца “ssl_c_err” и опцию “crt-ignore-err”.

  • “ssl_c_ca_err” — состояние проверки цепочки сертификатов клиента. Согласование может завершиться успешно даже при ненулевом коде ошибки проверки, если эта ошибка игнорируется. См. функцию извлечения образца “ssl_c_ca_err” и опцию “ca-ignore-err”.

  • “ssl_fc_is_resumed” истинно, если входящий сеанс TLS возобновлён с помощью кэша состояния или билета без сохранения состояния. Помните, что один сеанс TLS может использоваться несколькими запросами.

  • “ssl_fc_sni” — SNI (Server Name Indication), переданный клиентом для выбора сертификата. Обычно он совпадает с именем узла первого запроса в соединении. Отсутствие поля может означать, что клиент не передал SNI; тогда haproxy использует сертификат по умолчанию либо отклоняет соединение при strict-sni.

  • “ssl_version” — версия SSL фронтенда.

  • “ssl_ciphers” — шифр SSL, используемый в соединении.

8.2.5. Формат журнала ошибок

Если входящее соединение завершается ошибкой из-за согласования SSL или некорректного заголовка протокола PROXY, HAProxy записывает событие в сокращённом фиксированном формате, если строкой “error-log-format” не задан специальный формат журнала ошибок. По умолчанию записи выдаются с уровнем LOG_INFO, но при включённой в бэкенде опции “log-separate-errors” используется LOG_ERR. Соединения без обмена данными, например пробы, не записываются, если задана опция “dontlognull”.

Формат по умолчанию выглядит так:

  >>> Dec  3 18:27:14 localhost \
        haproxy[6103]: 127.0.0.1:56059 [03/Dec/2012:17:35:10.380] frt/f1: \
        Connection error during SSL handshake

Поле    Формат                                Фрагмент приведённого примера
    1   process_name '[' pid ']:'                             haproxy[6103]:
    2   client_ip ':' client_port                            127.0.0.1:56059
    3   '[' accept_date ']'                       [03/Dec/2012:17:35:10.380]
    4   frontend_name "/" bind_name ":"                              frt/f1:
    5   message                        Connection error during SSL handshake

Эти поля дают лишь минимальные сведения для отладки ошибок соединения.

При использовании директивы “error-log-format” описанный выше устаревший формат больше не применяется: все записи ошибок следуют заданному формату.

Ниже приведён пример достаточно полного error-log-format. Он сообщает адрес и порт источника, дату и время принятия соединения вызовом accept(), имя фронтенда, число активных соединений процесса и этого фронтенда, внутренний ID ошибки haproxy на входящем соединении, шестнадцатеричный номер ошибки OpenSSL (его можно скопировать в “openssl errstr” для полной расшифровки), статус извлечения сертификата клиента (0 означает отсутствие ошибки), статус проверки сертификата клиента с использованием CA (0 означает отсутствие ошибки), логический признак нового или возобновлённого соединения, необязательный SNI, переданный клиентом, имя версии SSL и шифры SSL соединения, если они есть. Ошибки соединений с бэкендом здесь никогда не отражаются: чтобы попытка соединения с бэкендом состоялась и могла завершиться ошибкой, поток уже должен был пройти успешную обработку. Поэтому такой случай доступен в обычном журнале трафика (см. option httplog или option httpslog).

# detailed frontend connection error log
error-log-format "%ci:%cp [%tr] %ft %ac/%fc %[fc_err]/\
      %[ssl_fc_err,hex]/%[ssl_c_err]/%[ssl_c_ca_err]/%[ssl_fc_is_resumed] \
      %[ssl_fc_sni]/%sslv/%sslc"

8.2.6. Пользовательский формат журнала

Исторически пользовательские форматы применялись только для журналов. Однако удобство построения строки из нескольких сложных выражений привело к их использованию во многих директивах, которые раньше принимали только строковый аргумент, а теперь также принимают описание пользовательского формата журнала. Такие аргументы, обычно обозначаемые в этом документе как “<fmt>”, задаются точно так же, как описанный здесь аргумент директивы “log-format”.

Если стандартных форматов журнала недостаточно, можно определить новые с очень подробной настройкой. Создать log-format с нуля не всегда просто, поэтому настоятельно рекомендуется сначала изучить существующие форматы (“option tcplog”, “option httplog”, “option httpslog”), выбрать наиболее близкий к нужному, скопировать соответствующую строку “log-format” и изменить её.

С точки зрения конфигурации описание пользовательского формата журнала — один аргумент. Поэтому оно не может содержать пробелы или табуляцию, если они не экранированы обратной косой чертой (’\’) либо всё описание не заключено в кавычки, что является рекомендуемым способом. Использовать строки формата без кавычек больше не рекомендуется: опыт показал, что они часто приводят к ошибкам, поскольку один пропущенный обратный слеш может вызвать незаметное усечение формата. Такие конфигурации всё ещё распространены из-за массового внедрения форматов журналов после версии 1.5-dev9, за 3 года до появления поддержки кавычек. Теперь рекомендуется преобразовать их в строки в кавычках и убрать обратные слеши.

Описание формата журнала состоит из произвольного числа элементов, разделённых текстом и пробелами. Элемент начинается с ‘%’. Чтобы вывести сам символ ‘%’, перед ним нужно поставить ещё один ‘%’, получив ‘%%’.

Элементы logformat могут быть алиасами или выражениями образцов:

Если имя элемента заключено в квадратные скобки (’[’ .. ‘]’), оно используется как правило выражения образца (см. раздел 7.3 ). Это позволяет добавлять менее распространённые сведения, например DN сертификата SSL клиента, или записывать ключ, который использовался бы для хранения записи в таблице привязок. Этот способ также часто применяется в действиях, не связанных с журналом: работе с заголовками, переменными и т. д.

Если же элемент задан буквенно-цифровым именем, это алиас. Список доступных алиасов приведён в таблице ниже.

Элементы могут принимать аргументы в фигурных скобках (’{}’); несколько аргументов разделяются запятыми внутри скобок. Флаги можно добавлять и удалять с помощью префиксов ‘+’ и ‘-’ (список доступных флагов см. ниже).

Специальный алиас “%o” распространяет свои флаги на все остальные элементы logformat в той же строке формата. Это особенно удобно для строковых форматов с кавычками (“Q”) и экранированием (“E”).

Специальный алиас “%OG” позволяет получить источник записи — когда и где она была создана — в понятном человеку виде. Это особенно полезно с “option logasap”: некоторые переменные журнала или функции извлечения образца могут возвращать неполные значения либо вести себя по-разному в зависимости от момента и места вычисления выражения logformat. Возможные значения:

  • “sess_error”: запись создана при обработке ошибки сеанса
  • “sess_killed”: запись создана при прерывании сеанса (уничтожен ещё не полностью созданный сеанс)
  • “txn_accept”: запись создана сразу после принятия соединения фронтендом
  • “txn_request”: запись создана после получения запроса клиента
  • “txn_connect”: запись создана после установления соединения с бэкендом
  • “txn_response”: запись создана при обработке ответа сервера
  • “txn_close”: запись создана на заключительном этапе txn перед закрытием
  • “unspec”: источник неизвестен или не указан. “%OG” имеет смысл только в контексте ведения журнала.

Элементам можно задавать имена с помощью (’()’). Имя должно идти сразу после ‘%’ перед аргументами. При включении флага кодирования, например “json” или “cbor”, оно автоматически используется как имя ключа. Если флаг кодирования не задан (по умолчанию), имя элемента игнорируется. Также можно принудительно задать тип выводимого значения, добавив ‘:type’ после имени: %(itemname:itemtype)aliasname или %(itemname:itemtype)[expr], где itemtype может быть ‘str’, ‘sint’ или ‘bool’. Указание типа имеет смысл только при использовании кодирования. Поддерживается и пустое имя, позволяющее задать тип вывода для безымянного элемента: %(:itemtype), то есть когда кодирование не включено глобально. Подробнее см. описание флагов ниже.

Поскольку пользовательские форматы изначально предназначались только для журналов, непечатаемые и небезопасные символы (за пределами кодов ASCII от 32 до 126 и некоторые другие) обрабатываются особо в зависимости от места использования. В разделе 8.6 подробно описана обработка в журналах, предотвращающая вывод небезопасных кодов, которые ухудшают читаемость в терминале. При формировании полей заголовков, проверок работоспособности или содержимого ответов правила менее строгие: только символы, запрещённые в полях заголовков HTTP, заменяются шестнадцатеричным кодом с префиксом ‘%’. Обычно это не создаёт проблем, но может повлиять на вывод, если символ должен был воспроизводиться буквально, например при построении страницы ошибки или полного тела ответа, где переводы строк могут выглядеть как “%0A”.

Примечание: в директивах конфигурации “log-format”, “log-format-sd” и “unique-id-format” пробелы считаются разделителями и объединяются.

Примечание: в формате сообщений syslog RFC5424 символы ‘"’, ‘\’ и ‘]’ внутри PARAM-VALUE следует экранировать префиксом ‘\’ (подробнее см. https://tools.ietf.org/html/rfc5424#section-6.3.3 ). В таких случаях стоит рассмотреть флаг “E”.

Поддерживаются следующие флаги элементов; их можно включать и выключать в аргументах элемента:

  • Q: заключает строку в кавычки
  • X: шестнадцатеричное представление (адреса IP, порты, %Ts, %rt, %pid)
  • E: экранирует символы ‘"’, ‘\’ и ‘]’ в строке префиксом ‘\’ (предназначен для форматов журналов structured-data RFC5424)
  • bin: пытается сохранить двоичные данные. Это полезно для выражений образцов, возвращающих двоичные данные, чтобы сохранить исходное содержимое. Однако возможны непечатаемые символы, включая NULL-байт, которых большинство получателей syslog не ожидает. Поэтому флаг предназначен главным образом для set-var-fmt, кольцевых буферов и получателей журналов с поддержкой двоичных данных. Его можно задать только глобально (через %o); в опциях отдельного элемента он игнорируется.
  • json: автоматически кодирует значение в JSON; при глобальном включении учитываются только именованные элементы формата журнала. Неполные числовые значения, например ‘%B’ при использовании logasap, которые без кодирования обычно получают префикс ‘+’, кодируются без изменений. Параметр ‘+E’ также игнорируется. Как описано в разделе 8.6 , символы вне диапазона 32..126 экранируются побайтно последовательностями JSON, чтобы при любых входных данных вывод оставался печатным ASCII. Это касается и корректных последовательностей UTF-8: после декодирования текст вне ASCII будет представлен отдельными байтами. Например, U+00E9, закодированный как 0xC3 0xA9, записывается как “\u00C3\u00A9”. Для сохранения такого текста см. “utf8” ниже.
  • utf8: в сочетании с “json” пропускает корректные многобайтовые последовательности UTF-8 без экранирования. Управляющие символы C1 (от U+0080 до U+009F) по-прежнему экранируются и представляются своей кодовой точкой. Некорректные последовательности экранируются побайтно, чтобы вывод всегда оставался корректным UTF-8. Поскольку корректный UTF-8 выводится без изменений, клиент может специальными символами изменить отображение строки журнала в терминале или просмотрщике, например переключением направления письма, символами нулевой ширины либо разделителями строк и абзацев. Поэтому рекомендуется использовать флаг только для данных из доверенных источников либо когда журналы не предназначены для отображения в терминале. Без “json” он не действует.
  • cbor: автоматически кодирует значение в CBOR; при глобальном включении учитываются только именованные элементы logformat. По умолчанию данные cbor представляются в HEX, чтобы их можно было печатать в stdout и использовать с обычными получателями syslog. Как и при кодировании json, неполные числовые значения кодируются как есть, а опция ‘+E’ игнорируется. В сочетании с ‘+bin’ сразу создаётся необработанная двоичная полезная нагрузка CBOR. При этом возникают непечатаемые символы, поэтому такой режим предназначен главным образом для set-var-fmt, кольцевых буферов и получателей журналов с поддержкой двоичных данных.

Пример:

log-format %T\ %t\ Some\ Text
log-format %{+Q}o\ %t\ %s\ %{-Q}r

log-format-sd %{+Q,+E}o\ [exampleSDID@1234\ header=%[capture.req.hdr(0)]]

log-format "%{+json}o %(request)r %(custom_expr)[str(custom)]"
log-format "%{+json,+utf8}o %(request)r %(custom_expr)[str(custom)]"
log-format "%{+cbor}o %(request)r %(custom_expr)[str(custom)]"

Ниже перечислены доступные алиасы:

  +---+------+------------------------------------------------------+---------+
  | R | алиас| имя поля (описание в 8.2.2 и 8.2.3)                  | тип     |
  |   |      | эквивалентное выражение извлечения образца           |         |
  +===+======+======================================================+=========+
  |   | %o   | особый: флаги применяются ко всем следующим элементам|         |
  +---+------+------------------------------------------------------+---------+
  |                          форматы даты                                     |
  +---+------+------------------------------------------------------+---------+
  |   | %T   | Время приёма соединения в UTC + часовой пояс         |         |
  |   |      | %[accept_date,utime("%d/%b/%Y:%H:%M:%S %z")]         | дата    |
  +---+------+------------------------------------------------------+---------+
  |   | %Tl  | Местное время приёма соединения + часовой пояс       |         |
  |   |      | %[accept_date,ltime("%d/%b/%Y:%H:%M:%S %z")]         | дата    |
  +---+------+------------------------------------------------------+---------+
  |   | %Ts  | Время приёма соединения как временная метка UNIX     | число   |
  |   |      | %[accept_date]                                       |         |
  +---+------+------------------------------------------------------+---------+
  |   | %t   | Местное время приёма (точность до миллисекунд)       |         |
  |   |      | %[accept_date(ms),ms_ltime("%d/%b/%Y:%H:%M:%S.%3N")] | дата    |
  +---+------+------------------------------------------------------+---------+
  |   | %ms  | Миллисекунды времени приёма соединения               |         |
  |   |      | %[accept_date(ms),ms_utime("%3N")]                   | число   |
  +---+------+------------------------------------------------------+---------+
  | H | %tr  | Местное время запроса (точность до миллисекунд)      |         |
  |   |      | %[request_date(ms),ms_ltime("%d/%b/%Y:%H:%M:%S.%3N")]| дата    |
  +---+------+------------------------------------------------------+---------+
  | H | %trg | Время запроса в UTC + часовой пояс                   |         |
  |   |      | %[request_date,utime("%d/%b/%Y:%H:%M:%S %z")]        | дата    |
  +---+------+------------------------------------------------------+---------+
  | H | %trl | Местное время запроса + часовой пояс                 |         |
  |   |      | %[request_date,ltime("%d/%b/%Y:%H:%M:%S %z")]        | дата    |
  +---+------+------------------------------------------------------+---------+
  |                          Временные показатели событий                     |
  +---+------+------------------------------------------------------+---------+
  | H | %Ta  | Время активной обработки запроса (от TR до конца)    |         |
  |   |      | %[txn.timer.total]                                   | число   |
  +---+------+------------------------------------------------------+---------+
  |   | %Tc  | Tc                                                   |         |
  |   |      | %[bc.timer.connect]                                  | число   |
  +---+------+------------------------------------------------------+---------+
  |   | %Td  | Td = Tt - (Tq + Tw + Tc + Tr)                        |         |
  |   |      | %[res.timer.data]                                    | число   |
  +---+------+------------------------------------------------------+---------+
  |   | %Th  | Время согласования соединения (SSL, протокол PROXY)  |         |
  |   |      | %[fc.timer.handshake]                                | число   |
  +---+------+------------------------------------------------------+---------+
  | H | %Ti  | Время простоя перед запросом HTTP                    |         |
  |   |      | %[req.timer.idle]                                    | число   |
  +---+------+------------------------------------------------------+---------+
  | H | %Tq  | Th + Ti + TR                                         |         |
  |   |      | %[req.timer.tq]                                      | число   |
  +---+------+------------------------------------------------------+---------+
  | H | %TR  | Время приёма полного запроса с 1-го байта            |         |
  |   |      | %[req.timer.hdr]                                     | число   |
  +---+------+------------------------------------------------------+---------+
  | H | %Tr  | Tr (время ответа)                                    |         |
  |   |      | %[res.timer.hdr]                                     | число   |
  +---+------+------------------------------------------------------+---------+
  |   | %Tt  | Tt                                                   |         |
  |   |      | %[fc.timer.total]                                    | число   |
  +---+------+------------------------------------------------------+---------+
  |   | %Tu  | Tu                                                   |         |
  |   |      | %[txn.timer.user]                                    | число   |
  +---+------+------------------------------------------------------+---------+
  |   | %Tw  | Tw                                                   |         |
  |   |      | %[req.timer.queue]                                   | число   |
  +---+------+------------------------------------------------------+---------+
  |                          Прочее                                           |
  +---+------+------------------------------------------------------+---------+
  |   | %B   | bytes_read           (от сервера к клиенту)          | число   |
  |   |      | %[res.bytes_in]                                      |         |
  +---+------+------------------------------------------------------+---------+
  | H | %CC  | captured_request_cookie                              | строка  |
  +---+------+------------------------------------------------------+---------+
  | H | %CS  | captured_response_cookie                             | строка  |
  +---+------+------------------------------------------------------+---------+
  |   | %H   | hostname                                             | строка  |
  |   |      | %[hostname]                                          |         |
  +---+------+------------------------------------------------------+---------+
  | H | %HM  | Метод HTTP (например, POST)                          | строка  |
  |   |      | %[method]
  +---+------+------------------------------------------------------+---------+
  | H | %HP  | URI запроса HTTP без строки параметров               | строка  |
  +---+------+------------------------------------------------------+---------+
  | H | %HPO | Только путь HTTP (без узла и строки параметров)      | строка  |
  +---+------+------------------------------------------------------+---------+
  | H | %HQ  | Строка параметров URI HTTP (например, ?bar=baz)      | строка  |
  |   |      | ?%[query]                                            |         |
  +---+------+------------------------------------------------------+---------+
  | H | %HU  | URI запроса HTTP (например, /foo?bar=baz)            | строка  |
  +---+------+------------------------------------------------------+---------+
  | H | %HV  | Версия HTTP (например, HTTP/1.0)                     | строка  |
  |   |      | HTTP/%[req.ver]                                      |         |
  +---+------+------------------------------------------------------+---------+
  |   | %ID  | unique-id                                            | строка  |
  |   |      | %[unique-id]                                         |         |
  +---+------+------------------------------------------------------+---------+
  |   | %ST  | status_code                                          | число   |
  |   |      | %[txn.status]                                        |         |
  +---+------+------------------------------------------------------+---------+
  |   | %U   | bytes_uploaded       (от клиента к серверу)          | число   |
  |   |      | %[req.bytes_in]                                      |         |
  +---+------+------------------------------------------------------+---------+
  |   | %ac  | actconn                                              |         |
  |   |      | %[act_conn]                                          | число   |
  +---+------+------------------------------------------------------+---------+
  |   | %b   | backend_name                                         |         |
  |   |      | %[be_name]                                           | строка  |
  +---+------+------------------------------------------------------+---------+
  |   | %bc  | beconn      (одновременные соединения бэкенда)       | число   |
  |   |      | %[be_conn]                                           |         |
  +---+------+------------------------------------------------------+---------+
  |   | %bi  | backend_source_ip       (адрес исходящего соединения)|         |
  |   |      | %[bc_src]                                            | IP      |
  +---+------+------------------------------------------------------+---------+
  |   | %bp  | backend_source_port     (адрес исходящего соединения)|         |
  |   |      | %[bc_src_port]                                       | число   |
  +---+------+------------------------------------------------------+---------+
  |   | %bq  | backend_queue                                        | число   |
  |   |      | %[bc_be_queue]                                       |         |
  +---+------+------------------------------------------------------+---------+
  |   | %ci  | client_ip                (адрес принятого соединения)|         |
  |   |      | %[src]                                               | IP      |
  +---+------+------------------------------------------------------+---------+
  |   | %cp  | client_port              (адрес принятого соединения)|         |
  |   |      | %[src_port]                                          | число   |
  +---+------+------------------------------------------------------+---------+
  |   | %f   | frontend_name                                        | строка  |
  |   |      | %[fe_name]                                           |         |
  +---+------+------------------------------------------------------+---------+
  |   | %fc  | feconn     (одновременные соединения фронтенда)      | число   |
  |   |      | %[fe_conn]                                           |         |
  +---+------+------------------------------------------------------+---------+
  |   | %fi  | frontend_ip              (адрес приёма соединений)   |         |
  |   |      | %[dst]                                               | IP      |
  +---+------+------------------------------------------------------+---------+
  |   | %fp  | frontend_port            (адрес приёма соединений)   |         |
  |   |      | %[dst_port]                                          | число   |
  +---+------+------------------------------------------------------+---------+
  |   | %ft  | frontend_name_transport (суффикс '~' для SSL)        | строка  |
  +---+------+------------------------------------------------------+---------+
  |   | %lc  | frontend_log_counter                                 | число   |
  +---+------+------------------------------------------------------+---------+
  |   | %hr  | captured_request_headers в стиле по умолчанию        | строка  |
  +---+------+------------------------------------------------------+---------+
  |   | %hrl | captured_request_headers в стиле CLF                 | строка  |
  |   |      |                                                      | список  |
  +---+------+------------------------------------------------------+---------+
  |   | %hs  | captured_response_headers в стиле по умолчанию       | строка  |
  +---+------+------------------------------------------------------+---------+
  |   | %hsl | captured_response_headers в стиле CLF                | строка  |
  |   |      |                                                      | список  |
  +---+------+------------------------------------------------------+---------+
  | L | %OG  | Источник записи журнала в понятном человеку виде     | строка  |
  +---+------+------------------------------------------------------+---------+
  |   | %pid | PID                                                  |         |
  |   |      | %[pid]                                               | число   |
  +---+------+------------------------------------------------------+---------+
  | H | %r   | http_request                                         | строка  |
  +---+------+------------------------------------------------------+---------+
  |   | %rc  | retries                                              | число   |
  |   |      | %[txn.redispatched,iif(+,)]%[txn.conn_retries]       |         |
  +---+------+------------------------------------------------------+---------+
  |   | %rt  | request_counter (запрос HTTP или сеанс TCP)          | число   |
  |   |      | %[txn.id32]                                          |         |
  +---+------+------------------------------------------------------+---------+
  |   | %s   | server_name                                          | строка  |
  |   |      | %[srv_name]                                          |         |
  +---+------+------------------------------------------------------+---------+
  |   | %sc  | srv_conn     (одновременные соединения сервера)      | число   |
  +---+------+------------------------------------------------------+---------+
  |   | %si  | server_IP                   (адрес назначения)       |         |
  |   |      | %[bc_dst]                                            | IP      |
  +---+------+------------------------------------------------------+---------+
  |   | %sp  | server_port                 (адрес назначения)       |         |
  |   |      | %[bc_dst_port]                                       | число   |
  +---+------+------------------------------------------------------+---------+
  |   | %sq  | srv_queue                                            | число   |
  |   |      | %[bc_srv_queue]                                      |         |
  +---+------+------------------------------------------------------+---------+
  | S | %sslc| ssl_ciphers (например, AES-SHA)                      |         |
  |   |      | %[ssl_fc_cipher]                                     | строка  |
  +---+------+------------------------------------------------------+---------+
  | S | %sslv| ssl_version (например, TLSv1)                        |         |
  |   |      | %[ssl_fc_protocol]                                   | строка  |
  +---+------+------------------------------------------------------+---------+
  |   | %ts  | termination_state                                    | строка  |
  |   |      | %[txn.sess_term_state]                               |         |
  +---+------+------------------------------------------------------+---------+
  | H | %tsc | termination_state со статусом cookie                 | строка  |
  +---+------+------------------------------------------------------+---------+
R = Ограничения: H = только режим http; S = только SSL; L = только журнал

8.3. Расширенные параметры ведения журнала

Некоторые расширенные параметры журналирования нужны часто, но их нелегко найти простым просмотром опций. Здесь собрано несколько опций, позволяющих улучшить ведение журнала. Подробнее об их использовании см. справочник ключевых слов.

8.3.1. Отключение записи внешних проверок

Инструменты мониторинга часто проверяют работоспособность HAProxy. Это может быть балансировщик уровня 3, например LVS или коммерческий балансировщик, либо более полноценная система мониторинга, например Nagios. При очень частых проверках пользователи часто спрашивают, как отключить их запись в журнал. Есть три возможности:

  • Если соединения приходят из разных источников и представляют собой лишь пробы TCP, обычно удобно отключить запись соединений без обмена данными, задав “option dontlognull” во фронтенде. Это также отключает запись сканирования портов, что может быть как желательным, так и нежелательным.

  • Можно использовать действие “http-request set-log-level silent” с различными условиями: исходными сетями, путями, пользовательскими агентами и т. д.

  • Если проверки обращаются к известному URI, с помощью “monitor-uri” можно выделить этот URI для мониторинга. Любой узел, отправивший такой запрос, получит только результат проверки работоспособности, а сам запрос не будет записан в журнал.

8.3.2. Запись журнала до завершения потока

При записи журнала в конце соединения невозможно узнать, что происходит во время очень долгих потоков, например сеансов удалённого терминала или скачивания больших файлов. Это можно обойти, задав во фронтенде “option logasap”. Тогда HAProxy выдаёт запись как можно раньше, непосредственно перед началом передачи данных. Для TCP в журнал по-прежнему попадёт состояние соединения с сервером, а для HTTP запись выдаётся сразу после обработки заголовков сервера. В этом случае указанное число байтов — это число байтов заголовков, отправленных клиенту. Чтобы отличать такие записи от обычных, перед полями полного времени и числа байтов ставится ‘+’: реальные значения заведомо больше.

8.3.3. Повышение уровня журнала при ошибках

Иногда удобнее отделять журналы ошибок от обычного трафика, например для упрощения контроля ошибок по файлам журналов. При использовании “log-separate-errors” для соединений с ошибками, тайм-аутами, повторными попытками, перенаправлениями или кодами состояния HTTP 5xx уровень syslog повышается с “info” до “err”. Это позволяет демону syslog сохранять записи в отдельный файл. Очень важно также оставлять ошибки в файле обычного трафика, чтобы порядок записей не нарушался. Следует быть осторожным, если демон syslog уже настроен сохранять все записи выше “notice” в файл “admin”: уровень “err” выше “notice”.

8.3.4. Отключение записи успешных соединений

Хотя поначалу это может показаться странным, некоторые крупные сайты обрабатывают по несколько тысяч записей журнала в секунду и испытывают трудности с их длительным сохранением в полном объёме или поиском ошибок среди них. Если во фронтенде задана “dontlog-normal”, все нормальные соединения исключаются из журнала. Нормальным здесь считается соединение без ошибок, тайм-аутов, повторных попыток и перенаправлений. В HTTP также проверяется код состояния: ответ 5xx не считается нормальным и тоже записывается. Однако этот способ настоятельно не рекомендуется, поскольку убирает из журналов большую часть полезной информации. Применяйте его только при отсутствии альтернатив.

8.3.5. Профили журналов

Директивы “log-format”, “log-format-sd”, “error-log-format” и “log-tag” позволяют задавать форматирование журналов глобально или на уровне прокси. Однако иногда полезно задавать эти параметры как можно ближе к получателям журналов, то есть для каждой директивы “log”.

Для этого служит секция “log-profile”: “log-profile” можно определить в любом месте конфигурации. Она принимает набор ключевых слов, описывающих построение записей для определённой директивы log.

В директиве “log” можно выбрать конкретный log-profile по имени. Один профиль может использоваться несколькими директивами “log”.

log-profile <name> Создаёт новый профиль журнала с именем <name>

log-tag <string> Переопределяет тег syslog, заданный глобально или для прокси директивой “log-tag”.

on <step> [drop] [format <fmt>] [sd <sd_fmt>] Переопределяет строку log-format, обычно используемую для построения записи на этапе <step>. <fmt> заменяет строку “log-format” или “error-log-format” в зависимости от <step>, а <sd_fmt> заменяет строку “log-format-sd”; оба параметра можно сочетать.

Специальное ключевое слово “drop” указывает, что на данном этапе <step> запись не должна выдаваться. Оно имеет приоритет над ранее заданными “format” и “sd”.

Возможные значения <step>:

  • “accept” : переопределяет log-format, если запись создаётся сразу после принятия соединения фронтендом
  • “request” : переопределяет log-format, если запись создаётся после получения запроса клиента
  • “connect” : переопределяет log-format, если запись создаётся после установления соединения с бэкендом
  • “response”: переопределяет log-format, если запись создаётся при обработке ответа сервера
  • “close” : переопределяет log-format, если запись создаётся на заключительном этапе транзакции (txn)
  • “error” : переопределяет error-log-format, если запись создаётся из-за ошибки транзакции
  • “any” : переопределяет log-format и error-log-format для всех этапов, если не задано переопределение для более конкретного этапа.

Дополнительные применимые значения <step> см. в описании действия “do-log”.

Эта настройка имеет смысл только для директив “log” в контекстах, где применима директива “log-format”, например для прокси http и tcp. В остальных случаях она просто игнорируется.

Пример:

log-profile myprof

  log-tag "custom-tag"

  on error format "%ci: error"
  on connect drop
  on any sd "custom-sd"

listen myproxy
  mode http
  option httplog
  log-tag "normal"

  log stdout format rfc5424 local0
  # success:
  # <134>1 2024-06-12T10:09:11.823400+02:00 - normal 224482 - - 127.0.0.1:53594 [12/Jun/2024:10:09:11.814] myproxy myproxy/<NOSRV> 0/-1/-1/-1/0 200 49 - - LR-- 1/1/0/0/0 0/0 "GET / HTTP/1.1"
  #
  # error:
  # <134>1 2024-06-12T10:09:44.810929+02:00 - normal 224482 - - 127.0.0.1:59258 [12/Jun/2024:10:09:44.426] myproxy myproxy/<NOSRV> -1/-1/-1/-1/384 400 0 - - CR-- 1/1/0/0/0 0/0 "<BADREQ>"

  log 127.0.0.1:514 format rfc5424 profile myprof local0
  # success:
  # <134>1 2024-06-12T10:09:11.823428+02:00 - custom-tag 224482 - custom-sd 127.0.0.1:53594 [12/Jun/2024:10:09:11.814] myproxy myproxy/<NOSRV> 0/-1/-1/-1/0 200 49 - - LR-- 1/1/0/0/0 0/0 "GET / HTTP/1.1"
  #
  # error:
  # <134>1 2024-06-12T10:09:51.566524+02:00 - custom-tag 224482 - - 127.0.0.1: error

8.4. Временные показатели событий

Таймеры существенно помогают при поиске сетевых проблем. Все значения указаны в миллисекундах (ms). Их следует использовать вместе с флагами завершения потока. В режиме TCP с “option tcplog” во фронтенде выводятся 3 контрольные точки в виде “Tw/Tc/Tt”, а в режиме HTTP — 5 в виде “TR/Tw/Tc/Tr/Ta”. Дополнительно доступны ещё три показателя: “Th”, “Ti” и “Tq”.

Временные показатели событий в режиме HTTP:

                 первый запрос               2-й запрос
      |<-------------------------------->|<-------------- ...
      t         tr                       t    tr ...
   ---|----|----|----|----|----|----|----|----|--
     : Th   Ti   TR   Tw   Tc   Tr   Td: Ti   ...
     :<---- Tq ---->:                  :
     :<-------------- Tt -------------->:
     :<--        -----Tu--------------->:
               :<--------- Ta --------->:

Временные показатели событий в режиме TCP:

           Сеанс TCP
      |<----------------->|
      t                   t
   ---|----|----|----|----|---
      | Th   Tw   Tc   Td |
      |<------ Tt ------->|
  • Th: полное время принятия соединения tcp и согласования низкоуровневых протоколов. Сейчас это proxy-protocol и SSL. Такое согласование возможно только один раз за всё время жизни соединения. Большое значение может означать, что клиент заранее установил соединение, но не передаёт данные, что сетевые проблемы мешают ему завершить согласование за разумное время (например, проблемы MTU) либо что согласование SSL потребовало больших вычислительных затрат. Это время указывается только перед первым запросом, поэтому его можно усреднять по всем запросам, распределяя затраты между ними. Для второго и последующих запросов здесь всегда указывается ноль.

    Этот таймер доступен как алиас log-format %Th и функция извлечения образца fc.timer.handshake.

  • Ti: время простоя перед запросом HTTP (только режим HTTP). Таймер отсчитывает время от окончания согласования до первого байта запроса HTTP. Для второго запроса в режиме keep-alive отсчёт начинается после окончания передачи предыдущего ответа. Для мультиплексированного протокола, например HTTP/2, — сразу после предыдущего запроса. Некоторые браузеры заранее устанавливают соединения с сервером, чтобы уменьшить задержку будущего запроса, и оставляют их в ожидании до необходимости. Эта задержка отражается как время простоя. Значение -1 означает, что по соединению ничего не было получено.

    Этот таймер доступен как алиас log-format %Ti и функция извлечения образца req.timer.idle.

  • TR: полное время получения запроса клиента (только режим HTTP). Это время от получения первых байтов до получения прокси пустой строки, отмечающей конец заголовков HTTP. Значение “-1” означает, что конец заголовков так и не был получен: клиент преждевременно закрыл соединение или истёк тайм-аут. Обычно время очень мало, поскольку большинство запросов помещается в один пакет. Большое значение может указывать на ручной ввод запроса во время тестирования.

    Этот таймер доступен как алиас log-format %TR и функция извлечения образца req.timer.hdr.

  • Tq: полное время получения запроса клиента с момента принятия соединения либо отправки последнего байта предыдущего ответа (только режим HTTP). Оно в точности равно Th + Ti + TR, кроме случая, когда хотя бы одно из этих значений равно -1: тогда результат тоже -1. Этот таймер был очень полезен до появления HTTP keep-alive и упреждающих подключений браузеров. Сейчас рекомендуется заменить его на TR, поскольку время простоя вносит много шума в отчёты.

    Этот таймер доступен как алиас log-format %Tq и функция извлечения образца req.timer.tq.

  • Tw: общее время ожидания свободного места для соединения в очередях. Учитываются очередь бэкенда и очереди серверов; время зависит от размера очереди и времени, нужного серверу для завершения предыдущих запросов. Значение “-1” означает, что запрос прерван до попадания в очередь, что обычно происходит с некорректными или запрещёнными запросами.

    Этот таймер доступен как алиас log-format %Tw и функция извлечения образца req.timer.queue.

  • Tc: полное время установления соединения TCP с сервером. Это время между отправкой прокси запроса на соединение и его подтверждением сервером, то есть между пакетом TCP SYN и соответствующим ответным SYN/ACK. Значение “-1” означает, что соединение так и не было установлено.

    Этот таймер доступен как алиас log-format %Tc и функция извлечения образца bc.timer.connect.

  • Tr: время ответа сервера (только режим HTTP). Это время от установления соединения TCP с сервером до отправки сервером всех заголовков ответа. Оно отражает только время обработки запроса, без сетевых издержек передачи данных. Однако если клиенту нужно отправить данные серверу, например при запросе POST, отсчёт уже идёт, и это может исказить видимое время ответа. Поэтому обычно не стоит слишком полагаться на это поле для запросов POST от клиентов из ненадёжной сети. Значение “-1” означает, что последний заголовок ответа (пустая строка) так и не был получен, скорее всего из-за истечения тайм-аута сервера до завершения обработки запроса либо некорректного ответа сервера.

    Этот таймер доступен как алиас log-format %Tr и функция извлечения образца res.timer.hdr.

  • Td: полное время передачи полезной нагрузки ответа до отправки клиенту последнего байта. В HTTP отсчёт начинается после последнего заголовка ответа (после Tr).

    Получение отправленных данных клиентом не гарантируется: они могут задержаться в ядре или сети.

    Этот таймер доступен как алиас log-format %Td и функция извлечения образца res.timer.data.

  • Ta: полное время активности запроса HTTP от получения прокси первого байта заголовка запроса до отправки последнего байта тела ответа. Исключение — заданная опция “logasap”: тогда оно равно только (TR+Tw+Tc+Tr) и начинается со знака ‘+’. Из этого поля можно вычислить “Td”, время передачи данных, вычтя остальные таймеры с допустимыми значениями:

Td = Ta - (TR + Tw + Tc + Tr)
Таймеры со значением "-1" необходимо исключить из этого уравнения.
"Ta" никогда не может быть отрицательным.

Этот таймер доступен как алиас log-format %Ta и функция извлечения
образца txn.timer.total.
  • Tt: полная длительность потока от принятия его прокси до закрытия обеих сторон. Исключение — заданная опция “logasap”: тогда значение равно только (Th+Ti+TR+Tw+Tc+Tr) и начинается со знака ‘+’. Из этого поля можно вычислить “Td”, время передачи данных, вычтя остальные таймеры с допустимыми значениями:
Td = Tt - (Th + Ti + TR + Tw + Tc + Tr)
Таймеры со значением "-1" необходимо исключить из этого уравнения.
В режиме TCP также необходимо исключить "Ti", "Tq" и "Tr".
"Tt" никогда не может быть отрицательным, а для HTTP Tt просто
равно (Th+Ti+Ta).

Этот таймер доступен как алиас log-format %Tt и функция извлечения
образца fc.timer.total.
  • Tu: оценка полного времени с точки зрения клиента от принятия соединения прокси до закрытия обеих сторон, без времени простоя. Она помогает приблизительно измерить сквозное время так, как его видит пользователь, без влияния простоя keep-alive между запросами. Это лишь оценка пользовательского времени, поскольку предполагается одинаковая сетевая задержка в обоих направлениях. Исключение — заданная опция “logasap”: тогда значение равно только (Th+TR+Tw+Tc+Tr) и начинается со знака ‘+’.

    Этот таймер доступен как алиас log-format %Tu и функция извлечения образца txn.timer.user.

Эти таймеры дают ценные подсказки о причинах проблем. Поскольку протокол TCP задаёт задержки повторной передачи 3, 6, 12… секунд, значения, близкие к кратным 3s, почти всегда связаны с потерей пакетов из-за сетевых проблем: кабелей, согласования или перегрузки. Кроме того, если “Ta” или “Tt” близко к тайм-ауту из конфигурации, это часто означает, что поток прерван по тайм-ауту.

Наиболее частые случаи:

  • Если “Th” или “Ti” близки к 3000, вероятно, между клиентом и прокси был потерян пакет. В локальных сетях это очень редко, но возможно для клиентов в далёких удалённых сетях, отправляющих большие запросы. Повышенные значения могут появляться и без сетевой причины. Иногда во время атаки или сразу после устранения нехватки ресурсов HAProxy принимает тысячи соединений за несколько миллисекунд. Время на их принятие неизбежно немного задерживает обработку других соединений, поэтому после одновременного принятия нескольких тысяч новых соединений время запроса может составлять несколько десятков миллисекунд. В режимах keep-alive время простоя может быть больше, поскольку “Ti” измеряет ожидание дополнительных запросов.

  • Если “Tc” близко к 3000, при установлении соединения с сервером, вероятно, был потерян пакет между сервером и прокси. Это значение всегда должно быть очень малым: например, 1 ms в локальной сети и менее нескольких десятков ms в удалённых сетях.

  • Если “Tr” почти всегда ниже 3000, за исключением редких значений, похожих на среднее плюс 3000, вероятно, между прокси и сервером теряются пакеты.

  • Если “Ta” велико даже при малом числе байтов, обычно причина в том, что ни клиент, ни сервер не закрывают соединение: HAProxy работает в туннельном режиме, а обе стороны согласовали keep-alive. Для решения потребуется задать во фронтенде или бэкенде одну из опций HTTP, управляющих keep-alive или закрытием соединения. При регулировании соединений через серверную опцию “maxconn” важно свести ‘Ta’ или ‘Tt’ к минимуму: новое соединение не направляется на сервер, пока не освободится другое.

Другие примечательные случаи в журнале HTTP (‘xx’ означает любое значение, которое можно игнорировать):

TR/Tw/Tc/Tr/+Ta  Во фронтенде задано "option logasap", и запись журнала
                 выдана до фазы передачи данных. Все таймеры достоверны,
                 кроме "Ta", значение которого меньше действительного.

-1/xx/xx/xx/Ta   Клиент не успел отправить полный запрос или слишком рано
                 прервал соединение. Проверьте флаги завершения потока,
                 затем настройки "timeout http-request" и "timeout client".

TR/-1/xx/xx/Ta   Обработать запрос не удалось: возможно, серверы не работали,
                 запрос был некорректен или запрещён правилами ACL.
                 Проверьте флаги завершения потока.

TR/Tw/-1/xx/Ta   Установить соединение с сервером не удалось: он либо явно
                 отказал в соединении, либо истёк тайм-аут через Ta-(TR+Tw) ms.
                 Проверьте флаги завершения потока, затем настройку
                 "timeout connect". Действие tarpit может давать похожие
                 последовательности, где "Tw" равно времени, в течение
                 которого соединение с клиентом оставалось открытым.

TR/Tw/Tc/-1/Ta   Сервер принял соединение, но не успел вернуть полный ответ
                 или неожиданно закрыл соединение через Ta-(TR+Tw+Tc) ms.
                 Проверьте флаги завершения потока, затем настройку
                 "timeout server".

8.5. Состояние потока при разрыве соединения

В журналах TCP и HTTP поле “termination_state” непосредственно перед числом активных соединений содержит индикатор завершения потока. В режиме TCP он состоит из 2 символов, а в режиме HTTP — из 4. У каждого символа своё значение:

  • Первый символ — код первого события, вызвавшего завершение потока:
C: клиент неожиданно прервал сеанс TCP.

S: сервер неожиданно прервал сеанс TCP или явно отказал в соединении.

P: прокси преждевременно прервал поток или сеанс из-за ограничения числа
    соединений, совпадения с фильтром DENY либо проверки безопасности,
    которая обнаружила и заблокировала опасную ошибку в ответе сервера,
    способную вызвать утечку информации (например, кэшируемый cookie).

L: поток обработан локально HAProxy.

R: на прокси исчерпан ресурс (память, сокеты, исходные порты и т. д.).
    Обычно это происходит на этапе соединения; системные журналы должны
    содержать копию точного сообщения об ошибке. Такое событие должно
    рассматриваться как очень серьёзная аномалия, которую следует устранить
    как можно скорее любыми средствами.

I: при самопроверке прокси обнаружил внутреннюю ошибку. Этого НИКОГДА
    не должно происходить; рекомендуется сообщать о любой записи журнала
    с этим флагом, поскольку почти наверняка это программная ошибка.
    После такого события разумно также в качестве предосторожности
    перезапустить процесс на случай, если причина — повреждение памяти.

D: HAProxy завершил поток, поскольку сервер признан недоступным и настроен
    на завершение всех соединений при переходе в недоступное состояние.

U: HAProxy завершил поток на этом резервном сервере, поскольку активный
    сервер признан доступным и настроен на завершение всех соединений
    с резервными серверами при переходе в доступное состояние.

K: администратор принудительно завершил поток средствами HAProxy.

c: истёк тайм-аут на стороне клиента при ожидании отправки или получения
    данных клиентом.

s: истёк тайм-аут на стороне сервера при ожидании отправки или получения
    данных сервером.

-: нормальное завершение потока; клиент и сервер закрыли соединение,
    в буферах не осталось данных.
  • Второй символ — состояние потока TCP или HTTP в момент закрытия:
R: прокси ожидал полный корректный ЗАПРОС от клиента (только в режиме HTTP).
    Ни одному серверу ничего не было отправлено.

Q: прокси ожидал в ОЧЕРЕДИ свободное место для соединения. Это возможно
    только при заданном у серверов параметре 'maxconn'. Также это возможно
    в общей очереди после повторного распределения вслед за неудачной
    попыткой соединиться с отказывающим сервером. Если повторное
    распределение не отмечено, попыток соединения с серверами не было.

C: прокси ожидал установления СОЕДИНЕНИЯ с сервером. Сервер мог заметить
    максимум попытку соединения.

H: прокси ожидал полные корректные ЗАГОЛОВКИ ответа сервера
    (только HTTP).

D: поток находился в фазе передачи ДАННЫХ.

L: прокси ещё передавал ПОСЛЕДНИЕ данные клиенту, а сервер уже завершил
    работу. Это очень редкий случай: он возможен только при отказе клиента
    во время получения последних пакетов.

T: запрос попал в ловушку соединений (tarpit). Соединение с клиентом
    оставалось открытым в течение всего "timeout tarpit" или до закрытия
    клиентом; в обоих случаях длительность отражается в таймере "Tw".

-: нормальное завершение потока после окончания передачи данных.
  • Третий символ указывает, передал ли клиент cookie привязки (только в режиме HTTP):
N: клиент НЕ передал cookie. Это обычно бывает у новых посетителей,
    поэтому подсчёт этого флага в журналах обычно достоверно отражает
    динамику посещаемости сайта.

I: клиент передал НЕДЕЙСТВИТЕЛЬНЫЙ cookie, не соответствующий ни одному
    известному серверу. Возможные причины: недавнее изменение конфигурации,
    смешение cookie сайтов HTTP/HTTPS, условное игнорирование привязки
    сеанса или атака.

D: клиент передал cookie, указывающий на НЕДОСТУПНЫЙ сервер. Если задано
    "option persist", клиент был направлен на этот сервер; если эта опция
    не задана, клиент был перенаправлен на другой сервер.

V: клиент передал ДЕЙСТВИТЕЛЬНЫЙ cookie и был направлен на связанный
    с ним сервер.

E: клиент передал действительный cookie, но последняя дата в нём старше,
    чем допускает параметр cookie "maxidle", поэтому cookie считается
    ПРОСРОЧЕННЫМ и игнорируется. Запрос будет распределён заново,
    как если бы cookie отсутствовал.

O: клиент передал действительный cookie, но первая дата в нём старше,
    чем допускает параметр cookie "maxlife", поэтому cookie считается
    слишком СТАРЫМ и игнорируется. Запрос будет распределён заново,
    как если бы cookie отсутствовал.

U: cookie присутствовал, но не использовался для выбора сервера,
    поскольку применялся другой механизм выбора (обычно правило
    "use-server").

-: неприменимо (cookie не задан в конфигурации).
  • Последний символ сообщает, какие операции выполнены с cookie привязки, возвращённым сервером (только в режиме HTTP):
N: сервер НЕ передал cookie, и прокси также не вставил его.

I: сервер не передал cookie, и прокси ВСТАВИЛ его. В режиме "cookie insert",
    если сервер передаёт cookie, тот всё равно перезаписывается
    и здесь отмечается как "I".

U: прокси ОБНОВИЛ последнюю дату в cookie, переданном клиентом. Это возможно
    только в режиме insert с "maxidle" и происходит при активности
    с датой, отличающейся от указанной в cookie. При любом другом изменении,
    например повторном распределении, cookie вместо этого отмечается
    как вставленный.

P: сервер ПЕРЕДАЛ cookie, который был отправлен без изменений.

R: прокси ПЕРЕПИСАЛ cookie сервера; это происходит в режимах
    "cookie rewrite" или "cookie prefix".

D: прокси УДАЛИЛ cookie, переданный сервером.

-: неприменимо (cookie не задан в конфигурации).

Сочетание первых двух флагов даёт много сведений о том, что происходило при завершении потока или сеанса и почему он завершился. Это помогает обнаруживать перегрузку серверов, сетевые проблемы, нехватку локальных системных ресурсов, атаки и т. д.

Ниже приведены наиболее частые сочетания флагов завершения. Они отсортированы по алфавиту, причём строчные буквы идут сразу после соответствующих прописных для удобства поиска и понимания.

Флаги Причина

 --   Нормальное завершение.

 CC   Клиент прервал соединение до его установления с сервером.
      Это возможно, когда HAProxy пытается подключиться к недавно
      отказавшему или непроверенному серверу, а клиент прерывает
      соединение, пока HAProxy ждёт ответа сервера или истечения
      "timeout connect".

 CD   Клиент неожиданно прервал соединение при передаче данных.
      Причиной может быть сбой браузера, принудительный разрыв
      соединения оборудованием между клиентом и HAProxy, проблемы
      сетевой маршрутизации между клиентом и HAProxy либо поток
      keep-alive между сервером и клиентом, который первым завершил
      клиент.

 cD   Клиент не отправлял и не подтверждал данные в течение
      "timeout client". Частые причины — сетевые сбои на стороне
      клиента или его отключение от сети без корректного завершения.

 CH   Клиент прервал соединение в ожидании начала ответа сервера.
      Возможно, сервер отвечал слишком долго или клиент слишком
      быстро нажал кнопку 'Stop'.

 cH   "timeout client" истёк при ожидании данных клиента во время
      запроса POST. Иногда причина в слишком больших значениях TCP MSS
      для сетей PPPoE, которые не могут передавать полноразмерные пакеты.
      Это также возможно, если тайм-аут клиента меньше серверного,
      а сервер отвечает слишком долго.

 CQ   Клиент прервал соединение, пока его поток стоял в очереди
      в ожидании сервера с достаточным числом свободных мест.
      Возможно, все серверы были перегружены либо назначенный сервер
      отвечал слишком долго.

 CR   Клиент прервал соединение, не отправив полный запрос HTTP.
      Вероятнее всего, запрос вводился вручную через клиент telnet
      и был прерван слишком рано. Здесь вероятен код состояния HTTP 400.
      Иногда причиной бывает IDS, разрывающая соединение между HAProxy
      и клиентом. "option http-ignore-probes" позволяет игнорировать
      соединения без передачи данных.

 cR   "timeout http-request" истёк до отправки клиентом полного запроса
      HTTP. Иногда причина в слишком больших значениях TCP MSS у клиента
      для сетей PPPoE, которые не могут передавать полноразмерные пакеты,
      либо в слишком медленном ручном вводе запроса или пропуске пустой
      строки в его конце. Здесь вероятен код состояния HTTP 408.
      Примечание: недавно некоторые браузеры начали реализовывать
      "pre-connect" — упреждающее подключение к недавно посещённым сайтам
      на случай, если пользователь захочет открыть их снова. В результате
      устанавливается много соединений с сайтами. Они заканчиваются
      ошибкой 408
      Request Timeout, если первым истечёт тайм-аут, или
      400 Bad Request, если браузер первым решит их закрыть. Такие случаи
      засоряют журнал и увеличивают счётчики ошибок. Сообщалось даже,
      что некоторые версии некоторых браузеров показывают код ошибки.
      Чтобы обойти нежелательные последствия, можно добавить "option
      http-ignore-probes" во фронтенд: тогда соединения без передачи
      данных полностью игнорируются. Однако это также полностью скроет
      ошибки пользователей с проблемами подключения.

 CT   Клиент прервал соединение, пока его поток находился в tarpit.
      Важно проверить, происходит ли это с корректными запросами,
      чтобы убедиться в отсутствии ошибочных правил tarpit. Если таких
      случаев много, имеет смысл уменьшить "timeout tarpit" до значения,
      близкого к среднему значению таймера "Tw", чтобы не расходовать
      ресурсы лишь на нескольких атакующих.

 LC   Запрос перехвачен и обработан локально самим HAProxy.
      На сервер запрос не отправлялся. Это возможно только при
      перенаправлении из-за параметра "redir" в строке server.

 LR   Запрос перехвачен и обработан локально самим HAProxy.
      На сервер запрос не отправлялся. Обычно это означает возврат
      перенаправления, выполнение директивы HTTP return либо обработку
      запроса апплетом (stats, cache, экспортёр Prometheus, апплет lua...).

 LH   Ответ перехвачен и обработан локально самим HAProxy. Обычно это
      означает возврат перенаправления или выполнение директивы HTTP return.

 SC   Сервер или оборудование между ним и HAProxy явно отказали
      в соединении TCP: прокси получил в ответ TCP RST или сообщение ICMP.
      Иногда так сетевой стек сообщает прокси о недоступности сервера,
      например при отсутствии маршрута или ответа ARP в локальной сети.
      В режиме HTTP код состояния в этом случае, вероятно, будет 502
      или 503.

 sC   "timeout connect" истёк до установления соединения с сервером.
      В режиме HTTP код состояния в этом случае, вероятно, будет
      503 или 504.

 SD   Соединение с сервером завершилось с ошибкой во время передачи
      данных. Обычно это означает, что при обмене данными с сервером
      HAProxy получил от него RST или сообщение ICMP от промежуточного
      оборудования. Причиной может быть аварийное завершение сервера
      или сетевая проблема на промежуточном оборудовании.

 sD   На этапе передачи данных сервер не отправлял и не подтверждал
      данные в течение времени "timeout server". Частые причины —
      слишком короткие тайм-ауты на оборудовании L4 перед сервером
      (межсетевые экраны, балансировщики нагрузки и т. д.) либо сеансы
      keep-alive между клиентом и сервером, которые раньше всего
      истекают на HAProxy.

 SH   Сервер прервал соединение до отправки всех заголовков ответа HTTP
      либо аварийно завершился при обработке запроса. Прерывание сервером
      на этом этапе встречается очень редко, поэтому стоит проверить
      его журналы: не было ли сбоя и чем он вызван. Запрос в журнале
      может помочь выделить небольшой набор проблемных запросов,
      указывающих на ошибки приложения. Иногда причиной бывает IDS,
      разрывающая соединение между HAProxy и сервером.

 sH   "timeout server" истёк до того, как сервер вернул заголовки ответа.
      Это наиболее частая аномалия: транзакции длятся слишком долго,
      вероятно, из-за перегрузки сервера или базы данных. Временное
      решение — увеличить "timeout server", но следует помнить, что
      столь долгий ответ ухудшает работу пользователей. Единственное
      долговременное решение — исправить приложение.

 sQ   Поток провёл слишком много времени в очереди и завершился
      по тайм-ауту. Если это происходит слишком часто, см. параметры
      "timeout queue" и "timeout connect". Частые массовые случаи
      в короткие промежутки могут указывать на общие проблемы
      затронутых серверов из-за перегрузки ввода-вывода или базы данных
      либо на перегрузку из-за внешних атак.

 PC   Прокси отказался устанавливать соединение с сервером, поскольку
      при попытке подключения был достигнут лимит сокетов процесса.
      Чтобы это больше не повторялось, в конфигурации можно увеличить
      глобальный параметр "maxconn". Этот статус встречается очень редко
      и может возникать при ручном задании глобального "ulimit-n".

 PD   Прокси заблокировал сообщение с неверным форматом chunked-кодирования
      в запросе или ответе после того, как сервер отправил заголовки.
      В большинстве случаев это указывает на некорректное сообщение
      от сервера клиенту. HAProxy поддерживает размеры блоков до
      2GB - 1 (2147483647 байт). Любой больший размер считается ошибкой.

 PH   Прокси заблокировал ответ сервера, потому что он был некорректным,
      неполным, опасным с точки зрения управления кэшем или соответствовал
      фильтру безопасности. В любом случае клиенту отправляется ошибка
      HTTP 502. Возможная причина — неверный синтаксис имени заголовка HTTP
      с недопустимыми символами. Ещё возможно, хотя и редко, что прокси
      до ответа сервера заблокировал запрос клиента с chunked-кодированием
      из-за неверного синтаксиса. Тогда клиенту отправляется ошибка
      HTTP 400, которая также записывается в журнал. Наконец, причиной
      может быть ошибка перезаписи заголовка HTTP в ответе. В этом случае
      отправляется ошибка HTTP 500; подробнее см. "tune.maxrewrite"
      и "http-response strict-mode".

 PR   Прокси заблокировал запрос HTTP клиента либо из-за неверного
      синтаксиса HTTP, вернув клиенту ошибку HTTP 400, либо из-за
      совпадения с запрещающим фильтром, вернув ошибку HTTP 403.
      Причиной также может быть ошибка перезаписи заголовка HTTP
      в запросе. Тогда отправляется ошибка HTTP 500; подробнее см.
      "tune.maxrewrite" и "http-request strict-mode".

 PT   Прокси заблокировал запрос клиента и задержал его соединение
      в tarpit, прежде чем вернуть ошибку сервера 500. На сервер ничего
      не отправлялось. Соединение оставалось открытым в течение времени,
      указанного в поле таймера "Tw".

 RC   Локальный ресурс (память, сокеты, исходные порты) исчерпан,
      что не позволило установить соединение с сервером. Журналы ошибок
      точно укажут, чего не хватило. Это очень редкий случай, который
      устраняется только правильной настройкой системы.

Сочетание двух последних флагов даёт много сведений о том, как клиент, сервер и HAProxy обрабатывали привязку сеанса. Это очень важно при поиске причин разрывов соединений, когда пользователи жалуются на необходимость повторной аутентификации. Часто встречаются следующие флаги:

--   Cookie привязки сеанса не включён.

NN   Клиент не передал cookie, и в ответ cookie не вставлен. Например,
     это возможно в режиме insert с "postonly" для запроса GET.

II   Клиент передал cookie, указывающий на недействительный сервер;
     в ответ вставлен действительный cookie. Обычно это происходит
     после удаления записи "server" из конфигурации: клиент может
     передать её значение cookie, неизвестное остальным серверам.

NI   Клиент не передал cookie, и в ответ вставлен cookie. Обычно это
     происходит при первом запросе каждого пользователя в режиме "insert",
     что позволяет легко подсчитывать реальных пользователей.

VN   Клиент передал cookie, и в ответ cookie не вставлен. Это происходит
     для большинства ответов клиентам, у которых cookie уже есть.

VU   Клиент передал cookie с не вполне актуальной датой последнего визита,
     поэтому в ответ отправлен обновлённый cookie. Это также возможно,
     если даты не было вообще либо дата была, но параметр "maxidle"
     не задан: тогда cookie может стать бессрочным.

EI   Клиент передал cookie с датой последнего визита, слишком старой
     для параметра "maxidle"; cookie проигнорирован, и в ответ вставлен
     новый cookie.

OI   Клиент передал cookie с датой первого визита, слишком старой
     для параметра "maxlife"; cookie проигнорирован, и в ответ вставлен
     новый cookie.

DI   Сервер, указанный в cookie, был недоступен; выбран новый сервер,
     и в ответ отправлен новый cookie.

VI   Сервер, указанный в cookie, не был отмечен как недоступный, но связаться
     с ним не удалось. При повторном распределении выбран другой сервер,
     который затем был указан в ответе.

8.6. Непечатаемые символы

Чтобы при просмотре журналов не возникало проблем с анализаторами или терминалами, непечатаемые символы не записываются в файлы журналов как есть. Вместо этого используется двухзначное шестнадцатеричное представление их кода ASCII с префиксом ‘#’. Без экранирования можно записывать только символы с кодами от 32 до 126 включительно. Сам символ экранирования ‘#’ также кодируется во избежание неоднозначности ("#23"). То же относится к символу ‘"’, который превращается в “#22”, а при записи заголовков — к символам ‘{’, ‘|’ и ‘}’.

Это не относится к кодированию cbor, которое уже использует безопасные шестнадцатеричные цифры либо корректно разделённые двоичные блоки. Такие блоки не отправляются в терминал, а обрабатываются парсером CBOR.

Кодирование json вместо этого использует escape-последовательности JSON, а опция +utf8 также пропускает корректные многобайтовые последовательности UTF-8 без изменений (см. флаг “utf8” в разделе 8.2.6 ).

Пробел (’ ‘) в заголовках не кодируется. Это может создавать проблемы для инструментов, которые определяют расположение полей по числу пробелов. Типичный заголовок, содержащий пробелы, — “User-Agent”.

Наконец, некоторые демоны syslog, например syslog-ng, экранируют кавычку (’"’) обратной косой чертой (’\’). Обратное преобразование безопасно, поскольку в других местах журнала кавычки появляться не могут.

8.7. Захват cookie HTTP

Захват cookie упрощает отслеживание всего пользовательского сеанса. Для этого во фронтенде используется директива “capture cookie”. Подробнее см. раздел 4.2 . Можно захватить только один cookie, причём один и тот же cookie одновременно проверяется в запросе (заголовок “Cookie:”) и ответе (заголовок “Set-Cookie:”). Соответствующие значения записываются в поля “captured_request_cookie” и “captured_response_cookie” журнала HTTP (о формате журнала HTTP см. раздел 8.2.3 ). Если какой-либо из cookie не обнаружен, вместо его значения ставится дефис (’-’). Так легко заметить, например, переход пользователя к новому сеансу: сервер назначит ему новый cookie. Также можно выявить неожиданную отправку сервером неверного cookie клиенту, приводящую к смешению сеансов.

Примеры:

# capture the first cookie whose name starts with "ASPSESSION"
capture cookie ASPSESSION len 32

# capture the first cookie whose name is exactly "vgnvisitor"
capture cookie vgnvisitor= len 32

Более сложный захват можно выполнить с помощью правил “http-request” и “http-response”, присваивая cookie переменным с областью видимости “txn”. Значения cookie извлекаются из запроса или ответа функциями извлечения образца “req.cook” и “res.cook” (см. раздел 7.3.6 ) и присваиваются переменной действиями “set-var” или “set-var-fmt” (см. раздел 4.3 ). Пользовательский log-format позволяет вывести эти переменные в нужном месте (см. раздел 8.2.6 ).

8.8. Захват заголовков HTTP (устаревший способ)

Захват заголовков помогает отслеживать уникальные ID запросов, заданные вышестоящим прокси, имена виртуальных узлов, пользовательские агенты, длину содержимого POST, источники переходов и т. д. В ответе можно искать сведения о его длине, указания сервера для кэша или местоположение объекта при перенаправлении.

Заголовки можно захватывать двумя способами. Современный способ — задавать переменные из захватываемых заголовков или составных образцов, возвращаемых “req.hdr_names”, “req.hdrs”, “res.hdr_names”, “res.hdrs” (все возможности см. в разделе 7.3.6 ). Их можно присваивать переменным с областью видимости “txn” действиями “set-var” и “set-var-fmt” из наборов правил “http-request” и “http-response” (см. раздел 4.3 ), а затем ссылаться на переменные в пользовательских форматах журналов (см. раздел 8.2.6 ). Это рекомендуемый способ захвата заголовков HTTP.

Есть и устаревший способ, появившийся раньше правил http-request и переменных. Он не требует изменения формата журнала и долгое время использовался как для ведения журнала, так и в качестве обходного способа передавать сведения о запросе на протяжении всей транзакции HTTP с помощью старых наборов правил “capture”. Именно этот способ описан в данном разделе.

При устаревшем способе заголовки захватываются директивами “capture request header” и “capture response header” во фронтенде. Подробнее см. их описание в разделе 4.2 .

Можно одновременно включить заголовки запроса и ответа. Отсутствующие заголовки записываются как пустые строки; если заголовок встречается несколько раз, записывается только последнее вхождение. Заголовки запроса группируются между фигурными скобками ‘{’ и ‘}’ в порядке объявления и разделяются вертикальной чертой ‘|’ без пробелов. Заголовки ответа представляются так же, но выводятся после блока заголовков запроса через пробел. Эти блоки располагаются в журнале непосредственно перед запросом HTTP.

В качестве особого случая захват заголовков HTTP можно настроить во фронтенде TCP. Это позволяет записывать заголовки, которые будут разобраны бэкендом HTTP, если запрос затем направляется в этот бэкенд HTTP.

Пример:

# This instance chains to the outgoing proxy
listen proxy-out
    mode http
    option httplog
    option logasap
    log global
    server cache1 192.168.1.1:3128

    # log the name of the virtual server
    capture request  header Host len 20

    # log the amount of data uploaded during a POST
    capture request  header Content-Length len 10

    # log the beginning of the referrer
    capture request  header Referer len 20

    # server name (useful for outgoing proxies only)
    capture response header Server len 20

    # logging the content-length is useful with "option logasap"
    capture response header Content-Length len 10

    # log the expected cache behavior on the response
    capture response header Cache-Control len 8

    # the Via header will report the next proxy's name
    capture response header Via len 20

    # log the URL location during a redirection
    capture response header Location len 20
    >>> Aug  9 20:26:09 localhost \
          haproxy[2022]: 127.0.0.1:34014 [09/Aug/2004:20:26:09] proxy-out \
          proxy-out/cache1 0/0/0/162/+162 200 +350 - - ---- 0/0/0/0/0 0/0 \
          {fr.adserver.yahoo.co||http://fr.f416.mail.} {|864|private||} \
          "GET http://fr.adserver.yahoo.com/"
    >>> Aug  9 20:30:46 localhost \
          haproxy[2022]: 127.0.0.1:34020 [09/Aug/2004:20:30:46] proxy-out \
          proxy-out/cache1 0/0/0/182/+182 200 +279 - - ---- 0/0/0/0/0 0/0 \
          {w.ods.org||} {Formilux/0.1.8|3495|||} \
          "GET http://trafic.1wt.eu/ HTTP/1.1"
    >>> Aug  9 20:30:46 localhost \
          haproxy[2022]: 127.0.0.1:34028 [09/Aug/2004:20:30:46] proxy-out \
          proxy-out/cache1 0/0/2/126/+128 301 +223 - - ---- 0/0/0/0/0 0/0 \
          {www.sytadin.equipement.gouv.fr||http://trafic.1wt.eu/} \
          {Apache|230|||http://www.sytadin.} \
          "GET http://www.sytadin.equipement.gouv.fr/ HTTP/1.1"

8.9. Примеры журналов

Ниже приведены практические примеры журналов с пояснениями. Некоторые из них составлены вручную. Для удобства чтения часть syslog удалена. Единственная цель примеров — объяснить, как их расшифровывать.

>>> haproxy[674]: 127.0.0.1:33318 [15/Oct/2003:08:31:57.130] px-http &#92;
      px-http/srv1 6559/0/7/147/6723 200 243 - - ---- 5/3/3/1/0 0/0 &#92;
      "HEAD / HTTP/1.0"

=> длительный ввод запроса (6.5s) вручную через 'telnet'. Сервер ответил
   за 147 ms, сеанс завершился нормально ('----')

>>> haproxy[674]: 127.0.0.1:33319 [15/Oct/2003:08:31:57.149] px-http &#92;
      px-http/srv1 6559/1230/7/147/6870 200 243 - - ---- 324/239/239/99/0 &#92;
      0/9 "HEAD / HTTP/1.0"

=> то же самое, но запрос попал в общую очередь после 9 других запросов
   и ожидал в ней 1230 ms.
    >>> haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17.654] px-http \
          px-http/srv1 9/0/7/14/+30 200 +243 - - ---- 3/3/3/1/0 0/0 \
          "GET /image.iso HTTP/1.0"
=> запрос на длительную передачу данных. Задана опция "logasap", поэтому
   запись журнала выдана непосредственно перед передачей данных. Сервер
   ответил за 14 ms, клиенту отправлено 243 байта заголовков, а общее время
   от принятия соединения до первого байта данных составило 30 ms.

>>> haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17.925] px-http &#92;
      px-http/srv1 9/0/7/14/30 502 243 - - PH-- 3/2/2/0/0 0/0 &#92;
      "GET /cgi-bin/bug.cgi? HTTP/1.0"

=> прокси заблокировал ответ сервера из-за правила "http-response
   deny", неверного формата ответа, не соответствующего HTTP,
   либо наличия конфиденциальных данных, которые могли попасть
   в кэш. В этом случае ответ заменяется на "502 bad
   gateway". Флаги ("PH--") показывают, что вернуть 502 решил
   HAProxy, а не сервер.

>>> haproxy[18113]: 127.0.0.1:34548 [15/Oct/2003:15:18:55.798] px-http &#92;
      px-http/`<NOSRV>` -1/-1/-1/-1/8490 -1 0 - - CR-- 2/2/2/0/0 0/0 ""

=> клиент так и не завершил запрос и сам прервал его ("C---") через
   8.5s, пока прокси ожидал заголовки запроса ("-R--").
   Ни на один сервер ничего не отправлялось.

>>> haproxy[18113]: 127.0.0.1:34549 [15/Oct/2003:15:19:06.103] px-http &#92;
     px-http/`<NOSRV>` -1/-1/-1/-1/50001 408 0 - - cR-- 2/2/2/0/0 0/0 ""

=> клиент так и не завершил запрос; он был прерван по тайм-ауту
   ("c---") через 50s, пока прокси ожидал заголовки запроса
   ("-R--"). Ни на один сервер ничего не отправлялось, но прокси
   смог отправить клиенту код ответа 408.

>>> haproxy[18989]: 127.0.0.1:34550 [15/Oct/2003:15:24:28.312] px-tcp &#92;
      px-tcp/srv1 0/0/5007 0 cD 0/0/0/0/0 0/0

=> эта запись журнала создана с "option tcplog". Тайм-аут клиента
   истёк через 5 секунд ("c----").

>>> haproxy[18989]: 10.0.0.1:34552 [15/Oct/2003:15:26:31.462] px-http &#92;
      px-http/srv1 3183/-1/-1/-1/11215 503 0 - - SC-- 205/202/202/115/3 &#92;
      0/0 "HEAD / HTTP/1.0"

=> приём запроса занял 3s (вероятно, из-за сетевой проблемы), а
   соединение с сервером не удалось установить ('SC--') после 4 попыток
   по 2 секунды (в конфигурации задано 'retries 3'). Перенаправления
   не было, иначе мы увидели бы "/+3". Клиенту вернулся код состояния 503.
   На этом сервере было 115 соединений, на этом прокси — 202,
   а у процесса в целом — 205. Возможно, сервер отказал в соединении
   из-за слишком большого числа уже установленных соединений.

18 - 9. Поддерживаемые фильтры

Фильтры трассировки, сжатия, SPOE, кеша, FastCGI, OpenTracing и ограничения пропускной способности

Ниже перечислены официально поддерживаемые фильтры и принимаемые ими параметры. В зависимости от параметров сборки некоторые фильтры могут быть недоступны. Список доступных фильтров выводится командой haproxy -vv.

См. также: «filter».

9.1. Трассировка

filter trace [name <name>] [random-forwarding] [max-fwd <max>] [hexdump]

Аргументы:

<name>               — произвольное имя, указываемое в сообщениях.
                     Если имя не задано, используется "TRACE".

<quiet>              подавляет сообщения трассировки.

<random-forwarding>  включает пересылку случайного объёма разобранных данных.
                     По умолчанию фильтр пересылает все ранее разобранные
                     данные. С этим параметром пересылается только случайная
                     часть разобранных данных.

<max>                — максимальный объём данных, пересылаемых за один раз.
                     Параметр "max-fwd" можно сочетать с пересылкой случайного
                     объёма данных. <max> должен быть положительным целым
                     числом. 0 означает отсутствие ограничения.

<hexdump>             выводит дамп всех данных, пересылаемых серверу и клиенту.

Этот фильтр можно использовать как основу для разработки новых фильтров. Он определяет все обратные вызовы и для каждого из них выводит в стандартный поток ошибок (stderr) сообщение с полезными сведениями. Это может пригодиться для отладки работы других фильтров или самого HAProxy.

Параметры <random-parsing> и/или <random-forwarding> удобны для проверки поведения фильтра, разбирающего данные, которыми обмениваются клиент и сервер: они добавляют задержки при обработке.

9.2. Сжатие HTTP

filter comp-req

Включает фильтр, явно пытающийся сжимать запросы HTTP в соответствии с настройками «compression». Неявно задаёт «compression direction request».

filter comp-res

Включает фильтр, явно пытающийся сжимать ответы HTTP в соответствии с настройками «compression». Неявно задаёт «compression direction response».

filter compression (устарел)

Псевдоним для обратной совместимости, функционально эквивалентный одновременному включению фильтров «comp-req» и «comp-res». Для настройки нужного поведения необходимо использовать директиву «compression»:

В HAProxy 1.7 сжатие HTTP было перенесено в фильтр. Для включения и настройки сжатия HTTP по-прежнему необходимо использовать директиву «compression». Если другие фильтры не используются, этого достаточно. Этого также достаточно при включённом кеше или fcgi-app. В таком случае сжатие всегда выполняется после сохранения ответа в кеше. Но если для того же слушателя/фронтенда/бэкенда используется хотя бы один фильтр, отличный от кеша или fcgi-app, для включения сжатия HTTP обязательно нужно явно добавить строку filter. Это необходимо для определения порядка выполнения фильтров.

См. также: «compression», раздел 9.4 о фильтре кеша и раздел 9.5 о фильтре fcgi-app.

9.3. Механизм вынесения обработки потоков (SPOE)

filter spoe [engine <name>] config <file>

Аргументы:

<name>      — имя обработчика, по которому в файле конфигурации ищется
            нужная область. Если имя не задано, разбирается весь файл.

<file>      — путь к файлу конфигурации обработчика. Файл может содержать
            конфигурации нескольких обработчиков. В этом случае каждая
            часть должна находиться в собственной области.

Stream Processing Offload Engine (SPOE) — фильтр, взаимодействующий с внешними компонентами. Он позволяет выносить отдельные виды обработки потоков во внешние уровни приложения. Эти внешние компоненты и сведения, которыми они обмениваются с HAProxy, в основном настраиваются в отдельных файлах. Также требуются выделенные бэкенды, определённые в конфигурации HAProxy.

SPOE взаимодействует с внешними компонентами по собственному двоичному протоколу Stream Processing Offload Protocol (SPOP).

Когда SPOE используется для потока, создаётся отдельный поток для взаимодействия с внешним компонентом. Основной поток является родительским для этого потока «SPOE». Это означает, что из потока «SPOE» можно получать переменные основного потока. Дополнительные сведения приведены в разделе 2.8 о переменных.

Полные сведения о настройке SPOE и спецификации SPOP приведены в «doc/SPOE.txt».

9.4. Кеш

filter cache <name>

Аргументы:

<name>      — имя секции cache, которую будет использовать этот фильтр.

Кеш использует фильтр для сохранения кешируемых ответов. Чтобы определить, как и когда использовать кеш, необходимо применять правила HTTP «cache-store» и «cache-use». По умолчанию соответствующий фильтр определяется неявно. Если не используются другие фильтры, кроме fcgi-app или сжатия, этого достаточно. В таком случае фильтр сжатия всегда выполняется после фильтра кеша. Но если для того же слушателя/фронтенда/бэкенда используется хотя бы один фильтр, отличный от сжатия или fcgi-app, для использования кеша обязательно нужно явно добавить строку filter. Это необходимо для определения порядка выполнения фильтров.

См. также: раздел 9.2 о фильтре сжатия, раздел 9.5 о фильтре fcgi-app и раздел 6 о кеше.

9.5. Fcgi-app

filter fcgi-app <name>

Аргументы:

<name>      — имя секции fcgi-app, которую будет использовать этот фильтр.

Приложение FastCGI использует фильтр для вычисления всех пользовательских параметров при обработке запроса и для обработки заголовков ответа. <name> должен ссылаться на существующую секцию fcgi-app. Для указания используемого приложения следует применять директиву «use-fcgi-app». По умолчанию соответствующий фильтр определяется неявно. Если не используются другие фильтры, кроме кеша или сжатия, этого достаточно. Но если для того же бэкенда используется хотя бы один фильтр, отличный от сжатия или кеша, для fcgi-app обязательно нужно явно добавить строку filter. Это необходимо для определения порядка выполнения фильтров.

См. также: «use-fcgi-app», раздел 9.2 о фильтре сжатия, раздел 9.4 о фильтре кеша и раздел 10 о приложениях FastCGI.

9.6. OpenTracing

Фильтр OpenTracing добавляет в HAProxy встроенную поддержку распределённой трассировки. Для этого запрос, соответствующий OpenTracing, отправляется одному из поддерживаемых трассировщиков: Datadog, Jaeger, Lightstep или Zipkin. Обратите внимание: трассировщики перечислены в алфавитном порядке, а не в порядке предпочтения.

Эта возможность доступна только при сборке HAProxy с USE_OT=1.

Фильтр OpenTracing включается явным указанием в конфигурации HAProxy. Если этого не сделать, фильтр OpenTracing никак не участвует в работе HAProxy.

filter opentracing [id <id>] config <file>

Аргументы:

<id>        — идентификатор фильтра OpenTracing, по которому в файле
            конфигурации ищется нужная область. Если идентификатор фильтра
            не указан, по умолчанию используется 'ot-filter'. Если область
            в файле конфигурации не задана, конфигурация применяется ко всем
            определённым фильтрам OpenTracing.

<file>      — путь к файлу конфигурации OpenTracing. Один файл может
            одновременно содержать конфигурации нескольких фильтров
            OpenTracing. В этом случае область можно не задавать, чтобы
            одна конфигурация применялась ко всем фильтрам, либо для каждого
            фильтра должна быть определена отдельная область.

Более подробная документация по работе, настройке и использованию фильтра находится в каталоге addons/ot.

Примечание: фильтр OpenTracing не следует использовать в новых проектах, поскольку сами авторы OpenTracing больше его не развивают и не поддерживают. Поэтому OpenTracing будет объявлен устаревшим в 3.3 и удалён в 3.5. Заменяющий его фильтр на основе OpenTelemetry доступен с 3.4; полные инструкции по сборке сейчас находятся по адресу:

https://github.com/haproxytech/haproxy-opentelemetry/

9.7. Ограничение пропускной способности

filter bwlim-in  <name> default-limit <size> default-period <time> [min-size <sz>]
filter bwlim-out <name> default-limit <size> default-period <time> [min-size <sz>]
filter bwlim-in  <name> limit <size> key <pattern> [table <table>] [min-size <sz>]
filter bwlim-out <name> limit <size> key <pattern> [table <table>] [min-size <sz>]

Аргументы:

<name>      — имя фильтра, которое действия 'set-bandwidth-limit' используют
            для ссылки на конкретный фильтр ограничения пропускной способности.

<size>      — максимальное число байтов, пересылаемых за период. Значение
            должно быть задано как для фильтров с ограничением на отдельный
            поток, так и для фильтров с общим ограничением. Оно соответствует
            формату размеров HAProxy и выражается в байтах.

<pattern>   — правило выражения образца, описанное в разделе 7.3. Определяет,
            какие элементы будут анализироваться, извлекаться, объединяться
            и использоваться для выбора записи таблицы, в которой обновляются
            счётчики. Должно задаваться только для фильтров с общим
            ограничением пропускной способности.

<table>     — необязательная таблица, используемая вместо таблицы по умолчанию,
            то есть stick-table, объявленной в текущем прокси. Может задаваться
            только для фильтров с общим ограничением пропускной способности.

<time>      — период по умолчанию для расчёта ограничения скорости передачи.
            Может задаваться только для фильтров с ограничением на отдельный
            поток. Соответствует формату времени HAProxy и выражается
            в миллисекундах.

<min-size>  — необязательное минимальное число байтов, пересылаемых потоком
            за один раз, кроме последнего пакета, который может быть меньше.
            Значение можно задавать для фильтров с ограничением на отдельный
            поток и с общим ограничением. Оно соответствует формату размеров
            HAProxy и выражается в байтах.

Фильтры ограничения пропускной способности следует использовать для ограничения скорости пересылки данных на уровне потока. Тем самым они ограничивают сетевую пропускную способность, потребляемую ресурсом. Можно использовать несколько таких фильтров. Например, один предел можно задать для каждого исходного адреса, чтобы клиент никогда не занимал всю пропускную способность сети в ущерб остальным, а другой — для каждого потока, чтобы справедливо обслуживать несколько соединений одного клиента.

Порядок определения этих фильтров важен. Если для потока включено несколько фильтров пропускной способности, они применяются в порядке определения. Важно понимать, что влияет и порядок определения остальных фильтров. Например, в зависимости от того, определён ли фильтр сжатия HTTP до или после фильтра ограничения пропускной способности, ограничение применяется к сжатой полезной нагрузке или к несжатой. То же верно для фильтра кеша.

Существуют два типа фильтров ограничения пропускной способности. Первый применяет ограничение по умолчанию отдельно к каждому потоку. Второй использует таблицу привязок для ограничения, поровну распределяемого между всеми потоками, использующими одну запись таблицы.

Кроме того, в зависимости от использованного ключевого слова фильтра ограничение может применяться к входящим данным, получаемым от клиента и пересылаемым серверу, либо к исходящим данным, получаемым от сервера и отправляемым клиенту. Для ограничения входящих данных необходимо использовать «bwlim-in», для исходящих — «bwlim-out». В обоих случаях ограничивается пересылка данных на уровне потока.

Ограничение пропускной способности действует на уровне потока, а не соединения. Для протоколов с мультиплексированием (H2, H3 и FastCGI) потоки одного соединения могут иметь разные ограничения.

Для фильтра, ограничивающего отдельные потоки, необходимо определить период и предел по умолчанию. Как следует из названий, это значения по умолчанию для настройки скорости потока. Однако для этого типа фильтра, и только для него, эти значения можно переопределить с помощью выражений образцов при включении фильтра действием TCP/HTTP «set-bandwidth-limit».

Для фильтра с общим ограничением таблица привязок должна хранить сведения о соответствующей скорости передачи байтов в зависимости от того, ограничиваются входящие или исходящие данные. Для ограничения входящих данных необходимо хранить счётчик «bytes_in_rate(<period>)», для исходящих — использовать «bytes_out_rate(<period>)».

Наконец, можно задать минимальное число байтов, которое фильтр ограничения пропускной способности может переслать за один раз для данного потока. Эту настройку следует использовать, чтобы не пересылать слишком маленькие порции данных и уменьшить потребление CPU. Значение нужно выбирать внимательно. Слишком маленькое значение может увеличить потребление CPU, а слишком большое — задержку. Оно также тесно связано с заданным пределом пропускной способности. Если значение слишком близко к этому пределу, могут возникать паузы, необходимые для соблюдения ограничения, поскольку за один раз передаётся слишком много байтов. Результат сильно зависит от конфигурации фильтра. Хорошая отправная точка — около 2 TCP MSS, обычно 2896 байтов, с последующей настройкой по результатам экспериментов.

Пример:

frontend http
    bind *:80
    mode http

    # If this filter is enabled, the stream will share the download limit
    # of 10m/s with all other streams with the same source address.
    filter bwlim-out limit-by-src key src table limit-by-src limit 10m

    # If this filter is enabled, the stream will be limited to download at 1m/s,
    # independently of all other streams.
    filter bwlim-out limit-by-strm default-limit 1m default-period 1s

    # Limit all streams to 1m/s (the default limit) and those accessing the
    # internal API to 100k/s. Limit each source address to 10m/s. The shared
    # limit is applied first. Both are limiting the download rate.
    http-request set-bandwidth-limit limit-by-strm
    http-request set-bandwidth-limit limit-by-strm limit 100k if { path_beg /internal }
    http-request set-bandwidth-limit limit-by-src
    ...

backend limit-by-src
    # The stickiness table used by <limit-by-src> filter
    stick-table type ip size 1m expire 3600s store bytes_out_rate(1s)

См. также: «tcp-request content set-bandwidth-limit», «tcp-response content set-bandwidth-limit», «http-request set-bandwidth-limit» и «http-response set-bandwidth-limit».

19 - 10. Приложения FastCGI

Настройка приложений FastCGI, параметры, примеры и ограничения

HAProxy может отправлять запросы HTTP приложениям FastCGI с ролью Responder. Эта возможность добавлена в HAProxy 2.1. Для её использования серверы необходимо настроить на протокол FastCGI (с помощью «proto fcgi» в строке server), а в управляющем ими бэкенде нужно настроить и подключить приложение FastCGI (с помощью «use-fcgi-app» в секции прокси). Можно определить несколько приложений FastCGI, но бэкенд одновременно может использовать только одно из них.

HAProxy реализует все возможности спецификации FastCGI для приложений Responder. В частности, он может мультиплексировать несколько запросов в одном соединении.

10.1. Настройка

10.1.1. Секция fcgi-app

fcgi-app <name>

fcgi-app <name>

Объявляет приложение FastCGI с именем <name>. Для корректной конфигурации необходимо определить как минимум корневой каталог документов.

acl <aclname> <criterion> [flags] [operator] <value> ...

acl <aclname> <criterion> [flags] [operator] <value> ...

Объявляет или дополняет список контроля доступа.

Подробности см. в описании директивы «acl» в разделе 4.2 и в разделе 7 об использовании ACL. Списки ACL, определённые для приложения FastCGI, доступны только ему. Их нельзя использовать в другом приложении или прокси. Аналогично приложение FastCGI не может использовать списки ACL, определённые в других секциях. Однако предопределённые ACL доступны.

docroot <path>

docroot <path>

Задаёт корневой каталог документов на удалённом узле. <path> используется для формирования значений по умолчанию параметров FastCGI SCRIPT_FILENAME и PATH_TRANSLATED. Это обязательная настройка.

index <script-name>

index <script-name>

Задаёт имя скрипта, добавляемое к URI, оканчивающемуся косой чертой («/»), чтобы получить значение по умолчанию параметра FastCGI SCRIPT_NAME. Это необязательная настройка.

Пример:

index index.php

log-stderr global

log-stderr global
log-stderr <target> [len <length>] [format <format>]
    [sample <ranges>:<sample_size>] <facility> [<level> [<minlevel>]]

Включает запись в журнал сообщений STDERR, выдаваемых приложением FastCGI.

Подробности см. в описании директивы «log» в разделе 4.2 . Это необязательная настройка. По умолчанию сообщения STDERR игнорируются.

pass-header <name> [ { if | unless } <condition> ]

pass-header <name> [ { if | unless } <condition> ]

Задаёт имя заголовка запроса, передаваемого приложению FastCGI. После него можно указать условие на основе ACL; тогда директива обрабатывается только при истинном условии.

Большинство заголовков запроса уже доступны приложению FastCGI с префиксом «HTTP_». Поэтому эта директива нужна только для передачи заголовков, которые намеренно исключаются. Сейчас исключаются заголовки «Authorization», «Proxy-Authorization» и заголовки, действующие только на одном участке соединения (hop-by-hop).

Обратите внимание: заголовки «Content-type» и «Content-length» никогда не передаются приложению FastCGI, поскольку уже преобразованы в параметры.

path-info <regex>

path-info <regex>

Задаёт регулярное выражение для извлечения script-name и path-info из пути после декодирования URL. <regex> может содержать две группы захвата: первая извлекает имя скрипта, вторая — path-info. Первая обязательна, вторая необязательна. Таким образом можно извлечь script-name из пути, игнорируя path-info. Это необязательная настройка. Если она не задана, сопоставление пути не выполняется, а параметры FastCGI PATH_INFO и PATH_TRANSLATED не заполняются.

Из соображений безопасности при заданном регулярном выражении в пути после декодирования URL запрещены символы перевода строки и нулевые символы. Ограничение связано с тем, что иначе сопоставление всегда завершается неудачей (из-за особенностей выполнения регулярных выражений в HAProxy). Поэтому, если после декодирования URL в пути обнаружен любой из этих двух символов, клиенту возвращается ошибка. Здесь применяется принцип наименьшего удивления.

Пример:

path-info ^(/.+\.php)(/.*)?$ # both script-name and path-info may be set
path-info ^(/.+\.php)        # the path-info is ignored

option get-values

option get-values
no option get-values

Включает или отключает получение переменных управления соединениями.

При установке соединения HAProxy может отправить запись FCGI_GET_VALUES, чтобы получить значения следующих переменных:

* FCGI_MAX_REQS     Максимальное число одновременных запросов,
                    которые принимает это приложение.

* FCGI_MPXS_CONNS   "0", если приложение не мультиплексирует соединения,
                    иначе "1".

Некоторые приложения FastCGI не поддерживают эту возможность. Другие закрывают соединение сразу после отправки ответа. Поэтому по умолчанию этот параметр отключён.

Обратите внимание: максимальное число одновременных запросов, принимаемых приложением FastCGI, является переменной соединения. Оно ограничивает только число потоков на соединение. Если требуется ограничить общую нагрузку на приложение, необходимо задать параметры сервера «maxconn» и «pool-max-conn». Кроме того, если приложение не поддерживает мультиплексирование соединений, максимальное число одновременных запросов автоматически устанавливается в 1.

option keep-conn

option keep-conn
no option keep-conn

Указывает приложению FastCGI, следует ли оставлять соединение открытым после отправки ответа.

Если параметр отключён, приложение FastCGI закрывает соединение после ответа на этот запрос. По умолчанию параметр включён.

option max-reqs <reqs>

option max-reqs <reqs>

Задаёт максимальное число одновременных запросов, которые принимает приложение.

Значение может быть переопределено, если при установке соединения получена переменная FCGI_MAX_REQS. Кроме того, если приложение не поддерживает мультиплексирование соединений, параметр игнорируется. Значение по умолчанию — 1.

option mpxs-conns

option mpxs-conns
no option mpxs-conns

Включает или отключает поддержку мультиплексирования соединений.

Значение может быть переопределено, если при установке соединения получена переменная FCGI_MPXS_CONNS. По умолчанию параметр отключён.

set-param <name> <fmt> [ { if | unless } <condition> ]

set-param <name> <fmt> [ { if | unless } <condition> ]

Задаёт параметр FastCGI, который следует передать приложению. Его значение, определённое через <fmt>, должно соответствовать правилам пользовательского формата журнала (см. раздел 8.2.6 «Пользовательский формат журнала»). После него можно указать условие на основе ACL; тогда директива обрабатывается только при истинном условии.

Эта директива позволяет переопределять значения стандартных параметров FastCGI. Если вычисленное значение является пустой строкой, правило игнорируется. Директивы выполняются в порядке объявления.

Пример:

# PHP only, required if PHP was built with --enable-force-cgi-redirect
set-param REDIRECT_STATUS 200

set-param PHP_AUTH_DIGEST %[req.hdr(Authorization)]

10.1.2. Секция прокси

use-fcgi-app <name> Задаёт приложение FastCGI, используемое бэкендом.

Аргументы:

<name>    — имя используемого приложения FastCGI.

Эта директива доступна только для прокси HTTP с возможностями бэкенда и хотя бы одним сервером FastCGI. При этом серверы FastCGI можно смешивать с серверами HTTP. Однако без веской причины делать это не рекомендуется (подробности см. в разделе 10.3 об ограничениях). Для каждого бэкенда одновременно можно определить только одно приложение.

Учтите: после привязки приложения FastCGI к бэкенду, в зависимости от конфигурации, часть обработки может выполняться даже для запросов, которые не отправляются на сервер FastCGI. Правила установки параметров и передачи заголовков приложению всё равно вычисляются.

10.1.3. Пример

frontend front-http
    mode http
    bind *:80

    use_backend back-dynamic if { path_reg ^/.+\.php(/.*)?$ }
    default_backend back-static

backend back-static
    mode http
    server www A.B.C.D:80

backend back-dynamic
    mode http
    use-fcgi-app php-fpm
    server php-fpm A.B.C.D:9000 proto fcgi

fcgi-app php-fpm
    log-stderr global
    option keep-conn

    docroot /var/www/my-app
    index index.php
    path-info ^(/.+\.php)(/.*)?$

10.2. Параметры по умолчанию

Приложение FastCGI с ролью Responder выполняет ту же задачу, что и программа CGI/1.1. Согласно спецификации CGI/1.1 (RFC3875), скрипту необходимо передавать несколько переменных. HAProxy задаёт их, а также некоторые другие переменные, часто используемые приложениями FastCGI. Все эти переменные можно переопределить, но делать это следует осторожно.

  +-------------------+-----------------------------------------------------+
  | AUTH_TYPE         | Указывает механизм аутентификации пользователя,     |
  |                   | используемый HAProxy, если он есть. Поддерживается  |
  |                   | только механизм аутентификации BASIC.               |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | CONTENT_LENGTH    | Содержит размер тела сообщения, переданного с       |
  |                   | запросом. Это означает, что только запросы с        |
  |                   | известным размером считаются корректными и          |
  |                   | передаются приложению.                              |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | CONTENT_TYPE      | Содержит тип тела сообщения, переданного с          |
  |                   | запросом. Может быть не задан.                      |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | DOCUMENT_ROOT     | Содержит корневой каталог на удалённом узле, в      |
  |                   | котором следует выполнять скрипт, согласно          |
  |                   | конфигурации приложения.                            |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | GATEWAY_INTERFACE | Содержит диалект CGI, который HAProxy использует    |
  |                   | для обмена с приложением FastCGI. Значение          |
  |                   | устанавливается в "CGI/1.1".                        |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | PATH_INFO         | Содержит часть иерархического пути URI после части, |
  |                   | идентифицирующей сам скрипт. Для задания этого      |
  |                   | параметра должна быть определена директива          |
  |                   | "path-info".                                        |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | PATH_TRANSLATED   | Если PATH_INFO задан, содержит результат его        |
  |                   | преобразования: объединение DOCUMENT_ROOT и         |
  |                   | PATH_INFO. Если PATH_INFO не задан, этот параметр   |
  |                   | также не задаётся.                                  |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | QUERY_STRING      | Содержит строку запроса. Может быть не задан.       |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | REMOTE_ADDR       | Содержит сетевой адрес клиента, отправившего        |
  |                   | запрос.                                             |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | REMOTE_USER       | Содержит строку идентификации пользователя,         |
  |                   | переданную клиентом при аутентификации.             |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | REQUEST_METHOD    | Содержит метод, который скрипту следует             |
  |                   | использовать для обработки запроса.                 |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | REQUEST_URI       | Содержит URI запроса.                               |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | SCRIPT_FILENAME   | Содержит абсолютный путь к скрипту: объединение     |
  |                   | DOCUMENT_ROOT и SCRIPT_NAME.                        |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | SCRIPT_NAME       | Содержит имя скрипта. Если определена директива     |
  |                   | "path-info", это начальная часть иерархического     |
  |                   | пути URI, заканчивающаяся именем скрипта. Иначе это |
  |                   | весь путь URI.                                      |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | SERVER_NAME       | Содержит имя серверного узла, которому направлен    |
  |                   | запрос клиента. Это значение заголовка "Host", если |
  |                   | он задан. Иначе используется адрес назначения       |
  |                   | соединения на стороне клиента.                      |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | SERVER_PORT       | Содержит TCP-порт назначения соединения на стороне  |
  |                   | клиента, то есть порт, к которому подключился       |
  |                   | клиент.                                             |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | SERVER_PROTOCOL   | Содержит протокол запроса.                          |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | SERVER_SOFTWARE   | Содержит строку "HAProxy", за которой следует       |
  |                   | текущая версия HAProxy.                             |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+
  | HTTPS             | Устанавливается в непустое значение ("on"), если к  |
  |                   | скрипту обратились по протоколу HTTPS.              |
  |                   |                                                     |
  +-------------------+-----------------------------------------------------+

10.3. Ограничения

В текущей реализации есть ряд ограничений. Первое связано с тем, как некоторые заголовки запроса скрываются от приложений FastCGI. Это происходит при анализе заголовков на стороне бэкенда, до установки соединения. На этом этапе HAProxy знает, что бэкенд использует приложение FastCGI, но ещё не знает, будет ли запрос направлен на сервер FastCGI. Чтобы скрыть заголовки запроса, он просто удаляет их из сообщения HTX. Поэтому, если в итоге запрос направляется на сервер HTTP, тот никогда не увидит эти заголовки. По этой причине не рекомендуется смешивать серверы FastCGI и HTTP в одном бэкенде.

Аналогично правила «set-param» и «pass-header» вычисляются при анализе заголовков запроса. То есть они выполняются всегда, даже если запрос в итоге пересылается на сервер HTTP.

При применении правила «set-param» в сообщение HTX добавляется псевдозаголовок. Поэтому, как и при переписывании заголовков HTTP, операция может завершиться неудачей при заполненном буфере. Правила «set-param» конкурируют за место с правилами «http-request».

Наконец, все параметры FastCGI и заголовки HTTP отправляются в одной записи FCGI_PARAM. Эту запись необходимо закодировать за один проход, иначе возвращается ошибка обработки. Это означает, что размер закодированной записи FCGI_PARAM не должен превышать размер буфера. Однако соблюдать резерв свободного места здесь не требуется.

20 - 11. Таблицы привязок и одноранговые узлы

Объявление хранилища таблиц привязок и репликации между одноранговыми узлами

Таблицы привязок в HAProxy позволяют связывать набор сведений и метрик с ключом определённого типа и хранить их в течение заданного времени после последнего обновления. Это можно представить как строку таблицы с несколькими столбцами: значение ключа определяет номер строки, а столбцы соответствуют отдельным критериям.

Изначально таблицы привязок предназначались для хранения привязки клиента к серверу, чтобы сохранять сеанс между ними. При подключении или отправке запроса клиент определялся по отличительному признаку — исходному адресу, cookie или параметру URL. Выбранный сервер сохранялся в таблице вместе с этим признаком на настраиваемый срок. Благодаря этому последующие обращения того же клиента автоматически направлялись на сервер, где он создал сеанс приложения.

Теперь таблицы привязок могут хранить не только номер сервера, но и метрики активности конкретного клиента: число и интенсивность запросов и соединений, количество и скорость передачи байтов и т. д. Также можно хранить произвольные счётчики событий (“gpc” — счётчики общего назначения) и метки характеристик клиента (“gpt” — метка общего назначения).

На таблицы привязок могут ссылаться директивы “stick”, обеспечивающие привязку клиента к серверу, правила “track-sc”, определяющие, какой ключ отслеживать в какой таблице для сбора метрик, а также функции извлечения образцов и преобразователи, которые могут немедленно найти заданный ключ и получить определённую метрику или данные. Общий принцип таков: обновление таблиц (gpt/gpc/metrics) и поиск сведений о привязке обновляют время доступа к записи и отодвигают срок её истечения. Простой поиск через функции извлечения образцов и преобразователи лишь получает данные, не отодвигая срок истечения записи.

Чтобы механизм масштабировался и сохранял работоспособность при перезагрузках HAProxy и переключении при отказе, обновлениями таблиц привязок можно обмениваться с другими узлами, называемыми “peers”, через механизм “Peers”, описанный в разделе 11.2 . Для точной настройки обмена можно также задать, что некоторые таблицы только получают сведения от одноранговых узлов либо что полученные от них обновления следует пересылать в другую таблицу.

Таблицы привязок можно объявлять в секциях прокси (фронтендах и бэкендах) директивой “stick-table”: в секции допускается лишь одна таблица, получающая имя секции. Либо их можно объявлять в секциях peers директивой “table”, за которой следует имя таблицы: так в одной секции “peers” можно определить несколько таблиц. Если нужно несколько таблиц привязок, обычно рекомендуется объявлять их в секции peers, когда предполагается обмен ими, либо создавать дополнительные секции бэкендов, содержащие только определение “stick-table”.

11.1. Объявление stick-table

Объявления stick-table в секциях прокси (“frontend”, “backend”, “listen”) и в секциях “peers” очень похожи. Отличие состоит в том, что объявление в секции peers требует имени и не принимает параметр “peers”.

В секции “frontend”, “backend” или “listen”:

stick-table type <type> size <size> [expire <expire>] [nopurge] [recv-only] [write-to <wtable>] [srvkey <srvkey>] [store <data_type>]* [brates-factor <factor>] [peers <peersect>]

В секции “peers”:

table <name> type <type> size <size> [expire <expire>] [nopurge] [recv-only] [write-to <wtable>] [srvkey <srvkey>] [store <data_type>]* [brates-factor <factor>]

Аргументы: (обязательные сначала, затем в алфавитном порядке):

  • type <type> — обязательный аргумент, задающий тип ключа <type>. Обычно это одно слово, но у него также могут быть собственные аргументы:

    • ip — следует предпочесть более явный тип, например “ipv4” или “ipv6”. До версии 3.2 это был единственный способ настроить IPv4. В версии 3.2 “ip” — псевдоним “ipv4”, причём “ipv4” предпочтителен. В одной из будущих версий “ip” будет означать “ipv6”. Этот тип предназначен только для облегчения перехода с версий до 3.2 на версии после 3.2.

    • ipv4 — таблица, объявленная с этим типом, хранит только адреса IPv4. Представление очень компактно, около 50 байт на запись, и обеспечивает очень быстрый поиск и сохранение записей почти без накладных расходов. Основное применение — хранение исходных IP-адресов клиентов.

    • ipv6 — таблица, объявленная с “type ipv6”, хранит только адреса IPv6. Представление очень компактно, около 60 байт на запись, и обеспечивает очень быстрый поиск и сохранение записей почти без накладных расходов. Основное применение — хранение исходных IP-адресов клиентов.

    • integer Таблица, объявленная с “type integer”, будет хранить 32-битные целые числа, которые могут представлять идентификатор клиента, найденный в запросе, например.

    • string [len <len>] — таблица с “type string” хранит подстроки длиной до <len> символов. Если строка, полученная средством извлечения шаблона, длиннее <len>, она обрезается перед сохранением. При сопоставлении строки в таблице с извлечённым шаблоном сравнивается не более <len> символов. Если длина не указана, строка ограничивается 32 символами. Увеличение длины может заметно повысить потребление памяти.

    • binary [len <len>] — таблица с “type binary” хранит двоичные блоки длиной <len> байт. Если блок, полученный средством извлечения шаблона, длиннее <len>, он обрезается перед сохранением. Если результат выражения образца короче <len>, он дополняется значениями 0. Если длина не указана, блок ограничивается 32 байтами. Увеличение длины может заметно повысить потребление памяти.

  • size <size> — обязательный аргумент, задающий максимальное число записей <size> в таблице. Он напрямую влияет на потребление памяти: требуется примерно 50 байт на запись, не считая указанного выше размера ключа, сохраняемых метрик и размера строки, если они есть. Поддерживаются суффиксы “k”, “m”, “g”, соответствующие множителям 2^10, 2^20 и 2^30.

  • expire <delay> — максимальное время хранения записи с момента её последнего создания, обновления через ’track-sc’ или сопоставления правилом ‘stick match’ либо ‘stick on’. Срок <delay> задаётся в стандартном формате времени, как и тайм-ауты; единица по умолчанию — миллисекунды. Максимальный срок немного превышает 24 дня. Подробнее см. раздел 2.5 . Если срок не задан, сеансы не истекают автоматически, но при заполнении таблицы создание новых записей приводит к удалению самых старых. Если срок не задан, нельзя использовать “nopurge”. Примечание: преобразователи ’table_*’ выполняют поиск, но не продлевают срок хранения записи, поскольку им не требуется ’track-sc’.

  • brates-factor <factor> — множитель для скорости входящего и исходящего потока байтов. Вместо отдельных байтов учитываются блоки байтов. Внутри используются 32-битные счётчики, ограниченные примерно 4 миллиардами за период. Этот параметр позволяет учитывать скорости выше предела 4G за заданный период. Множитель должен быть больше 0 и не больше 1024.

  • nopurge запрещает удалять старые записи при заполнении таблицы. Без этого параметра, если HAProxy требуется сохранить запись в полной таблице, несколько самых старых записей удаляются, освобождая место для новых. Обычно именно это и требуется. Однако в некоторых случаях предпочтительно отклонять новые записи, сохраняя старые: например, если объём данных значительно превышает возможности оборудования и лучше отказать новым клиентам, чем уже подключённым. При использовании этого параметра необходимо правильно настроить “expire” (см. выше).

  • recv-only указывает, что таблица предназначена только для получения интересующих данных от удалённого однорангового узла, а не для локальных обновлений. Параметр позволяет получать значения, которые обычно остаются локальными, например “conn_cur”. По умолчанию они не принимаются от других узлов, поскольку конфликтовали бы с обновлениями, которые локальный узел выполняет в этой таблице. Параметр имеет смысл только для таблиц, не используемых в правилах отслеживания или методах обновления: иначе говоря, для удалённых таблиц, из которых только читают сведения.

  • peers <peersect> — созданные и изменённые записи, а также записи с продлённым сроком хранения передаются одноранговым узлам из секции <peersect> для синхронизации. Ключи, полученные от узлов этой секции, также вставляются или обновляются в таблице. Кроме того, при запуске может предприниматься попытка получить записи от прежнего экземпляра процесса, обозначенного в этой секции как локальный одноранговый узел.

  • srvkey <srvkey> — способ идентификации сервера в таблице привязок. Допустимы “name” и “addr”. При “name” используется аргумент сервера <name>, который может быть сгенерирован шаблоном. При “addr” сервер определяется текущим сетевым адресом, включая порт. Значение “addr” особенно полезно, когда механизм обнаружения служб формирует адреса серверов с реплицируемыми таблицами привязок и требуется, чтобы один токен привязки указывал на один и тот же узел у всех участников.

  • store <data_type> — хранение дополнительных сведений в таблице привязок. ACL могут использовать их для проверки различных критериев активности клиента, соответствующего записи таблицы. Каждый указанный элемент увеличивает размер записи на объём дополнительных данных. В одной записи можно хранить несколько типов данных: перечислить их через запятую после “store” либо повторить “store” с одним или несколькими типами. Все сохраняемые типы должны быть объявлены явно, кроме “server_id”, который обнаруживается и включается автоматически. Если ACL ссылается на несохраняемый тип данных, совпадения не будет. Некоторым типам требуется аргумент, который необходимо указать в круглых скобках сразу после типа. Поддерживаемые типы и их аргументы перечислены ниже.

  • write-to <wtable> — имя другой таблицы привязок, куда обновления от одноранговых узлов записываются дополнительно к исходной таблице. Таблица <wtable> должна иметь тот же тип и длину ключа, что и объявляемая таблица; исходная таблица не может быть собственной целью. При каждом обновлении исходной таблицы, полученном от другого узла, HAProxy пытается обновить соответствующую запись <wtable>. Если записи нет, она создаётся; иначе обновляются её значения и таймер. В <wtable> записываются только типы, не участвующие в арифметических операциях, например server_id, server_key и gpt. Это предотвращает влияние вычисленных значений удалённой таблицы на арифметические операции в локальной целевой таблице, в частности бесконечный рост общего накопительного счётчика. Типичный случай применения — правила привязки к серверу в кластере одноранговых узлов, где ключи для сопоставления поступают из удалённых таблиц.

Ниже перечислены типы данных, которые можно связать с записью через директиву “store”. При хранении большого числа типов потребность в памяти может быть значительной. Все перечисленные показатели вместе могут занимать сотни байт на запись, а для таблицы из 1 миллиона записей — сотни мегабайт. Поэтому для каждого типа после аргумента в скобках указан приблизительный объём хранения.

Аргументы:

  • bytes_in_cnt [8 байт] Это количество байт от клиента к серверу. Это положительное 64-битное целое число, которое подсчитывает суммарное количество байт, полученных от клиентов, соответствующих этому элементу. Заголовки включаются в подсчёт. Это может быть использовано для ограничения злоупотреблений в функциях загрузки на серверах фото или видео. Примечание: значения измеряются при входе данных в HAProxy, поэтому подсчёты не зависят от сжатия.

  • bytes_in_rate(<period>) [12 байт] Это счётчик скорости передачи байт от клиента к серверу. Он принимает целочисленный параметр <period>, указывающий в миллисекундах длительность периода, в течение которого измеряется средняя скорость. Он отображает среднюю скорость входящей передачи байт за этот период, в байтах в период. Может использоваться для обнаружения пользователей, загружающих слишком много и слишком быстро. Предупреждение: при больших загрузках возможно, что объём переданных данных будет учтён один раз при завершении передачи, что приведёт к резким скачкам средней скорости передачи, вместо плавного изменения. Это может частично быть устранено с помощью “option contstats”, хотя это не является идеальным решением. Рекомендуется использовать byte_in_cnt для более справедливого учёта.

  • bytes_out_cnt [8 байт] Это счётчик байт от сервера к клиенту. Это положительное 64-битное целое число, которое подсчитывает накопленное количество байт, отправленных клиентам, соответствующим этому вхождению. В счёт включаются заголовки. Может использоваться для ограничения злоупотреблений ботами, забирающими весь сайт. Примечание: значения измеряются при входе данных в HAProxy, поэтому сжатие не влияет на подсчёт.

  • bytes_out_rate(<period>) [12 байт] Это счётчик скорости передачи байт от сервера к клиенту. Он принимает целочисленный параметр <period>, указывающий в миллисекундах длительность периода, в течение которого измеряется средняя скорость. Он отображает среднюю скорость исходящей передачи байт за этот период, в байтах в период. Может использоваться для обнаружения пользователей, скачивающих слишком много и слишком быстро. Предупреждение: при больших передачах возможно, что объём переданных данных будет учтён один раз при завершении передачи, что приведёт к резким скачкам средней скорости передачи, вместо плавного изменения. Это может частично быть устранено с помощью “option contstats”, хотя это не является идеальным решением. Рекомендуется использовать byte_out_cnt для более справедливого учёта.

  • conn_cnt [4 байта] Это количество соединений. Это положительное 32-битное целое число, которое подсчитывает абсолютное количество соединений, полученных от клиентов, соответствующих этому элементу. Оно не означает, что соединения были приняты, просто что они были получены.

  • conn_cur [4 байта] — число текущих соединений. Это положительное 32-битное целое число, хранящее количество одновременных соединений для записи. Оно увеличивается, когда входящее соединение соответствует записи, и уменьшается при завершении соединения. Так в любой момент известно точное число одновременных соединений для записи. По умолчанию этот тип не принимается от других одноранговых узлов: полученное значение не имело бы смысла, поскольку не учитывало бы локальный счётчик. С recv-only можно получать число одновременных соединений, наблюдаемое другими узлами.

  • conn_rate(<period>) [12 байт] Это счётчик частоты соединений. Он принимает целочисленный параметр <period>, указывающий в миллисекундах длительность периода, в течение которого измеряется среднее значение. Он отображает среднюю интенсивность соединений за этот период, в соединениях на период. Результат — целое число, которое может быть использовано в ACL. Прием или отклонение соединений не влияет на их измерение.

  • glitch_cnt [4 байта] — число протокольных аномалий на фронтенде. Это положительное 32-битное целое число, накапливающее число аномалий, отмеченных на клиентском соединении. Аномалии — необычные или неожиданные с точки зрения протокола действия клиента, которые могут указывать на серьёзную неисправность клиента либо на атакующего. Счётчик помогает выбрать способ обработки таких клиентов.

  • glitch_rate(<period>) [12 байт] Счётчик частоты протокольных аномалий. Принимает целочисленный параметр <period>, задающий в миллисекундах длительность периода усреднения. Возвращает среднюю частоту аномалий на фронтенде за этот период. Может использоваться для обнаружения неисправных клиентов или потенциальных атакующих, выполняющих необычные или неожиданные с точки зрения протокола действия, если HAProxy отметил их как таковые.

  • gpc(<nb>) [4 * <nb> байт] Массив из <nb> счётчиков общего назначения. Это массив положительных 32-битных целых чисел, которыми можно считать что угодно. Чаще всего их используют как увеличиваемые счётчики в записях, например чтобы отметить достижение предела и запустить действия. Массив ограничен 100 элементами, от gpc0 до gpc99, чтобы сообщение обновления для однорангового узла помещалось в буфер. Пользователям следует учитывать, что большое число счётчиков увеличивает объём данных и трафик протокола peers, поскольку при изменении любого элемента передаются все данные и счётчики. Этот data_type исключает использование устаревших data_types ‘gpc0’ и ‘gpc1’ в той же таблице. При использовании массива ‘gpc’ в качестве data_type все функции извлечения образцов и действия для ‘gpc0’ и ‘gpc1’ применяются к первым двум элементам массива.

  • gpc_rate(<nb>,<period>) [12 * <nb> байт] — массив интенсивностей приращения счётчиков общего назначения за период. Элементы — положительные 32-битные целые числа, пригодные для любых целей. Как и <gpc>, они учитывают события, но хранят интенсивность увеличения счётчика, а не накопленное значение. Обычно они измеряют частоту определённых событий, например запросов к конкретному URL. Массив ограничен 100 элементами: gpc_rate(100,<period>) позволяет хранить gpc0_rate–gpc99_rate, чтобы сообщение обновления для однорангового узла помещалось в буфер. В массиве должно быть не меньше 1 элемента; для одной интенсивности gpc0_rate используется gpc_rate(1,<period>). Следует учитывать, что большое число счётчиков увеличивает объём данных и трафик протокола peers: при изменении любого из них передаются все данные и счётчики. Этот data_type исключает устаревшие data_types ‘gpc0_rate’ и ‘gpc1_rate’ в той же таблице. При использовании массива ‘gpc_rate’ в качестве data_type все функции извлечения и действия для ‘gpc0’ и ‘gpc1’ относятся к первым двум элементам массива.

  • gpc0 [4 байта] Это первый счётчик общего назначения. Это положительное 32-битное целое число, которое может использоваться для любых целей. Чаще всего оно используется для присвоения специальной метки определённым записям, например, чтобы отметить, что определённое поведение было обнаружено и должно быть известно для последующих совпадений.

  • gpc0_rate(<period>) [12 байт] Это скорость увеличения первого счётчика общего назначения за определённый период. Это положительное 32-битное целое число, которое может использоваться для любых целей. Подобно <gpc0>, оно подсчитывает события, но вместо хранения накопленного значения, оно сохраняет скорость увеличения счётчика. Чаще всего оно используется для измерения частоты возникновения определённых событий (например, запросов к конкретному URL).

  • gpc1 [4 байта] Это второй счётчик общего назначения. Это положительное целое число из 32 бит, которое может быть использовано для любых целей. Чаще всего оно применяется для присвоения специальной метки некоторым записям, например, чтобы отметить, что определённое поведение было обнаружено и должно быть известно для последующих совпадений.

  • gpc1_rate(<period>) [12 байт] Это скорость увеличения второго счётчика общего назначения за определённый период. Это положительное целое число из 32 бит, которое может быть использовано для любых целей. Подобно <gpc1>, оно подсчитывает события, но вместо хранения накопленного значения, оно сохраняет скорость увеличения счётчика. Чаще всего оно используется для измерения частоты появления определённых событий (например, запросов к конкретному URL).

  • gpt(<nb>) [4 * <nb> байт] — массив из <nb> меток общего назначения. Его элементы — положительные 32-битные целые числа, пригодные для любых целей. Обычно ими помечают записи, например фиксируют обнаруженное поведение, которое необходимо учитывать при последующих сопоставлениях. Массив ограничен 100 элементами: gpt(100) позволяет хранить gpt0–gpt99, чтобы сообщение обновления для однорангового узла помещалось в буфер. В массиве должно быть не меньше 1 элемента; для одной метки gpt0 используется gpt(1). Следует учитывать, что большое число счётчиков увеличивает объём данных и трафик протокола peers: при изменении любого из них передаются все данные и счётчики. Этот data_type исключает устаревший data_type ‘gpt0’ в той же таблице. При использовании массива ‘gpt’ в качестве data_type все функции извлечения и действия для ‘gpt0’ относятся к первому элементу массива.

  • gpt0 [4 байта] — первая метка общего назначения. Это положительное 32-битное целое число, пригодное для любых целей. Обычно им помечают записи, например фиксируют обнаруженное поведение, которое необходимо учитывать при последующих сопоставлениях.

  • http_req_cnt [4 байта] — число запросов HTTP. Это положительное 32-битное целое число, подсчитывающее общее число запросов HTTP от клиентов, соответствующих записи. Корректность запросов не имеет значения. При постоянных соединениях на клиентской стороне это значение отличается от числа сеансов.

  • http_req_rate(<period>) [12 байт] Это счётчик частоты запросов. Он принимает целочисленный параметр <period>, указывающий в миллисекундах длительность периода, в течение которого вычисляется среднее значение. Он отображает среднюю интенсивность запросов HTTP в течение этого периода, в запросах за период. Результат — целое число, которое можно использовать в ACL. Не имеет значения, являются ли запросы действительными или нет. Примечание: это отличается от сессий при использовании постоянного соединения на клиентской стороне.

  • http_err_cnt [4 байта] — число ошибок запросов HTTP. Это положительное 32-битное целое число, подсчитывающее общее число ошибок запросов HTTP по вине клиентов, соответствующих записи. Учитываются некорректные и усечённые запросы, запрещённые запросы, запросы, задержанные ловушкой соединений (tarpit), и неудачные попытки аутентификации. Если сервер отвечает кодом 4xx, запрос также считается ошибочным, поскольку ошибка вызвана клиентом, например при сканировании уязвимостей.

  • http_err_rate(<period>) [12 байт] Это счётчик частоты запросов HTTP. Он принимает целочисленный параметр <period>, указывающий в миллисекундах длительность периода, за который измеряется среднее значение. Счётчик возвращает среднюю частоту ошибок HTTP запросов за этот период, в запросах на период (см. http_err_cnt выше, что считается ошибкой). Результат — целое число, которое можно использовать в ACL.

  • http_fail_cnt [4 байта] Это счётчик сбоев HTTP ответа. Это положительное 32-битное целое число, которое подсчитывает абсолютное количество сбоев HTTP ответов, вызванных серверами, соответствующими этому элементу. Ошибки учитываются при неверных и обрезанных ответах, а также при любых ответах 5xx, кроме 501 и 505. Предназначен для использования в сочетании с путём или URI для обнаружения сбоев сервиса.

  • http_fail_rate(<period>) [12 байт] Это счётчик частоты сбоев HTTP ответа. Он принимает целочисленный параметр <period>, указывающий в миллисекундах продолжительность периода, за который измеряется среднее значение. Счётчик возвращает среднюю частоту сбоев HTTP ответа за этот период, в запросах на период (см. http_fail_cnt выше, что считается сбоем). Результат — целое число, которое можно использовать в ACL.

  • server_id [4 байта] — целое число с числовым идентификатором сервера, которому назначен запрос. Используется правилами “stick match”, “stick store” и “stick on” и включается автоматически при обращении к нему. Привязка на основе накопленных сведений имеет ограничения: при перезапуске все накопленные связи теряются, если одноранговые узлы не настроены для их передачи при перезапуске. Такая настройка рекомендуется. Обычно этот способ полезен как дополнение к другим механизмам привязки, но не всегда подходит как единственный механизм.

  • sess_cnt [4 байта] — число сеансов. Это положительное 32-битное целое число, подсчитывающее общее число сеансов от клиентов, соответствующих записи. Сеансом считается соединение, принятое правилами уровня 4 (“tcp-request connection”).

  • sess_rate(<period>) [12 байт] Это счётчик частоты сессий. Принимает целочисленный параметр <period>, указывающий в миллисекундах длительность периода, в течение которого вычисляется среднее значение. Отображает среднюю частоту входящих сессий за этот период, в сессиях за период. Результат — целое число, которое может использоваться в ACL.

Пример:

# Keep track of counters of up to 1 million IP addresses over 5 minutes
# and store a general purpose counter and the average connection rate
# computed over a sliding window of 30 seconds.
stick-table type ip size 1m expire 5m store gpc0,conn_rate(30s)

См. также: “stick match”, “stick on”, “stick store-request”, “track-sc”, раздел 2.5 о формате времени, раздел 11.2 об одноранговых узлах, раздел 9.7 об ограничениях пропускной способности и раздел 7 об ACL.

11.2. Объявление одноранговых узлов

Записи любых типов данных в таблицах привязок можно распространять между несколькими экземплярами HAProxy по соединениям TCP в режиме с несколькими ведущими узлами. Каждый экземпляр отправляет свои локальные обновления и добавления удалённым одноранговым узлам. Переданные значения перезаписывают удалённые без агрегирования.

Исключение — тип данных “conn_cur”, который по умолчанию никогда не принимается от других узлов, поскольку должен отражать локальные значения. В старых версиях он синхронизировался по умолчанию, что приводило к отрицательным значениям в конфигурациях active-active и постоянному росту значений при перезагрузках или переключениях active-passive: локальное значение отражало больше соединений, чем имелось на самом деле. Однако иногда получать это значение от других узлов полезно, например для пассивной удалённой таблицы, используемой только для получения данных и мониторинга, без операций записи или обновления на её основе. Для этого в объявление таблицы добавляют “recv-only”. В любом случае сведения “conn_cur” всегда отправляются, чтобы системы мониторинга могли их наблюдать.

Прерванный обмен автоматически обнаруживается и возобновляется с последней известной точки. Кроме того, при мягком перезапуске старый процесс подключается к новому по такому соединению TCP и передаёт все свои записи до того, как новый процесс начнёт подключаться к другим одноранговым узлам. Это обеспечивает очень быструю репликацию при перезагрузке: обычно доли секунды даже для больших таблиц.

Учтите, что для удалённой идентификации серверов используются их ID. Поэтому важно, чтобы конфигурации были похожи или хотя бы чтобы для каждого сервера на всех участниках принудительно задавался один и тот же ID.

peers <peersect>

peers <peersect>

Создаёт список одноранговых узлов с именем <peersect>. Это независимая секция, на которую ссылаются одна или несколько таблиц привязок.

bind [<address>]:port [param*]

bind [<address>]:port [param*]
bind /<path> [param*]

Определяет параметры привязки локального узла данной секции “peers”. Такие строки не поддерживаются в сочетании с строкой “peer” в той же секции “peers”.

disabled

disabled

Отключает секцию peers: как прослушивание соединений, так и всю связанную с этой секцией синхронизацию. Это позволяет отключить синхронизацию таблиц привязок, не закомментировывая все ссылки на “peers”.

default-bind [param*]

default-bind [param*]

Определяет параметры привязки для локального узла, исключая его адрес.

default-server [param*]

default-server [param*]

Изменяет параметры по умолчанию для сервера в секции “peers”.

Аргументы:

<param*>  — список параметров сервера. Ключевое слово "default-server"
          принимает множество параметров, описанных в отдельном разделе.
          В секции peers поддерживаются транспортные параметры строки
          "default-server". Подробнее см. раздел 5, а некоторые ограничения
          приведены ниже, в описании ключевого слова "server" этой секции.

См. также: “server” и раздел 5 о параметрах сервера

enabled

enabled

Это включает секцию «peers», которая ранее была отключена с помощью ключевого слова “disabled”.

log <target> [len <length>] [format <format>] [sample <ranges>:<sample_size>]

log <target> [len <length>] [format <format>] [sample <ranges>:<sample_size>]
    <facility> [<level> [<minlevel>]]

Секции “peers” поддерживают то же ключевое слово “log”, что и прокси, для записи сведений о слушателе “peers” в журнал. Подробнее см. описание параметра “log” для прокси.

peer <peername> [<address>]:port [param*]

peer <peername> [<address>]:port [param*]
peer <peername> /<path> [param*]

Определяет узел внутри секции узлов. Если <peername> установлен в имя локального узла (по умолчанию имя хоста, или заданное с помощью параметра командной строки “-L” или настройки “localpeer” в глобальной конфигурации), HAProxy будет ожидать входящее соединение от удалённого узла на указанном адресе. В противном случае адрес определяет место подключения для присоединения к удалённому узлу, а <peername> используется на уровне протокола для идентификации и проверки удалённого узла на стороне сервера.

При мягком перезапуске адрес локального узла используется старым экземпляром для подключения к новому и инициализации полного реплицирования (процесса обучения).

Настоятельно рекомендуется иметь одинаковые объявления одноранговых узлов на всех узлах и полагаться только на аргумент командной строки “-L” или настройку “localpeer” в глобальной конфигурации для изменения имени локального узла. Это упрощает поддержку единообразных конфигурационных файлов на всех узлах.

В параметре адреса можно использовать переменные окружения; см. раздел 2.3 о переменных окружения.

Примечание: ключевое слово “peer” может быть прозрачно заменено на ключевое слово “server” (см. объяснение ключевого слова “server” ниже).

server <peername> [<address>:<port>] [param*]

server <peername> [<address>:<port>] [param*]
server <peername> [/<path>] [param*]

Как уже упоминалось, ключевое слово “peer” может быть заменено ключевым словом “server” с поддержкой всех параметров “server”, приведённых в разделе 5.2, относящихся к настройкам транспорта. Если указанный узел локальный, параметр адреса не должен присутствовать; он должен быть указан в строке “bind” (см. ключевое слово “bind” этой “peers” секции).

Некоторые параметры “server” неактуальны для секций “peers”. Узлы по своей природе не поддерживают динамическое разрешение имен хостов и проверку работоспособности, поэтому параметры, такие как “init_addr”, “resolvers”, “check”, “agent-check” или “track”, не поддерживаются. Аналогично, отсутствует балансировка нагрузки и привязка сеанса, поэтому параметры, такие как “weight” или “cookie”, не имеют эффекта.

Пример:

 # The old way.
 peers mypeers
     peer haproxy1 192.168.0.1:1024
     peer haproxy2 192.168.0.2:1024
     peer haproxy3 10.2.0.1:1024

 backend mybackend
     mode tcp
     balance roundrobin
     stick-table type ip size 20k peers mypeers
     stick on src

     server srv1 192.168.0.30:80
     server srv2 192.168.0.31:80

Пример:
  peers mypeers
     bind 192.168.0.1:1024 ssl crt mycerts/pem
     default-server ssl verify none
     server haproxy1 #local peer
     server haproxy2 192.168.0.2:1024
     server haproxy3 10.2.0.1:1024

shards <shards>

В некоторых конфигурациях желательно распределять содержимое stick-table по некоторым узлам вместо отправки всего содержимого stick-table каждому узлу, указанному в секции “peers”. В таких случаях, “shards” указывает количество узлов, участвующих в распределении содержимого stick-table. См. также параметр сервера “shard”.

table <tablename> type {ip | integer | string [len <length>] | binary [len <length>]}

table <tablename> type {ip | integer | string [len <length>] | binary [len <length>]}
  size `<size>` [expire `<expire>`] [write-to `<wtable>`] [nopurge] [store `<data_type>`]*
  [recv-only]

Настраивает таблицу привязок для текущей секции. Строка разбирается так же, как директива “stick-table” в других секциях, но аргумент “peers” здесь не требуется, а первым добавляется обязательный параметр с именем stick-table. В отличие от других секций, в “peers” может быть несколько строк “table”. Полные определения “table” и “stick-table” приведены выше в разделе 11.1 .

Секции “peers” имеют собственные пространства имён таблиц привязок, чтобы одинаковые имена в разных секциях “peers” не конфликтовали. Внутри HAProxy перед именем таблицы привязок добавляются имя секции “peers” и символ ‘/’. В других местах файла конфигурации на таблицу привязок из секции “peers” необходимо ссылаться по имени с этим префиксом:

peers mypeers
    peer A ...
    peer B ...
    table t1 ...

frontend fe1
    tcp-request content track-sc0 src table mypeers/t1

В CLI для обращения к таблице привязок также необходимо использовать имя с префиксом.

Для протокола “peers” такого различия не требуется, поскольку обмениваться данными могут только одноранговые узлы “peers”, принадлежащие одной секции. В нескольких секциях “peers” можно объявлять таблицы привязок с одинаковым именем. По сети передаётся сокращённое имя stick-table. Префикс состоит только из символа ‘/’, чтобы избежать конфликтов имён stick-table между таблицами, объявленными как бэкенды, и stick-table в секциях “peers”, как в следующей необычной, но поддерживаемой конфигурации:

peers mypeers
    peer A ...
    peer B ...
    table t1 type string size 10m store gpc0

backend t1
    stick-table type string size 10m store gpc0 peers mypeers

Здесь таблица “t1” объявленная в секции “mypeers” имеет глобальное имя “mypeers/t1”. Таблица “t1” объявленная как бэкенд имеет глобальное имя “t1”. Однако на уровне протокола узла первая таблица называется “/t1”, вторая снова называется “t1”.

21 - 12. Другие секции

Трассировка, пользователи, почтовые серверы, ошибки, кольцевые буферы, сертификаты, ACME и глобальные проверки работоспособности

Секции, описанные ниже, реже используются и обычно поддерживают лишь несколько параметров. Между ними нет неявной связи. Они все начинаются с одного ключевого слова. Ни одна из них не допускается до секции “global”. Поддержка некоторых из них может зависеть от опций сборки (например, что касается SSL).

12.1. Трассировка

Для отладки можно включить трассировку подсистемы HAProxy. При этом выводятся отладочные сообщения об определённой подсистеме. Это мощное средство диагностики проблем. Трассировку можно динамически настраивать через CLI. Некоторые параметры также можно заранее задать в файле конфигурации, в отдельных секциях “traces”. Подробнее о трассировке см. руководство по управлению. Это инструмент разработчика для сложных сеансов отладки. Он выводит много сообщений и требует дополнительных ресурсов, поэтому используйте его осторожно. Поскольку это инструмент разработчика, обратная совместимость этой секции не гарантируется.

traces

traces

Начинает новую секцию traces. Одна или несколько секций “traces” могут быть использованы. Все директивы оцениваются в порядке объявления, последующие перекрывают предыдущие.

trace <source> <args...>

trace <source> <args...>

Настраивает подсистему “trace”. Каждая подсистема описана в руководстве по управлению; синтаксис в точности совпадает. Весь вывод команды “trace” появляется при разборе секции. Обычно это ошибки и предупреждения, но некоторые неполные команды могут перечислять допустимые варианты. Команда не предназначена для обычного использования: как правило, разработчики рекомендуют её при сложной отладке. В зависимости от уровня и подробности трассировка может существенно снизить общую производительность. Синтаксис команд приведён в руководстве по управлению.

Пример:

ring buf1
  size 10485760 # 10MB
  format timed
  backing-file /tmp/h1.traces

ring buf2
  size 10485760 # 10MB
  format timed
  backing-file /tmp/h2.traces

traces
  trace h1 sink buf1 level developer verbosity complete start now
  trace h2 sink buf1 level developer verbosity complete start now

12.2. Списки пользователей

Доступ к секциям frontend/backend/listen или статистике HTTP можно ограничить, разрешив его только пользователям, прошедшим аутентификацию и авторизацию. Для этого необходимо создать хотя бы один список пользователей и определить в нём пользователей.

userlist <listname>

userlist <listname>

Создаёт новый пользовательский список с именем <listname>. Множество независимых пользовательских списков может быть использовано для хранения данных аутентификации и авторизации для независимых клиентов.

group <groupname> [users <user>,<user>,(...)]

group <groupname> [users <user>,<user>,(...)]

Добавляет группу <groupname> в текущий список пользователей. Также можно включить в неё пользователей, указав после ключевого слова “users” список имён через запятую.

user <username> [password|insecure-password <password>]

user <username> [password|insecure-password <password>]
                [groups <group>,<group>,(...)]

Добавляет пользователя <username> в текущий список. Допускаются как защищённые, зашифрованные пароли, так и незащищённые, незашифрованные. Зашифрованные пароли проверяются функцией crypt(3), поэтому набор алгоритмов зависит от возможностей системы. Например, современные системы Linux на основе Glibc поддерживают MD5, SHA-256, SHA-512 и классический алгоритм шифрования паролей на основе DES.

Внимание: зашифрованные пароли могут значительно повысить нагрузку на CPU в зависимости от числа запросов и выбранного алгоритма. При любом варианте с хешированием пароль каждого запроса необходимо обработать выбранным алгоритмом перед сравнением со значением в файле конфигурации. Большинство современных алгоритмов специально требует больших вычислительных затрат для защиты от перебора. Соль и хеширование применяются к открытому паролю не один, а тысячи раз. Это может быстро стать существенной частью общей нагрузки HAProxy на CPU и даже привести к аварийному завершению приложения!

Один из способов снизить нагрузку хеш-функций на CPU — уменьшить число раундов хеширования для алгоритмов семейства SHA либо снизить «стоимость» функции, если алгоритм это поддерживает.

Также можно учесть, что реализации musl, например в Alpine Linux, вычисляют хеши медленнее аналогов из glibc.

Все пароли считаются обычными аргументами, поэтому к ним применяются правила кавычек и экранирования из раздела 2.2 . Рекомендуется заключать пароли в одинарные кавычки.

Пример:

userlist L1
  group G1 users tiger,scott
  group G2 users xdb,scott

  user tiger password $6$k6y3o.eP$JlKBx9za9667qe4(...)xHSwRv6J.C0/D7cV91
  user scott insecure-password 'elgato'
  user xdb insecure-password 'hello'

userlist L2
  group G1
  group G2

  user tiger password $6$k6y3o.eP$JlKBx(...)xHSwRv6J.C0/D7cV91 groups G1
  user scott insecure-password 'elgato' groups G1,G2
  user xdb insecure-password 'hello' groups G2

Оба списка функционально идентичны.

12.3. Почтовые серверы

При изменении состояния серверов можно отправлять уведомления по электронной почте. Если уведомления настроены, они передаются каждому почтовому серверу из секции mailers. Для отправки используется Lua (см. examples/lua/mailers.lua).

mailers <mailersect>

mailers <mailersect>

Создаёт список почтовых серверов с именем <mailersect>. Это независимая секция, на которую ссылаются один или несколько прокси.

mailer <mailername> <ip>:<port>

mailer <mailername> <ip>:<port>

Определяет почтовый сервер в секции mailers.

Пример:

global
    # mailers.lua file as provided in the git repository
    # adjust path as needed
    lua-load examples/lua/mailers.lua

mailers mymailers
    mailer smtp1 192.168.0.1:587
    mailer smtp2 192.168.0.2:587

backend mybackend
    mode tcp
    balance roundrobin

    email-alert mailers mymailers
    email-alert from test1@horms.org
    email-alert to test2@horms.org

    server srv1 192.168.0.30:80
    server srv2 192.168.0.31:80

timeout mail <time>

timeout mail <time>

Определяет время, доступное для установления соединения и передачи письма на сервер. Если не определено, значение по умолчанию — 10 секунд. Для обеспечения передачи как минимум двух SYN-ACK пакетов в ходе инициализации TCP рукопожатия рекомендуется сохранять это значение выше 4 секунд.

Пример:

mailers mymailers
    timeout mail 20s
    mailer smtp1 192.168.0.1:587

12.4. Ошибки HTTP

Можно глобально объявить несколько групп ошибок HTTP, а затем импортировать их в любые секции прокси. На одну группу можно ссылаться из нескольких мест и импортировать её полностью или частично.

http-errors <name>

http-errors <name>

Создаёт группу http-errors с именем <name>. Это независимая секция, на которую по имени могут ссылаться один или несколько прокси.

errorfile <code> <file>

errorfile <code> <file>

Связывает содержимое файла с кодом ошибки HTTP.

Аргументы:

<code>    — код состояния HTTP. Сейчас HAProxy может выдавать коды
          200, 400, 401, 403, 404, 405, 407, 408, 410,
          425, 429, 500, 501, 502, 503 и 504.

<file>    — файл с полным ответом HTTP. Рекомендуется добавлять к имени
          расширение ".http", чтобы не путать ответ со страницами ошибок
          HTML, и использовать абсолютные пути, поскольку файлы читаются
          до выполнения chroot.

Подробнее см. описание “errorfile” в разделе 4 .

Пример:

http-errors website-1
    errorfile 400 /etc/haproxy/errorfiles/site1/400.http
    errorfile 404 /etc/haproxy/errorfiles/site1/404.http
    errorfile 408 /dev/null  # work around Chrome pre-connect bug

http-errors website-2
    errorfile 400 /etc/haproxy/errorfiles/site2/400.http
    errorfile 404 /etc/haproxy/errorfiles/site2/404.http
    errorfile 408 /dev/null  # work around Chrome pre-connect bug

12.5. Кольцевые буферы

Можно глобально объявить кольцевые буферы для использования в качестве получателей сообщений журналов или трассировок.

ring <ringname>

ring <ringname>

Создаёт новый кольцевой буфер с именем <ringname>.

backing-file <path>

backing-file <path>

Заменяет обычное выделение памяти для кольцевого буфера файлом, отображённым в память. Это удобно для сбора трассировок или журналов для анализа после завершения процесса без подключения медленного клиента к CLI. Новое содержимое автоматически заменяет старое, поэтому последние данные всегда доступны. Записанные в буфер данные будут видны в файле после остановки процесса. Обычно они видны вскоре после записи, но это не гарантируется, поскольку запись не синхронная.

При использовании этого параметра полезный объём области хранения уменьшается на размер “struct ring”, размещаемой в её начале и необходимой для восстановления содержимого. Владельцем создаваемого файла становится пользователь, запускающий процесс; режим доступа — 0600, размер задаётся директивой “size”. При разборе директивы, в том числе при проверке конфигурации, существующий непустой файл сначала переименовывается с добавлением суффикса “.bak”, а прежний файл с суффиксом “.bak” удаляется. Это защищает ценные отладочные данные при немедленной перезагрузке конфигурации или перезапуске процесса и даёт администратору время заметить новый файл “.bak” и при необходимости сохранить его в архиве. После аварийного завершения самые свежие данные находятся в <path>, а после перезапуска службы — в “<path>.bak”. Поэтому общий требуемый объём хранения вдвое больше размера кольцевого буфера. Ошибки ротации файла игнорируются без сообщений. Если резервная копия не нужна, достаточно поместить файл в каталог без права записи.

ПРЕДУПРЕЖДЕНИЕ: эта возможность влияет на стабильность и безопасность. Во-первых, размещение буфера на медленном устройстве, например физическом жёстком диске, может заметно замедлить доступ и даже вызвать аварийное завершение, если за доступ конкурирует слишком много потоков. Во-вторых, изменение области внешним процессом может привести к аварийному завершению haproxy или перезаписи части его собственной памяти данными трассировки. В-третьих, если файловая система заполнится раньше буфера, запись в буфер может вызвать аварийное завершение процесса.

Данные в этом кольцевом буфере структурированы и НЕ предназначены для непосредственного чтения текстовым редактором, хотя большую их часть с трудом можно разобрать. Содержимое файла предназначено только для разработчиков.

description <text>

description <text>

Описание — это необязательная строка описания кольца. Оно будет отображаться на CLI. По умолчанию, <name> используется для заполнения этого поля.

format <format>

format <format>

Формат хранения событий в кольцевом буфере.

Аргументы:

<format> — формат журнала при формировании сообщений syslog.
         Допустимы следующие значения:

  iso     Сообщение содержит только дату ISO и следующий за ней текст.
          PID, имя процесса и имя системы опускаются. Предназначено
          для локального сервера журналов.

  local   Аналог формата syslog rfc3164 без поля hostname.
          Это значение по умолчанию.
          Примечание: параметр "log-send-hostname" меняет значение
          по умолчанию на rfc3164.

  raw     Сообщение содержит только текст. Уровень, PID, дата, время,
          имя процесса и имя системы опускаются. Предназначено для
          контейнеров или разработки, где важность сообщения зависит
          только от файлового дескриптора (stdout/stderr).
          Это значение по умолчанию.

  rfc3164 Формат сообщений syslog RFC3164.
          (https://tools.ietf.org/html/rfc3164)

  rfc5424 Формат сообщений syslog RFC5424.
          (https://tools.ietf.org/html/rfc5424)

  short   Сообщение содержит только уровень в угловых скобках,
          например '<3>', и следующий за ним текст. PID, дата, время,
          имя процесса и имя системы опускаются. Предназначено для
          локального сервера журналов. Формат совместим со средством
          приёма журналов systemd.

 priority Сообщение содержит только уровень вместе с категорией syslog
          в угловых скобках, например '<63>', и следующий за ним текст.
          PID, дата, время, имя процесса и имя системы опускаются.
          Предназначено для локального сервера журналов.

  timed   Сообщение содержит только уровень в угловых скобках,
          например '<3>', затем дату ISO и текст. PID, имя процесса
          и имя системы опускаются. Предназначено для локального
          сервера журналов.

maxlen <length>

maxlen <length>

Максимальная длина сообщения о событии, хранящегося в кольце, включая сформированный заголовок. Если длина сообщения о событии превышает <length>, оно будет обрезано до этой длины.

server <name> <address> [param*]

server <name> <address> [param*]

Настраивает сервер syslog по tcp для пересылки сообщений из кольцевого буфера. Поддерживаются все параметры “server” из пункта 5.2. Некоторые из них не имеют смысла для секций “ring”. Важный момент: добавлять в кольцевой буфер несколько серверов почти бессмысленно, поскольку каждый из них получает одну и ту же копию его содержимого, и буфер продвигается со скоростью самого медленного сервера. Если один сервер не отвечает, старые сообщения нельзя будет удалять, что может заблокировать добавление новых. Для отправки сообщений нескольким серверам следует использовать отдельный кольцевой буфер для каждого сервера журналирования, а не привязывать несколько серверов к одному буферу. Специальная директива сервера “log-proto” задаёт протокол отправки сообщений.

size <size>

size <size>

Необязательный размер кольцевого буфера в байтах. По умолчанию равен BUFSIZE.

timeout connect <timeout>

timeout connect <timeout>

Задаёт максимальное время ожидания успешного установления соединения с сервером.

Аргументы:

<timeout> — тайм-аут, по умолчанию в миллисекундах. Можно использовать
          и другие единицы, добавляя их обозначение после числа,
          как объяснено в начале документа.

timeout server <timeout>

timeout server <timeout>

Задаёт максимальное время нахождения ожидающих отправки данных в выходном буфере.

Аргументы:

<timeout> — тайм-аут, по умолчанию в миллисекундах. Можно использовать
          и другие единицы, добавляя их обозначение после числа,
          как объяснено в начале документа.

Пример:

global
    log ring@myring local7

ring myring
    description "My local buffer"
    format rfc5424
    maxlen 1200
    size 32764
    timeout connect 5s
    timeout server 10s
    server mysyslogsrv 127.0.0.1:6514 log-proto octet-count

12.6. Пересылка журналов

Можно объявить одну или несколько секций пересылки журналов. HAProxy будет пересылать все полученные сообщения журналов серверам из заданного списка.

log-forward <name>

log-forward <name>

Создаёт прокси для пересылки журналов с именем <name>.

backlog <conns>

backlog <conns>

Сообщает системе желаемый приблизительный размер очереди ожидающих принятия соединений.

bind <addr> [param*]

bind <addr> [param*]

Настраивает потоковый слушатель журналов, принимающий сообщения для пересылки. Поддерживаются параметры “bind” из раздела 5.1, включая ssl, хотя некоторые директивы, например “alpn”, могут быть неуместны для syslog поверх TCP. Слушатели поддерживают оба режима из rfc-6587: подсчёт октетов (“Octet Counting”) и непрозрачное разделение сообщений (“Non-Transparent-Framing”).

dgram-bind <addr> [param*]

dgram-bind <addr> [param*]

Настраивает датаграммный слушатель журналов, принимающий сообщения для пересылки. Адрес должен иметь формат IPv4 или IPv6 с последующим портом. Поддерживаются некоторые параметры “bind” из раздела 5.1, в том числе “interface”, “namespace” и “transparent”. Остальные игнорируются без сообщений, поскольку неприменимы к UDP/syslog.

log global

log global
log <target> [len <length>] [format <format>] [sample <ranges>:<sample_size>]
    <facility> [<level> [<minlevel>]]

Настраивает целевые серверы журналов; подробнее см. документацию по прокси. Если формат не указан, HAProxy пытается сохранить формат входящего сообщения. Настроенная категория facility игнорируется, кроме случая, когда во входящем сообщении её нет, а выходной формат требует её наличия. Если во входном формате нет временной метки, но соответствующее поле есть в выходном, HAProxy использует локальную дату.

Пример:

global
   log stderr format iso local7

ring myring
    description "My local buffer"
    format rfc5424
    maxlen 1200
    size 32764
    timeout connect 5s
    timeout server 10s
    # syslog tcp server
    server mysyslogsrv 127.0.0.1:514 log-proto octet-count

log-forward sylog-loadb
    dgram-bind 127.0.0.1:1514
    bind 127.0.0.1:1514
    # all messages on stderr
    log global
    # all messages on local tcp syslog server
    log ring@myring local0
    # load balance messages on 4 udp syslog servers
    log 127.0.0.1:10001 sample 1:4 local0
    log 127.0.0.1:10002 sample 2:4 local0
    log 127.0.0.1:10003 sample 3:4 local0
    log 127.0.0.1:10004 sample 4:4 local0

maxconn <conns>

maxconn <conns>

Задаёт максимальное число одновременных соединений для пересылки журналов. По умолчанию — 10.

timeout client <timeout>

timeout client <timeout>

Задаёт максимальное время бездействия на стороне клиента.

option assume-rfc6587-ntf

option assume-rfc6587-ntf

Предписывает HAProxy всегда считать, что входящие потоки журналов по TCP используют непрозрачное разделение сообщений. Это упрощает логику разделения и обеспечивает единообразную обработку, особенно при некорректных начальных символах.

option dont-parse-log

option dont-parse-log

Позволяет HAProxy пересылать сообщения syslog без разбора и изменения структуры. Это удобно для сообщений, которые могут не соответствовать обычным форматам. Параметр следует сочетать с настройкой format raw у целевых получателей журналов, чтобы сохранить исходное содержимое сообщения.

option host { replace | fill | keep | append }

option host { replace | fill | keep | append }

Задаёт стратегию обработки поля hostname в секции log-forward для исходящих сообщений syslog в форматах rfc3164 или rfc5424.

  replace Если во входящем сообщении уже есть поле hostname, его значение
          заменяется исходным IP-адресом отправителя.
          Если значения поля hostname нет (например, во входящем сообщении
          rfc5424 стоит '-' либо сообщение не соответствует rfc3164 или
          rfc5424), в поле hostname подставляется исходный IP-адрес
          отправителя.

  fill    Если во входящем сообщении уже есть значение поля hostname,
          оно сохраняется.
          Если значения поля hostname нет (например, во входящем сообщении
          rfc5424 стоит '-' либо сообщение не соответствует rfc3164 или
          rfc5424), в поле hostname подставляется исходный IP-адрес
          отправителя.
          (Это значение по умолчанию.)

  keep    Если во входящем сообщении уже есть значение поля hostname,
          оно сохраняется.
          Если значения поля hostname нет, задаётся 'localhost' (rfc3164)
          или '-' (rfc5424).

  append  Если во входящем сообщении уже есть значение поля hostname,
          к нему добавляются запятая и IP-адрес отправителя.
          Если значения поля hostname нет, используется исходный IP-адрес
          отправителя.

Для всех перечисленных вариантов, если исходный IP-адрес отправителя недоступен, например при сокете UNIX/ABNS, применяется стратегия “keep”.

Этот параметр имеет смысл только для целевого формата журнала rfc3164 или rfc5424. В остальных случаях он не даёт видимого эффекта.

12.7. Хранилище сертификатов

HAProxy использует внутренний механизм хранения для загрузки и хранения сертификатов, используемых в конфигурации. Этот механизм хранения может быть настроен с помощью секции “crt-store”. Она позволяет настроить определения сертификатов и указать, какие файлы должны быть загружены в неё. Определение сертификата должно быть записано до его использования в других частях конфигурации.

crt-store [<name>]

Секция “crt-store” принимает необязательное имя. Если оно задано, на каждый сертификат этого хранилища необходимо ссылаться как “@<name>/<crt>” или “@<name>/<alias>”.

Файлы в хранилище сертификатов также можно обновлять динамически через CLI. См. “set ssl cert” в разделе 9.3 руководства по управлению.

В секции “crt-store” поддерживаются следующие ключевые слова:

  • crt-base
  • key-base
  • load

crt-base <dir>

crt-base <dir>

Задаёт каталог по умолчанию для загрузки сертификатов SSL, если в директивах “crt” указан относительный путь. Абсолютный путь имеет приоритет: “crt-base” для него игнорируется. При использовании в crt-store значение crt-base из секции global игнорируется.

key-base <dir>

key-base <dir>

Задаёт каталог по умолчанию для загрузки закрытых ключей SSL, если в директивах “key” указан относительный путь. Абсолютный путь имеет приоритет: “key-base” для него игнорируется. При использовании в crt-store значение key-base из секции global игнорируется.

load [crt <filename>] [param*]

load [crt <filename>] [param*]

Загружает файлы SSL в хранилище сертификатов. Список параметров приведён в разделе «12.7.1. Параметры загрузки».

Пример:

crt-store
    load crt "site1.crt" key "site1.key" ocsp "site1.ocsp" alias "site1"
    load crt "site2.crt" key "site2.key"

frontend in2
    bind *:443 ssl crt "@/site1" crt "site2.crt"

crt-store web
    crt-base /etc/ssl/certs/
    key-base /etc/ssl/private/
    load crt "site3.crt" alias "site3"
    load crt "site4.crt" key "site4.key"

frontend in2
    bind *:443 ssl crt "@/site1" crt "site2.crt"  crt "@web/site3" crt "@web/site4.crt"

12.7.1. Параметры загрузки

Загружает файлы SSL в хранилище сертификатов. Ключевое слово load принимает несколько параметров, перечисленных ниже. Они также допустимы в crt-list.

crt <filename>

crt <filename>

Обязательный аргумент. Загружает файл PEM, который должен содержать публичный сертификат, а также может содержать промежуточные сертификаты и закрытый ключ. Если закрытого ключа в файле нет, его можно задать ключевым словом “key”.

acme <string>

acme <string>

Этот параметр позволяет настроить протокол ACME для заданного сертификата. Это экспериментальная функция, требующая ключевого слова “expose-experimental-directives” в секции global.

Ключевое слово “acme” в crt-store позволяет запуститься без готового сертификата на диске. До получения сертификата ACME используется временная пара ключей. Это поведение доступно только в crt-store: ни строка crt-list, ни строка ssl-f-use не дают такого результата без предварительного объявления crt-store.

См. также раздел 12.8 (“ACME”) и “domains” в этом разделе.

alias <string>

alias <string>

Необязательный аргумент. Задаёт псевдоним сертификата для ссылок на него в конфигурации. При обращении из других частей конфигурации перед псевдонимом должен стоять префикс ‘@/’.

domains <string>

domains <string>

Задаёт список доменов для сертификатов ACME. Первый домен используется как CN. Домены в списке разделяются запятыми.

См. также раздел 12.8 (“ACME”) и “acme” в этом разделе.

Пример:

load crt "example.com.pem" acme LE domains "bar.example.com,foo.example.com"

ips <string>

ips <string>

Задаёт список IP-адресов, включаемых в сертификат ACME как IP SAN. Адреса в списке разделяются запятыми.

Создание сертификата с IP-адресами может потребовать использования профиля “shortlived”.

См. также раздел 12.8 (“ACME”), “acme” и “domains” в этом разделе.

Пример:

load crt "server.pem" acme LE ips "192.0.2.1,2001:db8::1"

key <filename>

key <filename>

Необязательный аргумент. Загружает закрытый ключ в формате PEM. Если ключ уже задан в “crt”, он будет заменён.

ocsp <filename>

ocsp <filename>

Необязательный аргумент. Загружает ответ OCSP в формате DER. Ответ можно обновлять через CLI.

issuer <filename>

issuer <filename>

Необязательный аргумент. Загружает сертификат издателя OCSP в формате PEM. Сертификат издателя необходим, чтобы определить, к какому сертификату относится ответ OCSP. Если его нет в файле “crt”, этот аргумент позволяет загрузить его из отдельного файла.

sctl <filename>

sctl <filename>

Необязательный аргумент. Включает поддержку расширения TLS Certificate Transparency (RFC6962). Файл должен содержать корректный список подписанных временных меток сертификатов (Signed Certificate Timestamp List), описанный в RFC. При разборе проверяется базовый синтаксис, но подписи не проверяются.

ocsp-update [ off | on ]

ocsp-update [ off | on ]

При значении ‘on’ включает автоматическое обновление ответов OCSP, иначе отключает его. По умолчанию — ‘off’. Для автоматического обновления OCSP в строке bind можно задать этот параметр в crt-store либо глобальный параметр “tune.ocsp-update.mode”. Если один сертификат используется в нескольких crt-lists с разными значениями ‘ocsp-update’, возникает ошибка. Такая же ошибка возникает, если сертификат в строке bind наследует глобальный параметр, а в crt-list для него явно задано несовместимое значение ‘ocsp-update’.

Примеры:

Вот пример конфигурации, включающей его с помощью crt-list:

haproxy.cfg:

frontend fe
    bind :443 ssl crt-list haproxy.list

haproxy.list:

server_cert.pem [ocsp-update on] foo.bar

Вот пример конфигурации, включающей его с использованием crt-store:

haproxy.cfg:

crt-store
  load crt foobar.pem ocsp-update on

frontend fe
    bind :443 ssl crt foobar.pem

При значении ‘on’ HAProxy пытается получить ответ ocsp, если в сертификате фронтенда найден uri ocsp. Единственное ограничение режима — издатель сертификата должен быть известен, чтобы можно было сформировать OCSP certid. Каждый ответ OCSP обновляется не реже раза в час, а если его срок действия истекает раньше — чаще. Минимальный интервал остаётся равным 5 минутам, чтобы не обновлять слишком часто ответы с очень коротким сроком действия или вообще без ‘Next Update’. Из-за этого ограничения при автоматическом обновлении ‘on’ любой ответ OCSP, загруженный при инициализации, обновится не раньше чем через 5 минут, даже если истекает до now+5m. Обычно это не должно создавать серьёзных затруднений: при загрузке во время инициализации ответ OCSP обязан быть действительным, с будущим сроком истечения, поэтому столь быстрое истечение маловероятно. Если же в сертификате указан OCSP uri, а ответа OCSP ещё нет, значение ‘on’ обеспечивает его автоматическое получение сразу после инициализации. Минимальную и максимальную задержки по умолчанию, соответственно 5 минут и 1 час, можно настроить глобальными параметрами “ocsp-update.maxdelay” и “ocsp-update.mindelay”.

При каждом обновлении ответа OCSP автоматической задачей или командой CLI “update ssl ocsp-response” формируется отдельная строка журнала. Её специальный формат содержит заголовок “<OCSP-UPDATE>”, затем сведения об OCSP: путь к соответствующему сертификату фронтенда, числовой и текстовый статусы обновления, число неудачных и успешных обновлений этого ответа. Полный список кодов и сообщений об ошибках приведён в описании команды CLI “show ssl ocsp-updates”. Строка выводится независимо от успеха обновления. Запрос и ответ OCSP передаются через экземпляр http_client с параметром dontlog-normal; при ошибке, например недоступности сервера OCSP, он использует обычный формат журнала HTTP. В таком случае рядом с обычной строкой OCSP, скорее всего со статусом “HTTP error”, появляется ещё одна строка со сведениями об HTTP. При ошибке именно уровня HTTP, например недоступности сервера OCSP, дополнительная строка соответствует обычному HTTP log-format. Ниже приведены примеры: сначала успешное обновление OCSP, затем ошибка HTTP с двумя разными строками. Для удобства чтения строки разбиты, а URL сокращён:

<133>Mar  6 11:16:53 haproxy[14872]: <OCSP-UPDATE> /path_to_cert/foo.pem 1 \
        "Update successful" 0 1

<133>Mar  6 11:18:55 haproxy[14872]: <OCSP-UPDATE> /path_to_cert/bar.pem 2 \
        "HTTP error" 1 0
<133>Mar  6 11:18:55 haproxy[14872]: -:- [06/Mar/2023:11:18:52.200] \
        <OCSP-UPDATE> -/- 2/0/-1/-1/3009 503 217 - - SC-- 0/0/0/0/3 0/0 {} \
        "GET http://127.0.0.1:12345/MEMwQT HTTP/1.1"

Устранение неполадок: при использовании сертификатов Let’s Encrypt часто возникает ошибка, если DNS возвращает адрес IPv6, а в системе нет подходящего исходящего маршрута IPv6. В этом случае можно создать маршрут или задать “httpclient.resolvers.prefer ipv4” в секции global. При ошибке “OCSP response check failure” следует проверить корректность предоставленного сертификата издателя. После общего сообщения в скобках может появиться более точное описание. Это возможно для ошибок “OCSP response check failure” и “Error during insertion”.

jwt [ off | on ]

jwt [ off | on ]

При значении ‘on’ разрешает использовать этот сертификат для проверки или расшифровки JWT преобразователями “jwt_verify_cert”, “jwt_decrypt_cert” и “jwt_decrypt”. По умолчанию — ‘off’.

При значении ‘on’ для сертификата команда CLI “del ssl cert” не работает. Для удаления сертификат не должен использоваться ни в рукопожатиях SSL, ни для проверки JWT.

Эту опцию можно изменить в режиме работы с помощью команд “add ssl jwt” и “del ssl jwt” CLI. См. также команду “show ssl jwt” CLI.

generate-dummy [ off | on ]

generate-dummy [ off | on ]

При значении ‘on’ разрешает генерацию закрытого ключа и его самоподписанного сертификата во время разбора конфигурации. Это может пригодиться, например, при тестировании без готового сертификата. Параметры “keytype”, “bits” и “curves” позволяют настроить закрытый ключ. По умолчанию, если параметр не задан, используется ‘off’. См. также “keytype”, “bits” и “curves”.

keytype [ RSA | ECDSA ]

keytype [ RSA | ECDSA ]

Позволяет выбрать тип закрытого ключа для генерации самоподписанного сертификата при разборе конфигурации, если для сертификата задано “generate-dummy” со значением ‘on’. По умолчанию — ‘RSA’. См. также “generate-dummy”.

bits <number>

bits <number>

Задаёт число бит для генерации самоподписанного сертификата RSA, если для него “generate-dummy” установлен в ‘on’, а “keytype” — в ‘RSA’. По умолчанию — 2048. См. также “generate-dummy”.

curves <string>

curves <string>

Задаёт кривые для самоподписанного сертификата, если “generate-dummy” установлен в ‘on’, а “keytype” — в ‘ECDSA’. По умолчанию — ‘P-384’.

12.8. ACME

acme <name>

Протокол ACME может быть настроен с помощью секции “acme”. Секция принимает аргумент “<name>”, который используется для привязки сертификата к секции.

Секция ACME позволяет настроить HAProxy как клиента ACMEv2. Эта функция является экспериментальной, что означает, что “expose-experimental-directives” должен быть указан в глобальной секции, чтобы можно было использовать эту функцию.

Руководство доступно на HAProxy wiki https://github.com/haproxy/wiki/wiki/ACME:--native-haproxy

Текущие ограничения:

- Возможность ограничена проверками http-01, dns-01 и dns-persist-01

- Возможность ограничена проверками http-01, dns-01 и dns-persist-01

на данный момент. Проверка http-01 полностью выполняется HAProxy, но dns-01 и dns-persist-01 требуют dataplaneAPI либо другого инструмента третьей стороны для обращения к API провайдера DNS. Для dns-persist-01 запись TXT достаточно задать один раз, поэтому её можно установить вручную, без дополнительного инструмента.

- Можно запуститься без готового сертификата на диске. Для этого

- Можно запуститься без готового сертификата на диске. Для этого

сертификат должен быть настроен в crt-store. При использовании ключевого слова “acme” в crt-store до получения сертификата ACME применяется временная пара ключей.

- Текущая архитектура HAProxy неблокирующая; обращение к диску

- Текущая архитектура HAProxy неблокирующая; обращение к диску

после загрузки конфигурации не предполагается, поскольку может заблокировать цикл событий и обработку трафика в том же потоке. Поэтому созданные HAProxy сертификаты и ключи необходимо выгружать извне, вызывая “dump ssl cert” через сокет статистики. Выгрузку можно автоматизировать с помощью dataplaneAPI или скрипта haproxy-dump-certs из каталога admin/cli/.

Планировщик ACME запускается вместе с HAProxy. Он перебирает сертификаты и запускает задачу продления ACME, когда notAfter проходит порог curtime + (notAfter - notBefore) / 12; если notBefore не задан, используется 7 дней. Затем планировщик засыпает и просыпается через 12 часов. Задачу продления можно запустить вручную командой “acme renew”. См. также “acme status” в руководстве по управлению.

Следующие ключевые слова доступны в секции ACME:

account-key <filename>

account-key <filename>

Задаёт путь к ключу учётной записи. Ключ необходимо создать до запуска HAProxy. Если ключевое слово account не используется, секция acme пытается загрузить файл “<name>.account.key”, названный по имени секции. Если файла нет, HAProxy создаёт его с параметрами из секции acme.

Закрытый ключ RSA также можно создать вручную с помощью openssl:

openssl genrsa -out account.key 2048

Или ключ ecdsa:

openssl ecparam -name secp384r1 -genkey -noout -out account.key

acme-vars <string>

acme-vars <string>

Передаёт произвольные переменные внешнему инструменту настройки DNS, например dataplaneAPI, через получатель “dpapi”. Смысл переменных зависит от инструмента; см. его документацию.

Ключевое слово имеет смысл только для проверок типа “dns-01” или “dns-persist-01”.

См. также: “challenge”, “provider-name”

bits <number>

bits <number>

Задаёт число бит для генерации сертификата RSA. По умолчанию — 2048. Слишком большое значение может вызвать предупреждение, если машина недостаточно производительна. Порог предупреждения настраивается через “warn-blocked-traffic-after”, но длительная блокировка трафика может привести к срабатыванию сторожевого таймера.

challenge <string>

challenge <string>

Принимает тип проверки: он должен быть http-01, dns-01 или dns-persist-01. По умолчанию, если параметр не задан, используется http-01.

dns-persist-01 реализует draft-ietf-acme-dns-persist. В отличие от dns-01, он использует статическую запись TXT по имени “_validation-persist.<domain>”, которая задаётся один раз и не меняется между продлениями сертификата. Запись должна содержать URI учётной записи и может содержать политику. Этот тип проверки не требует доступа на запись к API провайдера DNS при каждом продлении.

challenge-ready <value>[,<value>]*

challenge-ready <value>[,<value>]*

Задаёт условия, которые необходимо выполнить, прежде чем уведомлять сервер ACME о готовности проверки dns-01. Допустимы следующие значения:

cli  — ждёт, пока оператор подтвердит готовность командой CLI
       "acme challenge_ready <crt> domain <domain>" через CLI главного
       процесса или сокет статистики. Внешний инструмент настройки DNS
       может так подтвердить установку записи TXT перед продолжением
       работы HAProxy.

dns  — выполняет предварительную проверку DNS: разрешает запись TXT
       "_acme-challenge.<domain>" через настроенную секцию resolvers
       "default", а не через авторитетные серверы имён. Проверка ACME
       не запрашивается, пока запись TXT не совпадёт с ожидаемым токеном.
       Поэтому на результат может влиять кеш DNS на резолвере. Интервал
       между попытками разрешения задаётся "dns-delay". Этот параметр
       не зависит от команды CLI и не требует вмешательства человека.

       Для dns-01 разрешается запись TXT "_acme-challenge.<domain>",
       которая должна совпадать с ожидаемым токеном. Для dns-persist-01
       разрешается запись TXT "_validation-persist.<domain>", причём
       проверяется только её наличие.

delay — начальное ожидание "dns-delay" перед продолжением. Без "dns"
        проверка запрашивается по истечении задержки. В сочетании с "dns"
        начальная задержка применяется до предварительных проверок DNS.

none — нет условий готовности: запрос проверки сразу отправляется
       серверу ACME без ожидания внешнего подтверждения.
       Это значение нельзя сочетать с другими.

Несколько значений можно объединить через запятую. Если задано несколько условий, HAProxy сначала ждёт подтверждения через CLI (“cli”), затем выдерживает начальную задержку (“delay”), а после выполняет предварительные проверки DNS (“dns”).

Параметр совместим только с проверками типа dns-01 и dns-persist-01.

Когда “challenge” установлен в “dns-01” и этот параметр не настроен, значение по умолчанию — “cli”.

Когда “challenge” установлен в “dns-persist-01” и этот параметр не настроен, значение по умолчанию равно “dns,delay”.

Если “challenge” установлен в “dns-persist-01”, перед оценкой условий challenge-ready всегда выполняется пробная проверка DNS. Запись TXT “_validation-persist.<domain>” задаётся один раз и не меняется между продлениями, поэтому при продлении HAProxy проверяет, существует ли она уже. Если проверка успешна для всех доменов, запрос проверки сразу отправляется серверу ACME без этапов challenge-ready (cli, delay, dns). При неудаче HAProxy переходит к обычной последовательности challenge-ready.

Пример:

# Wait for CLI confirmation, then verify DNS propagation
challenge-ready cli,dns

contact <string>

contact <string>

Электронная почта для связи, которая будет привязана к ключу учетной записи в CA.

curves <string>

curves <string>

При использовании типа ключа ECDSA настройте кривые. По умолчанию — P-384.

directory <string>

directory <string>

Задаёт URL каталога центра сертификации (CA), используемого этой секцией acme. Параметр обязателен: URL по умолчанию отсутствует.

Пример:

directory https://acme-staging-v02.api.letsencrypt.org/directory

dns-delay <time>

dns-delay <time>

Настройте задержку, используемую условиями “challenge-ready” «delay» и «dns». Значение — время, выраженное в формате времени HAProxy (например, «5m», «300s»). По умолчанию — 30 секунд.

Её роль зависит от используемых условий “challenge-ready”:

delay     — проверка запрашивается по истечении задержки,
            без предварительной проверки DNS.

dns       — интервал между последовательными попытками разрешения DNS.
            Первая попытка выполняется сразу, без начального ожидания.

dns+delay — начальное ожидание перед первой попыткой разрешения DNS
            и интервал между последующими попытками.

Разрешение имён выполняется через настроенную секцию resolvers с именем “default”, а не через авторитетные серверы имён. Поэтому на результат по-прежнему может влиять кеш DNS на резолвере.

dns-timeout <time>

dns-timeout <time>

Если “challenge-ready” включает “dns”, задаёт максимальное время на успешное разрешение записи TXT до прерывания проверки. Значение указывается в формате времени HAProxy, например “10m” или “600s”. По умолчанию — 600 секунд.

Отсчёт начинается с первой попытки разрешения DNS после начальной задержки “dns-delay”. Если следующая попытка должна начаться уже после истечения тайм-аута, проверка прерывается с ошибкой. Это предотвращает бесконечные повторные попытки при проблемах распространения записи DNS.

См. также: “dns-delay”

keytype <string>

keytype <string>

Настройте тип ключа, который будет сгенерирован. Значение может быть либо “RSA”, либо “ECDSA”. Вы также можете настроить “curves” для ECDSA и количество “bits” для RSA. По умолчанию генерируются ключи EC384.

map <map>

map <map>

Настройте карту, которая будет использоваться для хранения токена (ключ) и отпечатка (значение), что позволяет отвечать на вызов при использовании нескольких аккаунтов. Задача acme добавит записи до проверки вызова и удалит их в конце выполнения задачи.

profile <string>

profile <string>

Запрашивает у центра сертификации определённый профиль сертификата, добавляя поле “profile” в запрос newOrder. Реализует draft-ietf-acme-profiles.

Имена профилей — короткие идентификаторы, зависящие от CA, например “classic” и “shortlived”. Если профиль задан, его имя передаётся без изменений в JSON-теле запроса newOrder. CA может проигнорировать запрос или вернуть ошибку, если профиль не поддерживается. Если профиль не задан, поле profile не включается и CA применяет политику выдачи по умолчанию.

См. https://letsencrypt.org/docs/profiles/ для профилей Let’s Encrypt.

Пример:

# Request short-lived certificates
profile shortlived

provider-name <string>

provider-name <string>

Задаёт имя провайдера DNS, передаваемое внешнему инструменту настройки DNS, например dataplaneAPI, через получатель “dpapi”. Допустимые значения зависят от инструмента; см. его документацию.

Ключевое слово имеет смысл только для проверок типа “dns-01” или “dns-persist-01”.

См. также: “challenge”, “acme-vars”

reuse-key { on | off }

reuse-key { on | off }

Если установлено “on”, HAProxy не генерирует новый приватный ключ и сохраняет предыдущий. Ротация приватных ключей рекомендуется; при включении этой опции рекомендуется регулярно вручную пересоздавать ключи.

Параметр может пригодиться для ключей RSA больше 2048, генерация которых занимает время и может замедлить выполняющий её поток.

Использование одного и того же ключа может быть полезным при работе с кэшем вашего ACME сервера, так как это поможет получить соответствующий действительный сертификат для текущего ключа.

Значение по умолчанию — “off”.

Пример:

global
    expose-experimental-directives
    httpclient.resolvers.prefer ipv4

frontend in
    bind *:80
    bind *:443 ssl
    http-request return status 200 content-type text/plain lf-string "%[path,field(-1,/)].%[path,field(-1,/),map(virt@acme)]\n" if { path_beg '/.well-known/acme-challenge/' }
    ssl-f-use crt "foo.example.com.pem.rsa"   acme LE1 domains "foo.example.com.pem,bar.example.com"
    ssl-f-use crt "foo.example.com.pem.ecdsa" acme LE2 domains "foo.example.com.pem,bar.example.com"

acme LE1
    directory https://acme-staging-v02.api.letsencrypt.org/directory
    account-key /etc/haproxy/letsencrypt.account.key
    contact john.doe@example.com
    challenge http-01
    keytype RSA
    bits 2048
    map virt@acme

acme LE2
    directory https://acme-staging-v02.api.letsencrypt.org/directory
    account-key /etc/haproxy/letsencrypt.account.key
    contact john.doe@example.com
    challenge http-01
    keytype ECDSA
    curves P-384
    map virt@acme

eab-key-id <filename>

eab-key-id <filename>

Укажите путь к файлу идентификатора ключа EAB. Средство аутентификации предоставляется Центром сертификации и должно быть размещено на указанном пути до запуска HAProxy. Оно используется только при создании аккаунта.

Файл должен содержать простую строку ASCII.

Учётные данные EAB требуются только при первоначальном создании учётной записи ACME; впоследствии их можно удалить из конфигурации или очистить соответствующие файлы. Пустой файл игнорируется без сообщения. Пробельные символы не игнорируются, за исключением завершающего перевода строки.

См. также: “eab-mac-key”, “eab-mac-alg”

eab-mac-key <filename>

eab-mac-key <filename>

Настройте путь к файлу ключа EAB MAC. Ключ предоставляется CA и должен быть размещён по указанному пути до запуска HAProxy. Используется только при создании учётной записи.

Файл должен содержать закодированный в формате base64url ключ MAC.

Учётные данные EAB требуются только при первоначальном создании учётной записи ACME; впоследствии их можно удалить из конфигурации или очистить соответствующие файлы. Пустой файл игнорируется без сообщения. Пробельные символы не игнорируются, за исключением завершающего перевода строки.

См. также: “eab-key-id”, “eab-mac-alg”

eab-mac-alg { HS256 | HS384 | HS512 }

eab-mac-alg { HS256 | HS384 | HS512 }

Настройте алгоритм MAC, используемый для подписи EAB. По умолчанию — HS256. Ключ EAB MAC должен быть достаточно велик, чтобы поддерживать заданный алгоритм MAC. Не все Центры сертификации поддерживают алгоритмы, кроме HS256.

См. также: “eab-key-id”, “eab-mac-key”

12.9. Проверки работоспособности

Возможно, глобально объявить несколько проверок работоспособности, которые могут быть использованы серверами во всей конфигурации, заменяя локальную конфигурацию прокси.

healthcheck <name>

healthcheck <name>

Создаёт проверку работоспособности с именем <name>. Имя должно быть уникальным. Его следует использовать в строке server для ссылки на конкретную секцию проверки работоспособности.

type <type>

type <type>

Определяет тип проверки работоспособности. Этот параметр обязательный. Поддерживаются следующие типы проверки работоспособности:

* tcp-check
* httpchk
* ssl-hello-chk
* smtpchk
* pgsql-check
* redis-check
* mysql-check
* ldap-check
* spop-check

Каждый тип использует те же параметры, если они есть, что и соответствующий параметр прокси. Например, для “httpchk” можно задать метод, uri и другие значения:

Примеры:

   healthcheck my-http-check
type httpchk GET /health HTTP/1.1 %[srv_name]

См. также: “option tcp-check”, “option httpchk”, “option ssl-hello-chk”, “option smtpchk”, “option mysql-check”, “option pgsql-check”, “option redis-check”, “option ldap-check” и “option spop-check”

http-check comment <string>

http-check comment <string>
http-check connect [default] [port <expr>] [addr <ip>] [send-proxy]
                   [via-socks4] [ssl] [sni <sni>] [alpn <alpn>] [linger]
                   [proto <name>] [comment <msg>]
http-check disable-on-404
http-check expect [min-recv <int>] [comment <msg>]
                  [ok-status <st>] [error-status <st>] [tout-status <st>]
                  [on-success <fmt>] [on-error <fmt>] [status-code <expr>]
                  [!] <match> <pattern>
http-check send [meth <method>] [{ uri <uri> | uri-lf <fmt> }>] [ver <version>]
                [hdr <name> <fmt>]* [{ body <string> | body-lf <fmt> }]
                [comment <msg>]
http-check send-state
http-check set-var(<var-name>[,<cond>...]) <expr>
http-check set-var-fmt(<var-name>[,<cond>...]) <fmt>
http-check unset-var(<var-name>)

Добавляет правило http-check для проверки работоспособности “httpchk”. Синтаксис совпадает с соответствующими директивами прокси; подробности приведены в документации по ним.

tcp-check comment <string>

tcp-check comment <string>
tcp-check connect [default] [port <expr>] [addr <ip>] [send-proxy] [via-socks4]
                  [ssl] [sni <sni>] [alpn <alpn>] [linger]
                  [proto <name>] [comment <msg>]
tcp-check expect [min-recv <int>] [comment <msg>]
                 [ok-status <st>] [error-status <st>] [tout-status <st>]
                 [on-success <fmt>] [on-error <fmt>] [status-code <expr>]
                 [!] <match> <pattern>
tcp-check send <data> [comment <msg>]
tcp-check send-lf <fmt> [comment <msg>]
tcp-check send-binary <hexstring> [comment <msg>]
tcp-check send-binary-lf <hexfmt> [comment <msg>]
tcp-check set-var(<var-name>[,<cond>...]) <expr>
tcp-check set-var-fmt(<var-name>[,<cond>...]) <fmt>
tcp-check unset-var(<var-name>)

Добавляет правило tcp-check для проверки работоспособности “tcp-check”. Синтаксис совпадает с соответствующими директивами прокси; подробности приведены в документации по ним.

22 - 1. Предварительные требования

Необходимые знания по администрированию UNIX и устранению неполадок

В этом документе описаны запуск, остановка, управление HAProxy и устранение неполадок, а также некоторые известные ограничения и подводные камни, которых следует избегать. Настройка HAProxy здесь не рассматривается (об этом читайте в configuration.txt ).

Предполагается, что читатель обладает достаточными навыками администрирования UNIX-подобной операционной системы, ежедневно использует командную оболочку и знаком с утилитами устранения неполадок, такими как strace и tcpdump.

23 - 2. Архитектура HAProxy

Процесс, потоки, цикл событий, chroot, журналы, часы и модель TCP-прокси

HAProxy — многопоточный неблокирующий демон с событийной архитектурой. Это означает, что для планирования всех своих действий он использует мультиплексирование событий, вместо того чтобы полагаться на системный планировщик при переключении между ними. Чаще всего он работает как один процесс, поэтому вывод “ps aux” в системе показывает только один процесс “haproxy”, кроме случаев, когда идёт плавная перезагрузка конфигурации и старый процесс завершает работу параллельно с новым. Поэтому его работу всегда легко отслеживать с помощью утилиты strace. Чтобы масштабироваться с ростом числа доступных процессоров, по умолчанию haproxy запускает по одному рабочему потоку на каждый процессор, на котором ему разрешено выполняться. Если явно не задана иная конфигурация, входящий трафик распределяется между всеми этими потоками, каждый из которых выполняет один и тот же цикл событий. Особое внимание уделяется сведению зависимостей между потоками к строгому минимуму, чтобы добиться масштабируемости, близкой к линейной. Это имеет ряд следствий, в частности каждое соединение обслуживается одним потоком. Поэтому для использования всей доступной вычислительной мощности необходимо как минимум столько же соединений, сколько потоков, что почти всегда обеспечивается.

HAProxy спроектирован так, чтобы при запуске изолировать себя в окружении chroot, где он вообще не может обращаться к файловой системе. Это относится и к библиотекам, от которых он зависит (например, libc, libssl и т. д.). Непосредственное следствие: работающий процесс не может повторно загрузить файл конфигурации, чтобы применить изменения; вместо этого запускается новый процесс с обновлённым файлом конфигурации. Есть и менее очевидные последствия: некоторые файлы часовых поясов или настройки разрешения имён, к которым libc может попытаться обратиться во время выполнения, не будут найдены, хотя обычно этого происходить не должно, поскольку после запуска они не нужны. Полезное следствие этого принципа — процесс HAProxy совершенно не сохраняет состояние, и после его принудительного завершения не нужна очистка: любой действенный способ завершения приведёт к правильному результату.

HAProxy не записывает файлы журналов, а использует стандартный протокол syslog для отправки записей на удалённый сервер (который часто находится на той же системе).

Для соблюдения тайм-аутов HAProxy использует внутренние часы, которые основаны на системном времени, но корректируют неожиданные отклонения. Для этого ограничивается время ожидания события в poll() и измеряется фактическая длительность ожидания. На практике оно никогда не превышает одну секунду. Поэтому при запуске strace для полностью бездействующего процесса видны периодические вызовы poll() (или одного из его вариантов), заключённые между двумя вызовами gettimeofday(). Это нормально, совершенно безвредно и настолько дёшево, что создаваемая нагрузка совершенно незаметна в масштабе системы; ничего необычного здесь нет. Пример:

16:35:40.002320 gettimeofday({1442759740, 2605}, NULL) = 0
16:35:40.002942 epoll_wait(0, {}, 200, 1000) = 0
16:35:41.007542 gettimeofday({1442759741, 7641}, NULL) = 0
16:35:41.007998 gettimeofday({1442759741, 8114}, NULL) = 0
16:35:41.008391 epoll_wait(0, {}, 200, 1000) = 0
16:35:42.011313 gettimeofday({1442759742, 11411}, NULL) = 0

HAProxy — TCP-прокси, а не маршрутизатор. Он работает с установленными соединениями, проверенными ядром, а не с пакетами какого-либо вида или сокетами в других состояниях (например, не с SYN_RECV и не с TIME_WAIT), хотя их наличие может помешать привязке к порту. Приём входящих соединений и установление исходящих он поручает системе. Непосредственное следствие: пакеты, наблюдаемые с двух сторон пересылаемого соединения, не связаны друг с другом и могут различаться размером, количеством и даже семейством. Поскольку соединение можно принять только с сокета в состоянии LISTEN, все прослушиваемые сокеты обязательно видны при использовании утилиты “netstat” для отображения прослушивающих сокетов. Пример:

# netstat -ltnp

Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1629/sshd tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 2847/haproxy tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 2847/haproxy

24 - 3. Запуск HAProxy

Синтаксис и параметры командной строки, загрузка конфигурации и поведение при запуске

HAProxy запускается путём вызова программы “haproxy” с передачей на командной строке нескольких аргументов. Фактический синтаксис следующий:

$ haproxy [<options>]*

где [<options>]* — произвольное число параметров. Параметр всегда начинается с ‘-’, за которым следуют одна или несколько букв и, возможно, один или несколько дополнительных аргументов. Без параметров HAProxy показывает страницу справки с перечнем поддерживаемых параметров. Доступные параметры могут немного различаться в зависимости от операционной системы. Многие из них имеют аналоги в секции “global”. В таком случае командная строка всегда имеет приоритет над файлом конфигурации, что позволяет быстро принудительно задать настройки, не изменяя конфигурационные файлы. Текущий список параметров:

-- <cfgfile>*

-- <cfgfile>*

все аргументы, следующие за “–”, являются путями к файлу/директории конфигурации, которые должны быть загружены и обработаны в порядке объявления. Это особенно полезно при использовании оболочки для загрузки большого количества файлов, упорядоченных по числовому значению. См. также “-f”. Разница между “–” и “-f” заключается в том, что перед каждым именем файла должно стоять одно “-f”, в то время как перед всеми именами файлов достаточно одного “–”. Оба варианта могут использоваться вместе, порядок аргументов командной строки остаётся действительным. При указании более чем одного файла каждый файл должен начинаться на границе секции, так что первое ключевое слово каждого файла должно быть одним из “global”, “defaults”, “peers”, “listen”, “frontend”, “backend”, и так далее. Файл не может содержать только список серверов, например.

-f <cfgfile|cfgdir>

-f <cfgfile|cfgdir>

добавляет <cfgfile> в список конфигурационных файлов для загрузки. Если <cfgdir> — директория, то все файлы (и только файлы), содержащиеся в ней, добавляются в лексикографическом порядке (используя LC_COLLATE=C), в список конфигурационных файлов для загрузки; добавляются только файлы с расширением “.cfg”, только не скрытые файлы (не начинающиеся с “.”). Конфигурационные файлы загружаются и обрабатываются в порядке их объявления. Данную опцию можно указывать несколько раз для загрузки нескольких файлов. См. также “–”. Разница между “–” и “-f” заключается в том, что перед каждым именем файла необходимо указывать один “-f”, в то время как перед всеми именами файлов достаточно одного “–”. Оба варианта могут использоваться вместе, порядок аргументов командной строки всё ещё применяется. При указании более чем одного файла каждый файл должен начинаться на границе секции, поэтому первое ключевое слово каждого файла должно быть одним из “global”, “defaults”, “peers”, “listen”, “frontend”, “backend” и так далее. Файл не может содержать только список серверов, например.

-C <dir>

-C <dir>

переходит в каталог <dir> перед загрузкой файлов конфигурации. Это удобно при использовании относительных путей. Будьте осторожны с подстановочными знаками после “–”: оболочка раскрывает их ещё до запуска haproxy.

-D

-D

запускать как демон. Процесс отсоединяется от текущего терминала после создания дочернего процесса, и ошибки больше не отображаются в терминале. Это эквивалентно ключу “daemon” в секции “global” конфигурации. Рекомендуется всегда включать его в любых скриптах инициализации, чтобы некорректная конфигурация не мешала загрузке системы.

-L <name>

-L <name>

изменяет имя локального однорангового узла на <name>; по умолчанию используется локальное имя хоста. Применяется только для репликации peers. Чтобы сослаться на имя узла в конфигурационном файле, можно использовать переменную $HAPROXY_LOCALPEER.

-N <limit>

-N <limit>

задаёт для каждого прокси значение maxconn по умолчанию, равное <limit>, вместо встроенного значения (обычно 2000). Полезно только для отладки.

-V

-V

включить режим подробного вывода (отключает режим тишины). Отменяет эффект “-q” или “quiet”.

-W

-W

режим master-worker. Эквивалентен директиве “master-worker” в секции “global” конфигурации. В этом режиме запускается главный процесс (“master”), контролирующий рабочие процессы (“workers”). HAProxy можно перезагрузить напрямую, отправив главному процессу сигнал SIGUSR2. Режим master-worker совместим как с работой на переднем плане, так и с режимом демона. Рекомендуется использовать его при многопроцессном запуске и с systemd.

-Ws

-Ws

Режим master-worker с поддержкой типа службы systemd notify.

-4

-4

принудительно ограничивает DNS-резолверы запросами и приёмом только адресов IPv4 (записей “A”). Это может помочь при проблемах в средах без сквозной связности по обоим стекам. Параметр переопределяет глобальную директиву “dns-accept-family”, принудительно устанавливая её в “ipv4”.

-c

-c

только проверяет файлы конфигурации и завершается, не пытаясь привязаться к портам. Код завершения равен нулю при успехе и ненулевому значению при ошибке. Если есть предупреждения, о них сообщается. По умолчанию сообщение об успехе не выводится. В сочетании с “-V” при успехе выводится сообщение “Configuration file is valid”.

Скрипты должны определять успешность команды по коду завершения.

-cc

-cc

вычисляет условие в том же формате, что используется в условных блоках конфигурации. Код завершения равен нулю, если условие истинно, 1 — если ложно, и 2 — при ошибке.

-d

-d

включает режим отладки. Он отключает режим демона, заставляет процесс оставаться на переднем плане и показывать входящие и исходящие события. Его никогда нельзя использовать в сценарии инициализации.

-dA[file]

-dA[file]

сразу после загрузки конфигурации сохраняет в указанном файле архив tar со всеми зависимостями, обнаруженными при запуске. Это эквивалентно “set-dumpable libs”, но библиотеки сохраняются в файл, а не удерживаются в памяти. Это можно использовать после получения дампа памяти процесса, чтобы передать разработчикам все библиотеки, необходимые для его анализа. Возможность доступна не во всех операционных системах. Настоятельно рекомендуется использовать её с обычными файлами конфигурации, а при ручном запуске — при необходимости с “-c”, чтобы haproxy завершился сразу после сохранения архива, не начиная работу. Пример:

$ haproxy -dA/tmp/libs.tar -c -f /etc/haproxy/haproxy.cfg

-dC[key]

-dC[key]

выводит файл конфигурации. Вывод формируется после разбиения строк на токены, поэтому комментарии удалены, а отступы приведены к единому виду. Если задан ненулевой ключ, строки обрезаются перед чувствительными или конфиденциальными полями, а идентификаторы и адреса хешируются этим ключом по тому же алгоритму, что используется в режиме анонимизации CLI. Поэтому вывод можно безопасно передать разработчику, которому нужно разобраться в дампе, анонимизированном тем же ключом. См. также команду CLI “set anon”.

-dD

-dD

Включает диагностический режим, который выводит дополнительные предупреждения о подозрительных конструкциях конфигурации. Некоторые сообщения препятствуют запуску в режиме “zero-warning”.

Такая диагностика предназначена прежде всего для привлечения внимания человека к потенциальным скрытым проблемам, которые могут быть полностью намеренными. Она может меняться даже внутри стабильной ветки и между машинами с совершенно одинаковой конфигурацией. Поэтому она будет регулярно отмечать допустимые конструкции как подозрительные; её следует использовать только вместе с “-c” для более глубокой диагностики. Её результаты никогда не следует использовать для запрета запуска службы, что происходит при сочетании с “zero-warning” или “-dW”.

-dF

-dF

отключает ускоренную пересылку данных. Этот механизм оптимизирует пересылку, передавая данные напрямую между сторонами без пробуждения потока. Данная директива позволяет отключить оптимизацию. Учтите, что она также отключает механизм tcp splicing в ядре. Команда не предназначена для обычного использования: как правило, разработчики рекомендуют её лишь при сложной отладке.

-dG

-dG

отключает использование getaddrinfo() для разрешения имён хостов в адреса. Параметр можно применять при подозрении, что getaddrinfo() работает неправильно. Он появился из-за множества ошибочных реализаций getaddrinfo() в разных системах, вызывающих труднодиагностируемые аномалии.

-dI

-dI

разрешает небезопасный вызов fork. Эквивалентен “insecure-fork-wanted” в секции global. Может пригодиться при запуске всех reg-тестов с ASAN, которым нужно запускать addr2line через fork для разрешения адресов.

-dK<class[,class]*>

-dK<class[,class]*>

выводит список зарегистрированных ключевых слов каждого класса. Список классов доступен через “-dKhelp”. Для вывода всех классов используется “-dKall”, иначе можно указать выбранные классы из справки через запятую. Формат зависит от класса: например, “cfg” показывает известные ключевые слова конфигурации в формате, похожем на конфигурационный файл, а “smp” — функции извлечения образцов, предварённые матрицей совместимости с наборами правил. Такие данные редко используются человеком напрямую, но очень полезны внешним инструментам, выявляющим новые ключевые слова для автоматического обновления документации, файлов подсветки синтаксиса, парсеров конфигурации, API и т. п. Формат может со временем немного меняться, поэтому настоятельно рекомендуется использовать вывод главным образом для поиска отличий от предыдущих архивов. Учтите, что перечисляются не все ключевые слова: многие появились задолго до создания подсистем регистрации и в них не представлены. Однако новые ключевые слова добавляются только современными механизмами, поэтому вывод позволяет достаточно точно обнаруживать расширение языка. Вывод выполняется только после полного разбора конфигурации, чтобы учесть даже динамически созданные ключевые слова. Удобный способ вывести список и завершиться — выполнить тихую проверку существующей конфигурации:

./haproxy -dKall -q -c -f foo.cfg

Если файла конфигурации нет, “-f /dev/null” также позволяет вывести все ключевые слова по умолчанию. Однако код завершения будет ненулевым из-за отсутствия слушателя, и его придётся игнорировать.

-dL

-dL

выводит список динамических разделяемых библиотек, загруженных к окончанию обработки конфигурации. Обычно в него также входят косвенные зависимости, например загруженные кодом Lua, и сам исполняемый файл. Формат достаточно легко обработать для непосредственного создания архива tar со всеми зависимостями. Поскольку параметр не останавливает запуск программы, рекомендуется использовать его только совместно с “-c” и “-q”: тогда выводится лишь список загруженных объектов либо ничего при ошибке. Кроме того, передавая такой пакет для анализа файла дампа памяти процесса, учитывайте, что большинство библиотек на самом деле являются символическими ссылками, которые необходимо разыменовывать при создании архива:

./haproxy -W -q -c -dL -f foo.cfg | tar -T - -hzcf archive.tgz

При запуске в режиме подробного вывода (-V) также перечисляются диапазоны адресов разделяемых библиотек, если не включён тихий режим (-q).

-dM[<byte>[,]][help|options,...]

-dM[<byte>[,]][help|options,...]

принудительно включает заполнение памяти контрольным байтом и/или меняет другие параметры отладки памяти. При таком заполнении каждая область, выделенная через malloc() или pool_alloc(), перед передачей вызывающей стороне заполняется значением <byte>. Если <byte> не задан, используется 0x50 (‘P’). Это немного замедляет работу, но помогает надёжно воспроизвести ошибки из-за пропущенной инициализации, вызывающие случайные аварийные завершения. Учтите: -dM0 фактически превращает любой malloc() в calloc(). Если применение параметра приводит к появлению или исчезновению проблемы, в haproxy есть ошибка, о которой следует сообщить. Другие параметры можно указывать отдельно либо после запятой, следующей за байтом. Специальный параметр “help” выводит список поддерживаемых параметров и их текущие значения. Каждый параметр отладки можно принудительно включить или отключить. Оптимальные значения обычно выбираются при сборке согласно операционной системе и не требуют изменения без рекомендации разработчика. Поддерживаются следующие параметры отладки (включение/отключение):

  • fail / no-fail:
Включает случайные отказы при выделении памяти совместно с глобальным
параметром "tune.fail-alloc". Используется для поиска мест, где код
не проверяет ошибки. Включение задаёт начальную долю отказов 1%.
  • no-merge / merge:
По умолчанию пулы близкого размера объединяются ради эффективности,
но это усложняет анализ некоторых дампов памяти. Параметр позволяет
отключить объединение, что может немного увеличить потребление памяти.
  • cold-first / hot-first:
Для повышения доли попаданий в кеш CPU по умолчанию при новых выделениях
памяти повторно используются недавно освобождённые, «горячие» объекты.
Это усложняет анализ дампов памяти и может скрывать ошибки обращения
к освобождённой памяти. Параметр позволяет сначала выбирать самые
«холодные» объекты, что может немного повысить нагрузку на CPU.
  • integrity / no-integrity:
Включает проверку целостности выделяемой области памяти: она не должна
измениться с момента последнего освобождения. Лучше всего работает
совместно с "no-merge", "cold-first" и "tag". Включение параметра
немного повышает нагрузку на CPU.
  • backup / no-backup:
Копирует каждый объект при освобождении, чтобы разработчики могли
его исследовать. При выделении памяти также выполняется сравнение,
обнаруживающее изменения после освобождения — признак обращения
к освобождённой памяти. Это удваивает потребление памяти и немного
повышает нагрузку на CPU, как и "integrity". При совместном использовании
с "integrity" содержимое по-прежнему копируется, но сравнение выполняет
только "integrity". Как и "integrity", лучше всего работает вместе
с "no-merge", "cold-first" и "tag".
  • no-global / global:
В зависимости от операционной системы может включаться общий кеш памяти
для всего процесса, если стандартный механизм выделения памяти считается
слишком медленным или неэффективным при работе с потоками. Параметр
позволяет принудительно включить или отключить этот кеш. Его отключение
может повысить нагрузку на CPU при неэффективном механизме выделения,
а включение — увеличить потребление памяти при эффективном механизме.
  • no-cache / cache:
Каждый поток использует очень быстрый локальный кеш объектов для
выделения памяти; по умолчанию он всегда включён. Параметр позволяет
отключить его. Поскольку общий кеш также работает через локальные кеши,
это фактически отключает все кеши: память выделяется непосредственно
стандартным механизмом. Нагрузка на CPU может значительно вырасти,
но на малых системах возможна небольшая экономия памяти.
  • caller / no-caller:
В каждом выделяемом объекте резервируется дополнительное место
для адреса последнего вызова, выделившего или освободившего объект.
Это помогает разработчикам восстановить предшествовавшие события
при анализе дампов памяти и понять причину неожиданного поведения.
  • tag / no-tag:
В каждом выделяемом объекте резервируется дополнительное место для
метки, позволяющей обнаруживать повторное освобождение, освобождение
некорректного объекта и переполнение буфера. Надёжность проверок заметно
повышается ценой 4 или 8 дополнительных байт на каждое выделение памяти.
Обычно это первый шаг при поиске повреждения памяти.
  • poison / no-poison:
Выделенные объекты заполняются фиксированным шаблоном, чтобы в поле,
которое по ошибке забыли инициализировать после добавления, не оказалось
случайного значения, например 0. Такие ошибки обычно воспроизводятся
редко, особенно если пулы не объединяются. Обычно заполнение включают,
передавая значение байта непосредственно в -dM; этот параметр позволяет
включать или отключать использование ранее заданного значения.

-dR

-dR

отключает параметр сокета SO_REUSEPORT для прослушиваемых портов. Эквивалентен директиве “noreuseport” в секции “global”. Может применяться в многопоточных конфигурациях при проблемах распределения нагрузки между потоками haproxy, которые можно наблюдать через top.

-dS

-dS

отключает системный вызов splice(). Эквивалентен директиве “nosplice” в секции “global”. Может применяться при подозрении на неправильную работу splice() или связанные с ним проблемы производительности, а также при просмотре пересылаемых данных через strace: при использовании splice() эти данные не видны.

-dT

-dT

отключает ktls. Эквивалентен директиве “noktls” в секции “global”. В основном полезен при подозрении на ошибку, связанную с ktls.

-dV

-dV

отключает проверку SSL на стороне сервера. Эквивалентен “ssl-server-verify none” в секции “global”. Полезен для воспроизведения проблем рабочей среды за её пределами. Никогда не используйте его в сценарии инициализации: он снижает безопасность SSL-соединений с серверами.

-dW

-dW

Если параметр задан, haproxy откажется запускаться, если при обработке конфигурации было выдано хотя бы одно предупреждение. Это помогает обнаруживать неочевидные ошибки и сохранять конфигурацию аккуратной и переносимой между версиями. Рекомендуется задавать этот параметр в сценариях службы, когда конфигурациями управляют люди, но не рекомендуется применять его к автоматически создаваемым конфигурациям, которые обычно вызывают больше предупреждений. Его можно сочетать с “-c”, чтобы предупреждения приводили к неуспешному результату проверки конфигурации. Он эквивалентен глобальному параметру “zero-warning”.

-dZ

-dZ

отключает пересылку данных в режиме “zero-copy”. Эквивалентен директиве “tune.disable-zero-copy-forwarding” в секции “global”. Может помочь при потере данных или нарушении их целостности, а также при просмотре пересылаемых данных через strace, поскольку отключает и механизм tcp splicing в ядре.

-db

-db

отключает фоновый и многопроцессный режимы. Процесс остаётся на переднем плане. Параметр в основном используется при разработке или небольших тестах: для остановки достаточно Ctrl-C. Никогда не используйте его в сценарии инициализации.

-dc

-dc

включает отладку привязки к CPU. Перед запуском выводится список выбранных и исключённых CPU вместе с их топологией.

-de

-de

отключает механизм опроса “epoll”. Эквивалентен директиве “noepoll” в секции “global”. В основном полезен при подозрении на ошибку этого механизма. В системах с поддержкой epoll вместо него обычно используется механизм “poll”.

-dk

-dk

отключает механизм опроса “kqueue”. Эквивалентен директиве “nokqueue” в секции “global”. В основном полезен при подозрении на ошибку этого механизма. В системах с поддержкой kqueue вместо него обычно используется механизм “poll”.

-dp

-dp

отключает механизм опроса “poll”. Эквивалентен директиве “nopoll” в секции “global”. В основном полезен при подозрении на ошибку этого механизма. В системах с поддержкой poll вместо него обычно используется “select”, который нельзя отключить и который ограничен 1024 файловыми дескрипторами.

-dr

-dr

игнорирует ошибки разрешения адресов серверов. При проверке конфигурации вне рабочей среды часто нет доступа к тем же резолверам, из-за чего разрешение адресов завершается ошибкой и мешает тестированию. Параметр просто добавляет метод “none” в список методов разрешения адресов всех серверов, чтобы даже при неудаче libc последовательность запуска не прерывалась.

-dt [<trace_desc>,...]

-dt [<trace_desc>,...]

включает трассировку с выводом в stderr. Без аргумента включаются все источники трассировки на уровне ошибок. Это особенно полезно для обнаружения нарушений протокола клиентами или серверами. Необязательный аргумент задаёт список конфигураций трассировки, разделённых символом ‘,’. Каждый элемент включает один или все источники. Для каждого элемента можно дополнительно задать уровень и подробность вывода, отделив их от имени источника символом ‘:’. При неверном имени уровня или степени подробности выводится список допустимых ключевых слов. Например, удобно сначала указать ‘help’ в каждом поле, чтобы посмотреть список.

-dv

-dv

отключает механизм опроса “evports”. Эквивалентен директиве “noevports” в секции “global”. В основном полезен при подозрении на ошибку этого механизма. В системах с поддержкой портов событий (SunOS на основе Solaris 10 и новее) вместо него обычно используется механизм “poll”.

-m <limit>

-m <limit>

ограничивает объём выделяемой памяти для данных процесса значением <limit> в мегабайтах. В зависимости от объёма памяти, необходимого для обычной работы, это может привести к отказам в приёме соединений или замедлению. Обычно параметр нужен, чтобы принудительно запустить процесс haproxy в условиях ограниченного потребления ресурсов. Важно учитывать, что память не является общей для процессов haproxy, а дочерний процесс, созданный системным вызовом fork(), наследует ограничения ресурсов родителя. Поэтому в режиме master-worker этот предел применяется отдельно к главному процессу и созданному им рабочему процессу.

-n <limit>

-n <limit>

ограничивает число соединений на процесс значением <limit>. Эквивалентен директиве “maxconn” секции global и имеет над ней приоритет. Позволяет быстро принудительно снизить предел, чтобы избежать недоступности службы в системах со слишком низкими ограничениями ресурсов.

-p <file>

-p <file>

при запуске записывает PID всех процессов в <file>. Эквивалентен директиве “pidfile” в секции “global”. Файл открывается до перехода в окружение chroot и после вызова chdir(), подразумеваемого параметром “-C”. Каждый PID записывается отдельной строкой.

-q

-q

включает режим “quiet”, отключающий вывод сообщений. Можно сочетать с “-c”, чтобы только проверить корректность файла конфигурации.

-S <bind>[,bind_options...]

-S <bind>[,bind_options...]

в режиме master-worker создаёт сокет CLI главного процесса, позволяющий обращаться ко всем процессам: работающим и завершающимся. Из соображений безопасности рекомендуется привязывать этот CLI к локальному сокету UNIX. Параметры привязки те же, что у директивы “bind” в конфигурации, но слова разделяются запятыми вместо пробелов.

Учтите, что через этот сокет нельзя получить прослушивающие сокеты старого процесса при плавной перезагрузке конфигурации.

-sf <pid>*

-sf <pid>*

после завершения запуска отправляет старым процессам сигнал завершения “finish” (SIGUSR1), предлагая закончить текущую работу и выйти. <pid> — список PID получателей, по одному на аргумент. Список заканчивается при появлении любого параметра, начинающегося с “-”. Пустой список допустим, поэтому его удобно формировать на лету по результату команды вроде “pidof” или “pgrep”.

-st <pid>*

-st <pid>*

после завершения запуска отправляет старым процессам сигнал “terminate” (SIGTERM), немедленно завершая их без окончания текущей работы. <pid> — список PID получателей, по одному на аргумент. Список заканчивается при появлении любого параметра, начинающегося с “-”. Пустой список допустим, поэтому его удобно формировать на лету по результату команды вроде “pidof” или “pgrep”.

-v

-v

показывает версию и дату сборки.

-vv

-vv

показывает версию, параметры сборки, версии библиотек и доступные механизмы опроса. Этот вывод всегда запрашивают при сообщении об ошибке.

-x <unix_socket>

-x <unix_socket>

подключается к указанному сокету, пытается получить прослушивающие сокеты старого процесса и использует их вместо создания новых привязок. Это позволяет не терять новые соединения при перезагрузке конфигурации в Linux.

Без режима master-worker эту возможность необходимо включить на сокете статистики с помощью “expose-fd listeners” в конфигурации.

В режиме master-worker “expose-fd listeners” не требуется: при перезагрузке главный процесс автоматически использует эту возможность через синтаксис “sockpair@”, позволяющий напрямую подключиться к рабочему процессу без сокета статистики из конфигурации. Чтобы отключить это поведение, можно передать -x /dev/null.

Безопасный способ запуска HAProxy из файла инициализации — принудительно включить режим демона, сохранить существующие PID в файл и использовать его для уведомления старых процессов, что им следует завершить работу и выйти:

haproxy -f /etc/haproxy.cfg \
        -D -p /var/run/haproxy.pid -sf $(cat /var/run/haproxy.pid)

Если конфигурация разделена на несколько отдельных файлов, например для tcp и http, рекомендуется использовать параметр “-f”:

haproxy -f /etc/haproxy/global.cfg -f /etc/haproxy/stats.cfg \
        -f /etc/haproxy/default-tcp.cfg -f /etc/haproxy/tcp.cfg \
        -f /etc/haproxy/default-http.cfg -f /etc/haproxy/http.cfg \
        -D -p /var/run/haproxy.pid -sf $(cat /var/run/haproxy.pid)

Если число файлов заранее неизвестно, например для отдельных файлов заказчиков, рекомендуется начинать их имена с порядкового номера фиксированной ширины и загружать их через “–”, при необходимости предварительно загрузив общие настройки:

haproxy -f /etc/haproxy/global.cfg -f /etc/haproxy/stats.cfg \
        -f /etc/haproxy/default-tcp.cfg -f /etc/haproxy/tcp.cfg \
        -f /etc/haproxy/default-http.cfg -f /etc/haproxy/http.cfg \
        -D -p /var/run/haproxy.pid -sf $(cat /var/run/haproxy.pid) \
        -f /etc/haproxy/default-customers.cfg -- /etc/haproxy/customers/*

Иногда может произойти сбой при запуске из-за каких-либо причин. В таком случае важно убедиться, что версия HAProxy, которую вы запускаете, соответствует ожидаемой версии и поддерживает требуемые функции (например: SSL, PCRE, сжатие, Lua и т.д.). Это можно проверить с помощью команды “haproxy -vv”. Там отображаются важные сведения, такие как определённые параметры сборки, целевая система и версии используемых библиотек. Именно этот вывод всегда запрашивают при сообщении об ошибке:

$ haproxy -vv

HAProxy version 1.6-dev7-a088d3-4 2015/10/08 Copyright 2000-2015 Willy Tarreau willy@haproxy.org

Build options:

TARGET  = linux2628
CPU     = generic
CC      = gcc
CFLAGS  = -pg -O0 -g -fno-strict-aliasing -Wdeclaration-after-statement \
          -DBUFSIZE=8030 -DMAXREWRITE=1030 -DSO_MARK=36 -DTCP_REPAIR=19
OPTIONS = USE_ZLIB=1 USE_DLMALLOC=1 USE_OPENSSL=1 USE_LUA=1 USE_PCRE=1

Default settings:

maxconn = 2000, bufsize = 8030, maxrewrite = 1030, maxpollevents = 200

Encrypted password support via crypt(3): yes Built with zlib version: 1.2.6 Compression algorithms supported: identity(“identity”), deflate(“deflate”), \ raw-deflate(“deflate”), gzip(“gzip”) Built with OpenSSL version: OpenSSL 1.0.1o 12 Jun 2015 Running on OpenSSL version: OpenSSL 1.0.1o 12 Jun 2015 OpenSSL library supports TLS extensions: yes OpenSSL library supports SNI: yes OpenSSL library supports prefer-server-ciphers: yes Built with PCRE version: 8.12 2011-01-15 PCRE library supports JIT: no (USE_PCRE_JIT not set) Built with Lua version: Lua 5.3.1 Built with transparent proxy support using: IP_TRANSPARENT IP_FREEBIND

Available polling systems:

 epoll: pref=300,  test result OK
  poll: pref=200,  test result OK
select: pref=150,  test result OK

Total: 3 (3 usable), will use epoll.

Следующая информация, которую многие пользователи, не являющиеся разработчиками, могут здесь проверить:

- версия

- версия

В приведённой выше строке 1.6-dev7-a088d3-4 означает, что код соответствует коммиту “a088d3”, 4-му после официальной версии “1.6-dev7”. Сама версия 1.6-dev7 отображалась бы как “1.6-dev7-8c1ad7”. Существенная часть здесь — “1.6-dev7”: это 7-я версия разработки будущего выпуска 1.6. Версия разработки не подходит для рабочей среды, если только вы в точности не понимаете, что делаете. Стабильная версия имеет номер из 3 чисел, например “1.5.14-16f863”, обозначающий 14-й корректирующий выпуск версии 1.5. Такая версия готова к использованию в рабочей среде.

- дата выпуска

- дата выпуска

2015/10/08. Дата представлена в универсальном формате год/месяц/день. Здесь это означает 8 октября 2015 года. Стабильные выпуски выходят раз в несколько месяцев: сначала через 1-2 месяца, а после достижения высокой стабильности — иногда через 6 месяцев. Поэтому старая дата, вероятно, означает наличие уже исправленных ошибок или уязвимостей; стоит проверить сведения на официальном сайте.

- параметры сборки

- параметры сборки

Они важны для тех, кто самостоятельно собирает пакеты, и помогают объяснить неожиданное поведение. Например, указанная выше версия разработки собрана для Linux 2.6.28 или новее с расчётом на универсальный CPU, без оптимизаций под конкретный CPU. Кроме того, оптимизация кода отключена (-O0), поэтому производительность будет низкой.

- версии библиотек

- версии библиотек

Версия zlib выводится по сведениям самой библиотеки. В целом zlib считается очень стабильным продуктом, обновлять который почти никогда не требуется. Для OpenSSL выводятся две версии: использованная при сборке и используемая сейчас, найденная в системе. Они могут отличаться последней буквой, но никогда не числами. Также выводится дата сборки, поскольку большинство ошибок OpenSSL связано с безопасностью и требует серьёзного отношения: эту библиотеку обязательно нужно поддерживать в актуальном состоянии. Версия возрастом 4 месяца вызывает серьёзные подозрения и означает пропущенное обновление. PCRE обеспечивает очень быстрые регулярные выражения и настоятельно рекомендуется. Некоторые расширения, например JIT, есть не во всех версиях и ещё сравнительно молоды, поэтому часть пользователей предпочитает собирать без них; именно поэтому выводится и состояние их включения при сборке. Что касается языка скриптов Lua, HAProxy ожидает версию 5.3, выпущенную совсем недавно, незадолго до HAProxy 1.6. Важно проверять на сайте Lua наличие исправлений для этой ветки.

- Доступные механизмы опроса влияют на масштабируемость процесса при

- Доступные механизмы опроса влияют на масштабируемость процесса при

обработке более чем примерно тысячи одновременных соединений. Они доступны только при правильном указании системы в переменной TARGET во время сборки. Для Linux настоятельно рекомендуется механизм “epoll”, для BSD — kqueue. При их отсутствии используется poll() или даже select(), что приводит к высокой нагрузке на CPU при большом числе соединений.

25 - 4. Остановка и перезапуск HAProxy

Сигналы, мягкая остановка, перезагрузка конфигурации и перезапуск в режиме master-worker

HAProxy поддерживает плавную и жёсткую остановку. Жёсткая остановка проста: при отправке процессу haproxy сигнала SIGTERM он немедленно завершается, а все установленные соединения закрываются. Плавная остановка запускается сигналом SIGUSR1, отправленным процессу haproxy. При этом процесс лишь освобождает прослушиваемые порты, продолжая обрабатывать существующие соединения до их закрытия. После закрытия последнего соединения процесс завершается.

Жёсткая остановка используется для действий «stop» и «restart» сценария управления службой. Плавная остановка применяется для действия «reload», которое пытается незаметно для клиентов загрузить новую конфигурацию в новом процессе.

Оба сигнала может отправлять сам новый процесс haproxy при перезагрузке конфигурации или перезапуске, чтобы это происходило как можно позже и только при крайней необходимости. Именно это делают параметры «-st» (жёсткая остановка) и «-sf» (плавная остановка) соответственно.

В режиме master-worker для перезагрузки конфигурации не требуется запускать новый процесс haproxy. Получив сигнал SIGUSR2, главный процесс повторно запускает себя с параметром -sf, за которым следуют PID рабочих процессов. Затем главный процесс разбирает файл конфигурации и создаёт новые рабочие процессы с помощью fork.

Чтобы лучше понять применение этих сигналов, важно разобраться во всём механизме перезапуска.

Изначально уже работает процесс haproxy. Администратор выполняет команду, принятую в данной системе, например «/etc/init.d/haproxy reload», чтобы применить новый файл конфигурации. Далее происходит следующее. Сначала сценарий службы (/etc/init.d/haproxy или его аналог) проверяет корректность разбора файла конфигурации командой «haproxy -c». Затем он пытается запустить haproxy с этим файлом конфигурации, используя «-st» или «-sf».

После этого HAProxy пытается привязаться ко всем прослушиваемым портам. При фатальной ошибке (например, если адрес отсутствует в системе или доступ запрещён) процесс завершается с ошибкой. Если привязка сокета не удалась из-за того, что порт уже занят, процесс сначала отправляет сигнал SIGTTOU всем PID из списка, заданного в «-st» или «-sf». Это так называемый сигнал приостановки: он предписывает всем существующим процессам haproxy временно прекратить прослушивание своих портов, чтобы новый процесс мог повторить попытку привязки. В это время старый процесс продолжает обрабатывать существующие соединения. Если привязка по-прежнему не удаётся (например, порт занят другим демоном), новый процесс отправляет старым процессам сигнал SIGTTIN, предписывая возобновить работу как ни в чём не бывало. Старые процессы снова начинают прослушивать порты и принимать соединения. Обратите внимание: этот механизм зависит от системы, и некоторые операционные системы могут не поддерживать его в многопроцессном режиме.

Если новому процессу удалось привязаться ко всем портам, он отправляет всем процессам либо SIGTERM (жёсткая остановка при «-st»), либо SIGUSR1 (плавная остановка при «-sf»), уведомляя их, что теперь он обслуживает трафик, а старые процессы должны завершиться — немедленно или после окончания своей работы.

Важно учитывать, что в этот промежуток есть два небольших окна длительностью по несколько миллисекунд, в течение которых при высокой нагрузке возможны единичные сбои соединений. Обычно наблюдается около 1 сбоя при перезагрузке конфигурации на каждые 10000 новых соединений в секунду. Это означает, что высоконагруженный сайт с 30000 новых соединений в секунду может получать примерно 3 неудачных соединения при каждой перезагрузке конфигурации. Такие сбои возникают в двух случаях:

  • Если новый процесс не может привязаться к порту из-за старого процесса, ему сначала приходится выполнить последовательность SIGTTOU+SIGTTIN. Для нескольких десятков фронтендов она обычно занимает около одной миллисекунды, в течение которой часть портов уже освобождена старым процессом, но ещё не занята новым. HAProxy обходит эту проблему в системах с поддержкой параметра сокета SO_REUSEPORT, который позволяет новому процессу привязаться к порту, не запрашивая предварительно его освобождение у старого. Большинство систем BSD поддерживают его уже очень давно. Linux поддерживал его в версии 2.0, но примерно в версии 2.2 поддержка была удалена, хотя к тому времени существовали отдельные патчи. Она вернулась в ядре 3.9, поэтому, если частота сбоев соединений выше указанной, убедитесь, что используете ядро 3.9 или новее либо что соответствующие патчи перенесены в ваше ядро (что менее вероятно).

  • Когда старые процессы закрывают прослушиваемые порты, ядро не всегда перераспределяет ожидающие соединения, оставшиеся в очереди сокета. При высокой нагрузке пакет SYN может прийти непосредственно перед закрытием сокета, что приведёт к отправке клиенту пакета RST. В некоторых критически важных средах, где недопустима даже одна потеря, с этим иногда борются с помощью правил межсетевого экрана, блокирующих пакеты SYN на время перезагрузки конфигурации и вынуждающих клиента повторить передачу. Поведение целиком зависит от системы: некоторые системы могут просмотреть другие очереди прослушивания и избежать отправки RST. Второй случай касается клиентского ACK для локального сокета, который непосредственно перед закрытием находился в состоянии SYN_RECV. Этот ACK вызовет отправку RST, хотя процесс haproxy ещё ничего об этом не знает. Избавиться от такого случая сложнее, но упомянутые правила фильтрации межсетевого экрана хорошо сработают, если применить их примерно за секунду до перезапуска процесса.

У подавляющего большинства пользователей подобных потерь никогда не возникает, поскольку нагрузки недостаточно для возникновения гонок. А для большинства пользователей с большим объёмом трафика частота сбоев остаётся в пределах статистического шума, если их системы хотя бы корректно поддерживают SO_REUSEPORT.

26 - 5. Ограничения файловых дескрипторов

Лимиты дескрипторов, расчёт потребности, системные ограничения и устранение неполадок

Чтобы обеспечить успешное обслуживание всех входящих соединений, HAProxy при загрузке вычисляет общее число файловых дескрипторов, которые потребуются за время жизни процесса. Обычному процессу Unix по умолчанию обычно предоставляется 1024 файловых дескриптора, а привилегированный процесс может самостоятельно увеличить этот лимит. Это одна из причин запускать HAProxy от имени root и позволять ему настроить лимит. Лимит по умолчанию в 1024 файловых дескриптора позволяет обслуживать примерно 500 одновременных соединений. Расчёт основан на глобальном параметре maxconn, ограничивающем общее число соединений на процесс, числе слушателей, числе серверов с включённой проверкой работоспособности, агентских проверках, одноранговых узлах, получателях журналов и, возможно, нескольких других технических потребностях. Для грубой оценки достаточно удвоить значение maxconn и добавить несколько десятков: получится приблизительное число необходимых файловых дескрипторов.

Изначально HAProxy не умел вычислять это значение, и его нужно было передавать через параметр “ulimit-n” в глобальной секции. Поэтому даже сегодня этот параметр встречается во множестве конфигураций. К сожалению, его часто рассчитывали неверно, что приводило к сбоям соединений при приближении к maxconn вместо ограничения приёма входящих соединений на время ожидания нужных ресурсов. Поэтому важно удалить все унаследованные параметры “ulimit-n”, которые могли остаться от очень старых версий.

Для работы даже с умеренной нагрузкой число файловых дескрипторов обязательно нужно увеличить, но это требует некоторых настроек, зависящих от ОС. Во-первых, механизм опроса select() ограничен 1024 файловыми дескрипторами. На самом деле в Linux он раньше мог обрабатывать и больше, однако некоторые ОС поставляются с излишне строгими политиками SELinux, запрещающими select() использовать более 1024 файловых дескрипторов. Поэтому теперь HAProxy в таком случае отказывается запускаться, чтобы избежать проблем во время выполнения. Во всех поддерживаемых операционных системах доступен poll(), который не имеет этого ограничения. Он выбирается автоматически, так что для получения рабочей конфигурации ничего делать не требуется. Однако poll() становится очень медленным с ростом числа файловых дескрипторов. Хотя HAProxy старается уменьшить влияние на производительность (например, используя внутренний кэш файловых дескрипторов и пакетную обработку), практическое правило таково: использование poll() при более чем тысяче одновременных соединений создаёт большую нагрузку на CPU.

В системах Linux с ядром 2.6 и выше используется системный вызов epoll(). Это гораздо более масштабируемый механизм на основе обратных вызовов в ядре, которые гарантируют постоянное время пробуждения независимо от числа зарегистрированных для наблюдения файловых дескрипторов. Он используется автоматически, если обнаружен, при условии, что HAProxy собран для одного из вариантов Linux. Его наличие и поддержку можно проверить с помощью “haproxy -vv”.

В системах BSD с соответствующей поддержкой доступна альтернатива — kqueue(). Он значительно быстрее poll() и даже немного быстрее epoll() благодаря пакетной обработке изменений. Его поддерживают как минимум FreeBSD и OpenBSD. Как и в случае с Linux epoll(), сведения о его поддержке и доступности выводятся командой “haproxy -vv”.

Наличие хорошего механизма опроса — лишь часть задачи: процесс обязательно должен иметь возможность достичь нужных лимитов. При запуске HAProxy сразу устанавливает новые лимиты файловых дескрипторов процесса и проверяет успешность операции. В случае неудачи он сообщает об этом до создания дочернего процесса, чтобы администратор увидел проблему. Если процесс запущен от имени root, оснований для отказа в этой настройке быть не должно. Однако она может завершиться неудачно, если процесс запускает непривилегированный пользователь. Если есть веская причина не запускать haproxy от имени root (например, его запускают конечные пользователи или учётная запись отдельного приложения), системный администратор может увеличить лимит файловых дескрипторов для конкретного пользователя. Действие настройки можно проверить командой “ulimit -n” в оболочке этого пользователя. Она должна показать новый лимит.

Предупреждение: при изменении лимитов в учётной записи непривилегированного пользователя часто оказывается, что новые значения учитываются только при входе пользователя в систему и совсем не применяются к некоторым сценариям, выполняемым при загрузке системы, или к заданиям crontab. Это полностью зависит от операционной системы, поэтому при таком способе запуска не забывайте проверять “ulimit -n” перед запуском haproxy. Общая рекомендация — никогда не запускать haproxy от имени непривилегированного пользователя в промышленной эксплуатации. Ещё одна веская причина в том, что такой запуск мешает haproxy включить некоторые защитные механизмы.

Когда установлено, что система разрешает процессу haproxy использовать запрошенное число файловых дескрипторов, могут встретиться ещё два системных ограничения. Первое — общесистемный лимит файловых дескрипторов, то есть общее число дескрипторов, открытых в системе всеми процессами. При достижении этого лимита accept() или socket() обычно возвращают ENFILE. Второе — жёсткий лимит числа файловых дескрипторов на процесс, который не позволяет установить через setrlimit() более высокое значение. Оба сильно зависят от операционной системы. В Linux системный лимит задаётся при загрузке в зависимости от объёма памяти. Его можно изменить параметром sysctl “fs.file-max”. Жёсткий лимит на процесс по умолчанию равен 1048576, но его можно изменить параметром sysctl “fs.nr_open”.

Если лимиты файловых дескрипторов слишком низкие, их действие можно наблюдать на работающем процессе. Утилита strace покажет, что accept() и socket() возвращают “-1 EMFILE”, когда достигнуты лимиты процесса. В этом случае достаточно увеличить значение “ulimit-n” (или удалить его), чтобы решить проблему. Если эти системные вызовы возвращают “-1 ENFILE”, это означает, что достигнуты лимиты ядра и нужно изменить общесистемный параметр. Такие проблемы обязательно необходимо устранить: они приводят к высокой загрузке CPU (при сбоях accept()) и неудачным соединениям, обычно заметным пользователю. Ещё один вариант решения — уменьшить глобальное значение maxconn, чтобы обеспечить последовательное обслуживание, и, возможно, отключить режим HTTP keep-alive, чтобы соединения освобождались и использовались повторно быстрее.

27 - 6. Управление памятью

Выделение памяти, ограничения, пулы, буферы и оценка потребностей процесса

HAProxy использует простое и быстрое управление памятью на основе пулов. Поскольку он работает с небольшим числом различных типов объектов, гораздо эффективнее брать новые объекты из пула, уже содержащего объекты подходящего размера, чем вызывать malloc() для каждого отдельного размера. Пулы организованы как стек, или LIFO: при выделении используются недавно освобождённые объекты, которые ещё находятся в кэшах CPU. Пулы близких размеров объединяются, чтобы ограничить фрагментацию памяти.

По умолчанию, поскольку приоритет отдаётся производительности, каждый освобождённый объект возвращается в свой исходный пул, а выделенная память под объекты никогда не освобождается, так как ожидается их скорое повторное использование.

В CLI можно проверить использование памяти пулами с помощью команды “show pools”:

> show pools
Dumping pools usage. Use SIGQUIT to flush them.
  - Pool cache_st (16 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9ccc40=03 [SHARED]
  - Pool pipe (32 bytes): 5 allocated (160 bytes), 5 used, 0 failures, 2 users, @0x9ccac0=00 [SHARED]
  - Pool comp_state (48 bytes): 3 allocated (144 bytes), 3 used, 0 failures, 5 users, @0x9cccc0=04 [SHARED]
  - Pool filter (64 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 3 users, @0x9ccbc0=02 [SHARED]
  - Pool vars (80 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 2 users, @0x9ccb40=01 [SHARED]
  - Pool uniqueid (128 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 2 users, @0x9cd240=15 [SHARED]
  - Pool task (144 bytes): 55 allocated (7920 bytes), 55 used, 0 failures, 1 users, @0x9cd040=11 [SHARED]
  - Pool session (160 bytes): 1 allocated (160 bytes), 1 used, 0 failures, 1 users, @0x9cd140=13 [SHARED]
  - Pool h2s (208 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 2 users, @0x9ccec0=08 [SHARED]
  - Pool h2c (288 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9cce40=07 [SHARED]
  - Pool spoe_ctx (304 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 2 users, @0x9ccf40=09 [SHARED]
  - Pool connection (400 bytes): 2 allocated (800 bytes), 2 used, 0 failures, 1 users, @0x9cd1c0=14 [SHARED]
  - Pool hdr_idx (416 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9cd340=17 [SHARED]
  - Pool dns_resolut (480 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9ccdc0=06 [SHARED]
  - Pool dns_answer_ (576 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9ccd40=05 [SHARED]
  - Pool stream (960 bytes): 1 allocated (960 bytes), 1 used, 0 failures, 1 users, @0x9cd0c0=12 [SHARED]
  - Pool requri (1024 bytes): 0 allocated (0 bytes), 0 used, 0 failures, 1 users, @0x9cd2c0=16 [SHARED]
  - Pool buffer (8030 bytes): 3 allocated (24090 bytes), 2 used, 0 failures, 1 users, @0x9cd3c0=18 [SHARED]
  - Pool trash (8062 bytes): 1 allocated (8062 bytes), 1 used, 0 failures, 1 users, @0x9cd440=19
Total: 19 pools, 42296 bytes allocated, 34266 used.

Имя пула носит лишь справочный характер: это имя первого типа объектов, использовавшего данный пул. Размер в скобках — размер объектов в этом пуле. Размеры объектов всегда округляются вверх до ближайшего числа, кратного 16 байтам. Выводятся текущее число выделенных объектов и соответствующее количество байтов, что позволяет легко определить, какой пул потребляет больше всего памяти. Число объектов, используемых в данный момент, также приводится в поле “used”. Разница между “allocated” и “used” соответствует освобождённым объектам, доступным для немедленного использования. Адрес в конце строки — это адрес пула, а следующее за ним число — индекс пула, если он существует; если индекс не назначен, выводится -1.

Объём памяти, выделяемой на процесс, можно ограничить параметром командной строки “-m”, указав после него число мегабайт. Он охватывает всё адресуемое пространство процесса, включая память некоторых библиотек и стек, но обеспечивает надёжное ограничение при построении системы с ограниченными ресурсами. Он работает так же, как “ulimit -v” в системах, где эта команда доступна, или “ulimit -d” в остальных.

Если выделить память не удалось из-за достижения лимита или из-за нехватки памяти в системе, haproxy сначала освобождает все доступные объекты во всех пулах, а затем снова пытается выделить память. Этот механизм освобождения неиспользуемой памяти можно запустить, отправив процессу haproxy сигнал SIGQUIT.

При перезагрузке конфигурации процесс, перешедший в состояние плавной остановки, также автоматически очищает память после освобождения каждого соединения, чтобы высвободить как можно больше памяти для нового процесса.

28 - 7. Использование CPU

Потоки, привязка к CPU, полная загрузка, профилирование и особенности производительности
Предупреждение

Примечание о версии: в этой главе сохранены исторические рекомендации по работе с несколькими процессами. Начиная с HAProxy 2.5, nbproc и bind process больше не поддерживаются. В этой редакции настраивайте потоки с помощью nbthread, thread-groups и cpu-map в глобальных настройках .

Обычно HAProxy проводит большую часть времени в системном режиме, а меньшую — в пользовательском пространстве. Тщательно настроенный CPU с частотой 3.5 GHz способен поддерживать около 80000 установок и закрытий сквозных соединений в секунду при загрузке CPU 100% на одном ядре. При полной загрузке одного ядра типичны следующие показатели:

  • 95% в системном режиме, 5% в пользовательском — для длительных соединений TCP или больших объектов HTTP;
  • 85% в системном режиме и 15% в пользовательском — для коротких соединений TCP или маленьких объектов HTTP в режиме закрытия соединений;
  • 70% в системном режиме и 30% в пользовательском — для маленьких объектов HTTP в режиме постоянных соединений.

Обработка правил и регулярных выражений увеличивает долю пользовательского времени. Наличие правил межсетевого экрана, отслеживания соединений и сложных таблиц маршрутизации в системе, напротив, увеличивает долю системного времени.

В большинстве систем время CPU при передаче данных по сети можно разделить на 4 части:

  • Время обработки прерываний: вся обработка при поступлении ввода-вывода, ещё до того, как определён целевой процесс. Обычно приём пакетов Rx учитывается как обработка прерываний. В некоторых системах, например Linux, обработка прерываний может откладываться и передаваться выделенному потоку; тогда она может отображаться как softirq, а поток называется ksoftirqd/0 (для CPU 0). CPU, выполняющий эту работу, обычно определяется настройками оборудования, хотя для softirq часто можно переназначить обработку на другой CPU. Эту долю времени часто воспринимают как паразитную, поскольку она не связана ни с одним процессом, но в действительности это подготовительная работа для процесса.

  • Системное время: вся обработка кодом ядра, вызываемым из пользовательского пространства. Например, системные вызовы учитываются как системное время. Все синхронно отправляемые пакеты Tx также учитываются здесь. Если отправку некоторых пакетов приходится отложить из-за заполнения очередей, впоследствии они могут обрабатываться в контексте прерывания (например, при получении ACK, открывающего окно TCP).

  • Пользовательское время: выполнение исключительно кода приложения в пользовательском пространстве. HAProxy работает только в этой области, хотя активно использует системные вызовы. Обработка правил, регулярные выражения, сжатие и шифрование увеличивают пользовательскую долю потребления CPU.

  • Время простоя: то, что CPU делает, когда работы нет. Например, HAProxy ожидает входящего соединения или отправки данных, то есть система ждёт ACK от клиента, чтобы передать эти данные.

На практике для оценки работы HAProxy обычно достаточно разумно (хотя и совершенно неточно) считать, что прерывания и softirq вызваны обработкой Rx в драйверах ядра, пользовательское время — обработкой на уровне 7 в HAProxy, а системное время — сетевой обработкой на пути Tx.

Поскольку HAProxy построен вокруг цикла событий, он ожидает новых событий с помощью poll() (или аналога), максимально быстро обрабатывает их, а затем возвращается к poll() для ожидания следующих событий. Он измеряет время ожидания в poll() относительно времени обработки событий. Отношение времени опроса к общему времени называется временем простоя «idle»: это доля времени, затраченная на ожидание событий. Она отображается на странице статистики в строке «idle» или в CLI как «Idle_pct». Значение, близкое к 100%, означает крайне низкую нагрузку. Значение, близкое к 0%, означает постоянную активность. В перегруженной системе этот показатель не может быть очень точным, поскольку другие процессы могут вытеснять haproxy с CPU, однако он хорошо отражает, как HAProxy оценивает собственную работу. Если и нагрузка, и доля простоя низкие, это может означать, что HAProxy выполняет много работы, возможно, обрабатывает очень затратные правила. Напротив, если HAProxy показывает простой, близкий к 100%, но работа идёт медленно, он ничего не может сделать для ускорения: он уже ожидает входящих данных для обработки. В следующем примере haproxy полностью бездействует:

$ echo "show info" | socat - /var/run/haproxy.sock | grep ^Idle
Idle_pct: 100

Когда доля простоя становится очень низкой, важно настроить систему и правильно распределить процессы и прерывания, чтобы сохранить как можно больше ресурсов CPU для всех задач. Если используется межсетевой экран, стоит попробовать отключить или настроить его, чтобы убедиться, что он не является основной причиной ограничения производительности. Учтите, что выгрузка межсетевого экрана с отслеживанием состояния обычно уменьшает и долю прерываний/softirq, и системное время, поскольку такие экраны работают на обоих путях — Rx и Tx. В Linux выгрузка модулей nf_conntrack и ip_conntrack покажет, можно ли получить выигрыш. Если да, значит модуль работает с настройками по умолчанию, и нужно выяснить, как настроить его для лучшей производительности. Обычно это сводится к значительному увеличению размера хеш-таблицы. Во FreeBSD команда «pfctl -d» одновременно отключает межсетевой экран «pf» и его механизм отслеживания состояния.

Если много времени уходит на прерывания/softirq, важно убедиться, что они не выполняются на том же CPU. Большинство систем старается закреплять задачи за тем CPU, на котором они получают сетевой трафик: при некоторых нагрузках это улучшает производительность. Но при сильно выраженной сетевой нагрузке эффект обратный, поскольку процесс haproxy вынужден конкурировать с соответствующей обработкой в ядре. Закрепление haproxy за одним ядром CPU, а прерываний — за другим ядром с общим кешем L3 обычно заметно повышает сетевую производительность. На практике объёмы работы haproxy и сетевого стека довольно близки, и каждый из них может почти полностью загрузить отдельный CPU. В Linux для этого используются taskset (для haproxy) или cpu-map (в конфигурации haproxy), а прерывания назначаются через /proc/irq. Многие сетевые интерфейсы поддерживают несколько очередей и прерываний. Обычно полезно распределить их по небольшому числу ядер CPU с общим кешем L3. Обязательно останавливайте irq_balance: при таких нагрузках он всегда действует наихудшим образом.

Для нагрузок, ограниченных CPU и связанных с большим объёмом трафика SSL или сжатия, может быть полезно выделить несколько процессов для определённых задач. Универсального правила здесь нет, поэтому придётся экспериментировать.

Для увеличения доступных ресурсов CPU можно запустить HAProxy в виде нескольких процессов с помощью директивы «nbproc» в секции global. Однако существуют ограничения:

  • Проверки работоспособности выполняются каждым процессом, поэтому целевые серверы получают столько проверок, сколько процессов запущено.
  • Значения maxconn и очереди относятся к отдельным процессам, поэтому необходимо правильно задать значение, чтобы не перегрузить серверы.
  • В исходящих соединениях следует избегать использования диапазонов портов, чтобы не возникали конфликты.
  • Таблицы stick-tables относятся к отдельным процессам и не являются общими для нескольких процессов.
  • Каждая секция peers одновременно может работать только в одном процессе.
  • Операции CLI одновременно действуют только на один процесс.

С учётом этих ограничений самый простой вариант часто состоит из первого уровня, работающего в нескольких процессах и выполняющего тяжёлую обработку, который передаёт трафик второму уровню, работающему в одном процессе. Этот механизм подходит для SSL и сжатия — двух наиболее затратных для CPU функций. Экземпляры легко объединить в цепочку через сокеты UNIX (они дешевле сокетов TCP и не расходуют порты) и протокол proxy, позволяющий передавать сведения о клиенте на следующий этап. При такой схеме обычно полезно закрепить все однопроцессные задачи за процессом номер 1, а дополнительные задачи — за следующими процессами: это упрощает генерацию похожих конфигураций для разных машин.

В Linux версии 3.9 и новее многопроцессный режим HAProxy гораздо эффективнее, если каждый процесс использует отдельный прослушивающий сокет на одной и той же паре IP:port. Тогда ядро равномерно распределяет нагрузку между процессами, вместо того чтобы пробуждать их все. Дополнительные сведения о параметре «process» в строках директивы «bind» приведены в руководстве по конфигурации.

29 - 8. Ведение журнала

Интеграция с syslog, журналы запуска и работы, устранение неполадок журналирования

Для ведения журнала HAProxy всегда использует сервер syslog, поскольку сам не обращается к файловой системе. Стандартный способ — отправлять журналы по UDP на сервер журналирования (по умолчанию на порт 514). Очень часто используется адрес 127.0.0.1, где работает локальный демон syslog, но также применяется передача по сети на центральный сервер. Центральный сервер даёт дополнительные преимущества, особенно в схемах active-active, где желательно объединять журналы в порядке поступления. HAProxy может отправлять журналы локальному демону syslog и через сокет UNIX, но это совершенно не рекомендуется: если сервер syslog перезапустить во время работы haproxy, сокет будет заменён, а новые записи журналов будут теряться. Поскольку HAProxy изолирован в окружении chroot, он не сможет повторно подключиться к новому сокету. На практике также наблюдалось, что буферы журналирования сокетов UNIX очень малы, из-за чего сообщения теряются даже при очень низкой нагрузке. Однако для тестирования такой вариант вполне допустим.

Чтобы HAProxy отправлял журналы локальному демону с категорией facility «local0», рекомендуется добавить в секцию «global» следующую директиву:

log 127.0.0.1:514 local0

а затем добавить следующую директиву в каждую секцию «defaults» либо в каждую секцию фронтенда и бэкенда:

log global

Таким образом, все журналы будут централизованно направляться на сервер, указанный в глобальном определении.

Некоторые демоны syslog по умолчанию не принимают трафик UDP, поэтому синтаксис включения этой возможности зависит от используемого демона:

  • Для sysklogd нужно передать аргумент «-r» в командной строке демона, чтобы он прослушивал сокет UDP для удалённых журналов. Учтите, что ограничить прослушивание адресом 127.0.0.1 невозможно, поэтому он будет принимать журналы и от удалённых систем.

  • Для rsyslogd в файл конфигурации необходимо добавить следующие строки:

$ModLoad imudp
$UDPServerAddress *
$UDPServerRun 514
  • Для syslog-ng можно создать новый источник следующим образом, а затем добавить его как допустимый источник в одну из директив «log»:
source s_udp {
  udp(ip(127.0.0.1) port(514));
};

Дополнительные сведения приведены в руководстве используемого демона syslog. Если в системных файлах журналов нет записей, выполните следующие проверки:

  • Перезапустите haproxy. Каждый фронтенд и бэкенд записывает строку о своём запуске. Если эти записи поступают, журналирование работает.

  • Выполните «strace -tt -s100 -etrace=sendmsg -p <haproxy’s pid>» и выполните действия, которые должны попасть в журнал. В выводе должны быть видны сообщения журнала, отправляемые через sendmsg(). Если их нет, перезапустите haproxy под strace. Если журналы по-прежнему отсутствуют, в конфигурации определённо есть ошибка.

  • Запустите tcpdump для наблюдения за портом 514, например на интерфейсе обратной петли, если трафик передаётся локально: «tcpdump -As0 -ni lo port 514». Если пакеты видны, это доказывает, что они отправляются, и нужно искать неисправность в демоне syslogd.

Хотя журналы трафика отправляют фронтенды, принимающие входящие соединения, бэкенды также должны иметь возможность отправлять записи, чтобы сообщать об изменении состояния сервера по результатам проверки работоспособности. Дополнительные сведения обо всех доступных настройках журналирования приведены в руководстве по конфигурации HAProxy.

Удобно выбрать категорию facility, которая не используется другими демонами. В примерах HAProxy часто предлагаются «local0» для журналов трафика и «local1» для административных журналов, поскольку на практике эти категории нигде не встречаются. Одной категории также было бы достаточно. Раздельные журналы удобны для анализа, но важно помнить, что в них иногда содержатся конфиденциальные сведения, поэтому их нельзя смешивать с другими журналами, которые могут случайно попасть к посторонним.

Для устранения неполадок в рабочей среде без существенного влияния на производительность сервера рекомендуется использовать утилиту «halog», поставляемую с HAProxy. Она похожа на grep и предназначена для очень быстрой обработки файлов журналов HAProxy. Типичная скорость составляет от 1 до 2 GB журналов в секунду. Она умеет извлекать только определённые записи (например, искать по классам кодов состояния HTTP, состояниям завершения соединений, диапазонам времени ответа или только ошибки), считать строки, ограничивать число выводимых строк и выполнять более сложную статистическую обработку: сортировать серверы по времени ответа или числу ошибок, URL по времени или числу обращений, адреса клиентов по числу обращений и так далее. Это очень удобно для быстрого выявления аномалий, например бота, бесконечно обходящего сайт, и их блокирования.

30 - 9. Статистика и мониторинг

Статистика в формате CSV и типизированном формате, команды CLI времени выполнения, CLI главного процесса и файлы статистики

HAProxy позволяет запрашивать сведения о своём состоянии. Чаще всего для этого используется страница статистики HTTP. Она также предоставляет альтернативный формат вывода CSV для средств мониторинга. Тот же формат доступен через сокет Unix.

Статистика сгруппирована по категориям, называемым доменами, которые соответствуют различным компонентам HAProxy. Доступны два домена: proxy и resolvers. Если домен не указан, выбирается proxy. На странице HTTP выводится только статистика домена proxy.

9.1. Формат CSV

Статистику можно получать через сокет Unix или страницу HTTP. Оба способа поддерживают формат CSV с перечисленными ниже полями. Первая строка начинается с решётки (’#’) и содержит по одному слову в каждом поле, отделённом запятой: это название столбца. Все строки начиная со второй используют обычный формат CSV с запятой в качестве разделителя и двойной кавычкой (’"’) в качестве необязательного ограничителя текста, но только если текст неоднозначен (содержит кавычку или запятую). Двойная кавычка (’"’) внутри текста удваивается (’""’); этот формат распознаётся большинством инструментов. Не вставляйте столбцы перед перечисленными, чтобы не нарушить работу инструментов с жёстко заданными позициями столбцов.

Для статистики прокси после имени каждого поля в скобках указаны типы объектов, у которых это поле может иметь значение: L (слушатели), F (фронтенды), B (бэкенды) и S (серверы). Существует фиксированный набор статических полей, всегда доступных в одном и том же порядке. Столбец с символом ‘-’ обозначает конец статических полей; наличие и порядок следующих за ним полей не гарантируются.

Ниже перечислены статические поля домена статистики proxy:

 0. pxname [LFBS]: имя прокси
 1. svname [LFBS]: имя службы (FRONTEND для фронтенда, BACKEND для бэкенда,
    произвольное имя для сервера/слушателя)
 2. qcur [..BS]: текущее число запросов в очереди. Для бэкенда — число
    запросов в очереди, которым ещё не назначен сервер.
 3. qmax [..BS]: максимальное значение qcur
 4. scur [LFBS]: текущее число сеансов
 5. smax [LFBS]: максимальное число сеансов
 6. slim [LFBS]: настроенный предел числа сеансов
 7. stot [LFBS]: суммарное число сеансов
 8. bin [LFBS]: полученные байты
 9. bout [LFBS]: отправленные байты
10. dreq [LFB.]: запросы, отклонённые по соображениям безопасности.
    - Для tcp — из-за совпадения с правилом tcp-request content.
    - Для http — из-за совпадения с правилом http-request или tarpit.
11. dresp [LFBS]: ответы, отклонённые по соображениям безопасности.
    - Для http — из-за совпадения с правилом http-request или
      "option checkcache".
12. ereq [LF..]: ошибки запросов. Некоторые возможные причины:
    - клиент преждевременно завершил соединение до отправки запроса.
    - ошибка чтения данных от клиента
    - тайм-аут клиента
    - клиент закрыл соединение
    - различные некорректные запросы от клиента.
    - запрос попал в ловушку соединений (tarpit).
13. econ [..BS]: число запросов, при попытке соединения которых с сервером
    бэкенда возникла ошибка. Для бэкенда показатель равен сумме показателей
    всех его серверов и ошибок соединения, не связанных с конкретным
    сервером (например, когда в бэкенде нет активных серверов).
14. eresp [..BS]: ошибки ответов. Здесь также учитывается srv_abrt.
    Некоторые другие ошибки:
    - ошибка записи в сокет клиента (не учитывается в статистике сервера)
    - ошибка применения фильтров к ответу.
15. wretr [..BS]: число повторных попыток соединения с сервером.
16. wredis [..BS]: число повторных направлений запроса на другой сервер.
    Значение для сервера показывает, сколько раз запрос был перенаправлен
    с этого сервера на другой.
17. status [LFBS]: состояние (UP/DOWN/NOLB/MAINT/MAINT(via)/MAINT(resolution)...)
18. weight [..BS]: суммарный эффективный вес (бэкенд), эффективный вес (сервер)
19. act [..BS]: число активных серверов (бэкенд), признак активности (сервер)
20. bck [..BS]: число резервных серверов (бэкенд), признак резервного сервера (сервер)
21. chkfail [...S]: число неудачных проверок. (Учитываются только проверки,
    завершившиеся неудачно, когда сервер доступен.)
22. chkdown [..BS]: число переходов UP->DOWN. Счётчик бэкенда учитывает
    переходы всего бэкенда в недоступное состояние, а не сумму счётчиков
    отдельных серверов.
23. lastchg [..BS]: число секунд с последнего перехода UP<->DOWN
24. downtime [..BS]: суммарное время простоя (в секундах). Для бэкенда это
    простой всего бэкенда, а не сумма времени простоя серверов.
25. qlimit [...S]: настроенное значение maxqueue для сервера; пустое поле,
    если значение равно 0 (по умолчанию, означает отсутствие ограничения)
26. pid [LFBS]: идентификатор процесса (0 для первого экземпляра, 1 для второго, ...)
27. iid [LFBS]: уникальный идентификатор прокси
28. sid [L..S]: идентификатор сервера (уникальный в пределах прокси)
29. throttle [...S]: текущий предел нагрузки сервера в процентах, если
    действует slowstart; пустое поле, если slowstart не действует.
30. lbtot [..BS]: общее число выборов сервера для новых сеансов или при
    повторном распределении. Счётчик сервера показывает, сколько раз
    был выбран этот сервер.
31. tracked [...S]: идентификатор прокси/сервера, если включено отслеживание.
32. type [LFBS]: (0=фронтенд, 1=бэкенд, 2=сервер, 3=сокет/слушатель)
33. rate [.FBS]: число сеансов в секунду за последнюю истёкшую секунду
34. rate_lim [.F..]: настроенный предел числа новых сеансов в секунду
35. rate_max [.FBS]: максимальное число новых сеансов в секунду
36. check_status [...S]: состояние последней проверки работоспособности, одно из:
       UNK     -> неизвестно
       INI     -> инициализация
       SOCKERR -> ошибка сокета
       L4OK    -> проверка уровня 4 пройдена, проверки верхних уровней отключены
       L4TOUT  -> тайм-аут уровня 1-4
       L4CON   -> проблема соединения на уровне 1-4, например
                  "Connection refused" (tcp rst) или "No route to host" (icmp)
       L6OK    -> проверка уровня 6 пройдена
       L6TOUT  -> тайм-аут уровня 6 (SSL)
       L6RSP   -> некорректный ответ уровня 6 — ошибка протокола
       L7OK    -> проверка уровня 7 пройдена
       L7OKC   -> проверка уровня 7 пройдена условно, например 404 при
                  disable-on-404
       L7TOUT  -> тайм-аут уровня 7 (HTTP/SMTP)
       L7RSP   -> некорректный ответ уровня 7 — ошибка протокола
       L7STS   -> ошибка ответа уровня 7, например HTTP 5xx
    Примечание: если проверка сейчас выполняется, выводится последнее
    известное состояние с префиксом "* ", например "* L7OK".
37. check_code [...S]: код уровня 5-7, если доступен
38. check_duration [...S]: длительность последней проверки работоспособности в ms
39. hrsp_1xx [.FBS]: ответы http с кодом 1xx
40. hrsp_2xx [.FBS]: ответы http с кодом 2xx
41. hrsp_3xx [.FBS]: ответы http с кодом 3xx
42. hrsp_4xx [.FBS]: ответы http с кодом 4xx
43. hrsp_5xx [.FBS]: ответы http с кодом 5xx
44. hrsp_other [.FBS]: ответы http с другими кодами (ошибка протокола)
45. hanafail [...S]: сведения о неудачных проверках работоспособности
46. req_rate [.F..]: число запросов HTTP в секунду за последнюю истёкшую секунду
47. req_rate_max [.F..]: максимальное наблюдавшееся число запросов HTTP в секунду
48. req_tot [.FB.]: общее число полученных запросов HTTP
49. cli_abrt [..BS]: число передач данных, прерванных клиентом
50. srv_abrt [..BS]: число передач данных, прерванных сервером
    (учитывается в eresp)
51. comp_in [.FB.]: число байтов ответов HTTP, переданных механизму сжатия
52. comp_out [.FB.]: число байтов ответов HTTP на выходе механизма сжатия
53. comp_byp [.FB.]: число байтов, прошедших в обход механизма сжатия HTTP
    (ограничение CPU/BW)
54. comp_rsp [.FB.]: число сжатых ответов HTTP
55. lastsess [..BS]: число секунд с момента назначения последнего сеанса
    серверу/бэкенду
56. last_chk [...S]: содержимое последней проверки работоспособности или текст ошибки
57. last_agt [...S]: содержимое последней проверки агента или текст ошибки
58. qtime [..BS]: среднее время в очереди в ms за последние 1024 запроса
59. ctime [..BS]: среднее время соединения в ms за последние 1024 запроса
60. rtime [..BS]: среднее время ответа в ms за последние 1024 запроса
    (0 для TCP)
61. ttime [..BS]: средняя общая длительность сеанса в ms за последние 1024
    запроса
62. agent_status [...S]: состояние последней проверки агента, одно из:
       UNK     -> неизвестно
       INI     -> инициализация
       SOCKERR -> ошибка сокета
       L4OK    -> проверка уровня 4 пройдена, проверки верхних уровней отключены
       L4TOUT  -> тайм-аут уровня 1-4
       L4CON   -> проблема соединения на уровне 1-4, например
                  "Connection refused" (tcp rst) или "No route to host" (icmp)
       L7OK    -> агент сообщил "up"
       L7STS   -> агент сообщил "fail", "stop" или "down"
63. agent_code [...S]: числовой код от агента, если есть (пока не используется)
64. agent_duration [...S]: длительность последней проверки в ms
65. check_desc [...S]: краткое понятное человеку описание check_status
66. agent_desc [...S]: краткое понятное человеку описание agent_status
67. check_rise [...S]: параметр сервера "rise", используемый проверками
68. check_fall [...S]: параметр сервера "fall", используемый проверками
69. check_health [...S]: значение проверки работоспособности сервера от 0 до rise+fall-1
70. agent_rise [...S]: параметр агента "rise", обычно 1
71. agent_fall [...S]: параметр агента "fall", обычно 1
72. agent_health [...S]: параметр работоспособности агента от 0 до rise+fall-1
73. addr [L..S]: address:port или "unix". Адрес IPv6 заключён в скобки.
74: cookie [..BS]: значение cookie сервера или имя cookie бэкенда
75: mode [LFBS]: режим прокси (tcp, http, health, unknown)
76: algo [..B.]: алгоритм балансировки нагрузки
77: conn_rate [.F..]: число соединений за последнюю истёкшую секунду
78: conn_rate_max [.F..]: наибольшее известное значение conn_rate
79: conn_tot [.F..]: суммарное число соединений
80: intercepted [.FB.]: суммарное число перехваченных запросов (monitor, stats)
81: dcon [LF..]: запросы, отклонённые правилами "tcp-request connection"
82: dses [LF..]: запросы, отклонённые правилами "tcp-request session"
83: wrew [LFBS]: суммарное число предупреждений о неудачной перезаписи заголовков
84: connect [..BS]: суммарное число попыток установления соединения
85: reuse [..BS]: суммарное число повторных использований соединений
86: cache_lookups [.FB.]: суммарное число поисков в кэше
87: cache_hits [.FB.]: суммарное число попаданий в кэш
88: srv_icur [...S]: текущее число неактивных соединений, доступных для повторного использования
89: src_ilim [...S]: предел числа доступных неактивных соединений
90. qtime_max [..BS]: максимальное наблюдавшееся время в очереди в ms
91. ctime_max [..BS]: максимальное наблюдавшееся время соединения в ms
92. rtime_max [..BS]: максимальное наблюдавшееся время ответа в ms (0 для TCP)
93. ttime_max [..BS]: максимальная наблюдавшаяся общая длительность сеанса в ms
94. eint [LFBS]: суммарное число внутренних ошибок
95. idle_conn_cur [...S]: текущее число небезопасных неактивных соединений
96. safe_conn_cur [...S]: текущее число безопасных неактивных соединений
97. used_conn_cur [...S]: текущее число используемых соединений
98. need_conn_est [...S]: оценка необходимого числа соединений
99. uweight [..BS]: суммарный пользовательский вес (бэкенд), пользовательский вес сервера (сервер)
100. agg_server_status [..B.]: агрегированный показатель состояния серверов бэкенда
101. agg_server_status_check [..B.]: (устарело)
102. agg_check_status [..B.]: агрегированный показатель состояния проверок
     работоспособности серверов бэкенда
103. srid [...S]: ревизия идентификатора сервера
104. sess_other [.F..]: общее число сеансов, отличных от HTTP, с запуска процесса
105. h1_sess [.F..]: общее число сеансов HTTP/1 с запуска процесса
106. h2_sess [.F..]: общее число сеансов HTTP/2 с запуска процесса
107. h3_sess [.F..]: общее число сеансов HTTP/3 с запуска процесса
108. req_other [.F..]: общее число сеансов, отличных от HTTP, обработанных
     этим объектом с запуска рабочего процесса
109. h1req [.F..]: общее число сеансов HTTP/1, обработанных этим объектом
     с запуска рабочего процесса
110. h2req [.F..]: общее число сеансов hTTP/2, обработанных этим объектом
     с запуска рабочего процесса
111. h3req [.F..]: общее число сеансов HTTP/3, обработанных этим объектом
     с запуска рабочего процесса
112. proto [L...]: протокол
113. priv_idle_cur [...S]: текущее число частных неактивных соединений
114. reqbin [LFBS]: общее число полученных байтов запросов с запуска
     рабочего процесса
115. reqbout [LFBS]: общее число отправленных байтов запросов с запуска
     рабочего процесса
116. resbin [LFBS]: общее число полученных байтов ответов с запуска
     рабочего процесса
117. resbout [LFBS]: общее число отправленных байтов ответов с запуска
     рабочего процесса

Для всех остальных доменов статистики наличие и порядок полей не гарантируются. В этом случае при разборе данных CSV всегда следует использовать строку заголовков.

9.2. Типизированный формат вывода

Команды “show info” и “show stat” поддерживают режим, в котором каждое выводимое значение сопровождается типом и сведениями, достаточными для определения способа его агрегации по процессам и характера изменения.

Во всех случаях каждое значение выводится в отдельной строке, а все сведения разделены на поля двоеточиями (’:’).

Первый столбец обозначает выводимый объект или метрику. Его формат зависит от команды, формирующей вывод, и в этом разделе не рассматривается. Обычно это последовательность идентификаторов и имён полей.

Второй столбец содержит 4 символа, обозначающих соответственно источник, характер, область действия и сохранность выводимого значения. Первый символ (источник) указывает, откуда извлечено значение. Возможны следующие символы:

M   Значение является метрикой. Оно действительно в определённый момент
    времени и может меняться в зависимости от своего характера.

S   Значение обозначает состояние. Это дискретное значение, которое по
    определению нельзя агрегировать. Это может быть состояние сервера
    ("UP" или "DOWN"), PID процесса и т. д.

K   Значение является ключом сортировки. Это идентификатор, позволяющий
    группировать значения, поскольку он уникален в своём классе. Все
    внутренние идентификаторы являются ключами. Некоторые имена могут
    считаться ключами, если они уникальны (например, имя фронтенда уникально).
    Обычно ключи берутся из конфигурации, хотя некоторые назначаются
    автоматически. В большинстве случаев ключи можно считать эквивалентом
    конфигурации.

C   Значение взято из конфигурации. Некоторые значения конфигурации полезны
    в выводе, например предел числа одновременных соединений или имя cookie.
    По определению эти значения одинаковы во всех процессах, запущенных
    с одним и тем же файлом конфигурации.

P   Значение задано самим продуктом. Таких значений очень мало; чаще всего
    они сообщают название продукта, версию и дату выпуска. Эти элементы
    также одинаковы во всех процессах.

Второй символ (характер) обозначает характер информации в поле, чтобы агрегатор мог выбрать операцию для объединения нескольких значений. Возможны следующие символы:

A   Значение обозначает время с момента последнего события. Оно несколько
    отличается от длительности: прошедшее время вычисляется автоматически
    на основе текущей даты. Типичный пример — время с последнего сеанса
    на сервере. Такие значения обычно агрегируют, выбирая минимум, и их
    не требуется хранить.

a   Значение уже усреднено. К этому типу относятся среднее время ответа
    и веса серверов. Средние значения обычно можно усреднять по процессам.

C   Значение является накопительным счётчиком. Такие показатели постоянно
    растут до переполнения. Некоторым протоколам мониторинга требуется
    различать счётчик и показатель текущего значения, чтобы сообщать разные
    типы. Обычно счётчики можно просто суммировать, поскольку они отражают
    события или объёмы. Примеры метрик такого типа — число соединений
    или число байтов.

D   Значение обозначает длительность состояния. Применений немного;
    чаще всего это длительность последней проверки работоспособности
    и время недоступности сервера. Длительности обычно не суммируют;
    чаще всего для расчёта SLA сохраняют максимальное значение.

G   Значение является показателем текущего значения (gauge): измерением
    в определённый момент времени. К этому типу относятся потребление памяти
    и текущее число активных соединений. При агрегации метрики этого типа
    обычно суммируют.

L   Значение обозначает ограничение (обычно заданное в конфигурации).
    Ограничения по своей природе труднее агрегировать, поскольку они
    относятся к конкретному месту измерения. В некоторых ситуациях их
    можно суммировать или учитывать отдельно.

M   Значение обозначает максимум. Обычно оно относится к показателю
    текущего значения и сохраняет наибольшее известное значение. Пример —
    максимальное число одновременных соединений за время работы продукта.
    Для правильной агрегации максимумов следует выводить диапазон от
    наибольшего из всех максимумов до их суммы: невозможно узнать,
    были ли эти максимумы достигнуты одновременно.

m   Значение обозначает минимум. Обычно оно относится к показателю
    текущего значения и сохраняет наименьшее известное значение. Пример —
    минимальное количество свободных пулов памяти за время работы продукта.
    Для правильной агрегации минимумов следует выводить диапазон от
    наименьшего из всех минимумов до их суммы: невозможно узнать,
    были ли эти минимумы достигнуты одновременно.

N   Значение обозначает имя и потому является строкой. Оно служит для
    вывода имён прокси, серверов и cookie. Имена берутся из конфигурации
    или ключей; предполагается, что они одинаковы во всех процессах.

O   Значение является произвольным текстом. К этому типу относятся вывод
    различных команд, результаты проверок работоспособности и описания узлов.

R   Значение обозначает интенсивность событий. Это измерение в определённый
    момент времени. Оно очень похоже на показатель текущего значения,
    но получатель знает, что оно меняется медленно, и может решить не хранить
    все значения. Пример такой метрики — измеренное число соединений
    в секунду. При агрегации метрики этого типа обычно суммируют.

T   Значение обозначает дату или время. К этому типу относилось бы поле
    с текущей датой. Способ агрегации таких данных зависит от реализации.
    Пока ни одно поле не использует этот тип.

Третий символ (область действия) указывает, к какой области относится значение. Одни элементы относятся к процессу, другие — к конфигурации или системе. Это различие важно для определения того, следует ли при агрегации оставить единственное значение или объединить несколько значений. В настоящее время поддерживаются следующие символы:

C   Значение действительно для всего кластера узлов — совокупности узлов,
    взаимодействующих по протоколу peers. Пример — число записей в таблице
    привязок, реплицируемой на другие узлы peers. В настоящее время ни одна
    метрика не использует эту область действия.

P   Значение действительно только для процесса, который его сообщает.
    Большинство метрик используют эту область действия.

S   Значение действительно для всей службы — совокупности процессов,
    запущенных вместе с одним и тем же файлом конфигурации. Все метрики,
    полученные из конфигурации, используют эту область действия.
    Некоторые другие метрики общих ресурсов также могут её использовать
    (например, статистика общего кэша SSL).

s   Значение действительно для всей системы, например имя узла системы,
    текущая дата или использование ресурсов. В настоящее время ни одна
    метрика не использует эту область действия.

Четвёртый символ (сохранность) указывает, теряется или сохраняется значение метрики при перезагрузках конфигурации. Ожидаются следующие символы:

V   Метрика непостоянная, поскольку она локальна для текущего процесса,
    и её значение теряется при перезагрузке конфигурации.

P   Метрика постоянная, поскольку может совместно использоваться другими
    процессами, благодаря чему значение сохраняется при перезагрузках.

Потребителям этих данных обычно достаточно указанных 4 символов, чтобы определить, как правильно представлять агрегированную информацию по нескольким процессам.

Следующий, третий столбец указывает тип поля: “s32” (знаковое 32-разрядное целое), “s64” (знаковое 64-разрядное целое), “u32” (беззнаковое 32-разрядное целое), “u64” (беззнаковое 64-разрядное целое) или “str” (строка). Для правильного чтения значения необходимо знать его тип до разбора. Например, строка, содержащая только цифры, остаётся строкой, а не целым числом (например, код ошибки, извлечённый при проверке).

Четвёртый столбец содержит само значение, закодированное в соответствии с его типом. Строки выводятся без изменений сразу после двоеточия, без начального пробела. Если строка содержит двоеточие, оно выводится как обычно. Поэтому нельзя просто разбивать весь вывод по двоеточиям: некоторые результаты проверок или адреса серверов могут оказаться усечёнными.

9.3. Команды сокета Unix

По умолчанию сокет статистики отключён. Для его включения необходимо добавить строку в секцию global конфигурации HAProxy. Рекомендуется добавить и вторую строку, задающую больший тайм-аут: это удобно при вводе команд вручную:

global
    stats socket /var/run/haproxy.sock mode 600 level admin
    stats timeout 2m

Повторив строку, можно добавить несколько сокетов статистики и настроить их на прослушивание порта TCP вместо сокета UNIX. По умолчанию это никогда не делается, поскольку это опасно, но в некоторых ситуациях может быть полезно:

global
    stats socket /var/run/haproxy.sock mode 600 level admin
    stats socket ipv4@192.168.0.1:9999 level admin
    stats timeout 2m

Для доступа к сокету требуется внешняя утилита, например “socat”. Socat — универсальное средство соединения разных источников и приёмников. Здесь она используется для подключения терминалов к сокету либо для подключения к нему пары каналов stdin/stdout из скриптов. Основные два варианта синтаксиса:

# socat /var/run/haproxy.sock stdio
# socat /var/run/haproxy.sock readline

Первый вариант используется в скриптах. Вывод скрипта можно направить в HAProxy, а вывод HAProxy — в другой скрипт. Это удобно, например, для получения счётчиков или следов атак.

Второй вариант полезен только для ввода команд вручную. Его преимущество — обработка терминала библиотекой readline, поддерживающей редактирование строк и историю. Это очень удобно при повторном вводе команд (например, для наблюдения за счётчиком).

Сокет поддерживает три режима работы:

  • неинтерактивный, без приглашения
  • интерактивный, без приглашения
  • интерактивный с приглашением

При подключении socat к сокету по умолчанию используется неинтерактивный режим. В нём можно отправить одну строку: она обрабатывается целиком, ответы отправляются обратно, а после завершения ответа соединение закрывается. Этот режим используют скрипты и средства мониторинга. В нём можно отправить несколько команд, разделив их точкой с запятой (’;’). Например:

# echo "show info;show stat;show table" | socat /var/run/haproxy stdio

Если в команде требуется точка с запятой или обратная косая черта (например, в значении), перед ней обязательно ставится обратная косая черта (’\’).

Интерактивный режим позволяет отправлять новые команды после завершения команд из предыдущих строк. Есть два варианта: без приглашения, работающий как неинтерактивный режим, но ожидающий новую команду вместо закрытия сокета, и с приглашением (’>’) в начале строки. Для более сложных инструментов предпочтителен интерактивный режим, а для ручной работы — режим с приглашением.

Режим меняется командой “prompt”. По умолчанию она переключает интерактивный режим и режим с приглашением. Ввод “prompt” в интерактивном режиме включает приглашение. Команда также может принимать обозначение конкретного режима:

  • “n”: неинтерактивный режим (одна команда и выход)
  • “i”: интерактивный режим (несколько команд, без приглашения)
  • “p”: режим с приглашением (несколько команд с приглашением)

Поскольку по умолчанию действует неинтерактивный режим, для его переключения “prompt” должна быть первой командой; иначе предыдущая команда приведёт к закрытию соединения. При переключении в неинтерактивный режим соединение закрывается после выполнения всех команд той же строки.

Поэтому при отладке вручную работу часто начинают с команды “prompt”:

# socat /var/run/haproxy readline
prompt

show info …

Интерактивным инструментам может быть удобнее начинать с “prompt i”, чтобы включить интерактивный режим без приглашения.

В приглашении также можно показывать время работы процесса. Команда “prompt timed” включает приглашение и переключает отображение времени. Время работы выводится в формате “d:hh:mm:ss”, где “d” — число дней, а “hh”, “mm” и “ss” — число часов, минут и секунд соответственно, по две цифры каждое:

# socat /var/run/haproxy readline
prompt timed

[23:03:34:39]> show version 2.8-dev9-e5e622-18

[23:03:34:41]> quit

Если приглашение со временем включено в CLI главного процесса, оно показывает время работы выбранного процесса. Это работает для главного процесса, текущего рабочего процесса и старого рабочего процесса:

master> prompt timed
[0:00:00:50] master> show proc
(...)
[0:00:00:58] master> @!11955     <-- master, switch to current worker
[0:00:01:03] 11955> @!11942      <-- current worker, switch to older worker
[0:00:02:17] 11942> @            <-- older worker, switch back to master
[0:00:01:10] master>

Поскольку за один раз можно передать несколько команд, HAProxy отмечает конец вывода каждой команды пустой строкой и гарантирует, что сами команды не выводят пустых строк. Поэтому скрипт легко разбирает вывод, даже если несколько команд переданы подряд в одной строке.

Некоторые команды принимают необязательную полезную нагрузку. Чтобы добавить её, первая строка команды должна заканчиваться последовательностью “<<\n”. Следующие строки считаются полезной нагрузкой; их может быть столько, сколько требуется. Для подтверждения команды с полезной нагрузкой ввод должен завершаться пустой строкой.

Маркер полезной нагрузки можно настроить, изменив способ определения её конца. Чтобы завершать полезную нагрузку чем-либо, кроме пустой строки, между ‘<<’ и ‘\n’ можно задать собственный маркер. В дополнение к ‘<<’ допускается не более 64 символов, иначе последовательность не будет распознана как начало полезной нагрузки. Этого должно хватать для случайных маркеров. Например, для передачи файла PEM с пустыми строками и комментариями:

# echo -e "set ssl cert common.pem <<%EOF%\n$(cat common.pem)\n%EOF%\n" | \
socat /var/run/haproxy.stat -

Есть ограничения: последовательность “<<” не должна примыкать к последнему слову строки. Длина командной строки не должна превышать tune.bufsize, включая маркер начала полезной нагрузки, но исключая саму полезную нагрузку. Её размер по умолчанию ограничен 128KB. Это можно изменить глобальным параметром “tune.cli.max-payload-size”, соблюдая осторожность. Маркер конца полезной нагрузки также входит в это ограничение.

При вводе полезной нагрузки в интерактивном режиме приглашение меняется с “> " на “+ “.

Важно понимать: если на одних и тех же сокетах запущено несколько процессов HAProxy, запрос может принять любой из них, и он выведет собственную статистику.

Ниже перечислены команды, которые сейчас поддерживает сокет статистики. В ответ на неизвестную команду HAProxy выводит справку со всеми поддерживаемыми командами. Некоторые команды имеют более сложный синтаксис; при ошибке обычно поясняется, какая часть команды некорректна.

Некоторым командам нужен более высокий уровень привилегий. При недостаточных привилегиях возвращается ошибка “Permission denied”. Подробнее см. описание опции “level” в строках ключевого слова “bind” в руководстве по конфигурации.

abort ssl ca-file <cafile>

abort ssl ca-file <cafile>

Прерывает и уничтожает временную транзакцию обновления файла CA.

См. также “set ssl ca-file” и “commit ssl ca-file”.

abort ssl cert <filename>

abort ssl cert <filename>

Прерывает и уничтожает временную транзакцию обновления сертификата SSL.

См. также “set ssl cert” и “commit ssl cert”.

abort ssl crl-file <crlfile>

abort ssl crl-file <crlfile>

Прерывает и уничтожает временную транзакцию обновления файла CRL.

См. также “set ssl crl-file” и “commit ssl crl-file”.

acme renew <certificate>

acme renew <certificate>

Запускает задачу выпуска сертификата ACME с указанным именем сертификата. Сертификат должен быть связан с секцией acme; см. раздел 12.8 “ACME” руководства по конфигурации. См. также “acme status”.

acme status

acme status

Показывает состояние всех сертификатов, настроенных с использованием ACME.

Команда выводит следующие поля, разделённые табуляцией:

  • Имя сертификата, заданное в HAProxy
  • Секция acme, используемая в конфигурации
  • Состояние задачи acme: “Running”, “Scheduled” или “Stopped”
  • Дата окончания срока действия сертификата в UTC в формате ISO8601
  • Время до окончания срока действия (0d, если срок истёк)
  • Запланированная дата для сертификата в UTC в формате ISO8601
  • Время до запланированного запуска (0d в состоянии Running)

Пример:

$ echo "@1; acme status" | socat /tmp/master.sock - | column -t -s $'\t'
# certificate   section  state      expiration date (UTC)  expires in        scheduled date (UTC)  scheduled in
ecdsa.pem       LE       Running    2020-01-18T09:31:12Z   0d 0h00m00s       2020-01-15T21:31:12Z  0d 0h00m00s
foobar.pem.rsa  LE       Scheduled  2025-08-04T11:50:54Z   89d 23h01m13s     2025-07-27T23:50:55Z  82d 11h01m14s

add acl [@<ver>] <acl> <pattern>

add acl [@<ver>] <acl> <pattern>

Добавляет запись в acl <acl>. <acl> — это #<id> или <name>, возвращённые командой “show acl”. Команда не проверяет, существует ли запись. Записи добавляются в текущую версию ACL, если конкретная версия не указана через “@<ver>”. Номер версии должен быть заранее выделен командой “prepare acl” и находиться в диапазоне от “curr_ver” до “next_ver” в выводе “show acl”. Записи с явно заданным номером версии не будут участвовать в сопоставлении до выполнения операции “commit acl”. Однако их можно просматривать командой “show acl @<ver>” и очищать командой “clear acl @<ver>”. Эту команду нельзя использовать, если ссылка <acl> является именем, которое также используется для карты. В этом случае необходимо использовать команду “add map”.

add backend <name> from <defproxy> [mode <mode>] [guid <guid>]

add backend <name> from <defproxy> [mode <mode>] [guid <guid>]

Создаёт новый бэкенд-прокси с именем <name>.

Можно создавать только прокси TCP или HTTP. Все настройки наследуются от экземпляра прокси defaults <defproxy>. По умолчанию режим бэкенда обязательно задаётся одноимённым аргументом, если только он уже не указан явно в <defproxy>. При необходимости также можно передать необязательный аргумент GUID.

Серверы можно добавлять командой “add server”. Бэкенд создаётся в неопубликованном состоянии. Когда он будет готов принимать трафик, команда “publish backend” делает новый экземпляр доступным.

Можно использовать любые именованные прокси defaults, если они удовлетворяют тем же правилам наследования, которые действуют при разборе конфигурации. Однако есть исключения, например режим, отличный от TCP и HTTP.

Команда имеет ограниченный доступ и может выполняться только через сокеты, настроенные с уровнем “admin”.

add map [@<ver>] <map> <key> <value>

add map [@<ver>] <map> <key> <value>
add map [@<ver>] <map> <payload>

Добавляет запись в карту <map>, связывая значение <value> с ключом <key>. Команда не проверяет, существует ли запись. В основном она используется для заполнения карты после операции “clear” или “prepare”. Записи добавляются в текущую версию ACL, если конкретная версия не указана через “@<ver>”. Номер версии должен быть заранее выделен командой “prepare acl” и находиться в диапазоне от “curr_ver” до “next_ver” в выводе “show acl”. Записи с явно заданным номером версии не будут участвовать в сопоставлении до выполнения операции “commit map”. Однако их можно просматривать командой “show map @<ver>” и очищать командой “clear acl @<ver>”. Если указанная карта также используется как ACL, ACL сопоставляет только часть <key> и игнорирует часть <value>. Синтаксис с полезной нагрузкой позволяет добавлять несколько пар ключ/значение, вводя их в отдельных строках. В каждой новой строке первое слово является ключом, а остаток строки считается значением, которое может содержать пробелы.

Пример:

# socat /tmp/sock1 -
prompt

> add map #-1 <<
+ key1 value1
+ key2 value2 with spaces
+ key3 value3 also with spaces
+ key4 value4

>

add server <backend>/<server> [args]*

add server <backend>/<server> [args]*

Создаёт новый сервер, связанный с бэкендом <backend>.

Имя <server> не должно уже использоваться в бэкенде. Для бэкенда действует особое ограничение: он должен использовать динамический алгоритм балансировки нагрузки. Поведение сервера можно настроить частью ключевых слов директивы server файла конфигурации (их список выводит “add server help”). Настройки возможной директивы ‘default-server’ в том же бэкенде не наследуются.

В настоящее время динамический сервер статически инициализируется методом init-addr “none”. Это означает, что при указании FQDN в качестве адреса разрешение имени не выполняется, хотя запрос на создание сервера будет признан корректным.

Для поддержки перезагрузки конфигурации сервер, созданный через CLI, следует также вручную добавить в соответствующий файл конфигурации HAProxy. Динамический сервер, отсутствующий в конфигурации, после её перезагрузки не восстанавливается.

Динамический сервер может использовать ключевое слово “track” для отслеживания состояния проверок другого сервера из конфигурации. Однако отслеживать другой динамический сервер нельзя. Это обеспечивает согласованность цепочки отслеживания даже при удалении динамических серверов.

Ключевое слово “check” включает поддержку проверок работоспособности. По умолчанию сама проверка отключена, и её необходимо включить отдельно от сервера командой “enable health”. Для проверок агента используются ключевое слово “agent-check” и команда “enable agent”. В этом случае агент может активировать сервер в зависимости от сообщённого состояния без явной команды “enable server”. Поэтому удаление динамического сервера с проверкой агента требует особой осторожности. Сначала следует отключить агент командой “disable agent”, чтобы перед удалением можно было перевести сервер в обязательный режим обслуживания.

При большом числе динамических серверов можно достичь предела числа файловых дескрипторов (fd). В этом случае см. документацию глобального ключевого слова “u-limit”.

add server help

add server help

Выводит ключевые слова, поддерживаемые для динамических серверов текущей версией HAProxy. Их синтаксис аналогичен строке server в файле конфигурации; подробности приведены в документации каждого ключевого слова.

add ssl ca-file <cafile> <payload>

add ssl ca-file <cafile> <payload>

Добавляет новый сертификат в ca-file. Команда полезна, когда достигнут предел размера буфера CLI и требуется добавить несколько сертификатов. Вместо “set” со всеми сертификатами можно добавлять их по одному. Команда “set ssl ca-file” сбрасывает содержимое ca-file.

Пример:

echo -e "set ssl ca-file cafile.pem <<\n$(cat rootCA.crt)\n" | \
socat /var/run/haproxy.stat -
echo -e "add ssl ca-file cafile.pem <<\n$(cat intermediate1.crt)\n" | \
socat /var/run/haproxy.stat -
echo -e "add ssl ca-file cafile.pem <<\n$(cat intermediate2.crt)\n" | \
socat /var/run/haproxy.stat -
echo "commit ssl ca-file cafile.pem" | socat /var/run/haproxy.stat -

add ssl crt-list <crtlist> <certificate>

add ssl crt-list <crtlist> <certificate>
add ssl crt-list <crtlist> <payload>

Добавляет сертификат в crt-list. Команду также можно использовать для каталогов, поскольку теперь они загружаются так же, как crt-list. Имя сертификата можно передать параметром; чтобы использовать опции SSL или фильтры, вместо этого необходимо передать строку crt-list как полезную нагрузку. В полезной нагрузке поддерживается только одна строка crt-list. Команда загружает сертификат для всех строк bind, использующих этот crt-list. Для передачи нового сертификата в HAProxy необходимо использовать команды “new ssl cert” и “set ssl cert”.

Пример:

$ echo "new ssl cert foobar.pem" | socat /tmp/sock1 -
$ echo -e "set ssl cert foobar.pem <<\n$(cat foobar.pem)\n" | socat
/tmp/sock1 -
$ echo "commit ssl cert foobar.pem" | socat /tmp/sock1 -
$ echo "add ssl crt-list certlist1 foobar.pem" | socat /tmp/sock1 -

$ echo -e 'add ssl crt-list certlist1 <<\nfoobar.pem [allow-0rtt] foo.bar.com
!test1.com\n' | socat /tmp/sock1 -

add ssl ech <bind> <payload>

add ssl ech <bind> <payload>

Добавляет ключ ECH в строку <bind>. Полезная нагрузка должна быть в формате PEM для ECH. (https://datatracker.ietf.org/doc/html/draft-farrell-tls-pemesni )

Формат строки bind: <frontend>/@<filename>:<linenum> (пример: frontend1/@haproxy.conf :19) или <frontend>/<name>, если строке bind назначено имя ключевым словом “name”.

Требуется версия OpenSSL с поддержкой ECH, а HAProxy должен быть собран с USE_ECH=1. Команда поддерживается только в соединении CLI, работающем в экспериментальном режиме (см. “experimental-mode on”).

См. также “show ssl ech” и “ech” в разделе 5.1 руководства по конфигурации.

Пример:

$ openssl ech -public_name foobar.com -out foobar3.com.ech
$ echo -e "experimental-mode on; add ssl ech frontend1/@haproxy.conf:19 <<%EOF%\n$(cat foobar3.com.ech)\n%EOF%\n" | \
  socat /tmp/haproxy.sock -
added a new ECH config to frontend1

add ssl jwt <filename>

add ssl jwt <filename>

Добавляет уже загруженный сертификат в список сертификатов для проверки JWT (см. преобразователь “jwt_verify_cert”). Команда не работает с незавершёнными транзакциями. См. также команды “del ssl jwt” и “show ssl jwt”. Дополнительные сведения приведены в описании опции сертификата “jwt”.

clear counters

clear counters

Сбрасывает максимальные значения статистических счётчиков в каждом прокси (фронтенде и бэкенде) и на каждом сервере. Накопительные счётчики не затрагиваются. Также сбрасываются внутренние счётчики активности, выводимые командой “show activity”. Это позволяет получить чистые счётчики после инцидента без перезапуска и без сброса счётчиков трафика. Команда имеет ограниченный доступ и может выполняться только через сокеты с уровнем “operator” или “admin”.

clear counters all

clear counters all

Сбрасывает все статистические счётчики в каждом прокси (фронтенде и бэкенде) и на каждом сервере. Эффект тот же, что при перезапуске. Команда имеет ограниченный доступ и может выполняться только через сокеты с уровнем “admin”.

clear acl [@<ver>] <acl>

clear acl [@<ver>] <acl>

Удаляет все записи из acl <acl>. <acl> — это #<id> или <name>, возвращённые командой “show acl”. Если ссылка <acl> является именем, общим с картой, эта карта также очищается. По умолчанию очищается только текущая версия ACL (используемая для сопоставления). Однако можно указать другую версию, поставив её номер после ‘@’.

clear map [@<ver>] <map>

clear map [@<ver>] <map>

Удаляет все записи из карты <map>. <map> — это #<id> или <name>, возвращённые командой “show map”. Если ссылка <map> является именем, общим с acl, этот acl также очищается. По умолчанию очищается только текущая версия карты (используемая для сопоставления). Однако можно указать другую версию, поставив её номер после ‘@’.

clear table <table> [ data.<type> <operator> <value> ] | [ key <key> ] |

clear table <table> [ data.<type> <operator> <value> ] | [ key <key> ] |
                    [ ptr <ptr> ]

Удаляет записи из таблицы привязок <table>.

Обычно команда используется для разблокировки пользователей, сообщающих о необоснованном отказе в доступе к службе. Ею также можно удалить записи привязки к серверу, который предстоит заменить (подробности см. ниже в описании “show table”). Иногда удаление записи отклоняется, поскольку она в данный момент отслеживается сеансом. Обычно достаточно повторить попытку через несколько секунд, когда сеанс завершится.

Если аргументы опций не заданы, удаляются все записи.

При использовании формы “data.” удаляются записи, соответствующие фильтру по сохранённым данным (см. “stick-table” в разделе 4.2). В <type> необходимо указать тип сохраняемых данных; этот тип должен храниться в таблице, иначе возвращается ошибка. Оператор <operator> определяет сравнение данных с 64-разрядным целым <value>. Операторы те же, что в ACL:

- eq: записи, данные которых равны этому значению
- ne: записи, данные которых не равны этому значению
- le: записи, данные которых меньше или равны этому значению
- ge: записи, данные которых больше или равны этому значению
- lt: записи, данные которых меньше этого значения
- gt: записи, данные которых больше этого значения

При использовании формы key удаляется запись <key>. Ключ должен иметь тот же тип, что и таблица; в настоящее время поддерживаются только IPv4, IPv6, целое число и строка.

При использовании формы ptr удаляется запись <ptr>. <ptr> задаётся в виде 0xffff и должен соответствовать адресу, возвращённому предыдущей командой “show table”. Поиск записи по указателю полезен, если найти её по ключу невозможно из-за пустого ключа или символов, несовместимых с CLI.

Если data.<type> имеет тип массива, для доступа к определённому индексу можно использовать “[]”, например: data.gpt[1]

Пример:

    $ echo "show table http_proxy" | socat stdio /tmp/sock1
>>> # table: http_proxy, type: ip, size:204800, used:2
>>> 0x80e6a4c: key=127.0.0.1 use=0 exp=3594729 gpc0=0 conn_rate(30000)=1 \
      bytes_out_rate(60000)=187
>>> 0x80e6a80: key=127.0.0.2 use=0 exp=3594740 gpc0=1 conn_rate(30000)=10 \
      bytes_out_rate(60000)=191
>>> 0x80e6b40: key=127.0.0.3 use=0 exp=3594743 gpc0=2 conn_rate(30000)=10 \
      bytes_out_rate(60000)=200

    $ echo "clear table http_proxy key 127.0.0.1" | socat stdio /tmp/sock1

    $ echo "show table http_proxy" | socat stdio /tmp/sock1
>>> # table: http_proxy, type: ip, size:204800, used:1
>>> 0x80e6a80: key=127.0.0.2 use=0 exp=3594740 gpc0=1 conn_rate(30000)=10 \
>>> 0x80e6b40: key=127.0.0.3 use=0 exp=3594743 gpc0=2 conn_rate(30000)=10 \
      bytes_out_rate(60000)=200
      bytes_out_rate(60000)=191
    $ echo "clear table http_proxy data.gpc0 eq 1" | socat stdio /tmp/sock1
    $ echo "show table http_proxy" | socat stdio /tmp/sock1
>>> # table: http_proxy, type: ip, size:204800, used:1
>>> 0x80e6b40: key=127.0.0.3 use=0 exp=3594743 gpc0=2 conn_rate(30000)=10 \
      bytes_out_rate(60000)=200

    $ echo "clear table http_proxy ptr 0x80e6b40" | socat stdio /tmp/sock1
    $ echo "show table http_proxy" | socat stdio /tmp/sock1
>>> # table: http_proxy, type: ip, size:204800, used:0

commit acl @<ver> <acl>

commit acl @<ver> <acl>

Фиксирует все изменения версии <ver> ACL <acl> и удаляет все предыдущие версии. <acl> — это #<id> или <name>, возвращённые командой “show acl”. Номер версии должен находиться в диапазоне от “curr_ver”+1 до “next_ver” из вывода “show acl”. При необходимости содержимое, которое будет записано в ACL, можно просмотреть командой “show acl @<ver> <acl>”. Обычно указанный номер версии создаётся командой “prepare acl”. Замена атомарна: текущая версия атомарно меняется на указанную, вследствие чего все записи других версий сразу становятся невидимыми, а все записи новой версии — видимыми. Команду также можно использовать для атомарного удаления всех видимых записей ACL: сначала вызвать “prepare acl”, затем выполнить фиксацию без добавления записей. Эту команду нельзя использовать, если ссылка <acl> является именем, которое также используется для карты. В этом случае необходимо использовать команду “commit map”.

commit map @<ver> <map>

commit map @<ver> <map>

Фиксирует все изменения версии <ver> карты <map> и удаляет все предыдущие версии. <map> — это #<id> или <name>, возвращённые командой “show map”. Номер версии должен находиться в диапазоне от “curr_ver”+1 до “next_ver” из вывода “show map”. При необходимости содержимое, которое будет записано в карту, можно просмотреть командой “show map @<ver> <map>”. Обычно указанный номер версии создаётся командой “prepare map”. Замена атомарна: текущая версия атомарно меняется на указанную, вследствие чего все записи других версий сразу становятся невидимыми, а все записи новой версии — видимыми. Команду также можно использовать для атомарного удаления всех видимых записей карты: сначала вызвать “prepare map”, затем выполнить фиксацию без добавления записей.

commit ssl ca-file <cafile>

commit ssl ca-file <cafile>

Фиксирует временную транзакцию обновления файла CA для SSL.

Если файл CA уже существует (имеет состояние “Used” в выводе “show ssl ca-file”), новая запись файла CA вставляется в дерево файлов CA, а каждый экземпляр, использовавший прежнюю запись, перестраивается вместе со всеми необходимыми ему контекстами SSL. Все контексты, ранее использовавшиеся перестроенными экземплярами, удаляются. При успехе прежняя запись файла CA удаляется из дерева. При сбое ничего не удаляется, а все исходные контексты SSL сохраняются и продолжают использоваться. После фиксации временная транзакция уничтожается.

Если файл CA новый (создан командой “new ssl ca-file” и имеет состояние “Unused” в выводе “show ssl ca-file”), он вставляется в дерево файлов CA, но нигде в HAProxy не используется. Чтобы использовать его и создать использующие его контексты SSL, необходимо добавить его в crt-list командой “add ssl crt-list”.

См. также “new ssl ca-file”, “set ssl ca-file”, “add ssl ca-file”, “abort ssl ca-file” и “add ssl crt-list”.

commit ssl cert <filename>

commit ssl cert <filename>

Фиксирует временную транзакцию обновления сертификата SSL.

Если сертификат уже существует (имеет состояние “Used” в выводе “show ssl cert”), создаёт и вставляет все необходимые ему контексты SSL и SNI, а прежние удаляет. Заменяет в памяти прежние сертификаты SSL везде, где в конфигурации использовался <filename>. При сбое ничего не удаляет и не вставляет. После фиксации временная транзакция уничтожается.

Если сертификат новый (создан командой “new ssl cert” и имеет состояние “Unused” в выводе “show ssl cert”), он фиксируется в хранилище сертификатов, но нигде в haproxy не используется. Чтобы использовать его и создать его SNI, необходимо добавить его в crt-list или каталог командой “add ssl crt-list”.

См. также “new ssl cert”, “set ssl cert”, “abort ssl cert” и “add ssl crt-list”.

commit ssl crl-file <crlfile>

commit ssl crl-file <crlfile>

Фиксирует временную транзакцию обновления файла CRL для SSL.

Если файл CRL уже существует (имеет состояние “Used” в выводе “show ssl crl-file”), новая запись файла CRL вставляется в дерево файлов CA (которое содержит как файлы CA, так и файлы CRL), а каждый экземпляр, использовавший прежнюю запись файла CRL, перестраивается вместе со всеми необходимыми ему контекстами SSL. Все контексты, ранее использовавшиеся перестроенными экземплярами, удаляются. При успехе прежняя запись файла CRL удаляется из дерева. При сбое ничего не удаляется, а все исходные контексты SSL сохраняются и продолжают использоваться. После фиксации временная транзакция уничтожается.

Если файл CRL новый (создан командой “new ssl crl-file” и имеет состояние “Unused” в выводе “show ssl crl-file”), файл CRL вставляется в дерево файлов CRL, но нигде в HAProxy не используется. Чтобы использовать его и создать использующие его контексты SSL, необходимо добавить его в crt-list командой “add ssl crt-list”.

См. также “new ssl crl-file”, “set ssl crl-file”, “abort ssl crl-file” и “add ssl crt-list”.

debug counters [reset|show|on|off|all|bug|chk|cnt|glt|?]*

debug counters [reset|show|on|off|all|bug|chk|cnt|glt|?]*

Выводит внутренние счётчики, размещённые в коде; их набор может зависеть от опций сборки. Одни зависят от DEBUG_STRICT, другие — от DEBUG_COUNTERS. Команда принимает сочетание нескольких аргументов: одни задают действия, другие — фильтры: - bug включает вывод счётчиков для операторов BUG_ON() - cnt включает вывод счётчиков для операторов COUNT_IF() - chk включает вывод счётчиков для операторов CHECK_IF() - glt включает вывод счётчиков для операторов COUNT_GLITCH() - all включает вывод счётчиков, которые ни разу не срабатывали (значение 0) - действие off: отключает обновление счётчиков COUNT_IF() - действие on: включает обновление счётчиков COUNT_IF() - действие reset: сбрасывает все указанные счётчики - действие show: выводит все указанные счётчики

По умолчанию используется действие “show”, выводящее счётчики, и показываются счётчики всех типов с ненулевым значением. Команда “show” подразумевается, если не указано другое действие; она предусмотрена лишь для упрощения формирования команд в скриптах.

Вывод начинается с целочисленного значения счётчика, за которым следуют его тип в верхнем регистре, местоположение в коде (file:line), имя функции и, при наличии описания, “: " с этим описанием. Обратите внимание: формат вывода может меняться между основными версиями, а новые типы и записи могут переноситься в стабильные версии для улучшения возможностей отладки. Если эти счётчики всё же используются для мониторинга, такой мониторинг должен быть очень терпимым к изменениям и отклонениям; предпочтительно вообще от него отказаться.

Обычно конечные пользователи не используют эту команду, но разработчик, выясняющий причину проблемы, может попросить выполнить её для поиска записей CNT или GLT. При этом ненулевые записи “CHK” не должны появляться; о них следует сообщать разработчикам, поскольку они могут указывать на неверные предположения в коде.

debug dev <command> [args]*

debug dev <command> [args]*

Вызывает команду для разработчиков. Поддерживается только в соединении CLI, работающем в экспертном режиме (см. “expert-mode on”). Такие команды крайне опасны и не прощают ошибок: любое неправильное использование может привести к аварийному завершению процесса. Они предназначены исключительно для специалистов, и их действительно нельзя применять без соответствующего указания. Некоторые доступны только при сборке haproxy с определением DEBUG_DEV, поскольку могут влиять на безопасность. Все эти команды требуют прав admin и намеренно не документированы, чтобы не побуждать к их использованию людей, плохо знакомых с исходным кодом.

del acl <acl> [<key>|#<ref>]

del acl <acl> [<key>|#<ref>]

Удаляет из acl <acl> все записи, соответствующие ключу <key>. <acl> — это #<id> или <name>, возвращённые командой “show acl”. Если используется <ref>, команда удаляет только указанную ссылку. Ссылку можно найти в списке содержимого acl. Если ссылка <acl> является именем, общим с картой, запись также удаляется из карты.

del backend <name>

del backend <name>

Удаляет прокси бэкенда с именем <name>.

Операция возможна только для прокси TCP или HTTP. Для её успешного выполнения экземпляр бэкенда предварительно должен быть снят с публикации. Кроме того, сначала необходимо удалить все его серверы (командой CLI “del server”). Наконец, к экземпляру бэкенда не должно оставаться привязанных потоков.

Есть и другие ограничения, препятствующие удалению бэкенда. Во-первых, бэкенд нельзя удалить, если на него явно ссылаются элементы конфигурации, например правило use_backend или выражения извлечения образцов. Некоторые опции прокси также несовместимы с удалением во время выполнения. В настоящее время это касается устаревших dispatch и option transparent. Кроме того, бэкенд нельзя удалить, если в нём объявлена таблица привязок. Наконец, пока невозможно удалить бэкенд, в котором присутствовали серверы QUIC.

Перед этой командой может быть полезно выполнить “wait be-removable”, чтобы проверить перечисленные условия. Это также позволяет дождаться окончательного закрытия потоков, привязанных к целевому бэкенду.

Команда имеет ограниченный доступ и может выполняться только через сокеты с уровнем “admin”.

del map <map> [<key>|#<ref>]

del map <map> [<key>|#<ref>]

Удаляет из карты <map> все записи, соответствующие ключу <key>. <map> — это #<id> или <name>, возвращённые командой “show map”. Если используется <ref>, команда удаляет только указанную ссылку. Ссылку можно найти в списке содержимого карты. Если ссылка <map> является именем, общим с acl, запись также удаляется из карты.

del ssl ca-file <cafile>

del ssl ca-file <cafile>

Удаляет из HAProxy запись дерева файлов CA. Файл CA не должен использоваться и должен быть удалён из всех crt-list. Команда “show ssl ca-file” показывает состояние файлов CA. Удаление не работает для сертификата, на который конфигурация ссылается напрямую через директивы “ca-file” или “ca-verify-file”.

del ssl cert <certfile>

del ssl cert <certfile>

Удаляет из HAProxy хранилище сертификата. Сертификат не должен использоваться (в том числе для проверки JWT) и должен быть удалён из всех crt-list и каталогов. Команда “show ssl cert” показывает состояние сертификата. Удаление не работает для сертификата, на который конфигурация ссылается напрямую через директиву “crt”.

del ssl crl-file <crlfile>

del ssl crl-file <crlfile>

Удаляет из HAProxy запись дерева файлов CRL. Файл CRL не должен использоваться и должен быть удалён из всех crt-list. Команда “show ssl crl-file” показывает состояние файлов CRL. Удаление не работает для сертификата, на который конфигурация ссылается напрямую через директиву “crl-file”.

del ssl crt-list <filename> <certfile[:line]>

del ssl crt-list <filename> <certfile[:line]>

Удаляет запись из crt-list. При этом удаляются все SNI, используемые этой записью во фронтендах. Если сертификат используется в crt-list несколько раз, необходимо указать строку, которую требуется удалить. Для вывода номеров строк используйте “show ssl crt-list -n <crtlist>”.

del ssl ech <bind>

del ssl ech <bind>

Удаляет ключи ECH строки bind.

Формат строки bind — <frontend>/@<filename>:<linenum> (пример: frontend1/@haproxy.conf :19) или <frontend>/<name>, если строке bind назначено имя с помощью ключевого слова “name”.

Требуется версия OpenSSL с поддержкой ECH, а HAProxy должен быть собран с USE_ECH=1. Команда поддерживается только в соединении CLI, работающем в экспериментальном режиме (см. “experimental-mode on”).

См. также “show ssl ech”, “add ssl ech” и “ech” в разделе 5.1 руководства по конфигурации.

Пример:

$ echo "experimental-mode on; del ssl ech frontend1/@haproxy.conf:19" | socat /tmp/haproxy.sock -
deleted all ECH configs from frontend1/@haproxy.conf:19

del ssl jwt <filename>

del ssl jwt <filename>

Удаляет уже загруженный сертификат из списка сертификатов, которые могут использоваться для проверки JWT (см. преобразователь “jwt_verify_cert”). Команда не работает с незавершёнными транзакциями. См. также команды “add ssl jwt” и “show ssl jwt”. Дополнительные сведения приведены в описании опции сертификата “jwt”.

del server <backend>/<server>

del server <backend>/<server>

Удаляет доступный для удаления сервер, привязанный к бэкенду <backend>. Для возможности удаления сервер должен удовлетворять всем следующим условиям:

  • на него не ссылаются другие элементы конфигурации
  • он уже должен находиться в режиме обслуживания (см. “disable server”)
  • у него не должно быть активных или простаивающих соединений

Если хотя бы одно из этих условий не выполнено, команда завершается с ошибкой.

Активными считаются соединения, в которых выполняется хотя бы один запрос. Их завершение можно ускорить командой “shutdown sessions server”. Настоятельно рекомендуется перед “del server” выполнить “wait srv-removable”, чтобы убедиться, что все активные и простаивающие соединения закрыты и команда завершится успешно.

disable agent <backend>/<server>

disable agent <backend>/<server>

Помечает вспомогательную агентскую проверку как временно остановленную.

Если агентская проверка выполняется как вспомогательная благодаря параметру agent-check директивы server, новые проверки запускаются только при включённом агенте. Таким образом, disable agent предотвращает запуск новых агентских проверок до повторного включения агента командой enable agent.

При отключении агента вспомогательная агентская проверка, запущенная при включённом агенте, обрабатывается следующим образом: все результаты, которые изменили бы вес, в частности “drain” или вес, возвращённый агентом, игнорируются. В остальном обработка агентской проверки не меняется.

Эта возможность позволяет приостановить изменение веса по результатам агентских проверок, чтобы вес сервера можно было настроить командой set weight без последующего переопределения агентом.

Команда имеет ограниченный доступ и может выполняться только через сокеты с уровнем “admin”.

disable dynamic-cookie backend <backend>

disable dynamic-cookie backend <backend>

Отключает создание динамических cookie для бэкенда <backend>

disable frontend <frontend>

disable frontend <frontend>

Помечает фронтенд как временно остановленный. Это соответствует режиму, используемому при плавном перезапуске: фронтенд освобождает порт, но при необходимости его можно включить снова. Пользоваться этим следует осторожно, поскольку в некоторых ОС, отличных от Linux, повторное включение невозможно. Команда предназначена для сред, где остановка прокси недопустима, но ошибочную конфигурацию прокси необходимо исправить. Таким способом можно освободить порт и привязать его к другому процессу, чтобы восстановить работу. На странице статистики фронтенд будет показан в состоянии “STOP”.

Фронтенд можно указать по имени или по числовому ID с префиксом решётки (’#’).

Команда имеет ограниченный доступ и может выполняться только через сокеты с уровнем “admin”.

disable health <backend>/<server>

disable health <backend>/<server>

Помечает основную проверку работоспособности как временно остановленную. Отправка проверок работоспособности отключается, а результат последней проверки игнорируется. Сервер переходит в состояние без проверок и считается UP, если только вспомогательная агентская проверка не переведёт его в состояние недоступности.

Команда имеет ограниченный доступ и может выполняться только через сокеты с уровнем “admin”.

disable server <backend>/<server>

disable server <backend>/<server>

Помечает сервер как DOWN для обслуживания. В этом режиме проверки сервера не выполняются, пока он не выйдет из режима обслуживания. Если состояние сервера отслеживают другие серверы, на время обслуживания они также переводятся в DOWN.

На странице статистики сервер в состоянии DOWN для обслуживания отображается со статусом “MAINT”, а отслеживающие его серверы — со статусом “MAINT(via)”.

И бэкенд, и сервер можно указать по имени или по числовому ID с префиксом решётки (’#’).

Команда имеет ограниченный доступ и может выполняться только через сокеты с уровнем “admin”.

dump ssl cert <certfile>

dump ssl cert <certfile>

Выгружает сертификат, загруженный в память HAProxy. Вывод производится в формате PEM: сначала закрытый ключ, затем конечный сертификат и, наконец, цепочка сертификатов. Можно также выгрузить транзакцию, поставив звёздочку перед именем файла. Это полезно для сохранения сертификатов в файловой системе, если они были обновлены через CLI, а не в файловой системе.

Команда имеет ограниченный доступ и может выполняться только через сокеты с уровнем “admin”.

Примеры:

$ echo "dump ssl cert cert1.pem" | socat /tmp/sock1 -

$ echo "dump ssl cert cert1.pem" | socat /tmp/sock1 - | openssl storeutl -noout -text /dev/stdin

dump stats-file

dump stats-file

Создаёт stats-file, который можно использовать для предварительной загрузки значений счётчиков haproxy при запуске. Подробнее см. раздел “Stats-file”.

echo <text>

echo <text>

Выводит текст через CLI. Это может быть полезно для записи комментариев между командами при выгрузке результатов нескольких команд.

Пример:

echo "expert-mode on; echo FDs from fdtab; show fd; echo wild FDs; debug dev fd" | socat /var/run/haproxy.sock -

enable agent <backend>/<server>

enable agent <backend>/<server>

Возобновляет вспомогательную агентскую проверку, которая была временно остановлена.

Описание последствий временного запуска и остановки вспомогательного агента см. в разделе “disable agent”.

Команда имеет ограниченный доступ и может выполняться только через сокеты с уровнем “admin”.

enable dynamic-cookie backend <backend>

enable dynamic-cookie backend <backend>

Включает создание динамических cookie для бэкенда <backend>. Также необходимо предоставить секретный ключ.

enable frontend <frontend>

enable frontend <frontend>

Возобновляет работу временно остановленного фронтенда. Привязка к некоторым прослушиваемым портам может оказаться невозможной (например, если после операции ‘disable frontend’ их занял другой процесс). В этом случае выводится ошибка. Некоторые операционные системы могут не поддерживать возобновление работы отключённого фронтенда.

Фронтенд можно указать по имени или по числовому ID с префиксом решётки (’#’).

Команда имеет ограниченный доступ и может выполняться только через сокеты с уровнем “admin”.

enable health <backend>/<server>

enable health <backend>/<server>

Возобновляет основную проверку работоспособности, которая была временно остановлена. Отправка проверок работоспособности снова включается. Подробнее см. “disable health”.

Команда имеет ограниченный доступ и может выполняться только через сокеты с уровнем “admin”.

enable server <backend>/<server>

enable server <backend>/<server>

Если сервер ранее был помечен как DOWN для обслуживания, помечает его как UP и снова включает проверки.

И бэкенд, и сервер можно указать по имени или по числовому ID с префиксом решётки (’#’).

Команда имеет ограниченный доступ и может выполняться только через сокеты с уровнем “admin”.

experimental-mode [on|off]

experimental-mode [on|off]

Без опций показывает, включён ли экспериментальный режим в текущем соединении. При передаче “on” включает экспериментальный режим только для текущего соединения CLI. При передаче “off” отключает его.

Экспериментальный режим предоставляет доступ к дополнительным возможностям, которые ещё разрабатываются. В настоящее время эти возможности нестабильны, поэтому их следует использовать с осторожностью. При переходе между версиями в них возможны несовместимые изменения.

При использовании из CLI главного процесса команду следует вводить без префикса, поскольку она задаёт режим для любого рабочего процесса при подключении к его CLI.

Пример:

echo "@1; experimental-mode on; <experimental_cmd>..." | socat /var/run/haproxy.master -
echo "experimental-mode on; @1 <experimental_cmd>..." | socat /var/run/haproxy.master -

expert-mode [on|off]

expert-mode [on|off]

Эта команда аналогична experimental-mode, но переключает экспертный режим.

Экспертный режим включает отображение команд для специалистов, которые могут быть крайне опасны для процесса и иногда помогают разработчикам собирать важную информацию о сложных ошибках. Любое неправильное использование этих возможностей с большой вероятностью приведёт к аварийному завершению процесса. Не используйте эту опцию без соответствующего указания. Обратите внимание: команда намеренно не включена в справочное сообщение. Она доступна только на уровне admin. Переход на другой уровень автоматически сбрасывает экспертный режим.

При использовании из CLI главного процесса команду следует вводить без префикса, поскольку она задаёт режим для любого рабочего процесса при подключении к его CLI.

Пример:

echo "@1; expert-mode on; debug dev exit 1" | socat /var/run/haproxy.master -
echo "expert-mode on; @1 debug dev exit 1" | socat /var/run/haproxy.master -

get map <map> <value>

get map <map> <value>
get acl <acl> <value>

Ищет значение <value> в карте <map> или в ACL <acl>. <map> или <acl> — это #<id> или <name>, возвращённые командой “show map” или “show acl”. Команда возвращает все совпадающие шаблоны, связанные с этой картой. Это полезно для отладки карт и ACL. Вывод содержит по одной строке для каждого типа сопоставления. Каждая строка состоит из последовательности слов, разделённых пробелами.

Первые два слова:

<match method>:   Применённый метод сопоставления. Возможные значения: "found", "bool",
                  "int", "ip", "bin", "len", "str", "beg", "sub", "dir",
                  "dom", "end" или "reg".

<match result>:   Результат. Возможные значения: "match" или "no-match".

Следующие слова возвращаются, только если шаблон совпадает с записью.

 `<index type>`:     "tree" или "list". Внутренний алгоритм поиска.

 `<case>`:           "case-insensitive" или "case-sensitive".
                   Учёт регистра.

 `<entry matched>`:  match="`<entry>`". Возвращает совпавший шаблон.
                   Это полезно для регулярных выражений.

Последние два слова показывают возвращённое значение и его тип. В случае “acl” шаблон отсутствует.

 return=nothing:        Ничего не возвращается, поскольку нет "map".
 return="`<value>`":      Значение, возвращённое в строковом формате.
 return=cannot-display: Значение невозможно преобразовать в строку.

 type="`<type>`":         Тип возвращённого образца.

get var <name>

get var <name>

Показывает наличие, тип и содержимое переменной ’name’ уровня процесса. Читать можно только переменные уровня процесса, поэтому имя должно начинаться с ‘proc.’, иначе переменная не будет найдена. Команда требует уровня “operator” или “admin”.

get weight <backend>/<server>

get weight <backend>/<server>

Выводит текущий и исходный вес сервера <server> в бэкенде <backend> либо ошибку, если один из них не существует. Исходный вес — это вес, указанный в файле конфигурации. Обычно оба значения равны, если текущий вес не был изменён. И бэкенд, и сервер можно указать по имени или по числовому ID с префиксом решётки (’#’).

help [<command>]

help [<command>]

Выводит список известных ключевых слов с основными способами их использования либо команды, соответствующие запрошенной. Та же справка отображается для неизвестных команд.

httpclient [--htx] <method> <URI>

httpclient [--htx] <method> <URI>

Выполняет клиентский запрос HTTP и выводит ответ в CLI. Поддерживается только в соединении CLI, работающем в экспертном режиме (см. “expert-mode on”). Предназначен только для отладки. httpclient может разрешать имя сервера в URL с помощью секции resolvers “default”, которая по умолчанию заполняется указанными в /etc/resolv.conf серверами DNS. Однако он не сможет разрешить имя узла из /etc/hosts, если не используется локальный демон dns, умеющий разрешать такие имена.

Опция –htx позволяет использовать внутреннее представление htx в haproxy с помощью функции htx_dump(); это в основном применяется для отладки.

new ssl ca-file <cafile>

new ssl ca-file <cafile>

Создаёт новую пустую запись дерева файлов CA, которую предстоит заполнить набором сертификатов CA и добавить в crt-list. Эту команду следует использовать совместно с “set ssl ca-file”, “add ssl ca-file” и “add ssl crt-list”.

new ssl cert <filename>

new ssl cert <filename>

Создаёт новое пустое хранилище сертификата SSL, которое предстоит заполнить сертификатом и добавить в каталог или crt-list. Эту команду следует использовать совместно с “set ssl cert” и “add ssl crt-list”.

new ssl crl-file <crlfile>

new ssl crl-file <crlfile>

Создаёт новую пустую запись дерева файлов CRL, которую предстоит заполнить набором CRL и добавить в crt-list. Эту команду следует использовать совместно с “set ssl crl-file” и “add ssl crt-list”.

prepare acl <acl>

prepare acl <acl>

Выделяет новый номер версии в ACL <acl> для атомарной замены. <acl> — это #<id> или <name>, возвращённые командой “show acl”. Новый номер версии выводится в ответе после “New version created:”. Затем этот номер можно использовать для подготовки добавления новых записей в ACL, которые после фиксации атомарно заменят текущие. В выводе “show acl” он представлен как “next_ver”. Выделение новых версий не влияет на работу: неиспользуемые версии автоматически удаляются после фиксации более новой. Номера версий — беззнаковые 32-разрядные значения, которые циклически переходят через границу диапазона, поэтому при сравнении во внешней программе требуется осторожность. Эту команду нельзя использовать, если ссылка <acl> является именем, которое также используется для карты. В этом случае необходимо использовать команду “prepare map”.

prepare map <map>

prepare map <map>

Выделяет новый номер версии в карте <map> для атомарной замены. <map> — это #<id> или <name>, возвращённые командой “show map”. Новый номер версии выводится в ответе после “New version created:”. Затем этот номер можно использовать для подготовки добавления новых записей в карту, которые после фиксации атомарно заменят текущие. В выводе “show map” он представлен как “next_ver”. Выделение новых версий не влияет на работу: неиспользуемые версии автоматически удаляются после фиксации более новой. Номера версий — беззнаковые 32-разрядные значения, которые циклически переходят через границу диапазона, поэтому при сравнении во внешней программе требуется осторожность.

prompt [help | n | i | p | timed]*

prompt [help | n | i | p | timed]*

Меняет поведение интерактивного режима и приглашение, отображаемое в начале строки в интерактивном режиме: - “help” : выводит справку по команде - “n” : переключает в неинтерактивный режим - “i” : переключает в интерактивный режим - “p” : переключает в интерактивный режим с приглашением - “timed” : переключает отображение времени в приглашении

Без опций циклически переключает режим с приглашением и неинтерактивный режим. В неинтерактивном режиме соединение закрывается после выполнения последней команды текущей строки. В интерактивном режиме соединение не закрывается после выполнения команды, чтобы можно было ввести следующую. В режиме с приглашением по-прежнему используется интерактивный режим, а в начале строки появляется приглашение, сообщающее пользователю, что интерпретатор ожидает новую команду. Приглашение состоит из правой угловой скобки и пробела “> “.

Режим с приглашением лучше подходит для ручной работы, интерактивный режим — для сложных скриптов, а неинтерактивный режим (по умолчанию) — для простых скриптов. Обратите внимание: неинтерактивный режим недоступен для сокета главного процесса.

publish backend <backend>

publish backend <backend>

Активирует переключение трафика на экземпляр бэкенда. Это операция, обратная команде “unpublish backend”. Команда имеет ограниченный доступ и может выполняться только через сокеты с уровнем “operator” или “admin”.

quit

quit

Закрывает соединение в интерактивном режиме.

set anon [on|off] [<key>]

set anon [on|off] [<key>]

Эта команда включает или отключает «режим анонимизации» для текущего сеанса CLI. В нём некоторые поля вывода команд, считающиеся чувствительными или конфиденциальными, заменяются хешами. Эти хеши сохраняют достаточно согласованности между элементами, чтобы разработчики могли выявлять связи при поиске ошибок, но имеют достаточно малую разрядность (24), чтобы восстановление исходных значений было невозможно из-за большого числа потенциальных совпадений. При включении режима без указания ключа используется глобальный ключ (заданный в файле конфигурации через “anonkey” или командой CLI “set anon global-key”). Если такой ключ не задан, создаётся случайный. Вместо этого можно указать 32-разрядный ключ для текущего сеанса, например повторно использовать ключ предыдущего дампа для упрощения сравнения вывода. Разработчикам этот ключ никогда не понадобится; рекомендуется никому его не передавать, поскольку он может позволить подтвердить или опровергнуть догадки о том, что скрывается за определёнными хешами.

set dynamic-cookie-key backend <backend> <value>

set dynamic-cookie-key backend <backend> <value>

Изменяет секретный ключ, используемый для создания динамических cookie привязки. Это нарушит работу существующих сеансов.

set anon global-key <key>

set anon global-key <key>

Задаёт глобальный ключ анонимизации <key>, который должен быть 32-разрядным целым числом от 0 до 4294967295 (0 отключает глобальный ключ). Команда требует прав admin.

set map <map> [<key>|#<ref>] <value>

set map <map> [<key>|#<ref>] <value>

Изменяет значение, соответствующее каждому ключу <key> в карте <map>. <map> — это #<id> или <name>, возвращённые командой “show map”. Если используется <ref> вместо <key>, изменяется только запись, на которую указывает <ref>. Новое значение — <value>.

set maxconn frontend <frontend> <value>

set maxconn frontend <frontend> <value>

Динамически изменяет настройку maxconn указанного фронтенда. Допускается любое положительное значение, а также ноль, но задавать значения выше глобального maxconn обычно не имеет смысла. Если лимит увеличен и есть ожидающие соединения, они принимаются немедленно. Если лимит снижен ниже текущего числа соединений, приём новых соединений откладывается до достижения порогового значения. Фронтенд можно указать по имени или по числовому ID с префиксом решётки (’#’).

set maxconn server <backend/server> <value>

set maxconn server <backend/server> <value>

Динамически изменяет настройку maxconn указанного сервера. Допускается любое положительное значение, а также ноль, но задавать значения выше глобального maxconn обычно не имеет смысла.

set maxconn global <maxconn>

set maxconn global <maxconn>

Динамически изменяет глобальную настройку maxconn в пределах диапазона, заданного исходной глобальной настройкой maxconn. Если лимит увеличен и есть ожидающие соединения, они принимаются немедленно. Если лимит снижен ниже текущего числа соединений, приём новых соединений откладывается до достижения порогового значения. Нулевое значение восстанавливает исходную настройку.

set profiling memory { on | off }

set profiling memory { on | off }
set profiling tasks { auto | on | off | lock | no-lock | memory | no-memory }

Включает или отключает профилирование CPU или памяти для указанной подсистемы. Это эквивалентно установке или сбросу настроек “profiling” в секции “global” файла конфигурации. См. также “show profiling”. Обратите внимание: ручное переключение профилирования задач в “on” автоматически сбрасывает статистику планировщика и тем самым позволяет проверить активность за определённый интервал. Профилирование памяти поддерживается лишь в некоторых операционных системах (известно, что оно работает для целевой платформы linux-glibc) и требует задания USE_MEMORY_PROFILING при компиляции.

. Для профилирования задач можно во время выполнения включать и отключать сбор времени операций с блокировками и памятью для каждой задачи, но изменение учитывается лишь при следующем переходе профилировщика из off/auto в on (автоматическом или ручном). Поэтому при использовании “no-lock” для отключения профилирования блокировок отдельных задач и экономии циклов CPU рекомендуется выключить, а затем включить профилирование задач, чтобы применить изменение.

set rate-limit connections global <value>

set rate-limit connections global <value>

Изменяет ограничение скорости установления соединений для всего процесса, задаваемое глобальной настройкой ‘maxconnrate’. Нулевое значение отключает ограничение. Этот лимит действует для всех фронтендов, и изменение применяется немедленно. Значение передаётся в числе соединений в секунду.

set rate-limit http-compression global <value>

set rate-limit http-compression global <value>

Изменяет максимальную скорость поступления данных на сжатие, задаваемую глобальной настройкой ‘maxcomprate’. Нулевое значение отключает ограничение. Значение передаётся в килобайтах в секунду. В выводе “show info” оно доступно в строке “CompressBpsRateLim” в байтах.

set rate-limit sessions global <value>

set rate-limit sessions global <value>

Изменяет ограничение скорости создания сеансов для всего процесса, задаваемое глобальной настройкой ‘maxsessrate’. Нулевое значение отключает ограничение. Этот лимит действует для всех фронтендов, и изменение применяется немедленно. Значение передаётся в числе сеансов в секунду.

set rate-limit ssl-sessions global <value>

set rate-limit ssl-sessions global <value>

Изменяет ограничение скорости создания сеансов SSL для всего процесса, задаваемое глобальной настройкой ‘maxsslrate’. Нулевое значение отключает ограничение. Этот лимит действует для всех фронтендов, и изменение применяется немедленно. Значение передаётся в числе сеансов в секунду, поступающих в стек SSL. Ограничение применяется до рукопожатия, чтобы защитить стек от злоупотребления рукопожатиями.

set server <backend>/<server> addr <ip4 or ip6 address> [port <port>]

set server <backend>/<server> addr <ip4 or ip6 address> [port <port>]

Заменяет текущий IP-адрес сервера указанным. При необходимости порт можно изменить с помощью параметра ‘port’. Обратите внимание: изменение порта также поддерживает переход к сопоставлению портов и обратно (запись с +X или -Y), но только если для проверки работоспособности настроен порт.

set server <backend>/<server> agent [ up | down ]

set server <backend>/<server> agent [ up | down ]

Принудительно переводит агент сервера в новое состояние. Это может быть полезно, например, для немедленного изменения состояния сервера независимо от медленных агентских проверок. Обратите внимание: изменение распространяется и на отслеживающие серверы, если они есть.

set server <backend>/<server> agent-addr <addr> [port <port>]

set server <backend>/<server> agent-addr <addr> [port <port>]

Изменяет addr для агентских проверок сервера. Позволяет во время выполнения перенести агентские проверки на другой адрес. Можно указать как IP, так и имя узла, которое будет разрешено. При необходимости можно также изменить порт агента.

set server <backend>/<server> agent-port <port>

set server <backend>/<server> agent-port <port>

Изменяет порт, используемый для агентских проверок.

set server <backend>/<server> agent-send <value>

set server <backend>/<server> agent-send <value>

Изменяет строку, отправляемую получателю агентских проверок. Позволяет обновить строку при изменении адреса сервера, чтобы сохранить их соответствие.

set server <backend>/<server> health [ up | stopping | down ]

set server <backend>/<server> health [ up | stopping | down ]

Принудительно задаёт новое состояние работоспособности сервера. Это может быть полезно, например, для немедленного изменения состояния сервера независимо от медленных проверок работоспособности. Обратите внимание: изменение распространяется и на отслеживающие серверы, если они есть.

set server <backend>/<server> check-addr <ip4 | ip6> [port <port>]

set server <backend>/<server> check-addr <ip4 | ip6> [port <port>]

Изменяет адрес IP, используемый для проверок работоспособности сервера. При необходимости также изменяет порт этих проверок.

set server <backend>/<server> check-port <port>

set server <backend>/<server> check-port <port>

Изменяет порт проверок работоспособности на <port>

set server <backend>/<server> state [ ready | drain | maint ]

set server <backend>/<server> state [ ready | drain | maint ]

Принудительно задаёт новое административное состояние сервера. Это может быть полезно для отключения балансировки нагрузки и/или всего трафика к серверу. Состояние “ready” переводит сервер в обычный режим; команда эквивалентна “enable server”. Состояние “maint” отключает весь трафик к серверу и все проверки работоспособности; это эквивалентно команде “disable server”. Режим “drain” лишь исключает сервер из балансировки нагрузки, но по-прежнему позволяет проверять его и принимать новые соединения с привязкой. Изменения распространяются и на отслеживающие серверы, если они есть.

set server <backend>/<server> weight <weight>[%]

set server <backend>/<server> weight <weight>[%]

Изменяет вес сервера на значение, переданное в аргументе. Это точный эквивалент команды “set weight”, описанной ниже.

set server <backend>/<server> fqdn <FQDN>

set server <backend>/<server> fqdn <FQDN>

Изменяет FQDN сервера на значение, переданное в аргументе. Для этого у сервера должен быть настроен и включён внутренний механизм разрешения DNS во время выполнения.

set server <backend>/<server> ssl [ on | off ] (deprecated)

set server <backend>/<server> ssl [ on | off ]  (deprecated)

Эта опция настраивает шифрование SSL для исходящих соединений с сервером. При отключении весь трафик передаётся открытым текстом; путь выполнения проверки работоспособности не меняется.

Команда устарела; вместо неё создавайте новый сервер динамически, с SSL или без него, с помощью команды “add server”.

set severity-output [ none | number | string ]

set severity-output [ none | number | string ]

Изменяет формат вывода уровня серьёзности для сокета статистики, к которому установлено соединение, на время текущего сеанса.

set ssl ca-file <cafile> <payload>

set ssl ca-file <cafile> <payload>

Эта команда входит в систему транзакций; могут потребоваться команды “commit ssl ca-file” и “abort ssl ca-file”. Если текущей транзакции нет, создаётся запись дерева файлов CA, в которую помещаются сертификаты из полезной нагрузки. Эта запись файла CA не сохраняется в дереве файлов CA, а остаётся только во временной транзакции. Если транзакция с тем же именем файла уже существует, прежняя запись файла CA удаляется и заменяется новой. После внесения изменений необходимо зафиксировать транзакцию вызовом “commit ssl ca-file”. Чтобы добавить несколько сертификатов по отдельности, можно использовать команду “add ssl ca-file”

Пример:

echo -e "set ssl ca-file cafile.pem <<\n$(cat rootCA.crt)\n" | \
socat /var/run/haproxy.stat -
echo "commit ssl ca-file cafile.pem" | socat /var/run/haproxy.stat -

set ssl cert <filename> <payload>

set ssl cert <filename> <payload>

Эта команда входит в систему транзакций; могут потребоваться команды “commit ssl cert” и “abort ssl cert”. Вся система транзакций работает с любым сертификатом, который выводит команда “show ssl cert”, то есть с любым сертификатом фронтенда или бэкенда. Если текущей транзакции нет, сертификат <filename> дублируется в памяти во временную транзакцию, после чего эта транзакция обновляется файлом PEM из полезной нагрузки. Если транзакция с тем же именем файла существует, она обновляется. Также можно обновлять файлы, связанные с сертификатом (.issuer, .sctl, .ocsp и т. д.). После внесения изменений необходимо зафиксировать транзакцию командой “commit ssl cert”.

Передавать файлы через CLI необходимо с осторожностью, поскольку пустая строка обозначает конец полезной нагрузки. Рекомендуется передавать предварительно очищенный файл PEM. Простой способ — удалить все пустые строки и оставить только содержимое секций PEM. Это можно сделать командой sed.

Пример:

# With some simple sanitizing
 echo -e "set ssl cert localhost.pem <<\n$(sed -n '/^$/d;/-BEGIN/,/-END/p' 127.0.0.1.pem)\n" | \
 socat /var/run/haproxy.stat -

 # Complete example with commit
 echo -e "set ssl cert localhost.pem <<\n$(cat 127.0.0.1.pem)\n" | \
 socat /var/run/haproxy.stat -
 echo -e \
 "set ssl cert localhost.pem.issuer <<\n $(cat 127.0.0.1.pem.issuer)\n" | \
 socat /var/run/haproxy.stat -
 echo -e \
 "set ssl cert localhost.pem.ocsp <<\n$(base64 -w 1000 127.0.0.1.pem.ocsp)\n" | \
 socat /var/run/haproxy.stat -
 echo "commit ssl cert localhost.pem" | socat /var/run/haproxy.stat -

set ssl crl-file <crlfile> <payload>

set ssl crl-file <crlfile> <payload>

Эта команда входит в систему транзакций; могут потребоваться команды “commit ssl crl-file” и “abort ssl crl-file”. Если текущей транзакции нет, создаётся запись дерева файлов CRL, в которую помещаются списки отзыва из полезной нагрузки. Запись файла CRL не сохраняется в дереве файлов CRL, а остаётся только во временной транзакции. Если транзакция с тем же именем файла уже существует, прежняя запись файла CRL удаляется и заменяется новой. После внесения изменений необходимо зафиксировать транзакцию вызовом “commit ssl crl-file”.

Пример:

echo -e "set ssl crl-file crlfile.pem <<\n$(cat rootCRL.pem)\n" | \
socat /var/run/haproxy.stat -
echo "commit ssl crl-file crlfile.pem" | socat /var/run/haproxy.stat -

set ssl ech <bind> <payload>

set ssl ech <bind> <payload>

Заменяет ключи ECH строки bind указанными ключами. Полезная нагрузка должна иметь формат PEM для ECH. (https://datatracker.ietf.org/doc/html/draft-farrell-tls-pemesni )

Формат строки bind — <frontend>/@<filename>:<linenum> (пример: frontend1/@haproxy.conf :19) или <frontend>/<name>, если строке bind назначено имя с помощью ключевого слова “name”.

Требуется версия OpenSSL с поддержкой ECH, а HAProxy должен быть собран с USE_ECH=1. Команда поддерживается только в соединении CLI, работающем в экспериментальном режиме (см. “experimental-mode on”).

См. также “show ssl ech”, “add ssl ech” и “ech” в разделе 5.1 руководства по конфигурации.

$ openssl ech -public_name foobar.com -out foobar3.com.ech
$ echo -e "experimental-mode on;
           set ssl ech frontend1/@haproxy.conf:19 <<%EOF%&#92;n$(cat foobar3.com.ech)&#92;n%EOF%&#92;n" | &#92;
  socat /tmp/haproxy.sock -
set new ECH configs for frontend1/@haproxy.conf:19

set ssl ocsp-response <response | payload>

set ssl ocsp-response <response | payload>

Эта команда обновляет ответ OCSP для сертификата (см. “crt” в строках “bind”). Выполняются те же проверки, что при первоначальной загрузке ответа. <response> необходимо передать как строку base64, кодирующую ответ сервера OCSP в формате DER. Команда не поддерживается с BoringSSL.

Пример:

openssl ocsp -issuer issuer.pem -cert server.pem \
             -host ocsp.issuer.com:80 -respout resp.der
echo "set ssl ocsp-response $(base64 -w 10000 resp.der)" | \
             socat stdio /var/run/haproxy.stat

using the payload syntax:
echo -e "set ssl ocsp-response <<\n$(base64 resp.der)\n" | \
             socat stdio /var/run/haproxy.stat

set ssl tls-key <id> <tlskey>

set ssl tls-key <id> <tlskey>

Задаёт следующий ключ TLS для слушателя <id> равным <tlskey>. Этот ключ становится последним, а предпоследний используется для шифрования (остальные — только для расшифровки). Самый старый из имеющихся ключей TLS перезаписывается. <id> — это числовой #<id> или <file>, возвращённый командой “show tls-keys”. <tlskey> — закодированный в base64 ключ билета TLS длиной 48 или 80 байт (например, openssl rand 80 | openssl base64 -A).

set table <table> key <key> [data.<data_type> <value>]*

set table <table> key <key> [data.<data_type> <value>]*
set table <table> ptr <ptr> [data.<data_type> <value>]*

Создаёт или обновляет запись в таблице привязок. Если ключ отсутствует, запись вставляется. Все допустимые значения <data_type> см. в описании stick-table в разделе 4.2. Наиболее вероятный вариант использования — динамическое добавление записей для адресов IP источников с флагом в gpc0, чтобы динамически блокировать адрес IP или менять качество его обслуживания. За один вызов можно передать несколько data_types.

Для существующей записи вместо поиска по key можно использовать поиск по ptr: <ptr> задаётся в виде 0xffff и должен соответствовать адресу, возвращённому предыдущей командой “show table”. Поиск записи по указателю полезен, если найти её по ключу невозможно из-за пустого ключа или символов, несовместимых с cli.

Если data.<data_type> имеет тип массива, для доступа к определённому индексу можно использовать “[]”, например: data.gpt[1]

set timeout cli <delay>

set timeout cli <delay>

Изменяет тайм-аут интерфейса CLI для текущего соединения. Это может быть полезно при длительной отладке, когда пользователю нужно постоянно проверять некоторые показатели без разрыва соединения. Задержка передаётся в секундах.

set var <name> <expression>

set var <name> <expression>
set var <name> expr <expression>
set var <name> fmt <format>

Позволяет задать или перезаписать переменную ’name’ уровня процесса результатом выражения <expression> или строки формата <format>. Можно использовать только переменные уровня процесса, поэтому имя должно начинаться с ‘proc.’, иначе переменная не будет установлена. В <expression> и <format> могут использоваться только «внутренние» ключевые слова извлечения образцов и преобразователи; наиболее полезными, вероятно, будут str(‘something’), int(), простые строки или ссылки на другие переменные. Учтите, что анализатор командной строки не учитывает кавычки, поэтому перед каждым пробелом в выражении необходимо ставить обратную косую черту. Команда требует уровня “operator” или “admin”. Она поддерживается только в соединении CLI, работающем в экспериментальном режиме (см. “experimental-mode on”).

set weight <backend>/<server> <weight>[%]

set weight <backend>/<server> <weight>[%]

Изменяет вес сервера на значение, переданное в аргументе. Если значение заканчивается знаком ‘%’, новый вес задаётся относительно исходного веса из конфигурации. Абсолютный вес может находиться в диапазоне от 0 до 256. Относительный вес должен быть положительным, а полученный абсолютный вес ограничивается значением 256. Для серверов фермы со статическим алгоритмом балансировки нагрузки ограничения строже, поскольку после задания вес не может меняться. Поэтому для таких серверов принимаются только значения 0 и 100% (либо 0 и исходный вес). Изменения применяются немедленно, хотя некоторым алгоритмам LB требуется определённое число запросов, чтобы учесть изменения. Типичный вариант использования — отключить сервер на время обновления, установив нулевой вес, а затем снова включить его, вернув вес 100%. Команда имеет ограниченный доступ и может выполняться только через сокеты с уровнем “admin”. И бэкенд, и сервер можно указать по имени или по числовому ID с префиксом решётки (’#’).

show acl [[@<ver>] <acl>]

show acl [[@<ver>] <acl>]

Выгружает сведения о преобразователях acl. Без аргумента возвращается список всех доступных acl. Если задан <acl>, выгружается его содержимое. <acl> — это #<id> или <name>. По умолчанию показывается текущая версия ACL (версия, с которой сейчас выполняется сопоставление и которая указана как ‘curr_ver’ в списке ACL). Можно выгрузить другие версии, поставив ‘@<ver>’ перед идентификатором ACL. Версия действует как фильтр: для несуществующей версии просто не будет результата. Формат выгрузки тот же, что для карт, даже для значений образцов. Возвращаемые данные представляют собой не список доступных ACL, а список всех шаблонов, составляющих какой-либо ACL. Многие из этих шаблонов могут быть общими с картами. Значение ’entry_cnt’ показывает число всех записей ACL, а не только активных, то есть включает и записи, добавляемые в данный момент.

show anon

show anon

Показывает текущее состояние режима анонимизации (включён или отключён) и ключ текущего сеанса.

show backend

show backend

Выгружает список бэкендов, доступных в работающем процессе

show cli level

show cli level

Показывает уровень CLI текущего сеанса CLI. Результат может быть ‘admin’, ‘operator’ или ‘user’. См. также команды ‘operator’ и ‘user’.

Пример:

$ socat /tmp/sock1 readline
prompt
> operator
> show cli level
operator
> user
> show cli level
user
> operator
Permission denied

operator

operator

Понижает уровень CLI текущего сеанса CLI до operator. Повысить его обратно нельзя. Команда также отключает экспертный и экспериментальный режимы. См. также “show cli level”.

unpublish backend <backend>

unpublish backend <backend>

Помечает бэкенд как недоступный для последующего выбора при направлении трафика. В результате ссылающиеся на него правила use_backend / default_backend игнорируются и проверяются следующие правила переключения трафика. В отличие от отключённых бэкендов, проверки работоспособности серверов остаются активными. Команда имеет ограниченный доступ и может выполняться только через сокеты с уровнем “operator” или “admin”.

user

user

Понижает уровень CLI текущего сеанса CLI до user. Повысить его обратно нельзя. Команда также отключает экспертный и экспериментальный режимы. См. также “show cli level”.

show activity [-1 | 0 | thread_num]

show activity [-1 | 0 | thread_num]

Выводит некоторые счётчики внутренних событий, помогающие разработчикам и другим людям, достаточно хорошо знающим haproxy, сузить круг возможных причин аномального поведения. Типичный пример — исправно работающий процесс, который никогда не засыпает и занимает 100% CPU. Каждая метрика выводится отдельной строкой, а счётчики отдельных потоков располагаются в той же строке. Эти счётчики 32-разрядные и за время жизни процесса переполняются; это не проблема, поскольку обычно команду вызывают дважды. Поля намеренно не документированы, чтобы их точный смысл проверялся в коде, где обновляются счётчики. Эти значения также сбрасываются командой “clear counters”. В многопоточных развёртываниях первый столбец содержит сумму (или среднее — в зависимости от природы метрики) по всем потокам, а значения отдельных потоков перечисляются в квадратных скобках в порядке потоков. При необходимости номер потока для вывода можно задать аргументом. Специальное значение “0” выводит агрегированное значение (первый столбец), а “-1”, используемое по умолчанию, — все столбцы. Обратите внимание: как и в однопоточном режиме, при запросе одного столбца скобки не выводятся.

show cli sockets

show cli sockets

Выводит список сокетов CLI. Формат вывода состоит из 3 полей, разделённых пробелами. Первое поле — адрес сокета: сокет unix, пара адрес:порт ipv4 или такая же пара ipv6. Сокеты других типов не выводятся. Второе поле описывает уровень сокета: ‘admin’, ‘user’ или ‘operator’. Последнее поле перечисляет через запятую процессы, к которым привязан сокет; это могут быть номера или ‘all’.

Пример:

$ echo 'show cli sockets' | socat stdio /tmp/sock1
# socket lvl processes
/tmp/sock1 admin all
127.0.0.1:9999 user 2,3,4
127.0.0.2:9969 user 2
[::1]:9999 operator 2

show cache

show cache

Выводит настроенные кеши и объекты, хранящиеся в дереве каждого кеша.

$ echo ‘show cache’ | socat stdio /tmp/sock1 0x7f6ac6c5b03a: foobar (shctx:0x7f6ac6c5b000, available blocks:3918) 1 2 3 4

  1. указатель на структуру кеша
  2. имя кеша
  3. указатель на область mmap (shctx)
  4. число блоков в shctx, доступных для повторного использования

0x7f6ac6c5b4cc hash:286881868 vary:0x0011223344556677 size:39114 (39 blocks), refcount:9, expire:237 1 2 3 4 5 6 7

  1. указатель на запись кеша
  2. первые 32 бита хеша
  3. вторичный хеш записи при использовании vary
  4. размер объекта в байтах
  5. число блоков, используемых объектом
  6. число транзакций, использующих запись
  7. время истечения срока действия; может быть отрицательным, если срок уже истёк

show dev

show dev

Эта команда собирает в одном месте сведения, которые могут понадобиться разработчикам HAProxy для понимания причин конкретной проблемы. Обычно они не представляют пользы для пользователя, но позволяют разработчикам исключить некоторые гипотезы. Формат примерно соответствует набору разделов со строками с отступом, по одному элементу в строке: например, тип и версия ОС, тип CPU или ограничения FD при запуске. Некоторые поля опускаются, чтобы избежать повторов и лишнего вывода, если они не добавляют полезной информации (например, неограниченные значения). В будущем могут появляться новые поля и меняться существующие. Этот вывод не предназначен для разбора скриптами, и на его стабильность не следует сильно полагаться; основная цель — сэкономить время тем, кто умеет его читать.

Технически эти сведения берутся без изменений из внутренней структуры, куда они вместе записываются при запуске, чтобы после аварии их можно было найти и в файле core. Поэтому разработчики могут попросить получить вывод заранее на нормально работающем процессе, чтобы сравнить его с дампом core или сопоставить несколько перезагрузок (например, некоторые лимиты могут измениться). Если включена анонимизация, все потенциально чувствительные значения также анонимизируются (например, имя узла).

Пример вывода:

$ socat stdio /tmp/sock1 <<< "show dev"
Platform info
  machine vendor: To be filled by O.E.M
  machine family: Altra
  cpu model: Impl 0x41 Arch 8 Part 0xd0c r3p1
  virtual machine: no
  container: no
  OS name: Linux
  OS release: 6.2.0-36-generic
  OS version: #37~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Mon Oct  9 18:01:07 UTC 2
  OS architecture: aarch64
  node name: 489aaf
Process info
  pid: 1735846
  boot uid: 509
  boot gid: 1002
  fd limit (soft): 1024
  fd limit (hard): 1048576

show env [<name>]

show env [<name>]

Выгружает одну или все переменные окружения, известные процессу. Без аргументов выгружаются все переменные. С аргументом выгружается только указанная переменная, если она существует. В противном случае выводится “Variable not found”. Переменные выводятся в том же формате, в каком они хранятся или возвращаются утилитой “env”, то есть “<name>=<value>”. Это удобно при отладке файлов конфигурации, активно использующих переменные окружения: можно убедиться, что они содержат ожидаемые значения. Команда имеет ограниченный доступ и может выполняться только через сокеты с уровнем “operator” или “admin”.

show errors [<iid>|<proxy>] [request|response]

show errors [<iid>|<proxy>] [request|response]

Выгружает последние известные ошибки запросов и ответов HTTP/1.x, собранные фронтендами и бэкендами. Если задан <iid>, вывод ограничивается ошибками фронтенда или бэкенда с ID <iid>. ID прокси “-1” приводит к выводу всех экземпляров. Если вместо этого задано имя прокси, в качестве фильтра используется его ID. Если после имени или ID прокси добавлено “request” или “response”, выводятся только ошибки запросов или ответов соответственно. Команда имеет ограниченный доступ и может выполняться только через сокеты с уровнем “operator” или “admin”.

Собираются последние ошибки запросов и ответов, вызванные нарушением протокола, часто из-за недопустимых символов в именах заголовков. Отчёт точно указывает символ, нарушивший протокол. Выводятся и другие важные сведения: точная дата обнаружения ошибки, имена фронтенда и бэкенда, имя сервера (если известно), внутренний ID транзакции и адрес источника, инициировавшего сеанс.

Возвращаются все символы, при этом непечатаемые символы кодируются. Наиболее распространённые (\t = 9, \n = 10, \r = 13 и \e = 27) кодируются одной буквой после обратной косой черты. Сама обратная косая черта кодируется как ‘\\’, чтобы избежать неоднозначности. Другие непечатаемые символы кодируются как ‘\xNN’, где NN — двухзначное шестнадцатеричное представление кода ASCII символа.

Перед строками указывается позиция их первого символа, начиная с 0 для начала буфера. В каждой строке вывода печатается не более одной входной строки, а длинные строки разбиваются на несколько последовательных строк вывода, чтобы ширина никогда не превышала 79 символов. Перенос легко распознать: строка не заканчивается на ‘\n’, а после смещения следующей строки стоит знак ‘+’, указывающий на продолжение предыдущей строки.

Пример:

    $ echo "show errors -1 response" | socat stdio /tmp/sock1
>>> [04/Mar/2009:15:46:56.081] backend http-in (#2): invalid response
      src 127.0.0.1, session #54, frontend fe-eth0 (#1), server s2 (#1)
      response length 213 bytes, error at position 23:

      00000  HTTP/1.0 200 OK\r\n
      00017  header/bizarre:blah\r\n
      00038  Location: blah\r\n
      00054  Long-line: this is a very long line which should b
      00104+ e broken into multiple lines on the output buffer,
      00154+  otherwise it would be too large to print in a ter
      00204+ minal\r\n
      00211  \r\n

В примере выше бэкенд "http-in" с внутренним ID 2 заблокировал неверный
ответ своего сервера s2 с внутренним ID 1. Запрос относился к транзакции
54 (здесь названной "session"), начатой источником 127.0.0.1 и принятой
фронтендом fe-eth0 с ID 1. При обнаружении ошибки общая длина ответа
составляла 213 байт, а ошибка находилась в байте 23: это косая черта ('/')
в имени заголовка "header/bizarre", недопустимая в имени заголовка HTTP.

show events [<sink>] [-w] [-n] [-0] [-s]

show events [<sink>] [-w] [-n] [-0] [-s]

Без опций выводит все известные приёмники событий и их типы. С опцией выгружает все доступные события из указанного приёмника, если он имеет тип buffer. Если после имени приёмника передана опция “-w”, по достижении конца буфера команда ожидает новые события и выводит их. Операцию можно остановить любым вводом (который будет отброшен) или закрытием сеанса. Опция “-n” сразу переходит к концу буфера; это часто удобно в сочетании с “-w”, чтобы выводить только новые события. Для удобства можно использовать “-wn” или “-nw”, включающие обе опции сразу. По умолчанию события разделяются символом перевода строки (’\n’, 10 или 0x0A). Передав аргумент “-0”, разделитель можно заменить символом NUL (’\0’ или 0). Опция “-s” очищает вывод, чтобы двоичное содержимое захваченных или декодированных данных не меняло отображение в терминале. Пробельные символы (пробел и табуляция) заменяются пробелом, чтобы каждая запись оставалась на одной строке. Остальные управляющие символы (от 0x00 до 0x1F и 0x7F), а также символы вне ASCII (0x80 и выше) заменяются на ‘?’. Длина вывода сохраняется. Поэтому выгрузка кольцевого буфера не может внедрить ANSI escape-последовательности или коды направления письма в терминал оператора. Это полезно при выводе в терминал либо в программу, ввод которой не должен интерпретироваться как специальные символы, например в скрипты мониторинга, чья выдача без изменений копируется в отчёты.

show fd [-!plcfbsd]* [[<tgid>]/[<fd>] | <fd>]

show fd [-!plcfbsd]* [[<tgid>]/[<fd>] | <fd>]

Выгружает список всех открытых файловых дескрипторов либо только дескриптор с номером <fd>, если он указан. Также принимается форма “<tgid>/<fd>”, в которой любую сторону можно оставить пустой для выбора всех соответствующих значений (”/<fd>” для fd <fd> во всех группах потоков, “<tgid>/” для всех fd группы <tgid>). Сейчас <tgid> разбирается, но игнорируется до появления поддержки отдельных таблиц fd для групп потоков. При необходимости можно передать набор флагов, чтобы выводить только определённые типы FD или исключать их. При встрече ‘-’ или ‘!’ выбор инвертируется для следующих символов того же аргумента. Перед каждым новым словом аргумента, отделённым пробельными символами, инверсия сбрасывается. Выбираемые типы FD: ‘p’ — каналы, ’l’ — слушатели, ‘c’ — соединения любого типа, ‘f’ — соединения фронтенда, ‘b’ — соединения бэкенда любого типа, ’s’ — соединения с серверами, ’d’ — соединения с адресом “dispatch” или прозрачным адресом бэкенда. Таким образом, ‘b’ — сокращение для ‘sd’, а ‘c’ — для ‘fb’ или ‘fsd’. ‘c!f’ эквивалентно ‘b’ («все соединения, кроме соединений фронтенда» действительно являются соединениями бэкенда). Команда предназначена только для разработчиков, которым нужно наблюдать внутренние состояния при отладке сложных проблем, например аномального потребления CPU. Каждый fd выводится отдельной строкой. Для него указывается состояние в механизме опроса: включённые флаги обозначаются прописными буквами, отключённые — строчными; “P” означает опрос, “R” — готовность, “A” — активность. Состояние событий обозначается как “H” — разрыв соединения, “E” — ошибка, “O” — вывод, “P” — приоритет и “I” — ввод. Есть и другие флаги: “N” — новый (только что добавлен в кеш fd), “U” — обновлённый (получил обновление в кеше fd), “L” — “linger_risk”, “C” — клонированный. Далее идут позиция записи в кеше, указатель на внутреннего владельца, указатель на функцию обратного вызова I/O и её имя, если оно известно. Если владелец — соединение, выводятся флаги соединения и его цель (фронтенд, прокси или сервер). Если владелец — слушатель, выводятся его состояние и фронтенд. Без хорошего знания внутреннего устройства пользоваться этой командой бессмысленно. Формат вывода со временем может меняться, поэтому этот вывод нельзя разбирать инструментами, рассчитанными на длительное использование. Некоторые состояния внутренних структур могут показаться подозрительными функции, которая их выводит; в этом случае в конце строки ставится восклицательный знак (’!’). Это может дать отправную точку при диагностике инцидента.

show info [typed|json] [desc] [float]

show info [typed|json] [desc] [float]

Выгружает сведения о состоянии haproxy в текущем процессе. Если передан необязательный аргумент “typed”, также выводятся номера, имена и типы полей, чтобы внешние средства мониторинга могли легко получать, при необходимости агрегировать, а затем представлять сведения из неизвестных им полей. Каждое поле выводится отдельной строкой. Если передан необязательный аргумент “json”, сведения из вывода “typed” представляются в формате JSON как список объектов JSON. По умолчанию формат содержит лишь два столбца, разделённых двоеточием (’:’): слева имя поля, справа значение. Очень важно учитывать, что в типизированном формате вывод одного объекта идёт непрерывно, поэтому получателю не требуется хранить всё сразу. Если передан необязательный аргумент “float”, некоторые поля, обычно выводимые как целые числа, могут выводиться как числа с плавающей точкой для повышения точности. Намеренно не уточняется, какие именно поля затрагиваются, поскольку со временем это может измениться. Использование этой опции предполагает, что получатель умеет обрабатывать числа с плавающей точкой. Используемый формат вывода — sprintf("%f”).

В типизированном формате каждая строка состоит из 4 столбцов, разделённых двоеточиями (’:’). Первый столбец — последовательность из 3 элементов, разделённых точками. Первый элемент — числовая позиция поля в списке (начиная с нуля). Эта позиция не должна меняться со временем, но возможны пропуски в зависимости от опций сборки или удаления некоторых полей в будущем. Второй элемент — имя поля, как в обычном выводе “show info”. Третий элемент — относительный номер процесса, начинающийся с 1.

Остаток строки после первого двоеточия соответствует «типизированному формату вывода», описанному выше. Второй столбец (после первого ‘:’) указывает происхождение, характер и область действия переменной. Третий столбец задаёт тип поля: “s32”, “s64”, “u32”, “u64” или “str”. Четвёртый столбец содержит само значение; благодаря столбцу 3 получатель знает, как его разобрать, а благодаря столбцу 2 — как его обработать.

Таким образом, общий формат строки в типизированном режиме:

<field_pos>.<field_name>.<process_num>:<tags>:<type>:<value>

Если к команде добавлено “desc”, в конец добавляется ещё одно двоеточие и строка в кавычках с описанием метрики. На момент написания это поддерживается только для формата “typed” и формата по умолчанию.

Пример:

> show info
Name: HAProxy
Version: 1.7-dev1-de52ea-146
Release_date: 2016/03/11
Nbproc: 1
Process_num: 1
Pid: 28105
Uptime: 0d 0h00m04s
Uptime_sec: 4
Memmax_MB: 0
PoolAlloc_MB: 0
PoolUsed_MB: 0
PoolFailed: 0
(...)

> show info typed
0.Name.1:POSV:str:HAProxy
1.Version.1:POSV:str:3.1-dev0-7c653d-2466
2.Release_date.1:POSV:str:2025/07/01
3.Nbthread.1:CGSV:u32:1
4.Nbproc.1:CGSV:u32:1
5.Process_num.1:KGPV:u32:1
6.Pid.1:SGPV:u32:638069
7.Uptime.1:MDPV:str:0d 0h00m07s
8.Uptime_sec.1:MDPV:u32:7
9.Memmax_MB.1:CLPV:u32:0
10.PoolAlloc_MB.1:MGPV:u32:0
11.PoolUsed_MB.1:MGPV:u32:0
12.PoolFailed.1:MCPV:u32:0
(...)

В типизированном формате ID процесса в конце первого столбца позволяет очень легко визуально объединять вывод нескольких процессов. Пример:

$ ( echo show info typed | socat /var/run/haproxy.sock1;    \
    echo show info typed | socat /var/run/haproxy.sock2 ) |  \
  sort -t . -k 1,1n -k 2,2 -k 3,3n
0.Name.1:POS:str:HAProxy
0.Name.2:POS:str:HAProxy
1.Version.1:POS:str:1.7-dev1-868ab3-148
1.Version.2:POS:str:1.7-dev1-868ab3-148
2.Release_date.1:POS:str:2016/03/11
2.Release_date.2:POS:str:2016/03/11
3.Nbproc.1:CGS:u32:2
3.Nbproc.2:CGS:u32:2
4.Process_num.1:KGP:u32:1
4.Process_num.2:KGP:u32:2
5.Pid.1:SGP:u32:30120
5.Pid.2:SGP:u32:30121
6.Uptime.1:MDP:str:0d 0h01m28s
6.Uptime.2:MDP:str:0d 0h01m28s
(...)

Формат вывода JSON описывается схемой, которую можно получить командой “show schema json”.

Чтобы уменьшить объём, вывод JSON не содержит лишних пробелов. Для чтения человеком его может быть удобно пропустить через средство форматирования. Пример:

$ echo “show info json” | socat /var/run/haproxy.sock stdio | \ python -m json.tool

Чтобы уменьшить объём, вывод JSON не содержит лишних пробелов. Для чтения человеком его может быть удобно пропустить через средство форматирования. Пример:

$ echo “show info json” | socat /var/run/haproxy.sock stdio | \ python -m json.tool

show libs

show libs

Выгружает список загруженных разделяемых динамических библиотек и объектных файлов в системах, которые это поддерживают. Если сведения доступны, для каждого разделяемого объекта указываются диапазон виртуальных адресов, размер и путь к объекту. Это можно использовать, например, чтобы определить, какая библиотека предоставляет функцию, встречающуюся в дампе. Учтите, что во многих системах адреса меняются при каждом перезапуске (рандомизация адресного пространства), поэтому для анализа файла core этот список нужно получать при запуске. Команда может выполняться только через сокеты с уровнем “operator” или “admin”. Формат вывода может различаться между операционными системами, архитектурами и даже версиями haproxy, поэтому в скриптах на него полагаться не следует.

show map [[@<ver>] <map>]

show map [[@<ver>] <map>]

Выгружает сведения о преобразователях карт. Без аргумента возвращается список всех доступных карт. Если задан <map>, выгружается его содержимое. <map> — это #<id> или <name>. По умолчанию показывается текущая версия карты (версия, с которой сейчас выполняется сопоставление и которая указана как ‘curr_ver’ в списке карт). Можно выгрузить другие версии, поставив ‘@<ver>’ перед идентификатором карты. Версия действует как фильтр: для несуществующей версии просто не будет результата. Значение ’entry_cnt’ показывает число всех записей карты, а не только активных, то есть включает и записи, добавляемые в данный момент.

В выводе первый столбец — уникальный идентификатор записи, который можно использовать как ссылку в операциях “del map” и “set map”. Второй столбец — шаблон, а третий — образец, если он доступен. Возвращаемые данные представляют собой не непосредственно список доступных карт, а список всех шаблонов, составляющих какую-либо карту. Многие из этих шаблонов могут быть общими с ACL.

show peers [dict|-] [<peers section>]

show peers [dict|-] [<peers section>]

Выгружает сведения об узлах peers, настроенных в секциях “peers”. Без аргумента перечисляются узлы из всех секций “peers”. Если задан <peers section>, выгружаются сведения только об узлах этой секции “peers”. Если перед именем секции peers указано “dict”, также полностью выгружаются кеши словарей Tx/Rx (очень большие). Для вывода секции peers с именем “dict” может потребоваться передать “-”.

Ниже приведены два примера вывода, где узлы peers hostA, hostB и hostC принадлежат секциям peers “sharedlb”. Соединение установлено только между hostA и hostB. Данные отправлял только hostA узлу hostB.

$ echo “show peers” | socat - /tmp/hostA 0x55deb0224320: [15/Apr/2019:11:28:01] id=sharedlb state=0 flags=0x3 \ resync_timeout=<PAST> task_calls=45122 0x55deb022b540: id=hostC(remote) addr=127.0.0.12:10002 status=CONN \ reconnect=4s confirm=0 flags=0x0 0x55deb022a440: id=hostA(local) addr=127.0.0.10:10000 status=NONE \ reconnect=<NEVER> confirm=0 flags=0x0 0x55deb0227d70: id=hostB(remote) addr=127.0.0.11:10001 status=ESTA reconnect=2s confirm=0 flags=0x20000200 appctx:0x55deb028fba0 st0=7 st1=0 task_calls=14456 \ state=EST xprt=RAW src=127.0.0.1:37257 addr=127.0.0.10:10000 remote_table:0x55deb0224a10 id=stkt local_id=1 remote_id=1 last_local_table:0x55deb0224a10 id=stkt local_id=1 remote_id=1 shared tables:

0x55deb0224a10 local_id=1 remote_id=1 flags=0x0 remote_data=0x65
  last_acked=0 last_pushed=3 last_get=0 teaching_origin=0 update=3
  table:0x55deb022d6a0 id=stkt update=3 localupdate=3 \
    commitupdate=3 syncing=0

$ echo “show peers” | socat - /tmp/hostB 0x55871b5ab320: [15/Apr/2019:11:28:03] id=sharedlb state=0 flags=0x3 \ resync_timeout=<PAST> task_calls=3 0x55871b5b2540: id=hostC(remote) addr=127.0.0.12:10002 status=CONN \ reconnect=3s confirm=0 flags=0x0 0x55871b5b1440: id=hostB(local) addr=127.0.0.11:10001 status=NONE \ reconnect=<NEVER> confirm=0 flags=0x0 0x55871b5aed70: id=hostA(remote) addr=127.0.0.10:10000 status=ESTA \ reconnect=2s confirm=0 flags=0x20000200 appctx:0x7fa46800ee00 st0=7 st1=0 task_calls=62356 \ state=EST remote_table:0x55871b5ab960 id=stkt local_id=1 remote_id=1 last_local_table:0x55871b5ab960 id=stkt local_id=1 remote_id=1 shared tables:

0x55871b5ab960 local_id=1 remote_id=1 flags=0x0 remote_data=0x65
  last_acked=3 last_pushed=0 last_get=3 teaching_origin=0 update=0
  table:0x55871b5b46a0 id=stkt update=1 localupdate=0 \
    commitupdate=0 syncing=0

show pools [byname|bysize|byusage] [detailed] [match <pfx>] [<nb>]

show pools [byname|bysize|byusage] [detailed] [match <pfx>] [<nb>]

Выгружает состояние внутренних пулов памяти. Это полезно для отслеживания использования памяти, например при подозрении на утечку. Команда делает то же самое, что SIGQUIT при работе в переднем плане, но не очищает пулы. По умолчанию вывод не сортируется. Если указано “byname”, он сортируется по имени пула; “bysize” — по убыванию размера элемента; “byusage” — по убыванию общего использования памяти, причём показываются только используемые записи. Вывод также можно ограничить первыми <nb> записями (например, при сортировке по использованию). Опция “detailed” позволяет дополнительно выгрузить внутренние сведения, включая список всех объединённых пулов. Наконец, если задано “match” с префиксом, показываются только пулы, чьи имена начинаются с этого префикса. Выводимый итог относится только к пулам, соответствующим условиям фильтрации. Пример:

$ socat - /tmp/haproxy.sock <<< "show pools match quic byusage"
Dumping pools usage. Use SIGQUIT to flush them.
  - Pool quic_conn_r (65560 bytes): 1337 allocated (87653720 bytes), ...
  - Pool quic_crypto (1048 bytes): 6685 allocated (7005880 bytes), ...
  - Pool quic_conn (4056 bytes): 1337 allocated (5422872 bytes), ...
  - Pool quic_rxbuf (262168 bytes): 8 allocated (2097344 bytes), ...
  - Pool quic_conne (184 bytes): 9359 allocated (1722056 bytes), ...
  - Pool quic_frame (184 bytes): 7938 allocated (1460592 bytes), ...
  - Pool quic_tx_pac (152 bytes): 6454 allocated (981008 bytes), ...
  - Pool quic_tls_ke (56 bytes): 12033 allocated (673848 bytes), ...
  - Pool quic_rx_pac (408 bytes): 1596 allocated (651168 bytes), ...
  - Pool quic_tls_se (88 bytes): 6685 allocated (588280 bytes), ...
  - Pool quic_cstrea (88 bytes): 4011 allocated (352968 bytes), ...
  - Pool quic_tls_iv (24 bytes): 12033 allocated (288792 bytes), ...
  - Pool quic_dgram (344 bytes): 732 allocated (251808 bytes), ...
  - Pool quic_arng (56 bytes): 4011 allocated (224616 bytes), ...
  - Pool quic_conn_c (152 bytes): 1337 allocated (203224 bytes), ...
Total: 15 pools, 109578176 bytes allocated, 109578176 used ...

show profiling [{all | status | tasks | memory}] [byaddr|bytime|byctx|aggr|<max_lines>]*

show profiling [{all | status | tasks | memory}] [byaddr|bytime|byctx|aggr|<max_lines>]*

Выгружает текущие настройки профилирования, по одной в строке, а также команды для их изменения. При включённом профилировании задач также выводится собранная планировщиком статистика по функциям: число вызовов, общее/среднее время CPU и общая/средняя задержка. При включённом профилировании памяти выводятся, например, число выделений/освобождений и их размеры. Соответствующими ключевыми словами можно ограничить вывод только состоянием профилирования, задачами или профилированием памяти; по умолчанию выгружаются все сведения о профилировании. Также можно задать числовой лимит строк вывода для каждой категории. Вместо сортировки по использованию можно запросить сортировку по адресу, общему времени выполнения или контексту вызова, например для упрощения сравнения последовательных вызовов или поиска того, что нужно оптимизировать. Можно также агрегировать активность задач по вызываемой функции вместо подробного вывода. Учтите, что профилирование предназначено главным образом для разработчиков: оно помогает понять, где в коде неэффективно расходуются циклы CPU или память. Полезных данных для мониторинга здесь нет.

show resolvers [<resolvers section id>]

show resolvers [<resolvers section id>]

Выгружает статистику указанной секции resolvers либо всех секций resolvers, если секция не задана.

Для каждого сервера имён выводятся следующие счётчики:

sent: число запросов DNS, отправленных этому серверу
valid: число корректных ответов DNS, полученных от этого сервера
update: число ответов DNS, использованных для обновления IP-адреса сервера
cname: число ответов CNAME
cname_error: ошибки CNAME при взаимодействии с этим сервером
any_err: число пустых ответов (т. е. сервер не поддерживает тип ANY)
nx: ответ о несуществующем домене, полученный от этого сервера
timeout: сколько раз этот сервер не ответил вовремя
refused: число запросов, отклонённых этим сервером
other: любые другие ошибки DNS
invalid: некорректный ответ DNS (с точки зрения протокола)
too_big: слишком большой ответ
outdated: число ответов, пришедших слишком поздно (после другого сервера имён)

show quic [<format>] [<filter>]

show quic [<format>] [<filter>]

Выгружает сведения обо всех активных соединениях QUIC фронтенда. Команда имеет ограниченный доступ и может выполняться только через сокеты с уровнем “operator” или “admin”.

Необязательный аргумент позволяет управлять подробностью вывода. Его значение можно интерпретировать разными способами. Первый вариант — предопределённые значения: “oneline” для формата по умолчанию, “stream” для перечисления всех активных потоков и “full” для вывода всех сведений. Вместо этого можно задать разделённый запятыми список полей, ограничив вывод. Сейчас поддерживаются “tp”, “sock”, “pktns”, “cc” и “mux”. Наконец, значение формата “help” выводит более подробную справку.

Последний аргумент ограничивает или расширяет список соединений. По умолчанию показываются только активные соединения фронтенда. Дополнительный аргумент “clo” позволяет вместо них вывести закрывающиеся соединения фронтенда, “be” — соединения бэкенда, “all” — все категории. Также можно ограничиться одним соединением, указав его шестнадцатеричный адрес.

show servers conn [<backend>]

show servers conn [<backend>]

Выгружает состояние текущих и простаивающих соединений серверов указанного бэкенда (или всех бэкендов, если ни один не указан). Можно использовать имя или идентификатор бэкенда.

Вывод начинается со строки с названиями полей, затем каждый сервер занимает одну строку: имя и ID бэкенда, имя и ID сервера, адрес, порт и ряд значений. Число полей зависит от числа потоков. Точный формат вывода может немного различаться между версиями и в зависимости от числа потоков. При извлечении значений нужно учитывать строку заголовка для сопоставления столбцов и число потоков, поскольку последние столбцы относятся к отдельным потокам:

bkname/svname         Имя бэкенда '/' имя сервера
bkid/svid             ID бэкенда '/' ID сервера
addr                  IP-адрес сервера
port                  Порт сервера (ноль, если отсутствует)
-                     Неиспользуемое поле, служит визуальным разделителем
purge_delay           Интервал между очистками соединений в миллисекундах
served                Число соединений, используемых в данный момент
used_cur              Число соединений, используемых в данный момент;
                      соединения, привязанные к сеансу, не учитываются
used_max              Наибольшее значение used_cur с запуска процесса
need_est              Плавающая оценка общего необходимого числа соединений
idle_sess             Число неактивных соединений, помеченных как частные
unsafe_nb             Число неактивных соединений, считающихся «небезопасными»
safe_nb               Число неактивных соединений, считающихся «безопасными»
idle_lim              Настроенный максимум числа неактивных соединений
idle_cur              Сумма текущего числа неактивных соединений по потокам
idle_per_thr[NB]      Неактивные соединения каждого из NB потоков

HAProxy закрывает часть <idle_cur> каждые <purge_delay>, когда сумма <idle_cur> + <used_cur> превышает оценку <need_est>. Эта оценка меняется в зависимости от активности соединений.

Из-за многопоточной обработки простаивающих соединений важно понимать, что некоторые значения могут измениться сразу после чтения, поэтому согласованность значений внутри строки не гарантируется. Этот вывод предназначен преимущественно для отладки и не подходит для регулярного мониторинга или построения графиков.

show servers state [<backend>]

show servers state [<backend>]

Выгружает состояние серверов из действующей конфигурации. Можно указать имя или идентификатор бэкенда, чтобы ограничить вывод только им.

Выгрузка имеет следующий формат:

  • первая строка содержит версию формата (1 в этой спецификации);
  • вторая строка содержит заголовки столбцов с префиксом решётки (’#’);
  • третья и последующие строки содержат данные;
  • любая строка, начинающаяся с решётки (’#’), считается комментарием.

Поскольку одновременно могут существовать несколько версий вывода, ниже приведены поля и их порядок для каждой версии формата файла:

1:
  be_id:                       Уникальный идентификатор бэкенда.
  be_name:                     Имя бэкенда.
  srv_id:                      Уникальный идентификатор сервера (в пределах бэкенда).
  srv_name:                    Имя сервера.
  srv_addr:                    IP-адрес сервера.
  srv_op_state:                Рабочее состояние сервера (UP/DOWN/...).
                                 0 = SRV_ST_STOPPED
                                   Сервер недоступен.
                                 1 = SRV_ST_STARTING
                                   Сервер постепенно выходит на рабочую нагрузку
                                   (доступен, но нагрузка ограничена).
                                 2 = SRV_ST_RUNNING
                                   Сервер полностью доступен.
                                 3 = SRV_ST_STOPPING
                                   Сервер доступен, но выполняет мягкую остановку
                                   (например, 404).
  srv_admin_state:             Административное состояние сервера (MAINT/DRAIN/...).
                               Состояние является битовой маской значений:
                                 0x01 = SRV_ADMF_FMAINT
                                   Сервер явно принудительно переведён
                                   в режим обслуживания.
                                 0x02 = SRV_ADMF_IMAINT
                                   Сервер унаследовал режим обслуживания
                                   от отслеживаемого сервера.
                                 0x04 = SRV_ADMF_CMAINT
                                   Сервер находится в режиме обслуживания
                                   из-за конфигурации.
                                 0x08 = SRV_ADMF_FDRAIN
                                   Сервер явно принудительно переведён
                                   в режим вывода из обслуживания (drain).
                                 0x10 = SRV_ADMF_IDRAIN
                                   Сервер унаследовал режим drain
                                   от отслеживаемого сервера.
                                 0x20 = SRV_ADMF_RMAINT
                                   Сервер находится в режиме обслуживания
                                   из-за ошибки разрешения IP-адреса.
                                 0x40 = SRV_ADMF_HMAINT
                                   FQDN сервера задан через сокет статистики.

  srv_uweight:                 Видимый пользователю вес сервера.
  srv_iweight:                 Исходный вес сервера.
  srv_time_since_last_change:  Время с последнего изменения рабочего состояния.
  srv_check_status:            Состояние последней проверки работоспособности.
  srv_check_result:            Результат последней проверки (FAILED/PASSED/...).
                                 0 = CHK_RES_UNKNOWN
                                   Начальное значение по умолчанию.
                                 1 = CHK_RES_NEUTRAL
                                   Корректная проверка без сведений о состоянии.
                                 2 = CHK_RES_FAILED
                                   Проверка не пройдена.
                                 3 = CHK_RES_PASSED
                                   Проверка пройдена, сервер снова
                                   полностью доступен.
                                 4 = CHK_RES_CONDPASS
                                   Проверка сообщает, что сервер не хочет
                                   принимать новые сеансы.
  srv_check_health:            Текущее значение счётчика проверок rise / fall.
  srv_check_state:             Состояние проверки (ENABLED/PAUSED/...).
                               Состояние является битовой маской значений:
                                 0x01 = CHK_ST_INPROGRESS
                                   Сейчас выполняется проверка.
                                 0x02 = CHK_ST_CONFIGURED
                                   Проверка настроена и может
                                   быть включена.
                                 0x04 = CHK_ST_ENABLED
                                   Проверка сейчас включена
                                   административно.
                                 0x08 = CHK_ST_PAUSED
                                   Проверки приостановлены из-за обслуживания
                                   (только проверки работоспособности).
  srv_agent_state:             Состояние проверки агента (ENABLED/PAUSED/...).
                               Использует те же значения маски, что и
                               "srv_check_state", с одним дополнительным:
                                 0x10 = CHK_ST_AGENT
                                   Проверка выполняется агентом (иначе это
                                   проверка работоспособности).
  bk_f_forced_id:              Флаг, указывающий, задан ли ID бэкенда
                               принудительно в конфигурации.
  srv_f_forced_id:             Флаг, указывающий, задан ли ID сервера
                               принудительно в конфигурации.
  srv_fqdn:                    FQDN сервера.
  srv_port:                    Порт сервера.
  srvrecord:                   Запись DNS SRV, связанная с этим SRV.
  srv_use_ssl:                 Использование ssl для соединений с сервером.
  srv_check_port:              Порт проверки работоспособности сервера.
  srv_check_addr:              Адрес проверки работоспособности сервера.
  srv_agent_addr:              Адрес агента проверки работоспособности сервера.
  srv_agent_port:              Порт агента проверки работоспособности сервера.

show sess [<options>*]

show sess [<options>*]

Выгружает все известные активные потоки (ранее называвшиеся «сеансами»). Не выполняйте это на медленных соединениях, поскольку объём вывода может быть огромным. Команда имеет ограниченный доступ и может выполняться только через сокеты с уровнем “operator” или “admin”. На машинах, где соединения быстро сменяют друг друга, вывод может содержать меньше записей, чем существует на самом деле: выводятся все существующие потоки вплоть до последнего созданного перед вводом команды; потоки, завершившиеся за это время, не появятся. Поддерживаемые опции описаны ниже.

show sess [<id> | all | help] [<options>*]

show sess [<id> | all | help] [<options>*]

Выводит множество внутренних сведений о соответствующих потоках. Команда поддерживает два формата: краткий, используемый по умолчанию, если не запрошен конкретный идентификатор потока, и расширенный — при перечислении указанных потоков. Краткий формат, используемый по умолчанию командой “show sess”, выводит каждый поток одной строкой с несколькими сведениями и его шестнадцатеричным идентификатором в начале строки (это указатель на поток).

В расширенной форме, используемой командами “show sess <id>” или “show sess all”, каждый поток выводится с большим количеством отладочных сведений на нескольких строках (около 20 на поток), по-прежнему начинаясь с идентификатора. Разделителем между потоками служит идентификатор в начале строки; дополнительные строки того же потока начинаются с одного или нескольких пробелов (поток выводится с отступом). Выгрузка большого числа потоков может дать огромный объём вывода, занять много времени и сильно загрузить CPU, поэтому всегда лучше выводить только необходимый минимум. Большинству пользователей эти сведения бесполезны, но разработчики HAProxy могут использовать их для диагностики сложных ошибок. Точный формат вывода намеренно не документирован, чтобы он мог свободно меняться по мере необходимости, в том числе в стабильных ветках. При интерпретации этого вывода следует сверяться с функцией strm_dump_to_buffer() в src/stream.c для определения точного смысла некоторых полей.

Аргумент “help” вместо выгрузки потоков выводит подробную справку по команде.

Можно задать опции для настройки выгрузки или применения фильтров. Поддерживаются следующие опции: - backend <b> — показывать только потоки, привязанные к этому бэкенду - frontend <f> — показывать только потоки, привязанные к этому фронтенду - older <age> — показывать только потоки старше <age> секунд - server <b/s> — показывать только потоки, привязанные к этой паре бэкенд+сервер - show-uri — выводить URI транзакции, захваченный при анализе запроса; он отображается только при наличии захвата - susp — показывать только потоки, которые разработчики считают подозрительными по критериям, способным меняться со временем или между версиями.

show stat [domain <resolvers|proxy>] [{<iid>|<proxy>} <type> <sid>] \

show stat [domain <resolvers|proxy>] [{<iid>|<proxy>} <type> <sid>] \
          [typed|json] [desc] [up|no-maint]

Выгружает статистику. Домен определяет, какую статистику выводить; сейчас доступны resolvers и proxy. По умолчанию используется формат CSV. Можно включить расширенный типизированный формат, описанный выше, передав “typed” после остальных аргументов, либо формат JSON, передав “json” после остальных аргументов. Аргументы <id>, <type> и <sid> позволяют вывести только выбранные элементы: - <iid> — ID прокси, -1 для вывода всего. Вместо него можно указать имя прокси <proxy>; тогда ID этого прокси используется для выбора по ID. - <type> выбирает тип выводимых объектов: 1 для фронтендов, 2 для бэкендов, 4 для серверов, -1 для всего. Эти значения можно объединять побитовым ИЛИ, например:

1 + 2     = 3   -> фронтенд + бэкенд.
1 + 2 + 4 = 7   -> фронтенд + бэкенд + сервер.
- `<sid>` — ID сервера, -1 для вывода всего из выбранного прокси.

Пример:

    $ echo "show info;show stat" | socat stdio unix-connect:/tmp/sock1
>>> Name: HAProxy
    Version: 1.4-dev2-49
    Release_date: 2009/09/23
    Nbproc: 1
    Process_num: 1
    (...)

    # pxname,svname,qcur,qmax,scur,smax,slim,stot,bin,bout,dreq,  (...)
    stats,FRONTEND,,,0,0,1000,0,0,0,0,0,0,,,,,OPEN,,,,,,,,,1,1,0, (...)
    stats,BACKEND,0,0,0,0,1000,0,0,0,0,0,,0,0,0,0,UP,0,0,0,,0,250,(...)
    (...)
    www1,BACKEND,0,0,0,0,1000,0,0,0,0,0,,0,0,0,0,UP,1,1,0,,0,250, (...)

    $

В этом примере одновременно выполнены две команды. Так в многопроцессном режиме легко определить, к какому процессу относится статистика. В типизированном формате это не требуется, поскольку номер процесса указан в каждой строке. Обратите внимание на пустую строку после вывода информации: она обозначает конец первого блока. Такая же пустая строка есть в конце второго блока (статистики), чтобы получатель мог убедиться, что вывод не обрезан.

При указании “typed” формат вывода лучше подходит средствам мониторинга, поскольку предоставляет числовые позиции и тип каждого поля. Каждое значение занимает отдельную строку с номером процесса, номером элемента, характером, происхождением и областью действия. Тот же формат доступен через статистику HTTP при добавлении “;typed” после URI. Очень важно учитывать, что в типизированном формате вывод одного объекта идёт непрерывно, поэтому получателю не требуется хранить всё сразу.

Модификатор “up” приводит к выводу только серверов, которые считаются доступными или не проверяются. Недоступные серверы, серверы с неразрешённым адресом и серверы в режиме обслуживания не выводятся. Это аналог опции “;up” в статистике HTTP. Аналогично, модификатор “no-maint” действует как модификатор HTTP “;no-maint” и исключает из вывода отключённые серверы. Разница в том, что включённые, но недоступные серверы остаются в выводе.

В типизированном формате каждая строка состоит из 4 столбцов, разделённых двоеточиями (’:’). Первый столбец — последовательность из 5 элементов, разделённых точками. Первый элемент — буква, указывающая тип описываемого объекта. Сейчас известны следующие типы: ‘F’ — фронтенд, ‘B’ — бэкенд, ‘L’ — слушатель и ‘S’ — сервер. Второй элемент — положительное целое число, представляющее уникальный идентификатор прокси, которому принадлежит объект. Он эквивалентен столбцу “iid” вывода CSV и соответствует значению необязательной директивы “id” в секции frontend или backend. Третий элемент — положительное целое число с уникальным идентификатором объекта внутри прокси, соответствующее столбцу “sid” вывода CSV. При выводе фронтенда или бэкенда указывается ID 0. Для слушателя или сервера это соответствующий ID внутри прокси. Четвёртый элемент — числовая позиция поля в списке (начиная с нуля). Эта позиция не должна меняться со временем, но возможны пропуски в зависимости от опций сборки или удаления некоторых полей в будущем. Пятый элемент — имя поля, как в выводе CSV. Шестой элемент — положительное целое число, относительный номер процесса, начинающийся с 1.

Остаток строки после первого двоеточия соответствует «типизированному формату вывода», описанному выше. Второй столбец (после первого ‘:’) указывает происхождение, характер, область действия и признак сохранения переменной. Третий столбец задаёт тип поля: “s32”, “s64”, “u32”, “u64”, “flt” или “str”. Четвёртый столбец содержит само значение; благодаря столбцу 3 получатель знает, как его разобрать, а благодаря столбцу 2 — как его обработать.

Если к команде добавлено “desc”, в конец добавляется ещё одно двоеточие и строка в кавычках с описанием метрики. На момент написания это поддерживается только для формата “typed”.

Таким образом, общий формат строки в типизированном режиме:

<obj>.<px_id>.<id>.<fpos>.<fname>.<process_num>:<tags>:<type>:<value>

Пример типизированного формата вывода:

$ echo "show stat typed" | socat stdio unix-connect:/tmp/sock1
F.2.0.0.pxname.1:KNSV:str:dummy
F.2.0.1.svname.1:KNSV:str:FRONTEND
F.2.0.4.scur.1:MGPV:u32:0
F.2.0.5.smax.1:MMPV:u32:0
F.2.0.6.slim.1:CLPV:u32:524269
F.2.0.7.stot.1:MCPP:u64:0
F.2.0.8.bin.1:MCPP:u64:0
F.2.0.9.bout.1:MCPP:u64:0
F.2.0.10.dreq.1:MCPP:u64:0
F.2.0.11.dresp.1:MCPP:u64:0
F.2.0.12.ereq.1:MCPP:u64:0
F.2.0.17.status.1:SGPV:str:OPEN
F.2.0.26.pid.1:KGPV:u32:1
F.2.0.27.iid.1:KGSV:u32:2
F.2.0.28.sid.1:KGSV:u32:0
F.2.0.32.type.1:CGSV:u32:0
F.2.0.33.rate.1:MRPP:u32:0
F.2.0.34.rate_lim.1:CLPV:u32:0
F.2.0.35.rate_max.1:MMPV:u32:0
F.2.0.46.req_rate.1:MRPP:u32:0
F.2.0.47.req_rate_max.1:MMPV:u32:0
F.2.0.48.req_tot.1:MCPP:u64:0
F.2.0.51.comp_in.1:MCPP:u64:0
F.2.0.52.comp_out.1:MCPP:u64:0
F.2.0.53.comp_byp.1:MCPP:u64:0
F.2.0.54.comp_rsp.1:MCPP:u64:0
(...)

В типизированном формате ID процесса в конце первого столбца позволяет очень легко визуально объединять вывод нескольких процессов, как в следующем примере, где каждая строка присутствует для каждого процесса:

$ ( echo show stat typed | socat /var/run/haproxy.sock1 -; \
    echo show stat typed | socat /var/run/haproxy.sock2 - ) | \
  sort -t . -k 1,1 -k 2,2n -k 3,3n -k 4,4n -k 5,5 -k 6,6n
B.3.0.0.pxname.1:KNSV:str:private-backend
B.3.0.0.pxname.2:KNSV:str:private-backend
B.3.0.1.svname.1:KNSV:str:BACKEND
B.3.0.1.svname.2:KNSV:str:BACKEND
B.3.0.2.qcur.1:MGPV:u32:0
B.3.0.2.qcur.2:MGPV:u32:0
B.3.0.3.qmax.1:MMPV:u32:0
B.3.0.3.qmax.2:MMPV:u32:0
B.3.0.4.scur.1:MGPV:u32:0
B.3.0.4.scur.2:MGPV:u32:0
B.3.0.5.smax.1:MMPV:u32:0
B.3.0.5.smax.2:MMPV:u32:0
B.3.0.6.slim.1:CLPV:u32:1000
B.3.0.6.slim.2:CLPV:u32:1000
(...)

Формат вывода JSON описывается схемой, которую можно получить командой “show schema json”.

Чтобы уменьшить объём, вывод JSON не содержит лишних пробелов. Для чтения человеком его может быть удобно пропустить через средство форматирования. Пример:

$ echo “show stat json” | socat /var/run/haproxy.sock stdio | \ python -m json.tool

Чтобы уменьшить объём, вывод JSON не содержит лишних пробелов. Для чтения человеком его может быть удобно пропустить через средство форматирования. Пример:

$ echo “show stat json” | socat /var/run/haproxy.sock stdio | \ python -m json.tool

show ssl ca-file [[*][\]<cafile>[:<index>]]

show ssl ca-file [[*][\]<cafile>[:<index>]]

Показывает список загруженных в процесс файлов CA и число сертификатов в каждом. Сертификаты не используются ни одним фронтендом или бэкендом, пока их состояние не станет “Used”. В списке может присутствовать запись “@system-ca”, которую по умолчанию загружает httpclient. Она содержит возвращённый OpenSSL список доверенных CA системы. Если перед именем файла стоит звёздочка, это ещё не зафиксированная транзакция. Если <cafile> указан без <index>, выводится состояние файла CA (“Used”/“Unused”), а затем сведения обо всех сертификатах в файле CA. Для каждого сертификата выводятся те же сведения, что командой “show ssl cert”. Если после <cafile> указан <index>, выводятся только сведения о сертификате с этим индексом. Индексы начинаются с 1. При недопустимом индексе (например, слишком большом) ничего не выводится. Команда позволяет проверить, правильно ли обновлён файл CA. Также можно вывести сведения о текущей транзакции, поставив ‘’ перед именем файла. Если первым символом имени файла является ‘’, его можно экранировать как ‘\*’.

Пример:

$ echo "show ssl ca-file" | socat /var/run/haproxy.master -
# transaction
*cafile.crt - 2 certificate(s)
# filename
cafile.crt - 1 certificate(s)

$ echo "show ssl ca-file cafile.crt" | socat /var/run/haproxy.master -
Filename: /home/tricot/work/haproxy/reg-tests/ssl/set_cafile_ca2.crt
Status: Used

Certificate #1:
Serial: 11A4D2200DC84376E7D233CAFF39DF44BF8D1211
notBefore: Apr  1 07:40:53 2021 GMT
notAfter: Aug 17 07:40:53 2048 GMT
Subject Alternative Name:
Algorithm: RSA4096
SHA1 FingerPrint: A111EF0FEFCDE11D47FE3F33ADCA8435EBEA4864
Subject: /C=FR/ST=Some-State/O=HAProxy Technologies/CN=HAProxy Technologies CA
Issuer: /C=FR/ST=Some-State/O=HAProxy Technologies/CN=HAProxy Technologies CA

$ echo "show ssl ca-file *cafile.crt:2" | socat /var/run/haproxy.master -
Filename: */home/tricot/work/haproxy/reg-tests/ssl/set_cafile_ca2.crt
Status: Unused

Certificate #2:
Serial: 587A1CE5ED855040A0C82BF255FF300ADB7C8136
[...]

show ssl cert [[*][\]<filename>]

show ssl cert [[*][\]<filename>]

Показывает список сертификатов, загруженных в процесс. Они не используются ни одним фронтендом или бэкендом, пока их состояние не станет “Used”. Если перед именем файла стоит звёздочка, это ещё не зафиксированная транзакция. Если указано имя файла, выводятся подробные сведения о сертификате. Команда позволяет проверить, правильно ли обновлён сертификат. Также можно вывести сведения о транзакции, поставив ‘’ перед именем файла. Если первым символом имени файла является ‘’, его можно экранировать как ‘\*’. Эта команда также позволяет вывести сведения об ответе OCSP сертификата: для этого к имени файла добавляется расширение “.ocsp”. Это работает как для зафиксированных сертификатов, так и для текущих транзакций. Для зафиксированного сертификата команда эквивалентна вызову “show ssl ocsp-response” с ID соответствующего ответа OCSP.

Пример:

$ echo "@1 show ssl cert" | socat /var/run/haproxy.master -
# transaction
*test.local.pem
# filename
test.local.pem

$ echo "@1 show ssl cert test.local.pem" | socat /var/run/haproxy.master -
Filename: test.local.pem
Status: Used
Serial: 03ECC19BA54B25E85ABA46EE561B9A10D26F
notBefore: Sep 13 21:20:24 2019 GMT
notAfter: Dec 12 21:20:24 2019 GMT
Issuer: /C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
Subject: /CN=test.local
Subject Alternative Name: DNS:test.local, DNS:imap.test.local
Algorithm: RSA2048
SHA1 FingerPrint: 417A11CAE25F607B24F638B4A8AEE51D1E211477

$ echo "@1 show ssl cert *test.local.pem" | socat /var/run/haproxy.master -
Filename: *test.local.pem
Status: Unused
[...]

$ echo "@1 show ssl cert \*.local.pem" | socat /var/run/haproxy.master -
Filename: *.local.pem
Status: Used
[...]

show ssl crl-file [[*][\]<crlfile>[:<index>]]

show ssl crl-file [[*][\]<crlfile>[:<index>]]

Показывает список файлов CRL, загруженных в процесс. Они не используются ни одним фронтендом или бэкендом, пока их состояние не станет “Used”. Если перед именем файла стоит звёздочка, это ещё не зафиксированная транзакция. Если <crlfile> указан без <index>, выводится состояние файла CRL (“Used”/“Unused”), а затем сведения обо всех списках отзыва в файле CRL. Для каждого списка сведения основаны на выводе “openssl crl -text -noout -in <file>”. Если после <crlfile> указан <index>, выводятся только сведения о списке с этим индексом. Индексы начинаются с 1. При недопустимом индексе (например, слишком большом) ничего не выводится. Команда позволяет проверить, правильно ли обновлён файл CRL. Также можно вывести сведения о текущей транзакции, поставив ‘’ перед именем файла. Если первым символом имени файла является ‘’, его можно экранировать как ‘\*’.

Пример:

$ echo "show ssl crl-file" | socat /var/run/haproxy.master -
# transaction
*crlfile.pem
# filename
crlfile.pem

$ echo "show ssl crl-file crlfile.pem" | socat /var/run/haproxy.master -
Filename: /home/tricot/work/haproxy/reg-tests/ssl/crlfile.pem
Status: Used

Certificate Revocation List #1:
Version 1
Signature Algorithm: sha256WithRSAEncryption
Issuer: /C=FR/O=HAProxy Technologies/CN=Intermediate CA2
Last Update: Apr 23 14:45:39 2021 GMT
Next Update: Sep  8 14:45:39 2048 GMT
Revoked Certificates:
    Serial Number: 1008
        Revocation Date: Apr 23 14:45:36 2021 GMT

Certificate Revocation List #2:
Version 1
Signature Algorithm: sha256WithRSAEncryption
Issuer: /C=FR/O=HAProxy Technologies/CN=Root CA
Last Update: Apr 23 14:30:44 2021 GMT
Next Update: Sep  8 14:30:44 2048 GMT
No Revoked Certificates.

show ssl crt-list [-n] [<filename>]

show ssl crt-list [-n] [<filename>]

Показывает список crt-list и каталогов, используемых в конфигурации HAProxy. Если указано имя файла, выгружает содержимое crt-list или каталога. Полученный вывод можно использовать как файл crt-list. Опция ‘-n’ выводит номера строк; это полезно вместе с ‘del ssl crt-list’, когда запись повторяется. Вывод с опцией ‘-n’ несовместим с форматом crt-list и не может быть загружен haproxy.

Пример:

echo "show ssl crt-list -n localhost.crt-list" | socat /tmp/sock1 -
# localhost.crt-list
common.pem:1 !not.test1.com *.test1.com !localhost
common.pem:2
ecdsa.pem:3 [verify none allow-0rtt ssl-min-ver TLSv1.0 ssl-max-ver TLSv1.3] localhost !www.test1.com
ecdsa.pem:4 [verify none allow-0rtt ssl-min-ver TLSv1.0 ssl-max-ver TLSv1.3]

show ssl ech [<name>]

show ssl ech [<name>]

Показывает список ключей ECH, загруженных в процесс HAProxy.

Если указан <name>, показывает ключи определённой строки bind. Формат строки bind — <frontend>/@<filename>:<linenum> (пример: frontend1/@haproxy.conf :19) или <frontend>/<name>, если строке bind назначено имя с помощью ключевого слова “name”.

Поле ‘age’ представляет время в секундах с момента загрузки ключа в строку bind. Это значение сбрасывается при запуске HAProxy, перезагрузке его конфигурации или перезапуске.

Требуется версия OpenSSL с поддержкой ECH, а HAProxy должен быть собран с USE_ECH=1. Команда поддерживается только в соединении CLI, работающем в экспериментальном режиме (см. “experimental-mode on”).

См. также “ech” в разделе 5.1 руководства по конфигурации.

Пример:

$ echo "experimental-mode on; show ssl ech" | socat /tmp/haproxy.sock -
 ***
 frontend: frontend1

 bind: frontend1/@haproxy.conf:19

 ECH entry: 0 public_name: example.com age: 557 (has private key)
      [fe0d,94,example.com,[0020,0001,0001],c39285b774bf61c071864181c5292a012b30adaf767e39369a566af05573ef2b,00,00]

 ECH entry: 1 public_name: example.com age: 557 (has private key)
      [fe0d,ee,example.com,[0020,0001,0001],6572191131b5cabba819f8cacf2d2e06fa0b87b30d9b793644daba7b8866d511,00,00]

 bind: frontend1/@haproxy.conf:20

 ECH entry: 0 public_name: example.com age: 557 (has private key)
      [fe0d,94,example.com,[0020,0001,0001],c39285b774bf61c071864181c5292a012b30adaf767e39369a566af05573ef2b,00,00]

 ECH entry: 1 public_name: example.com age: 557 (has private key)
      [fe0d,ee,example.com,[0020,0001,0001],6572191131b5cabba819f8cacf2d2e06fa0b87b30d9b793644daba7b8866d511,00,00]

$ echo "experimental-mode on; show ssl ech frontend1/@haproxy.conf:19" | socat /tmp/haproxy.sock -
***
ECH for frontend1/@haproxy.conf:19
ECH entry: 0 public_name: example.com age: 786 (has private key)
      [fe0d,94,example.com,[0020,0001,0001],c39285b774bf61c071864181c5292a012b30adaf767e39369a566af05573ef2b,00,00]

ECH entry: 1 public_name: example.com age: 786 (has private key)
      [fe0d,ee,example.com,[0020,0001,0001],6572191131b5cabba819f8cacf2d2e06fa0b87b30d9b793644daba7b8866d511,00,00]

show ssl jwt

show ssl jwt

Показывает список сертификатов, которые можно использовать для проверки JWT. См. также команды “add ssl jwt” и “del ssl jwt”. Дополнительные сведения приведены в описании опции сертификата “jwt”.

Пример:

echo "show ssl jwt"  | socat /tmp/sock1 -
#filename
jwt.pem

show ssl ocsp-response [[text|base64] <id|path>]

show ssl ocsp-response [[text|base64] <id|path>]

Показывает ID записей дерева OCSP, соответствующих всем ответам OCSP, используемым в HAProxy, а также путь к соответствующему сертификату фронтенда, имя и хеш ключа издателя и серийный номер сертификата, для которого создан ответ OCSP. Если указан допустимый <id> или <path> действительного сертификата фронтенда, выводится содержимое соответствующего ответа OCSP. При указании <id> можно задать формат выгрузки данных. Опция ’text’ используется по умолчанию и выводит подробные сведения об ответе OCSP так же, как вызов “openssl ocsp -respin <ocsp-response> -text”. Формат ‘base64’ позволяет выгрузить содержимое ответа OCSP в base64.

Пример:

$ echo "show ssl ocsp-response" | socat /var/run/haproxy.master -
# Certificate IDs
  Certificate ID key: 303b300906052b0e03021a050004148a83e0060faff709ca7e9b95522a2e81635fda0a0414f652b0e435d5ea923851508f0adbe92d85de007a0202100a
  Certificate path: /path_to_cert/foo.pem
    Certificate ID:
      Issuer Name Hash: 8A83E0060FAFF709CA7E9B95522A2E81635FDA0A
      Issuer Key Hash: F652B0E435D5EA923851508F0ADBE92D85DE007A
      Serial Number: 100A

$ echo "show ssl ocsp-response 303b300906052b0e03021a050004148a83e0060faff709ca7e9b95522a2e81635fda0a0414f652b0e435d5ea923851508f0adbe92d85de007a0202100a" | socat /var/run/haproxy.master -
OCSP Response Data:
  OCSP Response Status: successful (0x0)
  Response Type: Basic OCSP Response
  Version: 1 (0x0)
  Responder Id: C = FR, O = HAProxy Technologies, CN = ocsp.haproxy.com
  Produced At: May 27 15:43:38 2021 GMT
  Responses:
  Certificate ID:
    Hash Algorithm: sha1
    Issuer Name Hash: 8A83E0060FAFF709CA7E9B95522A2E81635FDA0A
    Issuer Key Hash: F652B0E435D5EA923851508F0ADBE92D85DE007A
    Serial Number: 100A
  Cert Status: good
  This Update: May 27 15:43:38 2021 GMT
  Next Update: Oct 12 15:43:38 2048 GMT
  [...]

$ echo "show ssl ocsp-response base64 /path_to_cert/foo.pem" | socat /var/run/haproxy.sock -
  MIIB8woBAKCCAewwggHoBgkrBgEFBQcwAQEEggHZMIIB1TCBvqE[...]

show ssl ocsp-updates

show ssl ocsp-updates

Показывает сведения о записях, участвующих в механизме обновления OCSP. Команда выводит по одной строке на ответ OCSP: ожидаемое время обновления, время последнего успешного обновления и счётчики успешных и неудачных обновлений. Также выводится состояние последнего обновления (успех или ошибка) в числовом и текстовом виде. Полный список возможных ошибок приведён ниже. Строки сортируются по возрастанию времени ‘Next Update’. Каждая строка также содержит путь к первому сертификату фронтенда, использующему этот ответ OCSP. Подробнее об автоматическом обновлении OCSP см. команду “show ssl ocsp-response” и опцию “ocsp-update”.

Возможны следующие коды и строки ошибок обновления:

  +----+-------------------------------------+
  | ID | сообщение                           |
  +----+-------------------------------------+
  |  0 | "Unknown"                           |
  |  1 | "Update successful"                 |
  |  2 | "HTTP error"                        |
  |  3 | "Missing \"ocsp-response\" header"  |
  |  4 | "OCSP response check failure"       |
  |  5 | "Error during insertion"            |
  +----+-------------------------------------+

Пример:

$ echo "show ssl ocsp-updates" | socat /tmp/haproxy.sock -
  OCSP Certid | Path | Next Update | Last Update | Successes | Failures | Last Update Status | Last Update Status (str)
      303b300906052b0e03021a050004148a83e0060faff709ca7e9b95522a2e81635fda0a0414f652b0e435d5ea923851508f0adbe92d85de007a02021015 | /path_to_cert/cert.pem | 30/Jan/2023:00:08:09 +0000 | - | 0 | 1 | 2 | HTTP error
      304b300906052b0e03021a0500041448dac9a0fb2bd32d4ff0de68d2f567b735f9b3c40414142eb317b75856cbae500940e61faf9d8b14c2c6021203e16a7aa01542f291237b454a627fdea9c1 | /path_to_cert/other_cert.pem | 30/Jan/2023:01:07:09 +0000 | 30/Jan/2023:00:07:09 +0000 | 1 | 0 | 1 | Update successful

show ssl providers

show ssl providers

Показывает имена провайдеров, загруженных OpenSSL при инициализации. Загрузку провайдеров можно настроить в файле конфигурации OpenSSL, и эта опция позволяет убедиться, что загружены нужные провайдеры. Команда доступна только с OpenSSL v3.

Пример:

$ echo "show ssl providers" | socat /var/run/haproxy.master -
Loaded providers:
    - fips
    - base

show ssl sni [-f <frontend>] [-A] [-t <offset>]

show ssl sni [-f <frontend>] [-A] [-t <offset>]

Выгружает все SNI, настроенные для указанного фронтенда, либо для всех фронтендов, если фронтенд не указан. Это позволяет увидеть, какие SNI предлагаются фронтендом, и определить, не задан ли один SNI несколько раз разными сертификатами для одного фронтенда.

Опция -A фильтрует список и показывает только сертификаты, дата notAfter которых уже прошла, то есть только сертификаты с истёкшим сроком действия.

Опция -t принимает смещение в секундах или с единицей времени (s, m, h, d), которое добавляется к текущему времени. Вместе с -A это позволяет проверить, у каких сертификатов срок действия истечёт к моменту с этим смещением. Например, чтобы проверить, какие сертификаты истекут через 30d, выполните “show ssl sni -A -t 30d”.

Столбцы разделяются одним символом \t, что упрощает разбор.

Столбец ‘Frontend/Bind’ показывает имя фронтенда и положение строки bind в конфигурации (frontend/file:linenum).

Столбец ‘SNI’ показывает SNI: это может быть CN, SAN или фильтр из crt-list. Для сертификатов строки bind, используемых по умолчанию (явно заданных через ‘default-crt’ либо первого сертификата строки bind, если не используется ‘strict-sni’), в столбце SNI отображается символ ‘*’.

Столбец ‘Negative Filter’ — список отрицательных фильтров, связанных с шаблоном подстановки; здесь показываются все отрицательные фильтры из той же строки crt-list. Если их нет, выводится дефис.

Столбец ‘Type’ показывает тип алгоритма шифрования: “rsa”, “ecdsa” или “dsa”.

Столбец ‘Filename’ может содержать имя файла из конфигурации или псевдоним, объявленный в crt-store.

Столбцы ‘NotAfter’ и ‘NotBefore’ извлекаются непосредственно из конечного сертификата X509.

Пример:

$ echo "@1 show ssl sni -A -t 30d" | socat /var/run/haproxy-master.sock - | column -t -s $'\t'
# Frontend/Bind        SNI        Negative Filter  Type   Filename             NotAfter                  NotBefore
li1/haproxy.cfg:10021  *.ex.lan   !m1.ex.lan       rsa    example.lan.pem      Jun 13 13:37:21 2024 GMT  May 14 13:37:21 2024 GMT
li1/haproxy.cfg:10021  machine10  -                ecdsa  machine10.pem.ecdsa  Jun 13 13:37:21 2024 GMT  May 14 13:37:21 2024 GMT
li1/haproxy.cfg:10021  machine10  -                rsa    machine10.pem.rsa    Jun 13 13:37:21 2024 GMT  May 14 13:37:21 2024 GMT
li1/haproxy.cfg:10021  machine10  -                ecdsa  machine10.pem.ecdsa  Jun 13 13:37:21 2024 GMT  May 14 13:37:21 2024 GMT
li1/haproxy.cfg:10021  localhost  -                rsa    localhost.pem.rsa    Jun 13 13:37:11 2024 GMT  May 14 13:37:11 2024 GMT
li1/haproxy.cfg:10021  localhost  -                ecdsa  localhost.pem.ecdsa  Jun 13 13:37:10 2024 GMT  May 14 13:37:10 2024 GMT
li1/haproxy.cfg:10021  *          -                rsa    localhost.pem.rsa    Jun 13 13:37:11 2024 GMT  May 14 13:37:11 2024 GMT

show startup-logs

show startup-logs

Выгружает все сообщения, выданные при запуске текущего процесса haproxy. Каждый буфер startup-logs относится только к своему рабочему процессу haproxy.

Это ключевое слово также доступно в CLI главного процесса, где показывает последнюю попытку запуска или перезагрузки.

show table

show table

Выгружает общие сведения обо всех известных таблицах привязок: имя (имя прокси, которому принадлежит таблица), тип (сейчас ноль, всегда IP), размер в виде максимально возможного числа записей и число записей, используемых в данный момент.

Пример:

    $ echo "show table" | socat stdio /tmp/sock1
>>> # table: front_pub, type: ip, size:204800, used:171454
>>> # table: back_rdp, type: ip, size:204800, used:0

show table <name> [ data.<type> <operator> <value> [data.<type> ...]] |

show table <name> [ data.<type> <operator> <value> [data.<type> ...]] |
                  [ key <key> ] | [ ptr <ptr> ]

Выгружает содержимое таблицы привязок <name>. В этом режиме сначала выводится строка общих сведений о таблице, как в “show table”, а затем все записи. Поскольку это может быть довольно затратно, можно задать фильтр, определяющий, какие записи выводить.

При использовании формы “data.” фильтр применяется к сохранённым данным (см. “stick-table” в разделе 4.2). В <type> необходимо указать тип сохраняемых данных; этот тип должен храниться в таблице, иначе возвращается ошибка. Оператор <operator> определяет сравнение данных с 64-разрядным целым <value>. Операторы те же, что в ACL:

- eq: записи, данные которых равны этому значению
- ne: записи, данные которых не равны этому значению
- le: записи, данные которых меньше или равны этому значению
- ge: записи, данные которых больше или равны этому значению
- lt: записи, данные которых меньше этого значения
- gt: записи, данные которых больше этого значения

В этой форме можно задать несколько фильтров данных, не превышая максимума, установленного при сборке (по умолчанию 4).

При использовании формы key показывается запись <key>. Ключ должен иметь тот же тип, что и таблица; в настоящее время поддерживаются только IPv4, IPv6, целое число и строка.

При использовании формы ptr показывается запись <ptr>. <ptr> задаётся в виде 0xffff и должен соответствовать адресу, возвращённому предыдущей командой “show table”. Поиск записи по указателю полезен, если найти её по ключу невозможно из-за пустого ключа или символов, несовместимых с cli.

Если data.<type> имеет тип массива, для доступа к определённому индексу можно использовать “[]”, например: data.gpt[1]

Пример:

    $ echo "show table http_proxy" | socat stdio /tmp/sock1
>>> # table: http_proxy, type: ip, size:204800, used:2
>>> 0x80e6a4c: key=127.0.0.1 use=0 exp=3594729 gpc0=0 conn_rate(30000)=1  \
      bytes_out_rate(60000)=187
>>> 0x80e6a80: key=127.0.0.2 use=0 exp=3594740 gpc0=1 conn_rate(30000)=10 \
      bytes_out_rate(60000)=191

    $ echo "show table http_proxy data.gpc0 gt 0" | socat stdio /tmp/sock1
>>> # table: http_proxy, type: ip, size:204800, used:2
>>> 0x80e6a80: key=127.0.0.2 use=0 exp=3594740 gpc0=1 conn_rate(30000)=10 \
      bytes_out_rate(60000)=191

    $ echo "show table http_proxy data.conn_rate gt 5" | \
        socat stdio /tmp/sock1
>>> # table: http_proxy, type: ip, size:204800, used:2
>>> 0x80e6a80: key=127.0.0.2 use=0 exp=3594740 gpc0=1 conn_rate(30000)=10 \
      bytes_out_rate(60000)=191

    $ echo "show table http_proxy key 127.0.0.2" | \
        socat stdio /tmp/sock1
>>> # table: http_proxy, type: ip, size:204800, used:2
>>> 0x80e6a80: key=127.0.0.2 use=0 exp=3594740 gpc0=1 conn_rate(30000)=10 \
      bytes_out_rate(60000)=191

    $ echo "show table http_proxy ptr 0x80e6a80" | \
        socat stdio /tmp/sock1
>>> # table: http_proxy, type: ip, size:204800, used:2
>>> 0x80e6a80: key=127.0.0.2 use=0 exp=3594740 gpc0=1 conn_rate(30000)=10 \
      bytes_out_rate(60000)=191

Если критерий данных применяется к динамическому значению, зависящему от времени, например скорости передачи байтов, это значение вычисляется при оценке записи, чтобы решить, нужно ли её выводить. Поэтому запись может некоторое время соответствовать фильтру, а затем перестать: со временем средняя частота событий снижается.

Это можно использовать для получения списков адресов IP, с которых злоупотребляют службой, чтобы отслеживать их или даже вносить в чёрный список межсетевого экрана. Пример:

$ echo "show table http_proxy data.gpc0 gt 0" \
  | socat stdio /tmp/sock1 \
  | fgrep 'key=' | cut -d' ' -f2 | cut -d= -f2 > abusers-ip.txt
  ( или | awk '/key/{ print a[split($2,a,"=")]; }' )

Если таблица привязок синхронизируется с секцией peers, поддерживающей шардирование, для каждого ключа выводится номер шарда (иначе указывается ‘0’). Это позволяет определить, какие узлы peers получат этот ключ. Пример:

$ echo "show table http_proxy" | socat stdio /tmp/sock1 | fgrep shard=
  0x7f23b0c822a8: key=10.0.0.2 use=0 exp=296398 shard=9 gpc0=0
  0x7f23a063f948: key=10.0.0.6 use=0 exp=296075 shard=12 gpc0=0
  0x7f23b03920b8: key=10.0.0.8 use=0 exp=296766 shard=1 gpc0=0
  0x7f23a43c09e8: key=10.0.0.12 use=0 exp=295368 shard=8 gpc0=0

show tasks

show tasks

Выгружает число задач, находящихся в очереди выполнения, с числом вхождений для каждой функции и средней задержкой, если она известна (для собственно задач при включённом профилировании задач). Выгрузка — это моментальный снимок; результат может различаться в зависимости от того, какие задачи остались в очереди в этот момент, особенно в однопоточном режиме, где меньше вероятность пополнения очереди операциями I/O (если только очередь не заполнена). Команда получает исключительный доступ к процессу и на сильно нагруженном процессе может вызвать небольшие, но измеримые задержки, поэтому автоматическим средствам мониторинга нельзя злоупотреблять ею.

show threads

show threads

Выгружает для каждого потока некоторые внутренние состояния и структуры, которые могут помочь разработчикам понять проблему. Для удобства чтения каждому потоку отведён отдельный блок. Если haproxy собран с USE_THREAD_DUMP=1, применяется расширенный механизм выгрузки с сигналами потокам, чтобы каждый поток по очереди мог выгрузить собственное состояние. Без этой опции все подробности выводит поток, обрабатывающий команду, а сведения об остальных менее подробны. Перед потоком, обрабатывающим команду, показывается звёздочка (’*’). Перед потоками, которые не продвинулись в работе с предыдущего вызова команды, также может показываться правая угловая скобка (’>’); это указывает на ошибку в коде, о которой обязательно нужно сообщить. Если это происходит с двумя потоками, обычно причина — взаимная блокировка. Если поток один, это другая ошибка, например повреждённый список. В любом случае процесс уже не полностью работоспособен и нуждается в перезапуске.

Формат вывода намеренно не документирован, чтобы его можно было легко менять при появлении новых потребностей без сохранения обратной совместимости. Как и в случае “show activity”, без исходного кода эти значения лишены смысла.

show tls-keys [id|*]

show tls-keys [id|*]

Выгружает ссылки на все загруженные ключи билетов TLS. Показываются ID ссылки на ключи билетов TLS и файл, из которого загружены ключи. И то и другое можно использовать для обновления ключей TLS командой “set ssl tls-key”. Если в качестве параметра задан ID, выгружаются билеты; при использовании * выгружаются все ключи по всем ссылкам.

show schema json

show schema json

Выгружает схему, используемую для вывода “show info json” и “show stat json”.

Чтобы уменьшить объём, вывод не содержит лишних пробелов. Для чтения человеком его может быть удобно пропустить через средство форматирования. Пример:

$ echo “show schema json” | socat /var/run/haproxy.sock stdio | \ python -m json.tool

Схема соответствует “JSON Schema” (json-schema.org), поэтому совместимые средства проверки можно использовать для проверки вывода “show info json” и “show stat json” на соответствие схеме.

show trace [<source>]

show trace [<source>]

Показывает текущее состояние трассировки. Для каждого источника выводится строка с односимвольным статусом: трассировка остановлена, ожидает или выполняется. Указывается используемый приёмник вывода (или “none”, если он не задан), число отброшенных событий в этом приёмнике и краткое описание источника. Если указано имя источника, выводится подробный список всех поддерживаемых им событий и их состояние для каждого действия (report, start, pause, stop): “+”, если они включены, и “-” в противном случае. Все эти события независимы: событие может запускать трассировку, само не попадая в вывод, и наоборот.

show version

show version

Показывает версию текущего процесса HAProxy. Доступно в CLI главного и рабочих процессов. Пример:

$ echo "show version" | socat /var/run/haproxy.sock stdio
2.4.9

$ echo "show version" | socat /var/run/haproxy-master.sock stdio
2.5.0

shutdown frontend <frontend>

shutdown frontend <frontend>

Полностью удаляет указанный фронтенд. Все порты, к которым он был привязан, освобождаются. После этой операции включить фронтенд снова невозможно. Команда предназначена для сред, где остановка прокси недопустима, но ошибочную конфигурацию прокси необходимо исправить. Таким способом можно освободить порт и привязать его к другому процессу, чтобы восстановить работу. После завершения фронтенд вообще не отображается на странице статистики.

Фронтенд можно указать по имени или по числовому ID с префиксом решётки (’#’).

Команда имеет ограниченный доступ и может выполняться только через сокеты с уровнем “admin”.

shutdown session <id>

shutdown session <id>

Немедленно завершает поток с указанным идентификатором. Этот идентификатор — первое поле в начале строк вывода “show sess” (он соответствует указателю на поток). Команду можно использовать для завершения длительного потока без ожидания тайм-аута или при бесконечной передаче данных. Завершённые таким образом потоки отмечаются в журналах флагом ‘K’.

shutdown sessions server <backend>/<server>

shutdown sessions server <backend>/<server>

Немедленно завершает все потоки, привязанные к указанному серверу. Это можно использовать, например, для завершения длительных потоков после перевода сервера в режим обслуживания. Завершённые таким образом потоки отмечаются в журналах флагом ‘K’.

Соединения бэкенда остаются в состоянии простоя, если сервер ещё не находится в режиме обслуживания; если находится, для них немедленно планируется удаление.

trace

trace

Команда “trace” без аргументов выводит список источников трассировки, их текущее состояние и краткие описания. Она служит только меню для перехода на следующие уровни; см. другие команды “trace” ниже.

trace 0

trace 0

Немедленно останавливает все трассировки. Это быстрый способ завершить сеанс отладки или экстренная мера, если на нескольких источниках включены сложные трассировки, влияющие на работу службы.

trace <source> [<args...>]

trace <source> [<args...>]

Настраивает трассировку для источника <source>. Без аргументов выводит все поддерживаемые подкоманды этого источника. Несколько подкоманд можно объединять в цепочку. Поддерживаются следующие подкоманды:

event [ [+|-|!]<name> ] Без аргумента выводит все события, поддерживаемые указанным источником. Перед ними стоит “-”, если они отключены, или “+”, если включены. Важно учитывать, что одна запись трассировки может быть помечена несколькими событиями; если хотя бы одно включённое событие совпадает с одной из меток записи, событие передаётся подсистеме трассировки. Например, получение кадра HTTP/2 типа HEADERS может вызвать и событие кадра, и событие потока, поскольку кадр создаёт новый поток. Если для этого источника включено хотя бы одно из них, кадр передаётся механизму трассировки.

С аргументом можно переключать состояние каждого события, отдельно
включая и отключая их. Поддерживаются два специальных ключевых слова:
"none" не соответствует ни одному событию и отключает сразу все события,
а "any" соответствует всем событиям и включает их все сразу.
Остальные события зависят от источника. Чтобы включить событие,
можно указать его имя, при желании добавив префикс '+' для наглядности.
Чтобы отключить событие, нужно указать его имя с префиксом '-' или '!'.

Полностью отключить источник трассировки можно, передав "event none";
после этого он сразу будет полностью игнорироваться.

follow <other_source> Позволяет источнику <source> также выдавать записи трассировки, когда другой источник <other_source> привязан по определённому критерию и этот же критерий совпадает для текущего источника. Например, если источник привязан к сеансу, следование за ним из другого источника заставит второй источник выдавать записи для всех событий этого сеанса. В определённых пределах так можно отслеживать запросы бэкенда вместе с соответствующими соединениями фронтенда. Источник “session” упрощает это, предоставляя события “new” и “end”, которые можно использовать для привязки. Учтите, что в этом случае трассировка источника <source> не обязательно должна быть включена, а её состояние также не меняется. Однако некоторые события могут отсутствовать, если они не содержат сведений для сопоставления с отслеживаемым элементом. С этой командой также можно использовать метаисточник “all”: в этом случае все источники будут следовать за <other_source>.

Пример:

trace h1 lock session start sess_new pause sess_end follow session

level [<level>] Без аргумента выводит все уровни трассировки этого источника, помечая текущий звёздочкой (’*’) перед ним. С аргументом меняет уровень трассировки на указанный. Уровни детализации — это фильтры, применяемые перед выводом событий. Они позволяют выборочно включать или исключать события в зависимости от их важности. Например, разработчику может потребоваться точно знать, в каком месте кода заголовок HTTP признан недопустимым, тогда как конечному пользователю его корректность может быть вовсе не важна. Сейчас существует 5 уровней трассировки:

user       выводит информацию, подходящую обычному пользователю HAProxy,
           который хочет наблюдать за своим трафиком. Обычно выводятся
           некоторые запросы и ответы HTTP без особой детализации.
           Для упрощения эксплуатации большинство источников используют
           этот уровень по умолчанию.

proto      помимо информации уровня "user", показывает изменения на
           уровне протокола, например типы кадров или заголовки HTTP
           после декодирования.

state      помимо информации уровня "proto", показывает переходы
           состояний (или неудачные переходы) в парсерах. Таким образом,
           здесь видны попытки выполнить операцию, тогда как уровень
           "proto" показывает только конечную операцию.

data       помимо информации уровня "state", включает передачи данных
           между различными уровнями.

developer  выводит всю доступную информацию, в том числе подробности
           вроде «выход из этого цикла», которые нужны только разработчику,
           разбирающему редкую ошибку в рабочей среде. Имена функций
           выводятся только на этом уровне.
Настоятельно рекомендуется всегда использовать только уровень "user"
и переходить на другие уровни лишь по указанию разработчика. Кроме того,
полезно сначала настроить события и только затем повышать уровень:
это поможет избежать огромного вывода при отсутствии фильтров.
С этой командой также можно использовать метаисточник "all": тогда
уровень применяется сразу ко всем существующим источникам.

lock [criterion] Без аргумента выводит все критерии привязки, поддерживаемые этим источником, и помечает текущий выбор звёздочкой (’*’) перед ним. Привязка означает, что источник сосредоточится на первом подходящем событии и будет придерживаться только критерия, вызвавшего это событие, игнорируя остальные до остановки трассировки. Это позволяет, например, получить трассировку одного соединения или одного потока. Следующие критерии поддерживаются некоторыми трассировками, но не обязательно всеми, поскольку часть критериев может быть недоступна источнику:

backend      привязаться к бэкенду, с которого началась трассировка
connection   привязаться к соединению, с которого началась трассировка
frontend     привязаться к фронтенду, с которого началась трассировка
listener     привязаться к слушателю, с которого началась трассировка
nothing      ни к чему не привязываться
server       привязаться к серверу, с которого началась трассировка
session      привязаться к сеансу, с которого началась трассировка
thread       привязаться к потоку, с которого началась трассировка
Кроме того, каждый источник может предоставлять до 4 собственных
критериев, например внутренние состояния или ID соединений. Так, в HTTP/2
можно привязаться к потоку H2 и игнорировать остальные потоки
после начала трассировки.

Если критерий передан аргументом, он используется вместо остальных,
а текущее отслеживание немедленно завершается, чтобы его можно было
начать заново с новым критерием. Все источники поддерживают специальное
ключевое слово "nothing" для постоянного отключения отслеживания.

{ pause | start | stop } [ [+|-|!]event] Без аргумента выводит события, включённые для автоматической приостановки, запуска или остановки трассировки этого источника. Эти события зависят от источника трассировки. С аргументом включает событие для указанного действия (можно добавить префикс ‘+’) либо отключает его (с префиксом ‘-’ или ‘!’). Специальное ключевое слово “now” не является событием и требует немедленно выполнить действие. Ключевые слова “none” и “any” поддерживаются так же, как в “trace event”.

Поддерживаются 3 действия: "pause", "start" и "stop".
Действие "pause" перечисляет события, при которых выполняемая трассировка
останавливается и ожидает нового события запуска для возобновления.
Действие "start" перечисляет события, переводящие трассировку в режим
ожидания одного из событий запуска. Действие "stop" перечисляет события,
окончательно останавливающие трассировку до повторного ручного включения.
На практике удобно запускать трассировку вручную через "start now",
не заботясь о событиях, и останавливать через "stop now".
Для захвата более сложных последовательностей событий можно назначить
"start" обычное событие (например, получение запроса HTTP), а "stop" —
очень редкое событие, например выдачу определённой ошибки. Тогда последние
захваченные события будут соответствовать нужным критериям.
Событие pause полезно для определения конца последовательности,
снятия привязки и ожидания следующей возможности захвата. В этом случае
имеет смысл включить привязку по одному конкретному критерию
(например, потоку), задать "start" всё, что начинает этот критерий
(например, все события создания потока), "stop" — ожидаемую аномалию,
а "pause" — всё, что завершает критерий (например, любое событие
завершения потока). Тогда журнал трассировки будет содержать полные,
полностью нормальные последовательности событий одного объекта вплоть
до последней последовательности, включающей всё от начала до аномалии.

sink [<sink>] Без аргумента выводит все приёмники событий, доступные этому источнику, помечая текущий настроенный приёмник звёздочкой (’*’) перед ним. Приёмник “none” доступен всегда и означает, что все события просто отбрасываются, но их обработка не пропускается (например, привязка всё равно выполняется). Доступность других приёмников зависит от конфигурации и опций сборки; обычно в режиме отладки можно использовать “stdout” и “stderr”, также должны быть доступны кольцевые буферы в памяти. При указании имени приёмник для заданного источника меняется немедленно. Смена приёмника не меняет события. В худшем случае некоторые события могут потеряться при использовании недопустимого приёмника (или “none”), но обработка продолжается с другим назначением вывода. С этой командой также можно использовать метаисточник “all”: в этом случае приёмник применяется сразу ко всем существующим источникам.

verbosity [<level>] Без аргумента выводит все уровни подробности этого источника, помечая текущий звёздочкой (’*’) перед ним. С аргументом меняет уровень подробности на указанный.

Уровни подробности определяют, насколько глубоко декодер трассировки
должен разбирать данные для получения подробных сведений. Это зависит
от источника: некоторые источники вообще не предоставляют отдельного
декодера. Уровень "quiet" доступен всегда и отключает декодирование.
Он полезен, чтобы сначала понять, что происходит, не углубляясь в детали:
его влияние на производительность и размер трассировки очень мало.
Если источник не объявляет уровней подробности, доступен уровень
"default", при котором декодер вызывается, если он указан в трассировке.
Декодирование выполняется по мере возможности. Если источник объявляет
уровни подробности, они перечисляются с описанием своего назначения.
В этом случае декодер источника работает с максимально возможной
точностью на основе сведений, доступных в точке трассировки.
По умолчанию устанавливается первый уровень выше "quiet".

update ssl ocsp-response <certfile>

update ssl ocsp-response <certfile>

Создаёт запрос OCSP для указанного <certfile> и отправляет его ответчику OCSP, чей URI следует указать в разделе “Authority Information Access” сертификата. Учитывается только первый URI. Полученный ответ OCSP затем проверяется и вставляется в локальное дерево ответов OCSP. Команда работает только для сертификатов, у которых уже был сохранённый ответ OCSP: он был предоставлен при инициализации либо ранее задан командами “set ssl cert” или “set ssl ocsp-response”. Если полученный ответ OCSP корректен и успешно вставлен в локальное дерево, его содержимое выводится в стандартный вывод. Формат тот же, что описан для “show ssl ocsp-response”.

wait { -h | <delay> } [<condition> [<args>...]]

wait { -h | <delay> } [<condition> [<args>...]]

В простейшей форме, без условия, просто ожидает указанное время перед продолжением. Это можно использовать для сбора метрик с определённым интервалом.

С условием и необязательными аргументами команда ожидает выполнения указанного условия, неустранимой ошибки либо истечения всего времени <delay> без выполнения условия. Поддерживаются следующие условия:

  • be-removable <proxy>: ожидает, пока указанный прокси бэкенда можно будет удалить командой “del backend”. Некоторые состояния недопустимы в любом случае (например, бэкенд ещё не снят с публикации или содержит серверы); при них выводится конкретная ошибка с указанием невыполненного условия. Если до истечения времени все условия выполнены, возвращается успех и операция завершается.

  • srv-removable <proxy>/<server>: ожидает, пока указанный сервер можно будет удалить командой “del server”, то есть пока он не окажется в режиме обслуживания без каких-либо соединений (активных или простаивающих). Некоторые состояния недопустимы в любом случае (например, сервер не в режиме обслуживания); при них выводится конкретная ошибка с указанием невыполненного условия. Сервер может даже быть удалён параллельно и больше не существовать. Если до истечения времени все условия выполнены, возвращается успех и операция завершается.

Единица задержки по умолчанию — миллисекунды, но допускаются и другие единицы с обычными временными суффиксами (us, ms, s, m, h, d). При использовании с утилитой ‘socat’ не забудьте увеличить тайм-аут закрытия socat, чтобы он покрывал время ожидания. Передача “-h” первым или вторым аргументом выводит справку по команде. Пример:

$ socat -t20 /path/to/socket - <<< "show activity; wait 10s; show activity"

$ socat -t5 /path/to/socket - <<< "
    disable server px/srv1
    shutdown sessions server px/srv1
    wait 2s srv-removable px/srv1
    del server px/srv1"

9.4. CLI главного процесса

CLI главного процесса — это сокет, привязанный к главному процессу в режиме master-worker. Этот CLI предоставляет доступ к командам сокета unix во всех работающих или завершающихся процессах и позволяет выполнять базовый контроль за ними.

CLI главного процесса настраивается только аргументами программы haproxy через опцию -S. Эта опция также принимает опции bind, разделённые запятыми.

Пример:

# haproxy -W -S 127.0.0.1:1234 -f test1.cfg
# haproxy -Ws -S /tmp/master-socket,uid,1000,gid,1000,mode,600 -f test1.cfg
# haproxy -W -S /tmp/master-socket,level,user -f test1.cfg

9.4.1. Команды CLI главного процесса

@<[!]pid>

@<[!]pid>

Для доступа к нескольким процессам CLI главного процесса использует специальную запись с префиксом. Её легко распознать по начальному символу @.

После префикса @ можно указать относительный номер процесса либо восклицательный знак и PID (например, @1 или @!1271). Одиночный @ обозначает главный процесс. Завершающиеся процессы доступны только по PID, поскольку относительные номера можно использовать лишь для текущих процессов.

Этот префикс можно поставить перед командой, чтобы только она была отправлена указанному процессу. В этом случае полная команда заканчивается переводом строки или точкой с запятой, как обычная команда.

Ошибки: известно, что протокол sockpair@, используемый для связи между главным и рабочим процессами, ненадёжно работает в macOS из-за проблемы в реализации sendmsg(2) в macOS. Из-за этого команда может остаться без ответа.

Примеры:

$ socat /var/run/haproxy-master.sock readline
prompt
master> @1 show info; @2 show info
[...]
Process_num: 1
Pid: 1271
[...]
Process_num: 2
Pid: 1272
[...]
master>

$ echo '@!1271 show info; @!1272 show info' | socat /var/run/haproxy-master.sock -
[...]

Префикс также можно использовать как самостоятельную команду, переключающую контекст выполнения по умолчанию на указанный процесс. Тогда все последующие команды выполняются в нём, пока новая команда ‘@’ снова не сменит контекст.

Примеры:

$ socat /var/run/haproxy-master.sock readline
prompt
master> @1
1271> show info
[...]
1271> show stat
[...]
1271> @
master>

$ echo '@1; show info; show stat; @2; show info; show stat' | socat /var/run/haproxy-master.sock -
[...]

Примечание об ограничениях: некоторые редко используемые команды меняют состояние сеанса CLI (например, “set anon”, “set timeout”) и при запуске из CLI главного процесса могут вести себя несколько иначе, поскольку команды отправляются по одной, каждая в собственном сеансе CLI. Аналогично, некоторые редкие команды (“show events”, “wait”) активно отслеживают ввод или закрытие CLI и немедленно прерываются при закрытии CLI. Через CLI главного процесса они не будут работать ожидаемым образом, поскольку после каждой команды её вход закрывается. В таких редких случаях лучше может подойти вариант “@@”, описанный ниже.

@@<[!]pid> [command...]

@@<[!]pid> [command...]

Этот префикс или команда очень похож на описанный выше префикс “@”, но переходит в рабочий процесс, передаёт ему всю командную строку без изменений и остаётся там до завершения команды. Точки с запятой тоже передаются, что позволяет выполнить в рабочем процессе всю последовательность команд. Соединение с рабочим процессом остаётся открытым до выполнения списка команд. Любые данные, отправленные после команд, пересылаются в CLI рабочего процесса, могут быть прочитаны выполняемыми командами и будут потеряны для CLI главного процесса. Таким образом обеспечивается полноценное двунаправленное соединение с рабочим процессом. Поэтому пользователи таких команд должны внимательно дожидаться завершения команды, прежде чем отправлять новые команды в CLI главного процесса.

Вместо выполнения одной команды можно открыть полностью интерактивный сеанс в рабочем процессе, не указав команду (то есть введя “@@1” в отдельной строке). Такой сеанс завершается закрытием соединения или выходом из сеанса рабочего процесса (командой “quit”). В этом случае режим приглашения сокета главного процесса (interactive, prompt, timed) передаётся рабочему процессу.

Ошибки: известно, что протокол sockpair@, используемый для связи между главным и рабочим процессами, ненадёжно работает в macOS из-за проблемы в реализации sendmsg(2) в macOS. Из-за этого команда может остаться без ответа.

Примеры:

# gracefully close connections and delete a server once idle (wait max 10s)
$ socat -t 11 /var/run/haproxy-master.sock - <<< \
   "@@1 disable server app2/srv36; \
   wait 10000 srv-removable app2/srv36; \
   del server app2/srv36"

# forcefully close connections and quickly delete a server
$ socat /var/run/haproxy-master.sock - <<< \
   "@@1 disable server app2/srv36; \
   shutdown sessions server app2/srv36; \
   wait 100 srv-removable app2/srv36; \
   del server app2/srv36"

# show messages arriving to this ring in real time ("tail -f" equivalent)
$ (echo "show events buf0 -w"; read) | socat /var/run/haproxy-master.sock -

expert-mode [on|off]

expert-mode [on|off]

Эта команда включает “expert-mode” для каждого рабочего процесса, к которому обращаются из CLI главного процесса. В сочетании с “mcli-debug-mode” также активирует команду в главном процессе. В приглашении CLI главного процесса отображается флаг “e”.

См. также “expert-mode” в разделе 9.3 и “mcli-debug-mode” в 9.4.1.

experimental-mode [on|off]

experimental-mode [on|off]

Эта команда включает “experimental-mode” для каждого рабочего процесса, к которому обращаются из CLI главного процесса. В сочетании с “mcli-debug-mode” также активирует команду в главном процессе. В приглашении CLI главного процесса отображается флаг “x”.

См. также “experimental-mode” в разделе 9.3 и “mcli-debug-mode” в 9.4.1.

hard-reload

hard-reload

Эта команда делает то же, что “reload” через CLI главного процесса, но выполняет жёсткую остановку (-st) вместо остановки (-sf) прежнего процесса. Это означает, что прежний процесс ничего не дожидается перед выходом, поэтому все соединения будут закрыты.

См. также команду “reload”.

mcli-debug-mode [on|off]

mcli-debug-mode [on|off]

Это ключевое слово включает в CLI главного процесса специальный режим, в котором доступны все ключевые слова, предназначенные для CLI рабочего процесса. Так можно отлаживать главный процесс. После включения новые доступные ключевые слова CLI можно вывести командой “help”. В сочетании с “experimental-mode” или “expert-mode” доступно ещё больше ключевых слов. В приглашении CLI главного процесса отображается флаг “d”.

prompt

prompt

При включённом приглашении (через команду “prompt”) в нём отображается контекст, с которым работает CLI. Главный процесс обозначается строкой “master”, остальные процессы — своим PID. Если последняя перезагрузка завершилась с ошибкой, приглашение главного процесса меняется на “master[ReloadFailed]>”, чтобы было видно, что процесс всё ещё работает с прежней конфигурацией, а новая не действует.

Приглашение CLI главного процесса может отображать несколько флагов включённых режимов: “d” для mcli-debug-mode, “e” для expert-mode и “x” для experimental-mode.

Пример:

$ socat /var/run/haproxy-master.sock -
prompt
master> expert-mode on
master(e)> experimental-mode on
master(xe)> mcli-debug-mode on
master(xed)> @1
95191(xed)>

reload

reload

Главный процесс HAProxy также можно перезагрузить командой “reload”, которая действует так же, как kill -USR2 для главного процесса, если пользователь имеет как минимум права “operator” или “admin”.

Команда позволяет выполнить синхронную перезагрузку и возвращает её статус после завершения. При разборе результата инструментом учитывайте тайм-аут: статус возвращается только после разбора конфигурации и создания нового рабочего процесса через fork. Команда “socat” по умолчанию использует тайм-аут 0.5s, поэтому при слишком долгой перезагрузке завершится до вывода сообщения. У “ncat” тайм-аута по умолчанию нет. При сборке с USE_SHM_OPEN=1 команда reload также может выгружать startup-logs главного процесса.

Пример:

$ echo "reload" | socat -t300 /var/run/haproxy-master.sock stdin
Success=1
--
[NOTICE]   (482713): haproxy version is 2.7-dev7-4827fb-69
[NOTICE]   (482713): path to executable is ./haproxy
[WARNING]  (482713): config: 'http-request' rules ignored for proxy 'frt1' as they require HTTP mode.
[NOTICE]   (482713): New worker (482720) forked
[NOTICE]   (482713): Loading success.

$ echo "reload" | socat -t300 /var/run/haproxy-master.sock stdin
Success=0
--
[NOTICE]   (482886): haproxy version is 2.7-dev7-4827fb-69
[NOTICE]   (482886): path to executable is ./haproxy
[ALERT]    (482886): config: parsing [test3.cfg:1]: unknown keyword 'Aglobal' out of section.
[ALERT]    (482886): config: Fatal errors found in configuration.
[WARNING]  (482886): Loading failure!

$

Команда reload выполняется в CLI главного процесса последней; все последующие команды игнорируются. После возврата статуса reload закрывает соединение с CLI.

Учтите, что перезагрузка закрывает все соединения с CLI главного процесса. См. также команду “hard-reload”.

show proc [debug]

show proc [debug]

В CLI главного процесса предусмотрена команда ‘show proc’ для контроля процессов.

Пример:

$ echo 'show proc' | socat /var/run/haproxy-master.sock -
#<PID>          <type>          <reloads>       <uptime>        <version>
1162            master          5 [failed: 0]   0d00h02m07s     2.5-dev13
# workers
1271            worker          1               0d00h00m00s     2.5-dev13
# old workers
1233            worker          3               0d00h00m43s     2.0-dev3-6019f6-289

В этом примере главный процесс перезагружался 5 раз, но один из старых рабочих процессов всё ещё работает и пережил 3 перезагрузки. Можно обратиться к CLI этого рабочего процесса, чтобы выяснить причину.

Параметр ‘debug’ выводит отладочные подробности; сейчас это FD для связи IPC. Учтите, что стабильность отладочного вывода между версиями haproxy не гарантируется.

show startup-logs

show startup-logs

Для корректной работы в CLI главного процесса HAProxy должен быть собран с USE_SHM_OPEN=1, иначе будут видны не все сообщения.

Как и аналогичная команда на сокете статистики, эта команда показывает сообщения запуска HAProxy. Однако она выгружает сообщения не текущего рабочего процесса, а последнего запуска или перезагрузки, то есть может вывести сообщения разбора конфигурации при неудачной перезагрузке.

Эти сообщения также выгружаются командой “reload”.

9.5. Файл статистики

Так называемый stats-file позволяет при запуске процесса предварительно загрузить ненулевые значения внутренних счётчиков haproxy. Его основное назначение — сохранять статистику рабочих процессов при перезагрузках. В stats-file содержится лишь часть всей публикуемой статистики haproxy, поскольку предварительно загружать имеет смысл только значения типа метрик.

В настоящее время stats-file поддерживает только счётчики прокси. Это позволяет предварительно загружать значения для фронтендов, бэкендов, серверов и слушателей. Однако в stats-file сохраняются только экземпляры объектов с непустым GUID. Это гарантирует загрузку значения для объекта с совпадающими типом и GUID, даже если другие параметры отличаются.

Команда CLI “dump stats-file” предназначена для создания stats-file. Его формат определяется внутренней реализацией и может свободно меняться и расширяться в будущем. Он рассчитан на совместимость как минимум между выпусками соседних стабильных веток haproxy, но при загрузке stats-file в процесс, работающий на более старой версии, могут потребоваться дополнительные настройки.

31 - 10. Упрощение управления конфигурацией

Способы упрощения сопровождения больших конфигураций HAProxy

Очень часто два узла HAProxy, образующие кластер, используют совершенно одинаковую конфигурацию, за исключением нескольких адресов. Вместо того чтобы сопровождать отдельную копию конфигурации для каждого узла, которые неизбежно начнут различаться, можно включить в конфигурацию переменные окружения. Тогда несколько конфигураций смогут использовать один и тот же файл, различаясь лишь несколькими общесистемными переменными окружения. Эта возможность появилась в версии 1.5, где переменные окружения допускались только в адресах; версия 1.6 расширяет их поддержку на все параметры. Синтаксис такой же, как в оболочке UNIX: переменная начинается со знака доллара (’$’), за которым следуют открывающая фигурная скобка (’{’), имя переменной и закрывающая скобка (’}’). За исключением адресов, переменные окружения интерпретируются только в аргументах, заключённых в двойные кавычки (это ограничение было необходимо, чтобы не нарушить работу существующих конфигураций с регулярными выражениями, содержащими знак доллара).

Переменные окружения также удобны для конфигураций, которые должны работать на разных площадках и различаться только адресами. Кроме того, они позволяют убрать пароли из некоторых конфигурационных файлов. В приведённом ниже примере сценарий инициализации при запуске загружает файл «site1.env»:

$ cat site1.env
LISTEN=192.168.1.1
CACHE_PFX=192.168.11
SERVER_PFX=192.168.22
LOGGER=192.168.33.1
STATSLP=admin:pa$$w0rd
ABUSERS=/etc/haproxy/abuse.lst
TIMEOUT=10s

$ cat haproxy.cfg
global
    log "${LOGGER}:514" local0

defaults
    mode http
    timeout client "${TIMEOUT}"
    timeout server "${TIMEOUT}"
    timeout connect 5s

frontend public
    bind "${LISTEN}:80"
    http-request reject if { src -f "${ABUSERS}" }
    stats uri /stats
    stats auth "${STATSLP}"
    use_backend cache if { path_end .jpg .css .ico }
    default_backend server

backend cache
    server cache1 "${CACHE_PFX}.1:18080" check
    server cache2 "${CACHE_PFX}.2:18080" check

backend server
    server cache1 "${SERVER_PFX}.1:8080" check
    server cache2 "${SERVER_PFX}.2:8080" check

32 - 11. Известные подводные камни, которых следует избегать

Ошибки эксплуатации и неожиданное поведение, которых следует избегать

Время от времени кто-нибудь сообщает, что после перезагрузки системы служба haproxy не запустилась, но при ручном запуске работает. Чаще всего такие пользователи применяют механизм кластерного IP-адреса, например keepalived, чтобы назначать IP-адрес службы только главному узлу. Пока haproxy был привязан к адресу 0.0.0.0, всё работало, но после привязки к виртуальному IP-адресу запуск перестал удаваться. Причина в том, что при запуске службы виртуальный IP-адрес ещё не принадлежит локальному узлу, и, когда HAProxy пытается к нему привязаться, система отклоняет запрос, поскольку адрес не локальный. Решение состоит не в задержке запуска службы haproxy (это не помогло бы при перезапуске), а в правильной настройке системы, разрешающей привязку к нелокальным адресам. В Linux это легко сделать, установив параметр sysctl net.ipv4.ip_nonlocal_bind в 1. Это также необходимо для прозрачного перехвата IP-трафика, проходящего через HAProxy к определённому адресу назначения.

Многопроцессные конфигурации с диапазонами исходящих портов могут выглядеть работоспособными, но при высокой нагрузке вызывают случайные сбои: несколько процессов могут попытаться использовать один и тот же исходящий порт для подключения к одному серверу, что невозможно. Система сообщит об ошибке, после чего будет выполнена повторная попытка с выбором другого порта. Высокое значение параметра “retries” может в некоторой степени скрыть этот эффект, но также увеличивает загрузку CPU и время обработки. В журналах тоже будет отражено некоторое число повторных попыток. Поэтому в многопроцессных конфигурациях следует избегать диапазонов портов.

Поскольку HAProxy использует SO_REUSEPORT и поддерживает привязку нескольких независимых процессов к одному IP:port, при устранении неполадок может оказаться, что старый процесс не остановили перед запуском нового. Это приводит к абсурдным результатам проверок, создающим впечатление, что любые изменения конфигурации игнорируются. Причина в том, что, даже если новый процесс перезапущен с новой конфигурацией, старый тоже принимает часть входящих соединений и обрабатывает их, возвращая неожиданные результаты. При сомнениях просто остановите новый процесс и проверьте снова. Если всё ещё работает, скорее всего, старый процесс остался активен и его нужно остановить. Здесь хорошо помогает Linux-команда “netstat -lntp”.

При добавлении записей в ACL из командной строки (например, при внесении исходного адреса в чёрный список) важно помнить, что эти записи не синхронизируются с файлом и при перезагрузке конфигурации будут потеряны. Хотя часто это желаемый эффект (для чёрного списка), он может не соответствовать ожиданиям, если изменение было внесено для исправления проблемы. См. действие “add acl” интерфейса CLI.

33 - 12. Отладка и проблемы производительности

Методы исследования сбоев, зависаний, задержек и проблем пропускной способности

При запуске HAProxy с параметром «-d» процесс остаётся на переднем плане и выводит по строке на каждое событие — входящее соединение, завершение соединения, каждую встреченную строку заголовка запроса или ответа. Этот отладочный вывод формируется до обработки содержимого, поэтому локальные изменения в нём не учитываются. Основное назначение — показывать запросы и ответы без запуска анализатора сетевого трафика. При одновременной обработке нескольких соединений вывод читается хуже, но скрипты «debug2ansi» и «debug2html» из каталога examples/ заметно помогают, раскрашивая его.

Если HAProxy отклоняет запрос или ответ HTTP/1.x как некорректный, лучше всего подключиться к CLI и выполнить «show errors». Команда показывает последние сохранённые ошибочные запрос и ответ HTTP/1.x для каждого фронтенда и бэкенда, включая все сведения для точного определения первого отклонённого символа входного потока. Иногда это необходимо, чтобы доказать заказчикам или разработчикам наличие ошибки в их коде. В таком случае часто можно ослабить проверки, сохранив захват ошибок, с помощью «option accept-unsafe-violations-in-http-request» или аналогичного параметра для ответов сервера «option accept-unsafe-violations-in-http-response». Подробнее см. руководство по конфигурации.

Пример:

> show errors
Total events captured on [13/Oct/2015:13:43:47.169]: 1

[13/Oct/2015:13:43:40.918] frontend HAProxyLocalStats (#2): invalid request
  backend <NONE> (#-1), server <NONE> (#-1), event #0
  src 127.0.0.1:51981, session #0, session flags 0x00000080
  HTTP msg state 26, msg flags 0x00000000, tx flags 0x00000000
  HTTP chunk len 0 bytes, HTTP body len 0 bytes
  buffer flags 0x00808002, out 0 bytes, total 31 bytes
  pending 31 bytes, wrapping at 8040, error at position 13:

  00000  GET /invalid request HTTP/1.1\r\n

Вывод команды «show info» в CLI содержит полезные сведения о максимальной достигнутой интенсивности соединений, максимальной достигнутой скорости вычисления ключей SSL и в целом информацию, помогающую объяснить временные проблемы с использованием CPU или памяти. Пример:

> show info
Name: HAProxy
Version: 1.6-dev7-e32d18-17
Release_date: 2015/10/12
Nbproc: 1
Process_num: 1
Pid: 7949
Uptime: 0d 0h02m39s
Uptime_sec: 159
Memmax_MB: 0
Ulimit-n: 120032
Maxsock: 120032
Maxconn: 60000
Hard_maxconn: 60000
CurrConns: 0
CumConns: 3
CumReq: 3
MaxSslConns: 0
CurrSslConns: 0
CumSslConns: 0
Maxpipes: 0
PipesUsed: 0
PipesFree: 0
ConnRate: 0
ConnRateLimit: 0
MaxConnRate: 1
SessRate: 0
SessRateLimit: 0
MaxSessRate: 1
SslRate: 0
SslRateLimit: 0
MaxSslRate: 0
SslFrontendKeyRate: 0
SslFrontendMaxKeyRate: 0
SslFrontendSessionReuse_pct: 0
SslBackendKeyRate: 0
SslBackendMaxKeyRate: 0
SslCacheLookups: 0
SslCacheMisses: 0
CompressBpsIn: 0
CompressBpsOut: 0
CompressBpsRateLim: 0
ZlibMemUsage: 0
MaxZlibMemUsage: 0
Tasks: 5
Run_queue: 1
Idle_pct: 100
node: wtap
description:

Если в новой версии HAProxy проблема возникает как будто случайно (например, прерывается каждый второй запрос или изредка происходит аварийное завершение), стоит попробовать включить заполнение памяти контрольным значением: тогда сразу после каждого вызова malloc() выделенная область заполняется заданным байтом. По умолчанию используется байт 0x50 (ASCII-код ‘P’), но можно выбрать любой другой, в том числе нулевой (это даёт тот же эффект, что calloc(), и может скрыть проблему). Заполнение памяти включается параметром командной строки «-dM». Оно немного снижает производительность и не рекомендуется для рабочей среды. Если с ним проблема возникает всегда либо никогда не возникает при заполнении нулями, это явно указывает на ошибку, о которой обязательно следует сообщить. Если заметных изменений нет, проблема с этим не связана.

При отладке задержек важно использовать и strace, и tcpdump на локальной машине, а также ещё один tcpdump на удалённой системе. Задержки возникают на всех этапах обработки, и нужно установить, какой именно этап их вызывает, чтобы понять, где вмешаться. На практике локальный tcpdump показывает время поступления входящих данных. Strace показывает, когда haproxy получает эти данные через recv/recvfrom. Внимание: OpenSSL использует системные вызовы read()/write() вместо recv()/send(). Strace также показывает, когда haproxy отправляет данные, а tcpdump — когда система передаёт их интерфейсу. Затем внешний tcpdump показывает, когда отправленные данные действительно получены (локальный показывает только постановку пакетов в очередь). Преимущество захвата трафика в локальной системе состоит в том, что strace и tcpdump используют одни и те же часы. Strace следует запускать с «-tts200», чтобы получать полные временные метки и достаточно большие для чтения фрагменты данных. Tcpdump следует запускать с «-nvvttSs0», чтобы видеть полные пакеты, реальные номера последовательности и полные временные метки.

На практике поступившие данные почти всегда сразу получает haproxy, если только CPU машины не перегружен либо данные некорректны и потому не доставляются. Если данные получены, но не отправлены, причина обычно в заполнении выходного буфера: получатель недостаточно быстро читает данные. Это можно подтвердить, заметив, что механизм опроса некоторое время не сообщает о возможности записи в выходной файловый дескриптор. Часто проще найти в выводе strace момент, когда данные наконец отправлены, а затем просмотреть более ранние события и установить, когда поступило уведомление о готовности к записи. Обычно оно совпадает с получением ACK от адресата, видимым в tcpdump. После отправки данные могут некоторое время бездействовать внутри системы. И здесь окно перегрузки TCP может быть ограничено и не позволять отправить данные до получения ACK, открывающего окно. Если трафик отсутствует, а отправка данных задерживается на 40 ms или 200 ms, причина иная и фактически не является неисправностью: алгоритм Нейгла не позволяет немедленно отправлять пустые пакеты в надежде объединить их с последующими данными. HAProxy автоматически отключает алгоритм Нейгла в чистом режиме TCP и в туннелях. Однако при пересылке тела HTTP он остаётся включённым, повышая производительность за счёт уменьшения числа пакетов. Некоторые приложения, не соответствующие HTTP, могут быть чувствительны к задержке доставки неполных ответов HTTP. В таком случае нужно включить «option http-no-delay», чтобы отключить алгоритм Нейгла и обойти особенности их реализации. При этом следует помнить, что любой другой прокси в цепочке может столкнуться с тем же эффектом. Если tcpdump показывает немедленную отправку данных, но другая сторона получает их с задержкой, причиной может быть перегруженный канал WAN, перегруженная локальная сеть с включённым управлением потоком, препятствующим отправке, либо, что встречается чаще, работа HAProxy в виртуальной машине, гипервизор которой по какой-то причине решил отложить отправку данных. В виртуализированных средах задержки почти всегда вызваны слоем виртуализации, поэтому для экономии времени стоит сначала сравнить tcpdump внутри виртуальной машины и на внешних компонентах. Любую разницу следует относить к гипервизору и сопутствующим драйверам.

Если в трассировке tcpdump с параметром -vv видны сегменты TCP SACK, это всегда означает, что отправившая их сторона получила подтверждение потери пакета. Отсутствие SACK не доказывает отсутствие потерь, но их наличие определённо указывает на потери в сети. Потери в сети нормальны, однако их частота должна быть такой, чтобы SACK не бросались в глаза. Если они часто встречаются в трассировке, стоит точно выяснить, что происходит и где теряются пакеты. HTTP плохо переносит потери TCP, поскольку они вызывают огромные задержки.

Команда «netstat -i» выводит статистику по интерфейсам. Рост счётчика Rx-Ovr означает, что системе не хватает ресурсов для приёма всех входящих пакетов и они теряются ещё до обработки сетевым драйвером. Rx-Drp показывает потери уже полученных пакетов в сетевом стеке из-за того, что приложение недостаточно быстро их обрабатывает. Такое возможно и при некоторых атаках. Tx-Drp означает, что выходные очереди заполнены и пакеты пришлось отбросить. При использовании TCP это должно происходить очень редко, но может указывать на перегрузку исходящего канала.

34 - 13. Соображения безопасности

Изоляция привилегий, поверхность атаки, Linux capabilities и безопасная эксплуатация

HAProxy рассчитан на работу с очень ограниченными привилегиями. Стандартный способ его использования — изолировать его в окружении chroot и сбросить привилегии до обычного пользователя, не имеющего никаких разрешений внутри этого окружения. Тогда, если в будущем обнаружится уязвимость, компрометация HAProxy не затронет остальную систему.

Чтобы выполнить chroot, процесс сначала нужно запустить от имени root. Создавать окружения chroot вручную и запускать процесс уже внутри них бессмысленно: их трудно создавать, их никогда не сопровождают должным образом, и ошибок в них всегда гораздо больше, чем в основной файловой системе. Кроме того, при компрометации злоумышленник сможет воспользоваться специально подготовленной файловой системой. К сожалению, многие администраторы путают «запустить от имени root» и «работать от имени root», из-за чего меняют UID ещё до запуска haproxy и тем самым ослабляют действующие ограничения безопасности.

HAProxy нужно запускать от имени root, чтобы:

  • изменять ограничения на число файловых дескрипторов;
  • привязываться к привилегированным портам;
  • привязываться к определённому сетевому интерфейсу;
  • прозрачно прослушивать чужой адрес;
  • изолировать себя в окружении chroot;
  • переходить на другой непривилегированный UID.

HAProxy может потребоваться работать от имени root, чтобы:

  • привязываться к интерфейсу для исходящих соединений;
  • привязываться к привилегированным исходным портам для исходящих соединений;
  • прозрачно привязываться к чужому адресу для исходящих соединений.

Большинству пользователей никогда не понадобится «работать от имени root». Однако «запуск от имени root» охватывает большинство сценариев использования.

Безопасная конфигурация содержит:

  • Директиву chroot, указывающую на пустой каталог без каких-либо прав доступа. Его можно подготовить следующей командой UNIX:
# mkdir /var/empty && chmod 0 /var/empty || echo "Failed"

и указать следующим образом в секции global конфигурации HAProxy:

chroot /var/empty
  • Обе директивы uid/user и gid/group в секции global:
user haproxy
group haproxy
  • Сокет stats, у которого mode, uid и gid соответствуют пользователю и/или группе, которым разрешён доступ к CLI, чтобы посторонние не могли получить к нему доступ:
stats socket /var/run/haproxy.stat uid hatop gid hatop mode 600

13.1. Поддержка Linux capabilities

Начиная с версии v2.9 haproxy поддерживает Linux capabilities. Если исполняемый файл собран с USE_LINUX_CAP=1, он может сохранять возможности, указанные в директиве ‘setcap’, при переходе от пользователя root к обычному пользователю.

Начиная с версии v3.1 haproxy также проверяет, установил ли администратор возможности из директивы ‘setcap’ в наборе Permitted его исполняемого файла (системный вызов capget). Если это так, он переносит эти возможности в набор Effective своего процесса (системный вызов capset), работая от имени обычного пользователя.

Это сделано, чтобы исключить все возможные случаи, когда haproxy запускается и работает от имени root: режим прозрачного прокси и привязку к привилегированным портам.

Директива ‘setcap’ поддерживает следующие сетевые возможности:

  • cap_net_admin: прозрачное проксирование, привязка сокета к определённому сетевому интерфейсу, использование действия set-mark;
  • cap_net_raw (подмножество cap_net_admin): прозрачное проксирование;
  • cap_net_bind_service: привязка сокета к привилегированному порту;
  • cap_sys_admin: создание сокета в определённом сетевом пространстве имён.

HAProxy никогда не переносит эти возможности из своего набора Permitted в Effective, если они не перечислены в аргументе ‘setcap’. Дополнительные сведения о директиве ‘setcap’ и поддерживаемых возможностях приведены в главе 3.1 «Управление процессами и безопасность» руководства по конфигурации.

Администратор может добавить необходимые возможности в набор Permitted исполняемого файла haproxy следующей командой:

Пример:

# setcap cap_net_admin,cap_net_bind_service=p /usr/local/sbin/haproxy

Добавленные возможности будут видны в наборе Permitted процесса после его запуска. Если те же возможности указаны в аргументах директивы ‘setcap’, они также могут быть видны в наборе Effective процесса. Это можно проверить следующей командой:

Пример:

# grep Cap /proc/<haproxy PID>/status
CapInh: 0000000000000000
CapPrm: 0000000000001400
CapEff: 0000000000001400
CapBnd: 000001ffffffffff
CapAmb: 0000000000000000

Дополнительные сведения о setcap и наборах возможностей приведены в справочных страницах Linux (capabilities(7)).

В некоторых сценариях, например при прозрачном проксировании или создании сокета в определённом сетевом пространстве имён, парсер конфигурации определяет, что требуются cap_net_raw, cap_sys_admin или другие поддерживаемые возможности. Затем на этапе инициализации процесс haproxy проверяет, можно ли включить их в свой набор Effective. Если это невозможно из-за сбоя системного вызова capget или capset (например, из-за ограничений на системные вызовы, наложенных модулями безопасности SELinux, Seccomp и т. п.), процесс выводит диагностические предупреждения (при запуске с -dD).

Из-за поддержки множества платформ с разными системными настройками парсер не может определить по файлу конфигурации, будет ли выполняться привязка к привилегированным портам. Поэтому при недостаточных привилегиях (работа от имени обычного пользователя) процесс завершится только с сообщением об ошибке наподобие приведённого ниже. Пользователь должен самостоятельно перепроверить конфигурацию и набор возможностей исполняемого файла haproxy.

Пример:

$ haproxy -dD -f haproxy.cfg
...
[ALERT]    (96797): Binding [haproxy.cfg:36] for frontend fe: cannot bind socket (Permission denied) for [0.0.0.0:80]
[ALERT]    (96797): [haproxy.main()] Some protocols failed to start their listeners! Exiting.