Описание HTTP-заголовка в Википедии X-Forwarded-For
является:
X-Forwarded-For: client1, proxy1, proxy2, ...
Документация nginx для директивы real_ip_header
гласит, в частности:
Эта директива устанавливает имя заголовка, используемого для передачи замещающего IP-адреса.
В случае X-Forwarded-For этот модуль использует последний ip в заголовке X-Forwarded-For для замены. [Акцент мой]
Эти два описания кажутся противоречащими друг другу. В нашем сценарии X-Forwarded-For
заголовок точно такой, как описано - «реальный» IP-адрес клиента - это крайняя левая запись. Аналогичным образом поведение nginx заключается в использовании право-наибольшее значение - это, очевидно, всего лишь один из наших прокси-серверов.
Мое понимание X-Real-IP
это то, что это предполагаемый будет использоваться для определения актуальный IP-адрес клиента - не прокси. Я что-то упустил или это ошибка в nginx?
И, помимо этого, есть ли у кого-нибудь предложения, как сделать X-Real-IP
заголовок отображает осталось-наибольшее значение, как указано в определении X-Forwarded-For
?
Я считаю, что ключом к решению проблем X-Forwarded-For, когда несколько IP-адресов связаны цепочкой, является недавно представленная опция конфигурации, real_ip_recursive
(добавлено в nginx 1.2.1 и 1.3.0). Из nginx realip docs:
Если включен рекурсивный поиск, исходный адрес клиента, соответствующий одному из доверенных адресов, заменяется последним недоверенным адресом, отправленным в поле заголовка запроса.
По умолчанию nginx получал последний IP-адрес в цепочке, потому что это был единственный, которому доверяли. Но с новым real_ip_recursive
включен и с несколькими set_real_ip_from
параметры, вы можете определить несколько доверенных прокси, и он будет получать последний ненадежный IP-адрес.
Например, с этим конфигом:
set_real_ip_from 127.0.0.1;
set_real_ip_from 192.168.2.1;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
И заголовок X-Forwarded-For, в результате чего:
X-Forwarded-For: 123.123.123.123, 192.168.2.1, 127.0.0.1
nginx теперь выберет 123.123.123.123 в качестве IP-адреса клиента.
Что касается того, почему nginx не просто выбирает крайний левый IP-адрес и требует, чтобы вы явно определяли доверенные прокси, это необходимо для предотвращения простой подмены IP-адреса.
Допустим, настоящий IP-адрес клиента 123.123.123.123
. Предположим также, что у клиента нет ничего хорошего, и он пытается подменить свой IP-адрес, чтобы 11.11.11.11
. Они отправляют запрос на сервер с уже установленным заголовком:
X-Forwarded-For: 11.11.11.11
Поскольку обратные прокси-серверы просто добавляют IP-адреса в эту цепочку X-Forwarded-For, предположим, что она будет выглядеть так, когда к ней подойдет nginx:
X-Forwarded-For: 11.11.11.11, 123.123.123.123, 192.168.2.1, 127.0.0.1
Если вы просто захватите крайний левый адрес, это позволит клиенту легко подделать свой IP-адрес. Но в приведенном выше примере конфигурации nginx nginx будет доверять только двум последним адресам в качестве прокси. Это означает, что nginx правильно выберет 123.123.123.123
в качестве IP-адреса, несмотря на то, что этот поддельный IP-адрес фактически является крайним левым.
Разбор X-Forwarded-For
заголовок действительно ошибочен в модуле nginx real_ip.
len = r->headers_in.x_forwarded_for->value.len;
ip = r->headers_in.x_forwarded_for->value.data;
for (p = ip + len - 1; p > ip; p--) {
if (*p == ' ' || *p == ',') {
p++;
len -= p - ip;
ip = p;
break;
}
}
Он начинается в крайнем правом углу строки заголовка, и как только он видит пробел или запятую, он перестает искать и вставляет часть справа от пробела или запятой в переменной IP. Итак, это лечение самый последний прокси-адрес как оригинальный клиент адрес.
Согласно спецификации, это не очень хорошо; это опасность того, что это не будет изложено в до боли очевидных терминах в RFC.
В стороне: Трудно даже найти хороший первоисточник в формате, который изначально был определен Squid - покопайтесь в их документация подтверждает заказ; крайний левый - исходный клиент, крайний правый - самое последнее добавление. Мне очень хочется добавить [нужна цитата] на эту страницу в Википедии. Один анонимный править кажется авторитетом в Интернете по этому вопросу.
Если возможно, можете ли вы, чтобы ваши промежуточные прокси перестали добавлять себя в конец заголовка, просто оставляя его только с реальным адресом клиента?
X-Real-IP - это IP-адрес реального клиента, с которым разговаривает сервер («настоящий» клиент сервера), который в случае прокси-соединения является прокси-сервером. Вот почему X-Real-IP будет содержать последний IP-адрес в заголовке X-Forwarded-For.
Больше предупреждение, чем ответ ...
Я попытался добавить несколько кеш-серверов Nginx в нескольких местах карты, не осознавая, что мой основной сервер (источник данных) уже находится за кеш-сервером Nginx, который работает локально, иногда локальный сервер настроен для запуска Apache, а Nginx помещается перед ним в качестве кеша.
Добавление второго отдельного сервера кеширования Nginx приведет к созданию двух серверов кеширования, поэтому ваш HTTP_X_REAL_IP
или HTTP_X_FORWARDED_FOR
отображается неправильно, показывая IP одного, если серверы вместо IP посетителя.
В моем случае я исправил, что, установив новый сервер кеширования, он будет получать данные непосредственно из порта Apache (в моем случае порт 7080), минуя локальный кеш Nginx на исходном / основном сервере.
Другим решением было бы удалить HTTP_X_REAL_IP
на локальном кеш-сервере.
Кстати, я запускал панель Plesk.