Рубрики
Uncategorized

PHP Получает реальный IP-адрес пользователя и пример кода механизма защиты от кисти

Автор оригинала: David Wong.

I. Как добраться IP-адрес пользователя Адрес

 public static function getClientIp()
 {
 if (getenv('HTTP_CLIENT_IP')) {
  $ip = getenv('HTTP_CLIENT_IP');
 }
 if (getenv('HTTP_X_REAL_IP')) {
  $ip = getenv('HTTP_X_REAL_IP');
 } elseif (getenv('HTTP_X_FORWARDED_FOR')) {
  $ip = getenv('HTTP_X_FORWARDED_FOR');
  $ips = explode(',', $ip);
  $ip = $ips[0];
 } elseif (getenv('REMOTE_ADDR')) {
  $ip = getenv('REMOTE_ADDR');
 } else {
  $ip = '0.0.0.0';
 }

 return $ip;
 }

Будьте осторожны:

Разница между $_SERVER и getenv заключается в том, что getenv не поддерживает PHP, работающий в режиме ISAPI, функция IIS Getenv (“REMOTE_ADDR”) может обычно получать IP-адрес в apache, но в iis это не влияет. Функция $_SERVER [‘REMOTE_ADDR’] может не только успешно получить IP-адрес посетителя в apache, но и быть эффективной в iis.

I. REMOTE_ADDR

Эта переменная получает IP-адрес прямого источника, который ссылается на IP-адрес клиента, который запрашивает адрес напрямую. В случае одного сервера этот IP-адрес является в точности IP-адресом клиента и не может быть подделан. Конечно, не все программы обязательно являются отдельными серверами, например, в случае балансировки нагрузки (например, haproxy или nginx для балансировки нагрузки), этот IP – адрес является IP-адресом машины пересылки, потому что процесс-клиент – > Балансировка нагрузки – > сервер. Это сервер, к которому осуществляется прямой доступ с помощью балансировки нагрузки, а не клиент.

На HTTP_X_FORWARDED_FOR и HTTP_CLIENT_IP На основе “I” невозможно получить IP-адрес клиента с помощью REMOTE_ADDR непосредственно при балансировке нагрузки. Это проблема, которую необходимо решить. Таким образом, балансировка нагрузки и добавляет IP-адрес клиента в HEAD и отправляет его на сервер, чтобы сервер мог получить реальный IP-адрес клиента. Конечно, есть то, что вы называете подделкой. В конце концов, у HEAD есть настраиваемые данные, кроме тех, которые зафиксированы в протоколе.

3. Зачем нам нужно по очереди получать HTTP_CLIENT_IP, HTTP_X_FORWARDED_FOR и REMOTE_ADDR, когда мы находим код для получения IP-адреса клиента в Интернете? Основываясь на “I” и “II”, а также на учете универсальности программы, это является причиной для этого. Предположим, вы пишете REMOTE_ADDR непосредственно в своей программе, и однажды вашей программе потребуется выполнить балансировку нагрузки, а затем вам придется ее изменить. Конечно, если вы хотите это сделать, вы также можете просмотреть личные увлечения и сценарии приложений. Вы также можете инкапсулировать метод только для REMOTE_ADDR и изменять его при необходимости.

Вывод:

HTTP_CLIENT_IP: Заголовки доступны, но не являются стандартными, и не обязательно все серверы реализованы.

X-Forwarded-For (XFF): поле заголовка HTTP-запроса, используемое для определения исходного IP-адреса клиента, подключенного к веб-серверу через HTTP-прокси или балансировку нагрузки. Формат: ip клиента, proxy1, proxy2

REMOTE_ADDR: Это надежно. Это последний IP-адрес, с которого можно обменяться рукопожатием с вашим сервером. Это может быть прокси-сервер пользователя или его собственный обратный прокси-сервер.

X-Переадресованный для и X-Реальный IP:

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

Для более подробного обсуждения, пожалуйста, обратитесь к https://www.douban.com/group/topic/27482290./

1. Балансировка нагрузки:

Многие серверы в производственной среде скрыты за узлом балансировки нагрузки. Вы можете получить IP-адрес узла балансировки нагрузки только через REMOTE_ADDR. Как правило, фактический IP-адрес интерфейса будет передаваться через HTTP_CLIENT_IP или HTTP_X_FORWARDED_FДЛЯ двух типов HTTP-заголовков.

Можно доверять тому, что серверная часть снова считывает это значение, потому что это то, что сообщает вам узел балансировки нагрузки, а не клиент. Но когда ваш сервер напрямую открыт для клиента, не доверяйте этим двум методам чтения, просто прочитайте REMOTE_ADDR.

2. Ситуация с CDN:

Поэтому, чтобы получить IP-адрес пользователя, мы должны перехватить первый действительный IP-адрес (неизвестный) http_x_forwarded_for.

В многоуровневом прокси-сервере он похож на cdn.

Будьте осторожны:

Будь то REMOTE_ADDR или HTTP_FORWARDED_FOR, эти сообщения заголовка могут быть недоступны, поскольку разные браузеры и сетевые устройства могут отправлять разные сообщения IP-заголовка.

II. Предотвращение атак с использованием IP-адресов

Добавьте следующий код для предотвращения атак с использованием IP-адресов:

// IP Address Validation to Prevent IP Injection Attacks
$long = sprintf("%u", ip2long($ip));
$ip = $long ? array($ip, $long) : array('0.0.0.0', 0);

Как правило, после получения IP-адреса обновите код базы данных, например:. get_client_ip(). “‘где…”, и если полученный IP-адрес: xxxx.xxxx.xxxx’; удалить из t_users; – – подставляя параметр, оператор SQL становится: “обновить t_set; удалить из t_users; — где…

Поэтому после получения IP-адреса мы должны использовать регуляризацию для проверки действительности IP-адреса. Кроме того, мы должны использовать параметризованную команду SQL.

Анализ:

Функция sprintf () записывает отформатированную строку в переменную. *% U – десятичное число без знака (больше или равно 0)

int ip2long ( строка $ip_адрес ):

Возвращает преобразованное количество IP-адресов или значение FALSE, если ip_address неверен.

Будьте осторожны:

Примеры иллюстрируют функцию печати переведенного адреса с помощью функции printf () в PHP4 и PHP5:

php
$ip = gethostbyname('www.example.com');
$long = ip2long($ip);
if ($long == -1 || $long === FALSE) {
 echo 'Invalid IP, please try again';
} else {
 echo $ip . "\n";  // 192.0.34.166
 echo $long . "\n";  // -1073732954
 printf("%u\n", ip2long($ip)); // 3221234342
}
?>

1. Поскольку целочисленный тип PHP является символическим, и существует множество IP-адресов, которые вызывают отрицательные числа в 32-разрядных системах, вам необходимо использовать “% u” для преобразования строки, полученной с помощью sprintf () или printf (), для представления IP-адреса без знака.

2. ip2long () вернет FALSE на IP 255.255.255.255.255, версия PHP 5.0.2. После ремонта PHP 5.0.3 вернет – 1 (так же, как PHP 4).

3. Механизм защиты от щеток

Для получения IP-адреса мы можем выполнить некоторые операции, защищающие кисти:

//ip limit
$ip = getClientIp();
$ipKey = "activity_key_{$ip}";
if (!frequencyCheckWithTimesInCache($ipKey, $duration, $limitTimes)) {
 return false;
}
return true;
// Limit id, requesting up to $times in the $second time 

public static function frequencyCheckWithTimesInCache($id, $second, $times)
 {
 $value = Yii::app()->cache->get($id);
 if (!$value) {
  $data[] = time();
  Yii::app()->cache->set($id, json_encode($data), $second);

  return true;
 }
 $data = json_decode($value, true);
 if (count($data) + 1 <= $times) {
  $data[] = time();
  Yii::app()->cache->set($id, json_encode($data), $second);

  return true;
 }

 if (time() - $data[0] > $second) {
  array_shift($data);
  $data[] = time();
  Yii::app()->cache->set($id, json_encode($data), $second);

  return true;
 }

 return false;
 }

Приведите пример:

Ограничьте количество запросов не более чем 50 в час

if (!frequencyCheckWithTimesInCache('times_uid_' . $uid, 3600, 50)) {
  Return'Too frequent requests';
 }

Обновление Щетки Ограниченное Количество Оборудования:

// Equipment number A device number can only be drawn three times at most.
 if(! empty($deviceId)){
  $deviceUseChance = Yii::app()->db->createCommand()
   ->select('count(id)')->from('activity00167_log')
   ->where('device_id=:deviceId',['deviceId'=>$deviceId])
   ->queryScalar();
  $deviceChance = 3 - $deviceUseChance;
 }

Для получения IP-адресов мы также можем анализировать географическое местоположение пользователей в больших данных, например, выполнять некоторые точные работы по размещению.

резюме

Выше приведен пример кода PHP для получения реального IP-адреса пользователя и механизма защиты от кисти, введенного Xiaobian. Я надеюсь, что это будет полезно для вас. Если у вас есть какие-либо вопросы, пожалуйста, оставьте мне сообщение, и Сяобянь ответит вам вовремя. Большое вам спасибо за вашу поддержку в развитии peer.