Pull to refresh

Comments 48

Вот что случается, когда технари берутся решать юридические вопросы.
По порядку:
1) любой способ установить страну пользователя в протоколе http по встроенным в него механизмам — это неправильно. Используется это только как предположение возможной страны для удобства в вебинтерфейсах (предложить пользователю сразу нужный язык сайта).
2) использовать полученную таким образом региональную принадлежность для ограничения доступа — неправильно. Все можно подделать и на практике подделывают.
3) с самого начала нужно было разобраться вашему юристу в вопросе штрафов за факты показа контента в не тех регионах. Единственный способ работать по такой схеме — это указать в договоре что техническими средствами в сети интернет однозначно и безошибочно определить страну клиента невозможно, и все технические ограничения не являются 100% превентивными мерами. И нести финансовую ответственность за случаи нерегулированного показа контента разработчик не может.
Ваш посыл не в ту сторону, понятно что можно обмануть… и обманывают… и анонимные прокси используют в интернетах… но мыдолжны решать вопросы последней мили. вот об этом и идёт речь.
Мой посыл как раз в том что вы решаете этот вопрос кардинально неправильно, или вообще решать не должны, раз нет такой технической возможности.
Ага… объясните это правообладателям :)
Вероятно 100% в договорах есть сноска о мошенничестве и прочем и как вы сказали «и все технические ограничения не являются 100% превентивными мерами» НО они обязаны быть!

PS
Информационная безопасность не гарантирует неавторизованный доступ, а лишь усложняет его.
UFO landed and left these words here
эммм… обычные пользователи даже не знают что такое «прокси»?)
как же мы это запретим?
первый знак вопроса лишний.
UFO landed and left these words here
Не правда. А как же офисные работники, которых анально ограничивают «продвинутые» шефы, пуская интернет через локальный прокси? Или в общаге, или даже дома, если компов много, а интернет монополизирован верховным жильцом? По-моему, в мохнатых годах, это практиковалось даже у провайдеров! А может быть и по сей день практикуется в каких-нибудь деревнях, где интернет раздается на 3 компа.
Хочу держать всех в курсе и заявить: я всей душой ненавижу слово «разраб».
Субъективно. Я являясь таковым и не боюсь его. Просто отношусь к нему как к сокращению (админ, ОС, и тд)
Хорошая профессия, что вы так?
Не профессия. :) Именно слово «разраб». Не знаю почему, но коробит всякий раз, как слышу или вижу.

Есть в слове какое-то пренебрежение, что ли.

Как со словом «человечек». Вроде бы слово, как слово. А фигня какая-то. :)
У нас в конторе бытует еще прекрасное слово «прилага» (в смысле — приложение).
Тоже вздрагиваю на каждом совещании.
тыц phpfaq.ru/ip
Админ связку nginx+apache настроить не может нормально.
Собственно вот готовое решение
www.linux.org.ru/forum/admin/7441791

Должны совпадать IP в RPAFproxy_ips и в интерфейсах, которые слушает апач — тут лучше везде ставить строго 127...1
Если вам еще нужен X-Forwarded-For то просто в конфигах юзаются X-Real-IP или любой другой хедер

блин, у вас fpm
fastcgi_param SERVER_ADDR $server_addr;
и все, извращенци
Вы вообще прочитали статью? ссылка на «тыц» есть по тексту

Из решения:
> proxy_set_header X-Real-IP $remote_addr;
> proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

Не подходит для каскадного проксирования — посмотрите в модуль для nginx nginx.org/ru/docs/http/ngx_http_realip_module.html
Разумеется я не заметил что там nginx+fpm потому что в данной конфигурации вообще проблем с IP не возникает при стандартной настройке. И конечно nginx айпишник php — значит проксирование, значит наверное на апач, а потом уже как запостил посмотрел и понял что вы вообще там упоролись!

У вас nginx+php-fpm. Тогда извиняюсь — админ не может настроить nginx в дефолтной конфигурации, когда все работает.
Да, я там еще ошибся — не ту строку скопировал
fastcgi_param REMOTE_ADDR $remote_addr;
это вообще стандартная конфигурация nginx при настройке fast-cgi
лежит в /etc/nginx/fastcgi_params

То-есть вместо того чтобы прозрачно передать заголовок X-Forwarded-For, раз он им нужен чтобы прокси отсекать
fastcgi_param X-Forwarded-For $proxy_add_x_forwarded_for;

(http://nginx.org/ru/docs/http/ngx_http_proxy_module.html)
они тут городят фиг знает что.
Хотя вроде прокси разбирать не нужно — поэтому вопрос — почему не устроила самая стандартная конфигурация
fastcgi_pass unix:/tmp/php-fpm.socket; (или порт)
include fastcgi_params;

Блин, армянский комсомол!

Тут вообще нету каскадного проксирования — каскадное это если было бы два нгинкса или nginx + апач а тут обычный fastcgi которому хедеры не выставили.
> и понял что вы вообще там упоролись
Это да! :)

Но и вы не уловили суть… либо я не понял что вы пытаетесь донести в этом наборе буквослов.
Можно проверять ВСЕ ip адреса на принадлежность к региону за исключением локальных. Если хотя бы один из них из неугодного региона, то фильтровать.
И не будет никакой заморочки первый, последний ip в цепочке или какую там переменную использовать…
Откуда проверять? абстрактно написали :) тут же говорю религиозный бой и дьявол в мелочах!
Ну есть у вас куча разных переменных HTTP_X_REAL_IP, HTTP_CLIENT_IP, REMOTE_ADDR и HTTP_X_FORWARDED_FOR. Все эти адреса слить в один массив. Что в нём может быть? 1 — адрес самого сервера, 2 — адреса прокси серверов, 3 — фактический адрес клиента, 4 — необнаружаемая подделка адреса клиента.
Если задействован пункт 4, то тут эти средства бессильны и в принципе нужны другие средства защиты.
Адреса из пункта 1 вы знаете (по крайней мере админ), так что ставим на них условие при проходе через массив и игнорируем.
Остаются адреса проксей и реальный адрес. Ставим условие, что все они должны быть в заданном регионе.
PROFIT

Разве нет?
да если кто-то хочет обмануть — обманит.
Решение забавное но не элегантное.
Рассматриваем позитивный случай когда у нас там всё корректно.
Как быть со списком корректных доверенных каскадных прокси-серверов? среди них может быть прокся из «левого» региона… или несколько… или все.
Это какие например доверенные прокси?
Если их так много, то да, мой подход не подойдёт. Если же их на самом деле не много, то тоже можно составить список и поставить в игнор.

ЗЫ. И часто ли вы вместе употребляете слова PHP и «элегантно»?...
Можно, но вот появилась еще одна прокся… или у какой-то сменился адрес, и что? переписывать код? тут всё же важную роль играет правильно настроенные nginx и врядли хочется в коде держать переменные IP адреса.

ЗЫ. Дело не в PHP. На его месте в общем случае мог бы быть и другой язык. Хоть брейнфак :) Это не важно
Напишите плиз окончательную рабочую функцию?
> весна :) просто я скину конечно что получилось, но позже.
функция будет не хитрой, как я сказал, вся суть в симбиозе с nginx конфигой
Напишите, а то мы тут тоже боремся… :) Желательно не на пыхе, а на псевдокоде.
собственно в теле статьи.
Вот почему хорошо пользоваться готовыми решениями и знать, что и как они умеют.
Symfony Request
     const HEADER_CLIENT_IP = 'client_ip';
     protected static $trustedHeaders = array(
        self::HEADER_CLIENT_IP    => 'X_FORWARDED_FOR',
        self::HEADER_CLIENT_HOST  => 'X_FORWARDED_HOST',
        self::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO',
        self::HEADER_CLIENT_PORT  => 'X_FORWARDED_PORT',
    );
    public function getClientIp()
    {
        $ip = $this->server->get('REMOTE_ADDR');

        if (!self::$trustProxy) {
            return $ip;
        }

        if (!self::$trustedHeaders[self::HEADER_CLIENT_IP] || !$this->headers->has(self::$trustedHeaders[self::HEADER_CLIENT_IP])) {
            return $ip;
        }

        $clientIps = array_map('trim', explode(',', $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_IP])));
        $clientIps[] = $ip;

        $trustedProxies = self::$trustProxy && !self::$trustedProxies ? array($ip) : self::$trustedProxies;
        $clientIps = array_diff($clientIps, $trustedProxies);

        return array_pop($clientIps);
    }
вот… это уже хорошо, по моему первый проникшийся :) не знал о таком — спасибо.
свою реализацию дописываю!
PS: и симфони молодцы! не то что Yii из-за чего мы, как написал товарищ iborzenkov, «упоролись»:

public function getUserHostAddress()
{
return isset($_SERVER['REMOTE_ADDR'])?$_SERVER['REMOTE_ADDR']:'127.0.0.1';
}
Симфони то молодцы потому что им нужно работать на всех конфигурациях — а серваки админы могут и похлеще настраивать на шаред хостингах.
Но у вас то есть доступ к конфигам сервера и меня интересует как раз почему вы не использовали именно стандартную конфигурацию, которая вам подходит, и причем та-же симфони юзает
!in_array(@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', 'fe80::1', '::1'))
и кстати замечу работает стандартно

location ~ ^/(app|app_dev)\.php(/|$) {
fastcgi_pass unix:/home/ivan/php-fpm.socket;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

Зачем криво настроенный nginx чинить на стороне php если есть доступ к конфигам nginx и можно нормально передавать заголовок.
Вот именно поэтому я и написал выше то что написал.
В Symfony2 такое продуманное решение вовсе не из-за упоротых админов шаред хостингов, а из-за уймы ситуаций с проксями, балансерами и т.д.
Ваша конфигурация сломается об любую из них.

!in_array(@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', 'fe80::1', '::1'))
используется исключительно только в app_dev.php, которому не место на продакшне.
Разумеется проверка на 127.0.0.1 используется только в dev окружении.
Но это не повод настраивать сервак криво, а потом решать это на стороне php.
Сломается оно только на кривую конфигурацию, а не на любую, и правильно сделает что сломается.
Собственно тут все правильно уже сказали habrahabr.ru/post/177113/#comment_6152675
сломается всё — если постараться!
Но представьте две ситуации будто вы попадаете в аварию на Оке и на Феррари.
Чувствую что товарищи из феррари не смотря на кривизну дорог в россии делают машины так, чтобы вы выжили при любом раскладе,
а вот товарищи выпускающие Оку рассуждают как Вы — «плохие дороги? — неее… это не повод делать подвеску которая останется вне салона при наезде на кочку»

Каждому своё — я же не настаиваю на использовании этого рецепта, он может и отравить вас :)
Глупый спор.
Haproxy, Varnish, ELB, Cloudfront. Все это может и быть и не быть на 127.0.0.1, может быть и одно и не одно. етц.
Эта статья неграмотна от первого слова до последнего. Вместо того, чтобы гадать на кофейной гуще, и определять назначение HTTP-заголовков через анализатор трафика, надо читать спецификации и руководства. Вместо того, чтобы разобраться в проблеме, автор скопипастил код какого-то индуса, он у него сломался, и теперь автор предлагает всем так же бездумно скопипастить его код аналогичного качества.

> и весь этот код рухнул от того, что в HTTP_X_FORWARDED_FOR пришёл не один адрес, а список адресов через запятую (что строго говоря законно, допустимо, и даже не регламентировано в доке по php

Искать описание HTTP-заголовков в мануале по PHP? Автор, вы про HTTP и про то, как работает сервер, хотя бы в википедии почитайте что ли.

Ваши администраторы, впрочем, не намного лучше разработчиков, если они не могут нгинкс настроить или модуль к нему скомпилировать.

Насчет определения страны — естественно, заголовкам, пришедним снаружи, доверять нельзя, в них может быть что угодно. например, расширение для браузера може подставлять любой X-Http-Forwarded-For. Потому стоит их игнорировать. Однако, если наша цель — банить по IP, то брать IP из этих заголовков вполне можно.

Логично было бы собирать все IP (а не один) из всех заголовков и если хоть один относится к запрещенной стране — банить запрос. Таким образом, люди использующие неанонимные прокси, останутся без видео.

Рассмешили… да все мы индусы, всё ведь относительно и качество в том числе :)

> Однако, если наша цель — банить по IP, то брать IP из этих заголовков вполне можно.
Цель вы не поняли. Наша цель максимально точно определить IP без возможности фэйка в заголовках… а уж там банить или не банить — вопрос номер два.

> Логично было бы собирать все IP (а не один) из всех заголовков и если хоть один относится к запрещенной стране — банить запрос
Этот вариант как бы отсекли вот здесь habrahabr.ru/post/177113/#comment_6150229

> Искать описание HTTP-заголовков в мануале по PHP? Автор, вы про HTTP и про то, как работает сервер, хотя бы в википедии почитайте что ли.
Но часть из них то там описана… разве нет? однако сложно не согласиться — это стезя не php)

PS
Мне кажется критика подразумевает первичное принятия позиции а потом её разбор, а вы как то с места в карьер…
Спрашивается, почему не использовали стандартный geoip модуль nginx-а, зачем было на php всё городить вообще?
По той же причине, что и realip модуль — большинство пакетов в репозиториях не собраны с его поддержкой
Зачем использовать пакеты из дистрибутива, которые, как правило, устарели, содержат больше известных багов и уязвимостей, и, к тому же, не имеют, как вы написали, нужных модулей? Есть же на официальном сайте репозитории для Ubuntu, Debian, CentOS, RHEL, и даже для Debian ARM.

Я уж не упоминаю о том, что чтобы сделать свой кастомный пакет с нужным набором модулей, нужно потратить максимум минут 15, если раньше никогда не делал. Автор топика не захотел собрать нужный модуль и в сумме потратил, вероятно, на два порядка больше времени.

Проблема с пакетами — высосана из пальца.
ну он и используется… а как вы думаете он IP получает для представления в страну?
Дело не в пакетах и даже не в сборках… изучите www.php.net/geoip
а вы… про nginx nginx.org/ru/docs/http/ngx_http_geoip_module.html так это без разницы, но решили делать на php, поскольку там много нюансов переопределения IP (аля hosts) и прочего.
Но сути не меняет… там тоже вычисляется ip настройками nginx и x-forwaeded-for
И дабы не писать свой велосипед, нагуглил на stackoverflow
Примерно такой же код использовал когда-то PhpMyAdmin (пруф). Но как по мне, этот код просто ужасен. Поэтому я в свое время все-таки написал свой велосипед https://gist.github.com/AgelxNash/4943199.
Здесь ужасен не код, а подход.
Все эти кульбиты с НТТР заголовками имеют смысла чуть менее, чем нисколько.
Прочтите статью до конца.
Прочтите ссылку на phpfaq.ru, что дана выше.
Прочтите, наконец, статью в стиле «Скандалы, интриги, расследования», если простые объяснения не помогают: habrahabr.ru/post/158417/
Only those users with full accounts are able to leave comments. Log in, please.