Я запускаю проверки безопасности по нескольким вызовам AJAX, чтобы узнать, запрашивает ли тот же IP-адрес, что у меня есть на записи.
Я использовал следующий набор функций класса, чтобы установить IP (который может поступать через балансировщики нагрузки, отсюда и длительная методология.
private function IPMask_Match ($network, $ip) { $ip_arr = explode('/', $network); if (count($ip_arr) < 2) { $ip_arr = array($ip_arr[0], null); } $network_long = ip2long($ip_arr[0]); $x = ip2long($ip_arr[1]); $mask = long2ip($x) == $ip_arr[1] ? $x : 0xffffffff << (32 - $ip_arr[1]); $ip_long = ip2long($ip); return ($ip_long & $mask) == ($network_long & $mask); } private function IPCheck_RFC1918 ($IP) { $PrivateIP = false; if (!$PrivateIP) { $PrivateIP = $this->IPMask_Match('127.0.0.0/8', $IP); } if (!$PrivateIP) { $PrivateIP = $this->IPMask_Match('10.0.0.0/8', $IP); } if (!$PrivateIP) { $PrivateIP = $this->IPMask_Match('172.16.0.0/12', $IP); } if (!$PrivateIP) { $PrivateIP = $this->IPMask_Match('192.168.0.0/16', $IP); } return $PrivateIP; } public function getIP () { $UsesProxy = (!empty($_SERVER['HTTP_X_FORWARDED_FOR']) || !empty($_SERVER['HTTP_CLIENT_IP'])) ? true : false; if ($UsesProxy && !empty($_SERVER['HTTP_CLIENT_IP'])) { $UserIP = $_SERVER['HTTP_CLIENT_IP']; } elseif ($UsesProxy && !empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $UserIP = $_SERVER['HTTP_X_FORWARDED_FOR']; if (strstr($UserIP, ',')) { $UserIPArray = explode(',', $UserIP); foreach ($UserIPArray as $IPtoCheck) { if (!$this->IPCheck_RFC1918($IPtoCheck)) { $UserIP = $IPtoCheck; break; } } if ($UserIP == $_SERVER['HTTP_X_FORWARDED_FOR']) { $UserIP = $_SERVER['REMOTE_ADDR']; } } } else{ $UserIP = $_SERVER['REMOTE_ADDR']; } return $UserIP; }
Проблема в том, что у меня возникают проблемы с пользователями, работающими через прокси. Может ли кто-нибудь указать, почему это может быть? Я использовал базовый бесплатный прокси в Интернете, чтобы попробовать и эмулировать, но он не выглядит, как получить переменные IP-адреса или что-то еще, поэтому я не уверен, почему это говорит о том, что два IP-адреса не совпадают.
Я собираюсь объяснить, что такое прокси-сервер, поэтому мы оба на одной странице.
Что такое прокси
Прокси-сервер обычно представляет собой один компьютер, который обращается к Интернету ОТ ИМЕНИ пользователя, а затем прокси отправляет результаты обратно пользователю. Проблема возникает, когда могут быть сотни или даже тысячи других людей, также использующих этот один компьютер, – и все они имеют ИДЕННЫЙ IP-адрес, но обычно заголовки указывают, что пользователи через прокси.
Ваш сценарий, который я предполагаю (без должного внимания), переводит IP-адреса и заголовки.
Различное решение
Существует лучший способ. Используйте сеансы и сохраните ключ в сеансе, гарантируя, что они ранее были на основном сайте сначала ПЕРЕД доступом к странице ajax. Пример:
index.php
session_start(); $_SESSION['ajax_ok'] = true;
Аякс / username_check.php
session_start(); if (empty($_SESSION['ajax_ok'])) { die("You can not access this page..."); }
Это обеспечит, чтобы они сначала посетили ваш основной сайт, и клиент также должен поддерживать сеансы, которые большинство браузеров будут представлять собой плюс, чтобы предотвратить запрет и т. Д. Злоупотреблять вашими сценариями ajax.
Более надежное и простое решение, чем использование этого маневра кода, который вы получили выше> <
Что делать, если вы не можете использовать сеансы?
Если вы не можете использовать сеансы на определенном компьютере, на котором вы находитесь, вы можете настроить другой компьютер, переписать обработчик сеанса (используя обратные вызовы, которые предоставляет php) или вместо использования файловой системы использовать что-то другое, например, базу данных для сеансов ? Там должно быть что-то, что ваш сайт использует, что сессии могут также использовать. Например, если у вас есть сеансы, основанные на балансировке нагрузки, обычно вообще не работают, поэтому обычно рекомендуется менять сеансы, чтобы использовать что-то еще, как я упоминал выше.
Проблема, к сожалению, почти наверняка не является прокси-сервером – это почти наверняка стационарный публичный IP-маршрутизатор, маршрутизирующий трафик через подсеть.
А подсети могут быть ОГРОМНЫМИ (скажем, в университетах).
И даже если бы какая-то случайность была подлинным прокси (в наши дни это редкость – 10-летняя технология), даже если прокси добровольно отправляется на пересылку, это ничего не значит, потому что это почти наверняка такой подсети ip, как 192.168. xx в любом случае .. Это, в основном, внутренний IP-адрес публичного IP-адреса (aka switchboard).
Вы можете пересечь свои пальцы и попробовать php ipv6 Работа с IPv6-адресами в PHP или даже еще более умный и попробовать mac-адрес. Как я могу получить MAC-адрес и IP-адрес подключенного клиента в PHP? но оба обречены на провал. Мой интуитивный инстинкт – попытаться обмануть: я бы сыграл в азартные игры, что лучший способ – это в основном использовать сетевой ресурс для хранилища сеансов и позволить сбалансированным нагрузкам серверам PHP всем обращаться к нему и делать все через один и тот же префикс DNS. Или, возможно, создать сторонний dns для проведения сессионного сбора.
Ответ заключается в том, что если вы не отслеживаете «куки», как в своем рекламном агентстве, вы не можете этого сделать.
Друг идентифицировал это, в основном, некоторые прокси могут возвращаться с X_FORWARDED_FOR как значение, разделенное запятой, или как разделенная запятая и разнесенная.
Исправить:-
после:
foreach ($UserIPArray as $IPtoCheck) {
добавьте эту строку:
$IPtoCheck = trim($IPtoCheck);
Критерий сортировки.
Проблема в том, что у меня возникают проблемы с пользователями, работающими через прокси. Может ли кто-нибудь указать, почему это может быть? Я использовал базовый бесплатный прокси в Интернете, чтобы попробовать и эмулировать, но он не выглядит, как получить переменные IP-адреса или что-то еще, поэтому я не уверен, почему это говорит о том, что два IP-адреса не совпадают.
Ваш синтаксический код взрывает HTTP_X_FORWARDED_FOR
в запятой, но разделитель может быть «запятой». Если это произойдет, проверка RFC 1918 завершится неудачно. Хотя некоторые прокси не добавляют места, стандарт должен использовать его:
http://en.wikipedia.org/wiki/X-Forwarded-For
Общий формат поля:
X-Forwarded-For: client, proxy1, proxy2
где значение представляет собой разделенный запятыми + пробел список IP-адресов, самый левый, являющийся исходным клиентом, и каждый последующий прокси-сервер, который передал запрос, добавляя IP-адрес, откуда он получил запрос. В этом примере запрос передал proxy1, proxy2 и proxy3 (proxy3 отображается как удаленный адрес запроса).
Поэтому вы должны изменить разделитель разрыва на «,» или лучше, используйте preg_split
с «, \ s *» в качестве разделителя и обведите оба случая.
Тогда ваша проблема заключается в аутентификации страницы, выполняющей вызов в AJAX, самому вызову AJAX.
Если вы не хотите использовать сеансы на основе файлов cookie, это лучший способ, вы можете попробовать и сделать это с помощью nonce . То есть, когда вы создаете страницу, вы выдаете уникальный идентификатор и вводите его в код HTML, где код AJAX будет восстанавливать его и передавать обратно на сервлет AJAX. Последний сможет добавить его в Access-Control-Request, как описано здесь , или просто добавить дополнительные данные в запрос.
Я хотел бы обсудить, делает ли ваше решение что-либо от имени безопасности.
$ _SERVER ['REMOTE_ADDR'] нельзя подделать. Он устанавливается веб-сервером из-за доступа к используемому IP-адресу. Любой ответ идет по этому адресу.
$ _SERVER ['HTTP_FORWARDED_FOR'] и $ _SERVER ['HTTP_CLIENT_IP'] могут быть легко подделаны, поскольку они являются HTTP-заголовками, отправленными на веб-сервер, и вы не знаете, что разговариваете с прокси-сервером, если он настроен на пропуски этих заголовков, знаете ли вы, что НЕ разговариваете с прокси-сервером, если клиент решает вставить эти заголовки.
Фильтрация, основанная на IP-адресе FORGED, на самом деле вам не поможет, но это очень зависит от того, что вы хотите достичь, – которое остается неизвестным до тех пор, пока вы не перейдете к нему более подробно.
Если вы посмотрите вокруг, вы наткнетесь на исправление и расширение Suhosin для PHP, и это функция для шифрования содержимого сеанса и файлов cookie. Ключ шифрования создается с использованием некоторого статического ключа, но добавляет такие вещи, как HTTP User Agent или части запрашивающего IP-адреса. Примечание: IP-адрес, используемый для фактического выполнения запроса, то есть прокси-сервера, если он используется, поскольку это только надежная информация.
Можно утверждать, что использование полного IP-адреса – не очень хорошая идея, если вы не знаете, что ваши пользователи не используют кластеры-прокси с изменяющимися IP-адресами для нескольких запросов, поэтому обычно используется только часть IP-адреса или вообще отсутствует.
Пользователь HTTP-агента, хотя и является хорошим источником уникальной информации. Да, это может быть подделано, но это не имеет никакого значения, потому что, если вы хотите только разрешить запросы из одного источника, допустимо предположить, что строка пользовательского агента не изменяется со временем, но будет отличаться для куча других пользователей. Следовательно, есть статистика, которая показывает, что вы можете создать почти уникальный отпечаток браузера, если вы просто посмотрите на все отправленные HTTP-заголовки, потому что каждый пользователь устанавливает разные расширения, которые что-то меняют, например заголовки accept-content.
Я не могу предоставить рабочий код, а также не могу сказать из вашего вопроса, применим ли какой-либо из этих ответов, но я бы предложил не использовать информацию IP, особенно если ее можно подделать. Это еще более актуально, если вы думаете о IPv6, где каждый клиент имеет несколько активных адресов даже на одном и том же интерфейсе, и все они генерируются случайным образом и вряд ли когда-либо снова появятся позже. (Конечно, это не применимо, если вы никогда не будете размещать IPv6, но в какой-то момент вы будете не в том случае.)