HTTP-заголовки X-Forwarded-For, Via и другие прокси-заголовки передают информацию о клиентском IP-адресе, цепочке прокси-серверов и деталях запроса через промежуточные узлы, позволяя конечному серверу и клиентским приложениям корректно обрабатывать запросы, прошедшие через прокси.
X-Forwarded-For (XFF)
Заголовок X-Forwarded-For (XFF) — это де-факто стандартный заголовок HTTP, используемый для идентификации исходного IP-адреса клиента, подключившегося к веб-серверу через HTTP-прокси или балансировщик нагрузки. Без этого заголовка сервер видит только IP-адрес прокси-сервера, что затрудняет логирование, аналитику и принятие решений на основе географического положения или черных списков.
Формат XFF
Заголовок X-Forwarded-For может содержать один или несколько IP-адресов, разделённых запятыми.
X-Forwarded-For: <client-ip>, <proxy1-ip>, <proxy2-ip>
Где:
* <client-ip>: IP-адрес исходного клиента.
* <proxy1-ip>: IP-адрес первого прокси-сервера, через который прошёл запрос.
* <proxy2-ip>: IP-адрес второго прокси-сервера, и так далее.
Прокси-серверы добавляют IP-адрес клиента (если он есть в заголовке) и свой собственный IP-адрес к заголовку при пересылке запроса. Если запрос проходит через несколько прокси, каждый из них добавляет свой IP-адрес в конец списка.
Пример XFF
- Клиент с IP
192.0.2.42отправляет запрос к Прокси А. - Прокси А (IP
192.168.1.1) пересылает запрос к Прокси Б. Прокси А добавляетX-Forwarded-For: 192.0.2.42. - Прокси Б (IP
10.0.0.5) пересылает запрос к конечному веб-серверу. Прокси Б добавляет свой IP к существующему заголовку.
Конечный веб-сервер получит:
X-Forwarded-For: 192.0.2.42, 192.168.1.1, 10.0.0.5
Исходный IP-адрес клиента — это первый IP в списке (192.0.2.42).
Вопросы безопасности XFF
Первый IP-адрес в заголовке X-Forwarded-For может быть подделан клиентом. Клиент может отправить запрос, самостоятельно добавив заголовок X-Forwarded-For: 8.8.8.8 (или любой другой IP-адрес). Доверенные прокси-серверы должны быть настроены на перезапись или игнорирование входящего X-Forwarded-For от недоверенных источников и добавление IP-адреса, с которого пришёл запрос.
Для корректной работы сервер-приемник должен доверять только последнему прокси-серверу в цепочке (или всем прокси в доверенной сети), чтобы получить достоверный список IP-адресов.
Via
Заголовок Via используется прокси-серверами для указания промежуточных протоколов и получателей, через которые запрос или ответ был передан. Он предоставляет информацию о пути, который прошёл запрос, и версиях протоколов, использованных на каждом шаге.
Формат Via
Каждый прокси-сервер, который обрабатывает запрос, добавляет свою информацию в заголовок Via. Прокси-серверы добавляют (prepend) свою запись в начало списка Via.
Via: <protocol-name>/<protocol-version> <host>:<port> (<comment>), <protocol-name>/<protocol-version> <host>:<port> (<comment>)
Где:
* <protocol-name>: Имя протокола (например, HTTP).
* <protocol-version>: Версия протокола (например, 1.1).
* <host>:<port>: Имя хоста и порт прокси-сервера.
* <comment>: Необязательный комментарий, часто содержащий информацию о программном обеспечении прокси (например, (Squid/3.1)).
Пример Via
- Клиент отправляет запрос.
- Прокси А (HTTP/1.1,
proxyA.example.com, Squid) получает запрос и пересылает его. Он добавляетVia: 1.1 proxyA.example.com (Squid). - Прокси Б (HTTP/1.0,
proxyB.example.com, Privoxy) получает запрос от Прокси А и пересылает его. Он добавляет свою запись в начало.
Конечный веб-сервер получит:
Via: 1.0 proxyB.example.com (Privoxy), 1.1 proxyA.example.com (Squid)
Заголовок Via полезен для отладки, обнаружения петель маршрутизации и определения, через какие прокси прошёл запрос.
Forwarded
Заголовок Forwarded является стандартизированной заменой для группы нестандартных заголовков X-Forwarded-* (включая X-Forwarded-For, X-Forwarded-Host, X-Forwarded-Proto). Он определён в RFC 7239 и предоставляет более унифицированный и структурированный способ передачи информации о прокси-цепочке.
Формат Forwarded
Заголовок Forwarded может содержать несколько параметров, каждый из которых представляет собой пару ключ-значение.
Forwarded: for=<identifier>;proto=<http|https>;host=<original-host>;by=<proxy-identifier>
Где:
* for: Идентификатор клиента, который инициировал запрос. Может быть IP-адресом, IP-адресом в квадратных скобках для IPv6, или анонимным идентификатором unknown.
* proto: Исходный протокол, используемый клиентом (например, http или https).
* host: Исходное значение заголовка Host из запроса клиента.
* by: Идентификатор прокси-сервера, который добавил этот элемент в заголовок.
Каждый прокси-сервер добавляет свою запись, разделяя их запятыми.
Пример Forwarded
- Клиент с IP
192.0.2.42отправляет HTTPS-запрос кwww.example.com. - Прокси А (IP
192.168.1.1) получает запрос, терминирует SSL и пересылает его по HTTP. - Прокси Б (IP
10.0.0.5) получает запрос и пересылает его.
Конечный веб-сервер получит:
Forwarded: for=192.0.2.42;proto=https;host=www.example.com, for=192.168.1.1;proto=http;by=192.168.1.1, for=10.0.0.5;by=10.0.0.5
В этом примере:
* Первый for (192.0.2.42) указывает исходный IP клиента.
* Первый proto (https) указывает исходный протокол клиента.
* Первый host (www.example.com) указывает исходный хост клиента.
* by указывает IP-адрес прокси, добавившего запись.
Преимущества Forwarded
- Стандартизация: Определён в RFC, что способствует унификации реализации.
- Комплексность: Объединяет информацию, которая ранее распределялась по нескольким
X-Forwarded-*заголовкам. - Ясность: Явно разделяет IP клиента (
for) и IP прокси (by), а также протокол и хост.
Другие прокси-заголовки
X-Real-IP
Заголовок X-Real-IP — это нестандартный заголовок, часто используемый в конфигурациях с Nginx. Он предназначен для хранения IP-адреса клиента, который отправил запрос. В отличие от X-Forwarded-For, который может содержать цепочку IP-адресов, X-Real-IP обычно содержит только один IP-адрес, который считается "реальным" IP-адресом клиента.
Этот заголовок часто устанавливается первым прокси-сервером или балансировщиком нагрузки в цепочке, который доверяет входящему соединению, и может быть получен либо из X-Forwarded-For (первый IP), либо из IP-адреса непосредственно подключенного клиента.
X-Real-IP: 192.0.2.42
X-Forwarded-Proto
Заголовок X-Forwarded-Proto указывает протокол (HTTP или HTTPS), который клиент использовал для подключения к прокси-серверу или балансировщику нагрузки. Это особенно важно, когда прокси выполняет SSL-терминацию. Конечный веб-сервер может получить запрос по HTTP от прокси, но исходный запрос клиента был по HTTPS.
X-Forwarded-Proto: https
Серверное приложение может использовать этот заголовок для генерации ссылок с правильным протоколом или для принудительного редиректа на HTTPS.
X-Forwarded-Host и X-Forwarded-Port
X-Forwarded-Host: Указывает исходное значение заголовкаHostиз запроса клиента. Это полезно, когда прокси изменяет заголовокHostпри пересылке запроса (например, для внутренней маршрутизации).
X-Forwarded-Host: www.example.comX-Forwarded-Port: Указывает исходный порт, который клиент использовал для подключения. Это актуально, если прокси пересылает запрос на другой порт.
X-Forwarded-Port: 443
Proxy-Authenticate и Proxy-Authorization
Эти заголовки связаны с аутентификацией на прокси-сервере.
* Proxy-Authenticate: Отправляется прокси-сервером клиенту в ответ на запрос (обычно с кодом статуса 407 Proxy Authentication Required), чтобы запросить аутентификационные данные.
Proxy-Authenticate: Basic realm="Proxy Protected Area"
* Proxy-Authorization: Отправляется клиентом прокси-серверу, содержащий учетные данные для аутентификации на прокси.
Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Warning
Заголовок Warning используется для передачи дополнительной информации о статусе или возможных проблемах при обработке запроса или ответа. Он может быть добавлен прокси-серверами или кэширующими серверами.
Warning: 110 fred "Response is stale"
Формат: <warn-code> <warn-agent> "<warn-text>" [<warn-date>]
* warn-code: Трехзначный числовой код предупреждения.
* warn-agent: Имя или псевдоним сервера, который добавил предупреждение.
* warn-text: Текст предупреждения.
* warn-date: Необязательная дата и время (в формате HTTP-даты).
Типичные коды предупреждений:
* 110 Response is stale: Кэшированный ответ устарел.
* 111 Revalidation failed: Проверка кэшированного ответа не удалась.
* 112 Disconnected operation: Кэшированный ответ был предоставлен, пока прокси был отключен от сети.
Практическое применение и конфигурация
Использование в веб-серверах
Веб-серверы и приложения должны быть настроены для корректной обработки прокси-заголовков, особенно X-Forwarded-For или Forwarded, для получения реального IP-адреса клиента.
Nginx
В Nginx используются директивы real_ip_header и set_real_ip_from для настройки определения реального IP-адреса.
http {
# Определяем доверенные прокси-серверы
set_real_ip_from 192.168.1.0/24; # Локальная сеть прокси
set_real_ip_from 10.0.0.0/8; # Другая внутренняя сеть
set_real_ip_from 203.0.113.42; # Конкретный IP прокси
# Указываем, какой заголовок содержит IP клиента
real_ip_header X-Forwarded-For;
# Если установлен real_ip_recursive on, Nginx будет удалять IP-адреса из
# X-Forwarded-For, которые соответствуют set_real_ip_from,
# пока не найдёт первый недоверенный IP (который считается клиентом).
real_ip_recursive on;
server {
listen 80;
server_name example.com;
location / {
# Теперь $remote_addr будет содержать реальный IP клиента
# или IP последнего недоверенного прокси.
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
В этом примере X-Real-IP будет установлен в remote_addr после обработки X-Forwarded-For и set_real_ip_from. Переменная $proxy_add_x_forwarded_for автоматически добавляет IP-адрес текущего прокси к существующему X-Forwarded-For.
Apache
В Apache 2.4+ для обработки X-Forwarded-For используется модуль mod_remoteip.
# Активация модуля mod_remoteip
LoadModule remoteip_module modules/mod_remoteip.so
# Указываем заголовок, содержащий IP клиента
RemoteIPHeader X-Forwarded-For
# Определяем доверенные прокси-серверы
RemoteIPInternalProxy 192.168.1.0/24
RemoteIPInternalProxy 10.0.0.0/8
RemoteIPInternalProxy 203.0.113.42
# Если используется RemoteIPTrustedProxyList, то RemoteIPInternalProxy не нужен.
# RemoteIPTrustedProxyList trusted-proxies.txt
# Теперь %a в логах будет отображать реальный IP клиента
LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
После настройки mod_remoteip, переменная REMOTE_ADDR в скриптах и %a в логах Apache будут содержать реальный IP-адрес клиента.
Влияние на логирование и аналитику
Корректная обработка прокси-заголовков критична для:
* Точного логирования: Запись реальных IP-адресов клиентов в журналы доступа.
* Геолокации: Определение местоположения пользователей.
* Безопасности: Идентификация источников атак, блокировка вредоносных IP-адресов.
* Аналитики: Понимание поведения пользователей, источников трафика.
Без этих заголовков логи и аналитика будут показывать только IP-адреса прокси-серверов, что искажает данные.
Вопросы безопасности и доверия
- Доверенные прокси: Принимать информацию из
X-Forwarded-ForилиForwardedследует только от доверенных прокси-серверов. Это означает, что конечный сервер должен знать IP-адреса или диапазоны IP-адресов своих собственных прокси и балансировщиков нагрузки. - Приоритет заголовков: Если присутствуют как
X-Forwarded-For, так иForwarded, предпочтение следует отдавать стандартизированномуForwarded. Однако на практике часто приходится обрабатывать оба, учитывая их распространённость. - Фильтрация и валидация: Приложения должны валидировать IP-адреса, полученные из прокси-заголовков, чтобы предотвратить инъекции или другие атаки.
Сравнение заголовков
| Заголовок | Назначение | Стандарт (RFC) | Модификация прокси | Замечания по безопасности |
|---|---|---|---|---|
X-Forwarded-For |
Исходный IP-адрес клиента | Нет (де-факто) | Каждый прокси добавляет свой IP в конец списка | Первый IP может быть подделан клиентом. Доверять только последнему доверенному IP в цепочке. |
Forwarded |
Исходный IP клиента, протокол, хост, IP прокси | Да (RFC 7239) | Каждый прокси добавляет свою запись в конец списка | Параметр for может быть подделан. Более детализирован, чем XFF. |
Via |
Цепочка прокси, версии протоколов, ПО | Да (RFC 7230) | Каждый прокси добавляет свою запись в начало списка | Используется для трассировки пути запроса. |
X-Real-IP |
"Реальный" IP-адрес клиента | Нет | Обычно устанавливается первым доверенным прокси | Часто используется Nginx. Может быть основан на XFF, подвержен тем же рискам. |
X-Forwarded-Proto |
Исходный протокол клиента (HTTP/HTTPS) | Нет | Устанавливается прокси, выполняющим SSL-терминацию | Помогает приложениям генерировать корректные URL. |
X-Forwarded-Host |
Исходный заголовок Host клиента | Нет | Устанавливается прокси, изменяющим Host | Предотвращает проблемы с маршрутизацией при изменении Host прокси. |
X-Forwarded-Port |
Исходный порт клиента | Нет | Устанавливается прокси, изменяющим порт | Обеспечивает корректное определение порта приложениями. |