Глава 30. Маршрутизация (Forwarding)¶
Действия маршрутизации определяют, куда направить запрос: напрямую к серверу, через upstream HTTP-прокси или через SOCKS-шлюз.
Аналоги BlueCoat:
forward(),direct.
30.1. forward(gateway) — перенаправить на upstream¶
Направляет запрос через указанный upstream HTTP-прокси. Аргумент может быть:
- Literal адрес —
host:portилиhost(порт по умолчанию 8080) - Имя группы — ссылка на Forwarding Group из конфигурации (балансировка, health check)
- Host alias — ссылка на Forwarding Host из конфигурации
Синтаксис:
where: gateway — один из:
- Literal адрес: 192.168.1.100:3128, proxy.corp:8080
- Имя группы: primary-group (из Configuration → Forwarding → Groups)
- Host alias: squid-primary (из Configuration → Forwarding → Hosts)
Порядок разрешения имён (registry resolution):
- Проверяется, есть ли группа с таким именем → выбор member по алгоритму балансировки
- Проверяется, есть ли хост с таким alias → возврат адреса если healthy
- Если не найдено → literal host:port (обратная совместимость)
Тип: Нетерминальное.
Слои и транзакции: Forward, Proxy. Применяется к HTTP/HTTPS-транзакциям.
Примеры:
; Способ 1: Literal адрес (без Forwarding конфигурации)
<Forward>
url.host=httpbin.org forward(192.168.1.100:3128)
</Forward>
; Способ 2: Через Forwarding Group (балансировка + health check)
<Forward>
url.host=*.corp.com forward(primary-group)
</Forward>
; Способ 3: Через Host alias
<Forward>
url.host=api.service.com forward(squid-primary)
</Forward>
; Комбинация: internal → direct, остальное → через группу
<Forward>
client.address=10.0.0.0/8 direct
forward(primary-group) forward.fail_open(yes)
</Forward>
Протоколы:
- HTTP: запрос отправляется на upstream прокси с absolute URI (GET http://target/path HTTP/1.1)
- HTTPS (CONNECT): прокси отправляет CONNECT target:443 на upstream, получает tunnel, затем TLS handshake через tunnel
Поведение: запрос на путь с
forward(127.0.0.1:1)(недоступный gateway) возвращает 502 (трафик действительно ушёл на gateway), а путьdirectвозвращает 200. Это подтверждает, чтоforward()действительно меняет маршрут, а не игнорируется.
См. также: direct, socks_gateway, forward.fail_open, Forwarding Groups
30.2. direct(yes|no) — прямое соединение¶
Управляет тем, направляется ли запрос напрямую к целевому серверу, минуя upstream-прокси/SOCKS:
- direct(yes) — идти напрямую: слой <Forward> для транзакции НЕ оценивается (перекрывает forward()).
- direct(no) — значение по умолчанию — разрешает форвардинг (используется <Forward>-политика / gateway).
Голое direct принимается как сокращение для direct(yes).
Синтаксис:
Тип: Нетерминальное. direct(no) не форсит прямое соединение (эквивалент дефолта) — обработка продолжается.
Слои и транзакции: <Cache>, <Proxy>. Не применяется к FTP-over-HTTP / transparent FTP.
Пример:
<Proxy>
url.host="myhost" direct(yes) ; напрямую, минуя forward gateway
url.host.is_private=yes direct ; = direct(yes)
Результат: при direct(yes)/direct запрос идёт прямо к origin (forward-gateway игнорируется); при direct(no) — через настроенный gateway.
Соответствие BlueCoat 7.3: дословно — «direct(yes):
<Forward>layer policy is not evaluated; default value is no, which allows request forwarding». Слои<Cache>/<Proxy>.
См. также: forward
30.3. socks_gateway(gateway, version) — SOCKS-шлюз¶
Направляет запрос через SOCKS-шлюз. Поддерживает SOCKS4 и SOCKS5.
Синтаксис:
where: gateway — строка с адресом шлюза (host:port); version — 4 или 5 (по умолчанию 5).
Тип: Нетерминальное.
Слои и транзакции: SOCKS, Forward. Применяется к HTTP/HTTPS-транзакциям.
Пример:
<Forward>
url.domain=*.onion socks_gateway(tor-proxy:9050, 5)
socks_gateway(socks-gw.corp:1080) ; SOCKS5 по умолчанию
См. также: socks.authenticate, forward
30.4. socks.authenticate / .allowed_versions / .allow_bind / .allow_udp — управление SOCKS¶
Важно: Все действия этой группы принимаются парсером, но не применяются — SOCKS-фронтенд, который бы их выполнял, пока не реализован. Правило загрузится, но эффекта не будет.
Группа действий для управления параметрами SOCKS-прокси.
30.4.1. socks.authenticate(yes/no)¶
Синтаксис:
where: yes — требовать SOCKS-аутентификацию; no — анонимный доступ.
30.4.2. socks.allowed_versions(4|5|both)¶
Синтаксис:
where: 4 — только SOCKS4; 5 — только SOCKS5; both — обе версии.
30.4.3. socks.allow_bind(yes/no)¶
Синтаксис:
where: yes — разрешить SOCKS BIND; no — запретить.
30.4.4. socks.allow_udp(yes/no)¶
Синтаксис:
where: yes — разрешить UDP ASSOCIATE; no — запретить.
Тип: Все четыре — нетерминальные.
Слои и транзакции: SOCKS. Применяется к SOCKS-транзакциям.
Пример:
30.5. reflect_ip(yes/no) — отражение IP клиента¶
Передаёт реальный IP-адрес клиента upstream-серверу через заголовок X-Forwarded-For или другой механизм.
Синтаксис:
where: yes — отражать IP; no — не отражать.
Тип: Нетерминальное.
Слои и транзакции: Proxy, Forward.
Пример:
30.6. forward.fail_open(yes/no) — поведение при отказе upstream¶
Определяет поведение при недоступности upstream-прокси, указанного в forward().
Синтаксис:
where: yes — при ошибке upstream направить запрос напрямую к origin (direct fallback); no — при ошибке вернуть 502 Bad Gateway клиенту.
Тип: Нетерминальное. Используется совместно с forward() на одной строке.
Слои и транзакции: Forward, Proxy. Применяется к HTTP/HTTPS-транзакциям.
Поведение:
| Настройка | Upstream доступен | Upstream недоступен |
|---|---|---|
fail_open(yes) |
Через upstream | Fallback на direct (к origin) |
fail_open(no) |
Через upstream | Ошибка 502 клиенту |
| Не указано | Через upstream | По умолчанию fail_open(no) |
Примечание: Если используется Forwarding Group, значение
fail_actionгруппы (fail-open/fail-closed) определяет поведение, когда все узлы группы недоступны. CPL-действиеforward.fail_open()переопределяет настройку группы для конкретного правила.Поведение: оба пути направляются на один недоступный gateway
127.0.0.1:1, различается толькоfail_open:fail_open(yes)→ 200 (переход на прямое соединение, запрос дошёл до origin),fail_open(no)→ 502 (отказ зафиксирован). Разница 200 против 502 показывает именно работуfail_open.
Пример:
<Forward>
; Через upstream, при ошибке — напрямую
forward(upstream:3128) forward.fail_open(yes)
; Через группу, при ошибке — ошибка клиенту
url.host=*.secure.com forward(secure-group) forward.fail_open(no)
30.7. Конфигурация Forwarding (Hosts, Groups, SOCKS Gateways)¶
Forwarding использует двухуровневую модель:
- Инфраструктура — определяет upstream прокси серверы, их группировку и мониторинг (Configuration → Forwarding в GUI, файл
forwarding.toml) - Политика — определяет правила маршрутизации трафика (CPL
<Forward>layer, файлpolicy.cpl)
30.7.1. Forwarding Hosts¶
Forwarding Host — описание upstream прокси-сервера с параметрами подключения и health check.
Конфигурация (/etc/rproxy/forwarding.toml):
[[hosts]]
alias = "squid-primary" # Уникальное имя (используется в groups и CPL)
address = "192.168.1.100" # IP-адрес или hostname
http_port = 3128 # Порт для HTTP forward (default: 8080)
https_port = 3129 # Порт для HTTPS CONNECT (default: 8443)
weight = 1 # Вес для балансировки (default: 1)
enabled = true # Включён/выключен (default: true)
[hosts.health_check]
check_type = "tcp" # tcp | http | none (default: tcp)
interval_secs = 30 # Интервал проверки (default: 30)
timeout_secs = 5 # Таймаут пробы (default: 5)
unhealthy_threshold = 3 # Кол-во неудач для unhealthy (default: 3)
healthy_threshold = 2 # Кол-во успехов для healthy (default: 2)
# url = "/health" # URL для HTTP-пробы (только check_type = "http")
# expected_status = 200 # Ожидаемый статус (только check_type = "http")
API:
| Метод | Путь | Назначение |
|---|---|---|
| GET | /api/v1/forwarding/hosts |
Список хостов (с health status) |
| POST | /api/v1/forwarding/hosts |
Создать хост |
| GET | /api/v1/forwarding/hosts/:alias |
Получить хост |
| PUT | /api/v1/forwarding/hosts/:alias |
Обновить хост |
| DELETE | /api/v1/forwarding/hosts/:alias |
Удалить хост |
| POST | /api/v1/forwarding/reload |
Перезагрузить конфигурацию |
Health Status:
Health monitor выполняет периодические TCP/HTTP пробы ко всем enabled хостам. Статус обновляется атомарно и доступен через API:
- up — хост отвечает на пробы
- down — хост не отвечает (threshold превышен)
- unknown — проба ещё не выполнялась
GUI (Configuration → Forwarding → Hosts) отображает health status в реальном времени с auto-refresh каждые 10 секунд.
30.7.2. Forwarding Groups¶
Forwarding Group — логическая группа хостов с балансировкой нагрузки и failover.
Конфигурация (/etc/rproxy/forwarding.toml):
[[groups]]
name = "primary-group" # Уникальное имя (используется в CPL)
members = ["squid-primary", "squid-backup"] # Ссылки на alias хостов
algorithm = "round-robin" # Алгоритм балансировки
fail_action = "fail-open" # Поведение при отказе всех members
Алгоритмы балансировки:
| Алгоритм | Описание | Время выбора |
|---|---|---|
round-robin |
Циклический перебор healthy members | ~5ns |
least-connections |
Выбор member с наименьшим числом активных соединений | ~20ns |
ip-hash |
Consistent hash по IP клиента (один клиент → один member) | ~10ns |
url-hash |
Consistent hash по URL запроса | ~10ns |
none |
Первый healthy member | ~5ns |
Fail Action:
| Режим | Когда все узлы недоступны |
|---|---|
fail-open |
Переход на прямое соединение (к origin) |
fail-closed |
Ошибка 502 клиенту |
API:
| Метод | Путь | Назначение |
|---|---|---|
| GET | /api/v1/forwarding/groups |
Список групп |
| POST | /api/v1/forwarding/groups |
Создать группу |
| PUT | /api/v1/forwarding/groups/:name |
Обновить группу |
| DELETE | /api/v1/forwarding/groups/:name |
Удалить группу |
Использование в CPL:
<Forward>
; Трафик к *.corp.com — через группу primary-group (round-robin)
url.domain=*.corp.com forward(primary-group)
; Остальной трафик — напрямую
direct
</Forward>
30.7.3. SOCKS Gateways¶
SOCKS Gateway — конфигурация SOCKS4/SOCKS5 прокси-сервера.
Конфигурация (/etc/rproxy/forwarding.toml):
[[socks_gateways]]
name = "tor-proxy" # Уникальное имя
address = "10.0.0.1" # IP-адрес или hostname
port = 9050 # Порт (default: 1080)
version = 5 # 4 или 5 (default: 5)
enabled = true # Включён/выключен
# username = "user" # SOCKS5 аутентификация (опционально)
# password = "pass" # SOCKS5 пароль (опционально)
API:
| Метод | Путь | Назначение |
|---|---|---|
| GET | /api/v1/forwarding/socks-gateways |
Список шлюзов |
| POST | /api/v1/forwarding/socks-gateways |
Создать шлюз |
| PUT | /api/v1/forwarding/socks-gateways/:name |
Обновить шлюз |
| DELETE | /api/v1/forwarding/socks-gateways/:name |
Удалить шлюз |
30.7.4. Полный пример конфигурации¶
Инфраструктура (forwarding.toml):
[[hosts]]
alias = "proxy-dc1"
address = "10.0.1.10"
http_port = 3128
weight = 2
[hosts.health_check]
check_type = "http"
url = "/health"
expected_status = 200
interval_secs = 15
[[hosts]]
alias = "proxy-dc2"
address = "10.0.2.10"
http_port = 3128
weight = 1
[hosts.health_check]
check_type = "tcp"
interval_secs = 30
[[groups]]
name = "corporate-proxies"
members = ["proxy-dc1", "proxy-dc2"]
algorithm = "round-robin"
fail_action = "fail-open"
[[socks_gateways]]
name = "tor-exit"
address = "10.0.0.50"
port = 9050
version = 5
Политика (policy.cpl):
<Forward>
; Внутренние ресурсы — напрямую
client.address=10.0.0.0/8 url.host.is_private=yes direct
; Tor — через SOCKS5
url.domain=*.onion socks_gateway(tor-exit:9050, 5)
; Корпоративный трафик — через группу с балансировкой
forward(corporate-proxies) forward.fail_open(yes)
</Forward>
<Proxy>
allow
Как это работает:
- Запрос от
10.0.0.5кintranet.corp→direct(внутренний) - Запрос к
hidden.onion→socks_gateway(tor-exit)→ SOCKS5 через 10.0.0.50:9050 - Запрос к
google.com→forward(corporate-proxies)→ registry resolve → round-robin выбирает proxy-dc1 или proxy-dc2 (с учётом health status) → HTTP forward через выбранный upstream - Если оба proxy-dc1 и proxy-dc2 down →
fail_open(yes)→ direct к google.com