# HAProxy в pfSense - обратный прокси и балансировка

> Установка и настройка HAProxy в pfSense - обратный прокси, балансировка нагрузки, SSL-терминация, ACL-маршрутизация и проверки здоровья бэкендов

Source: https://opennix.org/docs/pfsense/packages/pfsense-haproxy/


HAProxy (High Availability Proxy) - высокопроизводительное решение для проксирования и балансировки нагрузки TCP и HTTP-трафика. В pfSense HAProxy устанавливается как пакет и предоставляет функции обратного прокси-сервера, балансировщика нагрузки между несколькими серверами, SSL-терминатора для разгрузки шифрования с бэкенд-серверов и маршрутизатора HTTP-запросов на основе ACL-правил. HAProxy широко используется для публикации веб-приложений через единый внешний IP-адрес, обеспечения отказоустойчивости серверных пулов и распределения клиентских запросов между несколькими экземплярами приложения.

В контексте pfSense HAProxy работает совместно с файрволом, что позволяет объединить функции маршрутизации, фильтрации и проксирования на одном устройстве. Это упрощает архитектуру сети и сокращает количество точек отказа.

## Установка HAProxy

Установка выполняется через менеджер пакетов:

1. Перейти в **System > Package Manager > Available Packages**
2. Найти **haproxy** в строке поиска (доступны две версии: **haproxy** и **haproxy-devel**)
3. Нажать **Install** и подтвердить установку
4. Дождаться завершения установки

После установки конфигурация доступна через **Services > HAProxy**.

### Выбор версии

| Версия | Описание | Рекомендация |
|---|---|---|
| **haproxy** | Стабильная версия, отслеживает стабильную ветку FreeBSD-порта | Рабочие среды |
| **haproxy-devel** | Версия для разработки, содержит новые функции раньше | Тестовые среды |

## Архитектура HAProxy

HAProxy оперирует двумя основными сущностями:

```text
Клиент ──> Frontend (слушатель) ──> ACL (маршрутизация) ──> Backend (пул серверов)
                                                              ├── Server 1
                                                              ├── Server 2
                                                              └── Server 3
```

| Компонент | Описание |
|---|---|
| **Frontend** | Точка входа для клиентских подключений (IP:порт), определяет протокол и ACL-правила |
| **Backend** | Пул бэкенд-серверов с настройками балансировки и проверок здоровья |
| **Server** | Отдельный бэкенд-сервер в пуле (IP, порт, вес) |
| **ACL** | Условие маршрутизации запросов между бэкендами |

### Особенности реализации в pfSense

Веб-интерфейс pfSense отличается от стандартной конфигурации HAProxy. Вместо раздельных секций frontend/backend в конфигурационном файле, пакет pfSense генерирует секции `listen`, которые объединяют frontend и backend. Это упрощает базовую настройку, но ограничивает возможности продвинутых сценариев с множественными бэкендами.

## Настройка Backend

Backend (бэкенд) определяет группу серверов, на которые HAProxy направляет клиентские запросы. Настройка выполняется через **Services > HAProxy > Backend**.

### Создание Backend

1. Перейти в **Services > HAProxy > Backend**
2. Нажать **Add**
3. Заполнить параметры
4. Нажать **Save** и **Apply Changes**

### Основные параметры Backend

| Параметр | Описание |
|---|---|
| **Name** | Уникальное имя бэкенда (без пробелов) |
| **Server List** | Список серверов пула |
| **Balance** | Алгоритм балансировки нагрузки |
| **Connection Timeout** | Таймаут подключения к серверу |
| **Server Timeout** | Таймаут ожидания ответа от сервера |
| **Retries** | Количество повторных попыток подключения |

### Серверы в Backend

Для каждого сервера в пуле указываются:

| Поле | Описание | Обязательное |
|---|---|---|
| **Name** | Имя сервера для идентификации в логах | Да |
| **Address** | IP-адрес или FQDN бэкенд-сервера | Да |
| **Port** | Порт бэкенд-сервера | Да |
| **SSL** | Использование SSL при подключении к серверу | Нет |
| **Weight** | Вес сервера для взвешенной балансировки (1-256) | Нет |
| **Cookie** | Значение cookie для привязки сессий | Нет |

### Алгоритмы балансировки

| Алгоритм | Описание | Применение |
|---|---|---|
| **Round Robin** | Последовательное распределение по серверам | Серверы с одинаковой производительностью |
| **Least Connections** | Направление на сервер с наименьшим количеством соединений | Запросы с разной длительностью обработки |
| **Source** | Привязка клиента к серверу на основе IP-адреса | Требуется постоянство сессии без cookie |
| **URI** | Маршрутизация по URI-запроса | Кэширующие серверы |
| **First** | Заполнение серверов последовательно до максимума | Минимизация количества активных серверов |

Для большинства веб-приложений рекомендуется **Round Robin** или **Least Connections**. Алгоритм **Source** подходит для приложений, не поддерживающих распределённые сессии.

## Настройка Frontend

Frontend (фронтенд) определяет точку входа для клиентских подключений - IP-адрес, порт и протокол, на которых HAProxy принимает соединения. Настройка выполняется через **Services > HAProxy > Frontend**.

### Создание Frontend

1. Перейти в **Services > HAProxy > Frontend**
2. Нажать **Add**
3. Заполнить параметры
4. Нажать **Save** и **Apply Changes**

### Основные параметры Frontend

| Параметр | Описание |
|---|---|
| **Name** | Уникальное имя фронтенда |
| **Status** | Состояние: Active или Disabled |
| **External Address** | IP-адрес для прослушивания (WAN, VIP, localhost) |
| **External Port** | Порт для прослушивания |
| **Max Connections** | Максимальное количество одновременных соединений |
| **Type** | Тип: HTTP/HTTPS (Layer 7) или TCP (Layer 4) |
| **Default Backend** | Бэкенд по умолчанию для запросов без совпадений ACL |

### Настройка HTTPS Frontend

Для приёма HTTPS-соединений необходимо:

1. Установить **Type** в **HTTP / HTTPS (offloading)**
2. В разделе **SSL Offloading** выбрать сертификат
3. Указать **External Port** как **443**
4. Настроить Default Backend

При необходимости перенаправления HTTP на HTTPS создать дополнительный Frontend на порту 80 с действием **http-request redirect** или использовать ACL.

### Привязка к Virtual IP

Для приёма соединений на определённом IP-адресе, отличном от основного WAN-адреса, используйте Virtual IP:

1. Создать IP Alias или CARP VIP через **Firewall > Virtual IPs**
2. В настройках Frontend выбрать созданный VIP в поле **External Address**

Это позволяет обслуживать несколько доменов на разных IP-адресах через один экземпляр HAProxy.

## ACL - правила маршрутизации

ACL (Access Control Lists) определяют условия, по которым HAProxy направляет запросы на различные бэкенды. ACL анализируют параметры входящего запроса и применяют соответствующее действие.

### Создание ACL

ACL настраиваются в секции Frontend:

1. На странице редактирования Frontend перейти к разделу **Access Control Lists**
2. Нажать **Add ACL** (стрелка вниз)
3. Заполнить условие и действие
4. Повторить для каждого правила маршрутизации

### Типы условий ACL

| Условие | Описание | Пример |
|---|---|---|
| **Host matches** | Совпадение заголовка Host | `app.example.com` |
| **Host starts with** | Начало заголовка Host | `api.` |
| **Host ends with** | Окончание заголовка Host | `.example.com` |
| **Host contains** | Подстрока в заголовке Host | `staging` |
| **Host regex** | Регулярное выражение для Host | `^(www\.)?example\.com$` |
| **Path starts with** | Начало URI-пути | `/api/` |
| **Path ends with** | Окончание URI-пути | `.php` |
| **Path contains** | Подстрока в URI-пути | `/admin/` |
| **Path regex** | Регулярное выражение для пути | `^/v[0-9]+/` |
| **Source IP matches** | Совпадение IP-адреса клиента | `192.168.1.0/24` |
| **SSL SNI matches** | Совпадение SNI в TLS Client Hello | `app.example.com` |
| **Custom ACL** | Произвольное условие HAProxy | `hdr(X-Custom) -i value` |

### Действия ACL

| Действие | Описание |
|---|---|
| **Use Backend** | Направить запрос на указанный бэкенд |
| **http-request deny** | Отклонить запрос с кодом ошибки |
| **http-request redirect** | Перенаправить запрос на другой URL |
| **http-request set-header** | Установить или изменить HTTP-заголовок |

### Пример маршрутизации по доменам

Для публикации нескольких веб-приложений через один IP-адрес:

| ACL | Условие | Backend |
|---|---|---|
| ACL 1 | Host matches `app1.example.com` | backend_app1 |
| ACL 2 | Host matches `app2.example.com` | backend_app2 |
| ACL 3 | Host matches `api.example.com` | backend_api |
| Default | Все остальные запросы | backend_default |

### Пример маршрутизации по путям

| ACL | Условие | Backend |
|---|---|---|
| ACL 1 | Path starts with `/api/` | backend_api |
| ACL 2 | Path starts with `/static/` | backend_static |
| Default | Все остальные запросы | backend_webapp |

## SSL-терминация

SSL-терминация (SSL offloading) позволяет HAProxy принимать HTTPS-соединения от клиентов, расшифровывать трафик и пересылать его на бэкенд-серверы по HTTP. Это снимает нагрузку шифрования с бэкенд-серверов и упрощает управление сертификатами.

### Импорт сертификата

Перед настройкой SSL необходимо импортировать сертификат в pfSense:

1. Перейти в **System > Certificates > Certificates**
2. Нажать **Add/Sign**
3. Выбрать метод: **Import an existing Certificate**
4. Вставить сертификат и приватный ключ
5. Нажать **Save**

Для сертификатов Let's Encrypt рекомендуется использовать пакет **ACME** для автоматического получения и обновления.

### Настройка SSL Offloading в Frontend

1. В настройках Frontend установить **Type** в **HTTP / HTTPS (offloading)**
2. В разделе **SSL Offloading** выбрать сертификат
3. При необходимости добавить дополнительные сертификаты через **Additional Certificates** (для нескольких доменов)
4. Настроить минимальную версию TLS (рекомендуется TLS 1.2)

### Параметры SSL

| Параметр | Описание | Рекомендация |
|---|---|---|
| **Certificate** | Основной SSL-сертификат | Обязательно |
| **Additional Certificates** | Сертификаты для дополнительных доменов | По необходимости |
| **SSL/TLS Minimum Version** | Минимальная версия протокола | TLS 1.2 |
| **SSL/TLS Ciphers** | Набор шифров | По умолчанию или Mozilla Modern |
| **HSTS** | HTTP Strict Transport Security | Включить для рабочих сред |
| **OCSP Stapling** | Привязка статуса OCSP | Включить для улучшения производительности |

### SSL Pass-Through

Для случаев, когда SSL-терминация должна выполняться на бэкенд-сервере (например, клиентские сертификаты), используется режим **SSL/HTTPS (TCP mode)**. HAProxy передаёт зашифрованный трафик без расшифровки, маршрутизируя по SNI.

## Проверки здоровья

Проверки здоровья (health checks) позволяют HAProxy определять доступность бэкенд-серверов и автоматически исключать неработающие из балансировки.

### Типы проверок

| Тип | Описание | Параметры |
|---|---|---|
| **TCP Check** | Проверка TCP-подключения к порту | Не требует настройки |
| **HTTP Check** | Отправка HTTP-запроса и проверка кода ответа | URI, метод, ожидаемый код |
| **SSL Check** | Проверка SSL-соединения | Аналогично TCP с SSL |
| **LDAP Check** | Проверка LDAP-сервера | LDAP-специфичные параметры |
| **MySQL Check** | Проверка MySQL-сервера | Учётные данные |
| **PostgreSQL Check** | Проверка PostgreSQL-сервера | Учётные данные |
| **SMTP Check** | Проверка SMTP-сервера | HELO-домен |
| **ESMTP Check** | Расширенная проверка SMTP | EHLO-домен |

### Настройка HTTP-проверки

Для веб-приложений рекомендуется HTTP-проверка:

1. В настройках Backend перейти к **Health Checking**
2. Установить **Health Check Method** в **HTTP**
3. Указать **Check Frequency** (интервал проверки, например 5 секунд)
4. Указать **Health Check URI** (путь для проверки, например `/health`)
5. Указать **HTTP Check Method** (GET)
6. Указать ожидаемый код ответа (по умолчанию 200-399)

### Параметры проверок

| Параметр | Описание | Значение по умолчанию |
|---|---|---|
| **Check Frequency** | Интервал между проверками | 5 секунд |
| **Inter** | Интервал проверки для здоровых серверов | 5000 мс |
| **Down Inter** | Интервал проверки для недоступных серверов | 1000 мс |
| **Rise** | Количество успешных проверок для возврата сервера | 2 |
| **Fall** | Количество неуспешных проверок для вывода сервера | 3 |

## Привязка сессий

Привязка сессий (session persistence, sticky sessions) обеспечивает направление всех запросов одного клиента на один и тот же бэкенд-сервер. Это необходимо для приложений, хранящих состояние сессии локально на сервере.

### Методы привязки

| Метод | Описание | Применение |
|---|---|---|
| **Cookie-based** | HAProxy вставляет cookie с идентификатором сервера | Веб-приложения с поддержкой cookie |
| **Source IP** | Привязка по IP-адресу клиента (алгоритм Source) | Приложения без cookie, API |
| **SSL Session ID** | Привязка по идентификатору TLS-сессии | HTTPS без cookie |

### Настройка Cookie-based привязки

1. В настройках Backend в разделе **Cookie Persistence**:
   - **Cookie Name** - имя cookie (например, `SERVERID`)
   - **Cookie Mode** - режим: Insert (HAProxy вставляет cookie), Prefix, Rewrite
   - **Cookie Options** - дополнительные параметры (Indirect, NoCache, PostOnly)
2. Для каждого сервера в бэкенде указать уникальное значение в поле **Cookie**

## Страница статистики

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

### Включение статистики

Настройка выполняется через **Services > HAProxy > Settings** в разделе **Stats**:

| Параметр | Описание |
|---|---|
| **Stats Enabled** | Активация страницы статистики |
| **Stats URI** | URI для доступа (например, `/haproxy-stats`) |
| **Stats Realm** | Заголовок окна аутентификации |
| **Stats Username** | Имя пользователя |
| **Stats Password** | Пароль |
| **Stats Admin** | Разрешение на управление серверами через веб-интерфейс |
| **Stats Node** | Имя узла, отображаемое в статистике |

### Информация на странице статистики

Страница статистики отображает:

- Состояние каждого фронтенда (UP/DOWN, текущие соединения)
- Состояние каждого бэкенда и его серверов (UP/DOWN, активные/неактивные)
- Количество запросов, байт, ошибок за текущую и предыдущую сессии
- Время ответа серверов (avg, max)
- Queue status (очередь запросов при перегрузке серверов)
- Вес серверов и коэффициент распределения

При включённом **Stats Admin** доступны действия: отключение/включение серверов, слив соединений (drain), установка веса.

> **Внимание**:
>
> Страница статистики содержит конфиденциальную информацию об инфраструктуре. Обязательно настройте аутентификацию и ограничьте доступ по IP-адресам через правила файрвола или ACL.

## Типичные сценарии использования

### Обратный прокси для веб-серверов

Публикация нескольких веб-приложений через один внешний IP-адрес с маршрутизацией по доменным именам:

1. Создать Backend для каждого веб-приложения (backend_site1, backend_site2)
2. Создать Frontend на порту 443 с SSL-терминацией
3. Настроить ACL-правила маршрутизации по Host
4. Создать Frontend на порту 80 с перенаправлением на HTTPS
5. Настроить правила файрвола для пропуска трафика на порты 80 и 443

### Балансировка нагрузки веб-приложения

Распределение запросов между несколькими экземплярами приложения:

1. Создать Backend с несколькими серверами
2. Выбрать алгоритм балансировки (Round Robin или Least Connections)
3. Настроить HTTP-проверку здоровья на endpoint `/health`
4. При необходимости настроить Cookie-based привязку сессий
5. Создать Frontend с привязкой к VIP или WAN-адресу

### Публикация API

Маршрутизация API-запросов с разделением по версиям:

1. Создать Backend для каждой версии API
2. Создать Frontend с ACL по путям: `/v1/` - backend_v1, `/v2/` - backend_v2
3. Настроить проверки здоровья для каждого бэкенда
4. Добавить rate limiting через ACL при необходимости

## Глобальные настройки

Общие параметры HAProxy настраиваются через **Services > HAProxy > Settings**.

| Параметр | Описание | Рекомендация |
|---|---|---|
| **Enable HAProxy** | Активация HAProxy | Включить |
| **Maximum Connections** | Глобальный лимит соединений | 1000-10000 (зависит от RAM) |
| **Internal Connections Timeout** | Таймаут клиентских соединений | 30000 мс |
| **Connection Timeout** | Таймаут подключения к бэкенду | 30000 мс |
| **Server Timeout** | Таймаут ответа бэкенда | 30000 мс |
| **Tunnel Timeout** | Таймаут для WebSocket и длительных соединений | 3600000 мс |
| **DNS Resolvers** | DNS-серверы для разрешения имён бэкендов | Указать при использовании FQDN |

## Логирование

HAProxy записывает события в системный журнал pfSense (**Status > System Logs > HAProxy**).

### Уровни логирования

| Уровень | Описание |
|---|---|
| **Emergency** | Система неработоспособна |
| **Alert** | Требуется немедленное вмешательство |
| **Critical** | Критические ошибки |
| **Error** | Ошибки подключения и обработки |
| **Warning** | Предупреждения (недоступность серверов) |
| **Notice** | Нормальные, но важные события |
| **Info** | Информационные сообщения о запросах |
| **Debug** | Детальная отладочная информация |

### Формат логов HTTP

Каждая строка лога HTTP-запроса содержит:

- Клиентский IP и порт
- Время принятия соединения
- Имя фронтенда и бэкенда
- Код HTTP-ответа
- Длительность обработки (Tq/Tw/Tc/Tr/Tt)
- Переданный объём данных
- Заголовки запроса (при включении захвата)

## Диагностика проблем

### HAProxy не запускается

1. Проверить конфигурацию: **Services > HAProxy > Settings > Configuration Validity**
2. Просмотреть системные логи: **Status > System Logs > HAProxy**
3. Убедиться, что порты фронтендов не заняты другими сервисами
4. Проверить, что SSL-сертификаты корректны и не истекли

### Бэкенд-сервер помечен как DOWN

1. Проверить доступность сервера из pfSense: **Diagnostics > Ping**
2. Убедиться, что порт бэкенд-сервера принимает соединения: **Diagnostics > Test Port**
3. Проверить настройки health check - URI, метод, ожидаемый код ответа
4. Просмотреть логи HAProxy для определения причины отказа
5. Временно отключить health check для диагностики

### 502 Bad Gateway

1. Бэкенд-сервер не отвечает или возвращает ошибку
2. Проверить таймаут подключения к бэкенду (**Connection Timeout**)
3. Убедиться, что бэкенд-сервер способен обработать запрос (не перегружен)
4. При использовании SSL к бэкенду проверить корректность сертификата

### 503 Service Unavailable

1. Все серверы в бэкенде помечены как DOWN
2. Проверить проверки здоровья для каждого сервера
3. Убедиться, что максимальное количество соединений не превышено
4. Проверить очередь запросов на странице статистики

### SSL-ошибки

1. Проверить срок действия сертификата: **System > Certificates**
2. Убедиться, что цепочка сертификатов полная (включая промежуточные CA)
3. Проверить совпадение доменного имени в сертификате с запрашиваемым
4. При использовании нескольких сертификатов убедиться, что SNI настроен корректно
5. Проверить минимальную версию TLS - старые клиенты могут не поддерживать TLS 1.2+

### Сессия не сохраняется между запросами

1. Проверить настройки Cookie Persistence в бэкенде
2. Убедиться, что каждый сервер имеет уникальное значение Cookie
3. При использовании алгоритма Source убедиться, что клиенты подключаются с постоянного IP
4. Проверить, не включён ли прозрачный прокси или CDN, изменяющий IP клиента

## Связанные разделы

- [Управление пакетами](/docs/pfsense/packages/pfsense-package-management/) - установка и обновление пакетов pfSense
- [Сертификаты pfSense](/docs/pfsense/certificates/pfsense-certificate-management/) - управление SSL-сертификатами для HAProxy
- [Правила файрвола](/docs/pfsense/firewall/pfsense-firewall-rules/) - настройка правил для пропуска трафика к HAProxy
- [NAT в pfSense](/docs/pfsense/nat/pfsense-port-forwarding/) - альтернативный способ публикации сервисов через проброс портов

