Blog. Just Blog

Проверка принадлежности IP-адреса заданному диапазону

Версия для печати Добавить в Избранное Отправить на E-Mail 19.11.2008 | Категория: Web-мастеру и не только | Автор: ManHunter
Проверка вхождения IP в заданный диапазон может применяться во многих ситуациях. Например бан всей подсетки злоумышленника, принудительное ограничение скорости для зарубежного трафика, переадресация на различные разделы сайта в зависимости от провайдера пользователя и т.д. Я использую такие функции:
  1. // ------------------------------------------------------------
  2. // Проверка вхождения IP в заданный диапазон
  3. // На входе:
  4. // $ip - массив октетов проверяемого IP
  5. // $ip_start - массив октетов начала интервала
  6. // $ip_end - массив октетов конца интервала
  7. // В интервалах допускаются маски '*'
  8. // На выходе: TRUE или FALSE, входит IP или нет в диапазон
  9. // ------------------------------------------------------------
  10. function chk_ips($ip,$ip_start,$ip_end) {
  11.   for ($i=0$i<4$i++) {
  12.     // Проверка используется или нет маска в диапазоне
  13.     if ($ip_start[$i]=='*' || $ip_end[$i]=='*') {
  14.       // Переходим к следующему октету
  15.       continue;
  16.     }
  17.     // Поверяемый октет между начальным и конечным, значит весь IP-адрес
  18.     // входит в проверяемый диапазон
  19.     elseif ($ip[$i]>=$ip_start[$i] && $ip[$i]<$ip_end[$i]) {
  20.       break;
  21.     }
  22.     // Проверяемый октет равен октету начала или конца диапазона
  23.     elseif ($ip[$i]==$ip_start[$i] || $ip[$i]==$ip_end[$i]) {
  24.       // Переходим к следующему октету
  25.       continue;
  26.     }
  27.     else {
  28.       // IP не входит в интервал
  29.       return false;
  30.     }
  31.   }
  32.   // Весь IP совпадает с началом или концом диапазона, или входит в него
  33.   return true;
  34. }
Функция универсальная, позволяет обрабатывать одиночные IP-адреса, точно заданные диапазоны и диапазоны с маской "*" в любом октете. Дополнительных проверок на корректность диапазонов не производится.

Для разворачивания маски подсети используется вспомогательная функция:
  1. // ------------------------------------------------------------
  2. // Функция разворачивания маски подсети
  3. // На входе:
  4. // $ip - массив октетов начала диапазона
  5. // $mask - маска
  6. // На выходе:
  7. // массив IP конца диапазона
  8. // ------------------------------------------------------------
  9. function addip($ip,$mask) {
  10.   // Количество IP в каждой маске
  11.   $ip_count=Array(32=>031=>130=>329=>728=>1527=>3126=>63,
  12.                 25=>12724=>25523=>51122=>102321=>204720=>4095,
  13.                 19=>819118=>1638317=>3276716=>6553515=>131071,
  14.                 14=>26214313=>52428712=>104857511=>2097151,
  15.                 10=>41943039=>83886078=>167772157=>33554431,
  16.                 6=>671088635=>1342177274=>2684354553=>536870911,
  17.                 2=>1073741823);
  18.   $x=Array();
  19.   $ips=$ip_count[$mask];
  20.  
  21.   $x[0]=$ip[0]+intval($ips/(256*256*256));
  22.   $ips=($ips%(256*256*256));
  23.  
  24.   $x[1]=$ip[1]+intval($ips/(256*256));
  25.   $ips=($ips%(256*256));
  26.  
  27.   $x[2]=$ip[2]+intval($ips/(256));
  28.   $ips=($ips%256);
  29.  
  30.   $x[3]=$ip[3]+$ips;
  31.  
  32.   return ($x);
  33. }
И еще один небольшой вспомогательный парсер для разбора диапазона:
  1. // ------------------------------------------------------------
  2. // Парсер диапазонов IP
  3. // На входе:
  4. // $range - строка диапазона
  5. // На выходе:
  6. // Массив из двух массивов ([0]=>ip_start, [1]=>ip_end)
  7. // или FALSE если строка не является допустимым диапазоном
  8. // ------------------------------------------------------------
  9. function range_parser($range) {
  10.   $range=trim($range);
  11.   // Проверка диапазона вида x.x.x.x-y.y.y.y
  12.   if (strpos($range,"-")) {
  13.     $tmp=explode("-",$range);
  14.     $ip_start=explode(".",$tmp[0]);
  15.     $ip_end=explode(".",$tmp[1]);
  16.   }
  17.   // Проверка диапазона вида x.x.x.x/y
  18.   elseif (strpos($range,"/")) {
  19.     $tmp=explode("/",$range);
  20.     $ip_start=explode(".",$tmp[0]);
  21.     // Развернуть маску подсети
  22.     $ip_end=addip($ip_start,$tmp[1]);
  23.   
  24.   // Проверка диапазона вида x.x.*.* или одиночного IP
  25.   else {
  26.     $ip_start=$ip_end=explode(".",$range);
  27.   }
  28.   // Простенькая проверка на корректность полученных диапазонов
  29.   if (count($ip_start)==&& count($ip_end)==4) {
  30.     return array($ip_start$ip_end);
  31.   }
  32.   else {
  33.     return false;
  34.   }
  35. }
И рабочий пример с использованием всех этих функций:
  1. $ip="127.0.12.7";                  // IP для проверки
  2. $test_ip=explode(".",$ip);
  3.  
  4. $range="127.0.0.0/22";             // Маска подсети
  5. $chk=range_parser($range);
  6. chk_ips($test_ip,$chk[0],$chk[1]); // FALSE
  7.  
  8. $range="127.0.0.0-127.1.0.255";    // Интервал IP-адресов
  9. $chk=range_parser($range);
  10. chk_ips($test_ip,$chk[0],$chk[1]); // TRUE
  11.  
  12. $range="127.0.12.2";               // Одиночный IP
  13. $chk=range_parser($range);
  14. chk_ips($test_ip,$chk[0],$chk[1]); // FALSE
  15.  
  16. $range="127.*.*.*";                // Маска IP
  17. $chk=range_parser($range);
  18. chk_ips($test_ip,$chk[0],$chk[1]); // TRUE


Поделиться ссылкой ВКонтакте Поделиться ссылкой на Facebook Поделиться ссылкой на Я.ру Поделиться ссылкой на LiveJournal Поделиться ссылкой в Мой Круг Добавить в Мой мир Добавить на ЛиРу (Liveinternet) Поделиться ссылкой на Friendfeed Добавить в Яндекс.Закладки Добавить в закладки Memori Добавить в закладки Google
Просмотров: 8317 | Комментариев: 3

Комментарии

Отзывы посетителей сайта о статье
Энто (24.04.2012 в 21:59):
А не могли бы вы еще и написать где можно это дело откомпелированное скачать? или юзать онлайн?
pwn (20.07.2010 в 01:43):
а можно еще проще. вместо того чтоб городить городушки с массивом,
число адресов можно посчитать такой простой формулой

$ips=pow(2,32-$mask); это как раз будет число адресов. Но так как у автора в массиве юзается то же, но только на единицу меньше, то чтоб в его функции это работало нужно сказать так

$ips=pow(2,32-$mask)-1;
Валерий (09.06.2009 в 17:38):
Можно гораздо проще
  //-- Разрешенные диапазоны
  $Allow_Ip_Range                  = array('212.158.173.0/24','212.118.48.0/24','82.198.171.0/24');
  //-------------------------------------------------------------------
  //-- Функция проверки ip
  //------------------------------------------------------------------- 
  function Check_Ip ($Ip_For_Search, $Allow_Ip_Range)
  {
    $ip_count = array(32=>0, 31=>1, 30=>3, 29=>7, 28=>15, 27=>31, 26=>63, 25=>127, 24=>255, 23=>511, 22=>1023, 21=>2047, 20=>4095,
                      19=>8191, 18=>16383, 17=>32767, 16=>65535, 15=>131071, 14=>262143, 13=>524287, 12=>1048575, 11=>2097151,
                      10=>4194303, 9=>8388607, 8=>16777215, 7=>33554431, 6=>67108863, 5=>134217727, 4=>268435455, 3=>536870911,
                      2=>1073741823);
   
    $Ip_For_Search_Converted = ip2long($Ip_For_Search);
    $Result = FALSE;
    foreach ( $Allow_Ip_Range as $Value )
    {
      list($ip, $prefix)                    = preg_split('/\//',$Value);
      $Range_Start = ip2long($ip);
      $Range_End   = $Range_Start + $ip_count["$prefix"];
      echo "";
      if ( $Ip_For_Search_Converted >= $Range_Start && $Ip_For_Search_Converted <= $Range_End )
      {
        return TRUE;
      }
    }
    return $Result;
  }

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п. будут удаляться. Злостным нарушителям доступ к сайту может быть заблокирован.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2012
При использовании материалов ссылка на сайт обязательна
Время генерации: 0,15 сек. / MySQL: 2 (0,002 сек.) / Память: 3,5 Mb
Наверх