Доверенные прокси
Когда OxPHP работает за обратным прокси (Kubernetes Ingress, Cloudflare, AWS ALB, nginx), каждый запрос приходит с IP-адреса прокси. Без настройки доверенных прокси ограничение частоты запросов, журналирование доступа и $_SERVER['REMOTE_ADDR'] — все видят IP прокси вместо реального клиента.
Конфигурация
# 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"Если переменная не задана, OxPHP игнорирует все заголовки перенаправления. Это безопасное значение по умолчанию.
Как это работает
Когда запрос приходит с доверенного IP, OxPHP проверяет заголовки перенаправления в порядке приоритета:
Forwarded(RFC 7239) — стандартизированный заголовок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:
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 игнорируются полностью
Смотрите также
- Ограничение частоты запросов — ограничение частоты по IP использует определённый IP клиента
- Журналирование доступа — поле
remote_ipпоказывает определённый IP клиента - Справочник по конфигурации — все переменные окружения