ZIM-НИЙ SAAALEЗимние скидки: до −50% на старт и −20% на продление
до 31.01.2026 Подробнее
Выберите продукт

Реальный IP за прокси и CDN: X‑Forwarded‑For, PROXY Protocol и логи

Если сайт работает за CDN, балансировщиком или обратным прокси, в логах часто виден лишь адрес прокси. Разбираем, как вернуть реальный IP: когда выбирать X‑Forwarded‑For или PROXY Protocol, как настроить nginx/Apache, доверять источникам и правильно писать логи.
Реальный IP за прокси и CDN: X‑Forwarded‑For, PROXY Protocol и логи

Классическая ситуация: перед вашим веб‑сервером стоит CDN или балансировщик, а в логах и приложении вместо клиентского адреса виден IP обратного прокси. Это ломает гео‑таргетинг, антифрод, rate limit и статистику. В этой статье систематизируем подходы к получению real IP за прокси, разберём заголовки X-Forwarded-For и стандарт Forwarded, протокол PROXY (v1/v2), настройки для nginx и Apache, а также корректную запись IP в логи.

Почему за прокси теряется реальный IP

Когда фронтенд‑прокси или CDN принимает соединение от клиента и отправляет его дальше на ваш веб‑сервер, соединение устанавливается уже между прокси и бэкендом. Со стороны веб‑сервера источником TCP‑подключения становится адрес прокси, а не клиента. Чтобы передать реальный адрес, используют либо заголовки уровня HTTP (X-Forwarded-For, Forwarded), либо транспортный PROXY Protocol, добавляющий метаданные в начало TCP‑потока.

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

Заголовки уровня HTTP: X‑Forwarded‑For и Forwarded

X-Forwarded-For (XFF) — де‑факто стандартный заголовок, который прокси добавляет к запросу. Формат — список IP через запятую: первый адрес — исходный клиент, далее цепочка прокси. Пример:

X-Forwarded-For: 203.0.113.10, 198.51.100.5

Стандартный заголовок из RFC 7239 — Forwarded. Он более формальный и поддерживает IPv6 и дополнительные параметры:

Forwarded: for=203.0.113.10; proto=https; by=198.51.100.5
Forwarded: for="[2001:db8::1]"; proto=http

Плюсы заголовков:

  • Просто включить на большинстве прокси и балансировщиков.
  • Читаемо, видно полную цепочку.

Минусы:

  • Клиент может подделать заголовок. Верить ему можно только если запрос пришёл от доверенного прокси, который заголовок корректно формирует и/или переписывает.
  • Разночтения формата (пробелы, IPv6, кавычки), нужны аккуратные парсеры.

Транспортный уровень: PROXY Protocol v1/v2

PROXY Protocol — это префикс к TCP‑соединению. Прокси добавляет в начале сессии строку (v1, текстовая) или бинарный блок (v2), где указывает исходный и целевой адреса/порты. Так бэкенд получает достоверный адрес клиента, не полагаясь на заголовки HTTP.

Плюсы:

  • Подделать со стороны клиента невозможно: он не достучится до бэкенда минуя балансировщик.
  • Работает для любых протоколов поверх TCP (HTTP, SMTP и т.д.).

Минусы:

  • Нужно включить поддержку и на прокси, и на бэкенде. Иначе бэкенд увидит «мусор» в начале потока.
  • Не все софты и библиотеки автоматически поддерживают PROXY v2 (но веб‑сервера поддерживают давно).

Фрагмент конфигурации nginx для извлечения real IP из X‑Forwarded‑For

Базовая архитектура: где восстанавливать real IP

Есть два рабочих паттерна:

  1. Только HTTP‑заголовки: фронт добавляет/переписывает X-Forwarded-For и опционально Forwarded, бэкенд (nginx/Apache) доверяет заголовку только от известных адресов прокси и извлекает реальный IP.
  2. PROXY Protocol: фронт шлёт PROXY, бэкенд слушает сокет с опцией proxy_protocol (nginx) или ProxyProtocol On (Apache), и использует адрес из транспортных метаданных.

Если у вас цепочка: клиент → CDN → L4/L7 балансировщик → веб‑сервер, выберите один доверенный источник правды. Чаще всего — PROXY Protocol между балансировщиком и веб‑серверами. Заголовок XFF можно оставить для трассировки всей цепочки.

Для самостоятельной сборки периметра рационально использовать VDS, где вы контролируете и фронты, и бэкенды.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

nginx: настройка real IP через X‑Forwarded‑For

Чтобы nginx корректно определял реальный IP из заголовка XFF, необходимо:

  • Перечислить доверенные адреса прокси (CDN, балансировщиков) через set_real_ip_from.
  • Указать источник IP: real_ip_header X-Forwarded-For (или Forwarded при соответствующей конфигурации).
  • Включить real_ip_recursive on, если в цепочке несколько прокси и нужно брать первый адрес слева.
# http {}
log_format main_realip '$remote_addr - $remote_user [$time_local] '
                      '"$request" $status $body_bytes_sent '
                      '"$http_referer" "$http_user_agent" '
                      'xff="$http_x_forwarded_for" realip="$realip_remote_addr"';

set_real_ip_from 10.0.0.0/8;      # адреса внутренних балансировщиков
set_real_ip_from 192.0.2.0/24;    # пример подсети CDN/прокси
set_real_ip_from 2001:db8::/32;   # IPv6 диапазоны, если есть
real_ip_header X-Forwarded-For;
real_ip_recursive on;

access_log /var/log/nginx/access_realip.log main_realip;

После такой настройки $realip_remote_addr станет реальным адресом клиента, а $remote_addr останется адресом последнего прокси. Для rate limiting, geoip, WAF и ACL используйте именно $realip_remote_addr.

JSON‑логи в nginx с real IP

log_format json_real escape=json '{"time":"$time_iso8601",'
  '"remote":"$realip_remote_addr",'
  '"proxy":"$remote_addr",'
  '"xff":"$http_x_forwarded_for",'
  '"method":"$request_method","uri":"$request_uri",'
  '"status":$status,"bytes":$body_bytes_sent}';
access_log /var/log/nginx/access_json.log json_real;

nginx: настройка real IP через PROXY Protocol

Если балансировщик (или внешний прокси) умеет отдавать PROXY Protocol, включите его на бэкенде:

# сервер слушает порт с поддержкой PROXY Protocol
server {
    listen 80 proxy_protocol;

    # источник IP берём из PROXY Protocol
    real_ip_header proxy_protocol;

    # для логов
    log_format main_proxy '$proxy_protocol_addr - $remote_user [$time_local] '
                          '"$request" $status $body_bytes_sent '
                          'proxy="$remote_addr"';
    access_log /var/log/nginx/access_proxy.log main_proxy;

    location / {
        proxy_pass http://127.0.0.1:8080;
    }
}

В этом случае реальный адрес будет в $proxy_protocol_addr, а также подставится в $realip_remote_addr, если задан real_ip_header proxy_protocol. При использовании PROXY Protocol не требуется доверять заголовкам, но если вы параллельно принимаете XFF от CDN, оставьте $http_x_forwarded_for для диагностики.

Apache: X‑Forwarded‑For через mod_remoteip

Для Apache используйте модуль mod_remoteip, который заменяет адрес клиента на значение из доверённого заголовка.

# Загрузка модуля (если требуется вручную)
# LoadModule remoteip_module modules/mod_remoteip.so

# httpd.conf или внутри vhost
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 10.0.0.0/8
RemoteIPTrustedProxy 192.0.2.0/24
RemoteIPTrustedProxy 2001:db8::/32

# Логирование: %a станет реальным адресом клиента
LogFormat "%a %l %u %t \"%r\" %>s %b xff=\"%{X-Forwarded-For}i\"" combined_realip
CustomLog logs/access_realip.log combined_realip

Директивы RemoteIPInternalProxy и RemoteIPTrustedProxy ограничивают, от кого принимать заголовок — это критично для безопасности.

Apache: PROXY Protocol через mod_proxy_protocol

Чтобы Apache принимал PROXY Protocol от балансировщика, нужен модуль mod_proxy_protocol. С его помощью сервер читает адрес клиента из транспортного префикса, без участия заголовков.

# Загрузка модуля (если требуется вручную)
# LoadModule proxy_protocol_module modules/mod_proxy_protocol.so

# VirtualHost, принимающий соединения с PROXY Protocol
<VirtualHost *:80>
    ProxyProtocol On
    # Теперь %a уже равен реальному клиентскому IP
    CustomLog logs/access_proxy.log "%a %l %u %t \"%r\" %>s %b"
</VirtualHost>

Если одновременно используется mod_remoteip для XFF, убедитесь, что порядок директив и допущения о доверенных источниках не конфликтуют. Для PROXY достаточно включить ProxyProtocol On на нужном VirtualHost.

Пример настроек Apache для XFF и PROXY Protocol

Балансировщик: примеры для включения заголовков и PROXY

Ниже — иллюстративные примеры конфигурации популярного подхода. Суть в том, что фронт либо добавляет X-Forwarded-For, либо шлёт PROXY Protocol к бэкенду.

# Пример: фронт добавляет XFF
# (синтаксис условный; включайте опцию forwardfor у вашего балансировщика)
option forwardfor header X-Forwarded-For ifnone

# Пример: фронт шлёт PROXY Protocol на бэкенд
# (для конкретных балансировщиков это опция уровня сервера: send-proxy / proxy-protocol)
server app1 10.0.0.10:80 send-proxy

Выбирайте один основной механизм для определения real IP между балансировщиком и веб‑серверами. В сложных цепочках можно использовать оба: PROXY для надёжности и XFF для трассировки всей цепочки.

Логи: что именно писать

Практика показывает, что лучше логировать одновременно:

  • Реальный IP (после восстановления) — для аналитики и безопасности.
  • Адрес последнего прокси — для диагностики сетевого контура.
  • Цепочку из XFF — для трассировки при сложных инцидентах.

Для nginx это может быть формат, показанный выше: realip, proxy и xff. Для Apache используйте %a (реальный после модулей), опционально — %h как исходный адрес соединения (адрес прокси), и %{X-Forwarded-For}i для заголовка.

Если вы ещё выбираете стек, посмотрите Nginx vs Apache: что выбрать в 2025, а для внедрения базовой защиты — руководство по security headers для Nginx и Apache.

Безопасность: типовые ошибки

  • Доверять всем подряд. Нельзя ставить set_real_ip_from 0.0.0.0/0 или аналог в Apache: любой клиент сможет подделать IP через XFF.
  • Забыть IPv6 диапазоны доверенных прокси, из‑за чего часть трафика будет считаться «недоверенной» и адрес не восстановится.
  • Смешивать PROXY и XFF без явной приоритизации. Если включили PROXY между балансировщиком и nginx, используйте real_ip_header proxy_protocol как источник правды.
  • Конфигурировать limit_req_zone в nginx до real_ip_header: зона схватит $binary_remote_addr от прокси. Сначала определяйте real_ip_header, затем объявляйте лимиты.
  • Доверять клиентским нестандартным заголовкам. Используйте стандартные XFF/Forwarded, переписанные вашим прокси, а не произвольные заголовки.

Проверка и отладка

Начните с локального запроса, подставив XFF, и проверьте логи.

curl -H "X-Forwarded-For: 203.0.113.50" http://example.test/

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

server {
    listen 8081;
    location = /debug-ip {
        default_type text/plain;
        return 200 "remote_addr=$remote_addr\nrealip=$realip_remote_addr\nxff=$http_x_forwarded_for\nproxyproto=$proxy_protocol_addr\n";
    }
}
Виртуальный хостинг FastFox
Виртуальный хостинг для сайтов
Универсальное решение для создания и размещения сайтов любой сложности в Интернете от 95₽ / мес

Если используете PROXY Protocol, проверьте, что фронт действительно его шлёт, а бэкенд слушает сокет с включённым режимом. Признак ошибки — 400/408 на старте соединения или «мусор» в начале запроса при попытке читать HTTP без парсинга PROXY.

Где ещё влияет real IP

  • Rate limiting и анти‑боты: лимиты должны учитывать реальный IP, иначе вы лимитируете балансировщик.
  • WAF/IDS: решения на уровне веб‑сервера или приложений должны видеть IP клиента для корректных правил.
  • GeoIP и персонализация: база геолокации должна получать $realip_remote_addr или эквивалент.
  • fail2ban и алерты: регулярки в фильтрах должны соответствовать новым форматам логов (реальный IP в отдельном поле).

XFF vs Forwarded: что выбрать

X-Forwarded-For поддерживается везде и прост. Forwarded стандартизован и лучше описывает IPv6/протокол/порт, но поддержка в парсерах менее единообразна. На практике используйте XFF как базу совместимости, а Forwarded — дополнительно при наличии.

Чек‑лист внедрения

  1. Определите границы доверия: список IP/подсетей ваших прокси и CDN.
  2. Выберите механизм: XFF или PROXY между балансировщиком и веб‑серверами.
  3. Настройте nginx/Apache на восстановление real IP (директивы выше).
  4. Обновите форматы логов: добавьте реальный IP, адрес прокси, XFF.
  5. Проверьте rate limiting, WAF, аналитики — чтобы они брали реальный IP.
  6. Покройте IPv6 и пересмотрите конфиг при изменении периметра.

Итого

Чтобы стабильно получать real IP за прокси и CDN, выбирайте один проверенный источник правды: транспортный PROXY Protocol либо правильно оформленный и переписываемый на фронте X-Forwarded-For. В nginx и Apache это решается несколькими директивами, но ключевые моменты — доверять только своим прокси, корректно логировать и учитывать real IP во всех механизмах безопасности и производительности. После внедрения вы получите чистые логи, предсказуемое поведение лимитов и корректную аналитику.

Поделиться статьей

Вам будет интересно

Let’s Encrypt wildcard через DNS-01: acme.sh, TSIG для BIND9 и сценарии с NSD без ручных правок OpenAI Статья написана AI (GPT 5)

Let’s Encrypt wildcard через DNS-01: acme.sh, TSIG для BIND9 и сценарии с NSD без ручных правок

Практическая настройка DNS-01 для wildcard-сертификатов Let’s Encrypt с acme.sh: создание TSIG-ключей, update-policy в BIND9, пров ...
SSH hardening на VDS: Fail2ban vs sshguard, Match blocks и безопасные политики доступа OpenAI Статья написана AI (GPT 5)

SSH hardening на VDS: Fail2ban vs sshguard, Match blocks и безопасные политики доступа

Пошагово укрепляем SSH на VDS без лишней паранойи: готовим аварийный откат, переводим вход на ключи, запрещаем root и пароли, огра ...
Nginx: try_files, index и приоритет location — как избежать 404 и ловушек rewrite OpenAI Статья написана AI (GPT 5)

Nginx: try_files, index и приоритет location — как избежать 404 и ловушек rewrite

Разбираем, как Nginx выбирает location и что реально проверяет try_files, когда срабатывает index и где чаще всего появляются 404. ...