Modify

Ticket #23 (new enhancement)

Opened 5 months ago

Last modified 5 months ago

Поддержка HTTP заголовка X-Forwarded-For

Reported by: seroy Owned by:
Priority: major Component: general
Version: Keywords: force_show_code
Cc:

Description

Реализация поддержки HTTP заголовка X-Forwarded-For. Необходимо для правильного определения IP бота в случаях когда веб-сервер стоит за прокси (mod_proxy, nginx, и т.д.), как альтернатива к force_show_code=true.
Писалось (и тестировалось) под использование совместно с Django, при использовании с другими фреймворками возможно необходимо допиливать передачу объекту PageRequest? в параметре meta элемента с ключем HTTP_X_FORWARDED_FOR.

Attachments

http_x_forwarded_for_support.patch Download (762 bytes) - added by seroy 5 months ago.
http_x_forwarded_for_support.2.patch Download (767 bytes) - added by seroy 5 months ago.
исправлен косяк при meta=None

Change History

Changed 5 months ago by seroy

Changed 5 months ago by seroy

исправлен косяк при meta=None

comment:1 Changed 5 months ago by lostclus

Опять таки, добавленная фича не поддается контролю. А что если заголовок HTTP_X_FORWARDED_FOR присутствует, но его значение не верно, а вместо него нужно использовать значение из какого нибудь другого заголовка? Или нужно игнорировать HTTP_X_FORWARDED_FOR, и использовать обычный HTTP_REMOTE_ADDR. Я считаю лучше сделать параметр конфигурации, типа look_remote_addr_in_header, который будет задавать заголовок, или список заголовков в которых нужно искать IP-адрес, который в последствии будет присвоен атрибуту remote_addr. И чтоб не дублировать код такого выбора полей, может его вывести в класс PageRequest?

comment:2 follow-up: ↓ 3 Changed 5 months ago by seroy

Ну лично я считаю, что это уже некоторый перебор и перфекционизм, а лучшее оно, как известно враг хорошего. Что значит значение не в поле не верно? Во первых это значит, что он сам себе злой Буратино (и не умеет сервер нормально настраивать :) ), а во вторых код там достаточно простой (а как следствие надежный), ну даже если будет только один IP (у меня кстати так), а не список client1, proxy1, proxy2 ничего страшного не случится. Про нужно игнорировать: обычно такой заголовок на пустом месте не возникает, опять таки по моему надумано. Про другие заголовки: x-forwarded-for это уже сейчас стандарт де-факто, а в последствии скорее всего будет стандартный заголовок  http://tools.ietf.org/html/draft-petersson-forwarded-for-02, кроме того в других заголовках не понятно какой может быть формат.
По моему это как раз тот случай когда "20% усилий дают 80% результата". Необходимо только толково написать в документации этот момент, чтобы было понятно как оно работает. А если вдруг у кого что то не так, а по другому - код открытый, всегда можно поправить.

НО, Вы безусловно автор и вольны делать так как считаете нужным. Я всего лишь привел контраргументы (не могу же я с вами взять и просто согласится)))). Можно пока оставить так, а если будет потребность подтвержденная практикой внедрения, то сделать более гибкое решение. В любом случае выбор за Вами.

comment:3 in reply to: ↑ 2 ; follow-up: ↓ 4 Changed 5 months ago by lostclus

Replying to seroy:

По моему это как раз тот случай когда "20% усилий дают 80% результата". Необходимо только толково написать в документации этот момент, чтобы было понятно как оно работает. А если вдруг у кого что то не так, а по другому - код открытый, всегда можно поправить.

По крайней мере должна быть стандартная возможность отключать использование X-Forwarded-For.

Еще я считаю, что всегда брать первый адрес не совсем правильно, так как это будет означать, что нужно "пропустить" все прокси сервера, и получить адрес самой первой машины, которая отправила запрос. Но возможность использования X-Forwarded-For была добавлена исходя из того, что само веб-приложение развернуто через прокси сервер, т.е. нам точно известно, что последний один адрес (или несколько адресов, например какой-то вид балансировки нагрузки) в заголовке это адрес нашего прокси-сервера. И мы не можем отвечать за все остальные прокси сервера, которые использовались для доступа к нашему ресурсу. Поэтому считаю, что правильнее будет дать возможность задавать число, которые будет означать сколько адресов нужно пропустить с конца списка, чтобы получить нужный адрес. В обычной конфигурации, когда используется обратный прокси, это число 1.

comment:4 in reply to: ↑ 3 Changed 5 months ago by lostclus

т.е. нам точно известно, что последний один адрес (или несколько адресов, например какой-то вид балансировки нагрузки) в заголовке это адрес нашего прокси-сервера. И мы не можем отвечать за все остальные прокси сервера, которые использовались для доступа к нашему ресурсу. Поэтому считаю, что правильнее будет дать возможность задавать число, которые будет означать сколько адресов нужно пропустить с конца списка, чтобы получить нужный адрес. В обычной конфигурации, когда используется обратный прокси, это число 1.

Небольшая поправка: последний адрес, это не адрес последнего прокси, а адрес машины "перед ним". Тогда, если сайт развернут с использованием одного обратного прокси, то нужно пропускать 0 адресов с конца, т.е. брать последний адрес, а если используется два обратных прокси, то тогда нужно пропустить 1 адрес.

comment:5 follow-up: ↓ 6 Changed 5 months ago by seroy <seroy@…>

Брать всегда первый адрес правильно (подробнее  http://en.wikipedia.org/wiki/X-Forwarded-For). Нас интересует адрес клиента, а не адреса возможных прокси, адрес клиента это первый адрес (слева). При прохождении запроса через прокси адрес сервера добавляется в конец через запятую.

comment:6 in reply to: ↑ 5 ; follow-up: ↓ 7 Changed 5 months ago by lostclus

Replying to seroy <seroy@…>:

Брать всегда первый адрес правильно (подробнее  http://en.wikipedia.org/wiki/X-Forwarded-For). Нас интересует адрес клиента, а не адреса возможных прокси, адрес клиента это первый адрес (слева). При прохождении запроса через прокси адрес сервера добавляется в конец через запятую.

Объясните пожалуйста почему нас интересует адрес клиента? Например, я захожу в интернет через прокси со своей рабочей машины 192.168.0.3, которая расположена за маршрутизатором, на котором работает Squid с настройками по умолчанию. Тогда в заголовке X-Forwarded-For первым будет адрес 192.168.0.3, а не реальный адрес маршрутизатора. И зачем нам серый адрес 192.168.0.3? Почему адрес, который должен видеть LinkExchange где-то на сервере должен зависит от топологии моей домашней сети, из которой я захожу на этот сервер?

А теперь допустим, что сапа перевела свои рабочие сервера за такой вот маршрутизатор, и решила использовать прокси. Код на PHP будет продолжать работать корректно, потому что он использует HTTP_REMOTE_ADDR, в котором указан адрес прокси, а не какой-то серый адрес клиента, от которого пользы нет никакой.

comment:7 in reply to: ↑ 6 Changed 5 months ago by seroy <seroy@…>

Пожалуй соглашусь с Вами, для LinkExchange? брать последний адрес до обратного прокси все таки более правильно.

View

Add a comment

Modify Ticket

Change Properties
<Author field>
Action
as new
as The resolution will be set. Next status will be 'closed'
to The owner will be changed from (none). Next status will be 'assigned'
The owner will be changed from (none) to anonymous. Next status will be 'accepted'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.