Доверенные прокси

Когда OxPHP работает за обратным прокси (Kubernetes Ingress, Cloudflare, AWS ALB, nginx), каждый запрос приходит с IP-адреса прокси. Без настройки доверенных прокси ограничение частоты запросов, журналирование доступа и $_SERVER['REMOTE_ADDR'] — все видят IP прокси вместо реального клиента.

Конфигурация

bash
# Comma-separated CIDR list TRUSTED_PROXIES="10.0.0.0/8,172.16.0.0/12,192.168.0.0/16" # Shorthand: all RFC-1918 + loopback + link-local (IPv4 and IPv6) TRUSTED_PROXIES="private"
Note

Если переменная не задана, OxPHP игнорирует все заголовки перенаправления. Это безопасное значение по умолчанию.

Как это работает

Когда запрос приходит с доверенного IP, OxPHP проверяет заголовки перенаправления в порядке приоритета:

  1. Forwarded (RFC 7239) — стандартизированный заголовок
  2. X-Forwarded-For / X-Forwarded-Proto / X-Forwarded-Host / X-Forwarded-Port — де-факто резервный вариант

Если присутствует заголовок Forwarded, заголовки X-Forwarded-* игнорируются.

Извлечение IP-адреса клиента

OxPHP использует алгоритм rightmost-non-trusted (крайний правый недоверенный) — тот же подход, что и в nginx (real_ip_recursive on), Caddy, Traefik и Apache:

text
X-Forwarded-For: 203.0.113.50, 172.16.1.1, 10.0.0.5 TCP peer: 10.0.0.1 (trusted) Walk right-to-left: 10.0.0.5 → trusted → skip 172.16.1.1 → trusted → skip 203.0.113.50 → NOT trusted → client IP

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

Что меняется

Когда TRUSTED_PROXIES настроен и подключающийся IP является доверенным:

Компонент Без доверенных прокси С доверенными прокси
$_SERVER['REMOTE_ADDR'] IP прокси Реальный IP клиента
$_SERVER['REMOTE_PORT'] Исходный порт прокси Порт клиента из Forwarded: for=ip:port, иначе 0
$_SERVER['HTTPS'] На основе TLS-конфигурации OxPHP Из Forwarded: proto= или X-Forwarded-Proto
$_SERVER['REQUEST_SCHEME'] http или https из TLS Из перенаправленного протокола
$_SERVER['SERVER_NAME'] Из заголовка Host Из Forwarded: host= или X-Forwarded-Host
$_SERVER['SERVER_PORT'] Из заголовка Host Из X-Forwarded-Port, иначе порт из X-Forwarded-Host / Forwarded: host=, иначе 443/80
Ограничение частоты запросов По IP прокси По IP клиента
Журнал доступа IP прокси Реальный IP клиента

За прокси REMOTE_PORT равен 0, если только узел Forwarded: for=ip:port из RFC 7239 не несёт исходный порт клиента. У X-Forwarded-For нет поля порта, поэтому переписанное значение невозможно восстановить, и вместо угадывания оно обнуляется.

Сети private

Сокращение private включает:

Сеть Описание
10.0.0.0/8 Частная сеть класса A
172.16.0.0/12 Частная сеть класса B
192.168.0.0/16 Частная сеть класса C
127.0.0.0/8 Loopback
169.254.0.0/16 Link-local
::1/128 IPv6 loopback
fc00::/7 IPv6 unique local
fe80::/10 IPv6 link-local

Безопасность

  • Безопасное значение по умолчанию — без TRUSTED_PROXIES заголовки перенаправления не обрабатываются
  • Валидация CIDR — некорректные значения в TRUSTED_PROXIES приводят к ошибке при запуске
  • Устойчивость к подмене — алгоритм rightmost-non-trusted игнорирует добавленные атакующим значения
  • Заголовки перенаправления в запросах с недоверенных IP игнорируются полностью

Смотрите также