Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Поиск IP в списке диапазонов.
 
 автор: simbel   (21.08.2009 в 03:48)   письмо автору
 
 

Здравствуйте.

Есть список диапазонов IP разных провайдеров в таком виде:
8.2.144.0/24
12.8.167.0/24
12.18.210.0/24
12.23.142.0/24
12.26.226.0/23
12.27.222.0/23
12.107.230.0/24
12.107.239.0/24
12.107.246.0/23
12.107.248.0/23
12.107.250.0/23
12.169.52.0/24
12.180.224.0/24
12.191.164.0/22
13.0.0.0/16
13.1.0.0/16
13.2.0.0/16
13.3.0.0/16
13.4.8.0/22
13.7.0.0/16
13.7.64.0/24
24.72.248.0/21
24.107.160.0/20
........ и т.д.

Необходимо сделать скрипт, который бы искал IP адреса из лог-файла сайта в диапазонах из списка выше. Есть куча сервисов типа http://www.unix.lviv.ua/component/option,com_wrapper/Itemid,47/. Но он не очень подходит, т.к. диапазонов в которых нужно найти IP слишком много.

Как можно автоматизировать этот процесс? Подскажите пожалуйста.

  Ответить  
 
 автор: annonymоus   (21.08.2009 в 06:53)
 
   для: simbel   (21.08.2009 в 03:48)
 

что означает цифра после слэша ?
если 1.1.1.0/20 это 1.1.1.0-1.1.1.20 ,
то как бывает в случае
1.1.1.0-1.1.3.255 ?
извиняюсь , если вопрос наивный

  Ответить  
 
 автор: Саня   (21.08.2009 в 08:49)   письмо автору
 
   для: annonymоus   (21.08.2009 в 06:53)
 

> что означает цифра после слэша ?
Количество единиц в битовом представлении маски.

  Ответить  
 
 автор: Саня   (21.08.2009 в 09:56)   письмо автору
 
   для: simbel   (21.08.2009 в 03:48)
 

<?php

// список подсетей
$list = array('8.2.144.0/24',    '12.8.167.0/24',   '12.18.210.0/24',
              
'12.23.142.0/24',  '12.26.226.0/23',  '12.27.222.0/23',
              
'12.107.230.0/24''12.107.239.0/24''12.107.246.0/23',
              
'12.107.248.0/23''12.107.250.0/23''12.169.52.0/24',
              
'12.180.224.0/24''12.191.164.0/22''13.0.0.0/16',
              
'13.1.0.0/16',     '13.2.0.0/16',     '13.3.0.0/16',
              
'13.4.8.0/22',     '13.7.0.0/16',     '13.7.64.0/24',
              
'24.72.248.0/21',  '24.107.160.0/20');

// искомый IP
$target '12.107.249.10';

// искомый IP в long формате
$target_long sprintf('%u'ip2long($target));

// прочёсываем все подсети
foreach ( $list as $subnet_mask ) {

  
// отделяем маску от подсети
  
list($subnet$mask) = explode('/'$subnet_mask);

  
// получаем подсеть в битовом представлении
  
$subnet_brk explode('.'$subnet);
  
$subnet_brk array_map('decbin'$subnet_brk);
  foreach ( 
$subnet_brk as $k => $x )
    
$subnet_brk[$k] = str_pad($x8'0'STR_PAD_LEFT);

  
// получаем маску в битовом представлении
  
$mask str_repeat('1'$mask);
  
$mask str_pad($mask320);
  
preg_match('!^(\d{8})(\d{8})(\d{8})(\d{8})$!'$mask$mask_brk);

  
// инвертируем маску
  
$mask_inv = array();
  for ( 
$i 1$i 5$i++ )
    
$mask_inv[] = strtr($mask_brk[$i], '10''01');

  
// максимальный IP-адрес в данной подсети
  
$max = array();
  for ( 
$i 0$i 4$i++ )
    
$max[] = bindec($subnet_brk[$i] | $mask_inv[$i]);

  
// максимальный и минимальный адреса в данной подсети
  
$max sprintf('%u'ip2long(implode('.'$max)));
  
$min sprintf('%u'ip2long($subnet));

  
// проверим принадлежность проверяемого IP к текущей подсети
  
if ( $target_long >= $min && $target_long <= $max ) {
    print 
$target.' принадлежит подсети '.$subnet_mask;
    break;
  }

}

  Ответить  
 
 автор: Trianon   (21.08.2009 в 10:11)   письмо автору
 
   для: Саня   (21.08.2009 в 09:56)
 

:-(

  Ответить  
 
 автор: Саня   (21.08.2009 в 10:18)   письмо автору
 
   для: Trianon   (21.08.2009 в 10:11)
 

Что?

  Ответить  
 
 автор: annonymоus   (21.08.2009 в 10:28)
 
   для: Саня   (21.08.2009 в 10:18)
 

что-то не пойму как получается вообще что с чем сравнивать
вот напримерпробовал извлекать ту часть которая не должна меняться у адресов в подсети
<?
$ip 
0

list(
$i[],$i[],$i[],$i[],$mask)
 = 
sscanf('12.107.239.0/24''%3d.%3d.%3d.%3d/%d');
 
print_r($i);
 
$mask = -1<<(32-$mask);
foreach(
$i AS $k => $v$ip = ($ip | ($v << $k));

var_dump($ip $mask);

и у меня что 12.107.239.0 что 12.107.139.0 дают одну и ту-же цифру
, а должны вроде как разные ;) где я ошибся?

  Ответить  
 
 автор: Саня   (21.08.2009 в 12:04)   письмо автору
 
   для: annonymоus   (21.08.2009 в 10:28)
 

<?
$ip 
'8.2.144.200';
$mask = -<< 32 24;
$long ip2long('8.2.144.200');

print 
'CIDR-адрес: '.$ip.'/24<br/>'
     
.'Маска: '.long2ip($mask).'<br/>'
     
.'Подсеть: '.long2ip($long $mask);

  Ответить  
 
 автор: Trianon   (21.08.2009 в 10:44)   письмо автору
 
   для: Саня   (21.08.2009 в 10:18)
 

эффективность ....

  Ответить  
 
 автор: Саня   (21.08.2009 в 11:31)   письмо автору
 
   для: Trianon   (21.08.2009 в 10:44)
 

<?php

// список подсетей
$list = array('8.2.144.0/24',    '12.8.167.0/24',   '12.18.210.0/24',
              
'12.23.142.0/24',  '12.26.226.0/23',  '12.27.222.0/23',
              
'12.107.230.0/24''12.107.239.0/24''12.107.246.0/23',
              
'12.107.248.0/23''12.107.250.0/23''12.169.52.0/24',
              
'12.180.224.0/24''12.191.164.0/22''13.0.0.0/16',
              
'13.1.0.0/16',     '13.2.0.0/16',     '13.3.0.0/16',
              
'13.4.8.0/22',     '13.7.0.0/16',     '13.7.64.0/24',
              
'24.72.248.0/21',  '24.107.160.0/20');

// искомый IP
$target '12.107.249.10';

// искомый IP в long формате
$target_long ip2long($target);

// прочёсываем все подсети
foreach ( $list as $subnet_mask ) {

  
// отделяем маску от подсети
  
list($subnet$mask) = explode('/'$subnet_mask);

  
$subnet ip2long($subnet);
  
$mask 4294967295 << 32 $mask// полная маска
  
$max $subnet | ~$mask;          // максимальный IP в диапазоне

  
if ( $target_long >= $subnet && $target_long <= $max
       
|| $target_long <= $subnet && $target_long >= $max ) {
    print 
$target.' принадлежит подсети '.$subnet_mask;
    break;
  }

}

???

  Ответить  
 
 автор: annonymоus   (21.08.2009 в 12:45)
 
   для: Саня   (21.08.2009 в 11:31)
 

понял в чём была моя ошибка :)
не использовал ip2long и $k нужно было каждый раз умножать на 8

надо-бы сравнить по скорости
<?
$list= array('8.2.144.0/24','12.8.167.0/24','12.18.210.0/24',
'12.23.142.0/24','12.26.226.0/23','12.27.222.0/23',
'12.107.230.0/24','12.107.239.0/24','12.107.246.0/23',
'13.4.8.0/22','13.7.0.0/16','13.7.64.0/24',
'24.72.248.0/21 ','24.107.160.0/20 ');

// искомый IP
$target = ip2long('24.107.160.255');

function s2ip(&$m) {
global $target;
$ip = ($m[1]<<24 |($m[2]<<16) |($m[3]<<8) | $m[4]);
$mask = -1<<(32-$m[5]);
if (($target & $mask) == ($ip & $mask)) echo 'ip принадлежит подсети "'. $m[0] ."\"\n\n";
return '';
}

preg_replace_callback(
'#(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})\s*#',
's2ip',
$list);
?>

  Ответить  
 
 автор: Саня   (21.08.2009 в 12:57)   письмо автору
3.3 Кб
 
   для: annonymоus   (21.08.2009 в 12:45)
 

Отличаются несильно. При параметрах теста "ab -n 100000 -c 5 http://localhost/test.php" мой скрипт показал 1688.21 запросов/сек, ваш — 1570.55. Всё же сказывается разница между стандартной, специально заточенной для IP функцией и регвырами.

  Ответить  
 
 автор: Trianon   (21.08.2009 в 14:55)   письмо автору
 
   для: Саня   (21.08.2009 в 11:31)
 

:-(

  Ответить  
 
 автор: Саня   (21.08.2009 в 15:03)   письмо автору
 
   для: Trianon   (21.08.2009 в 14:55)
 

Что?

  Ответить  
 
 автор: Trianon   (21.08.2009 в 17:02)   письмо автору
 
   для: Саня   (21.08.2009 в 15:03)
 

Эффективность...

  Ответить  
 
 автор: Саня   (21.08.2009 в 17:15)   письмо автору
 
   для: Trianon   (21.08.2009 в 17:02)
 

Не могу придумать ничего эффективнее. Разве что вызов сторонней программы, написанной на асме.

  Ответить  
 
 автор: Trianon   (21.08.2009 в 18:09)   письмо автору
 
   для: Саня   (21.08.2009 в 17:15)
 

Собственно, при тестировании только одного IP-адреса, можно оставить и так.
Но если проверить нужно целый пакет - стоит изменить структуру хранения набора подсетей.
Вообще же для искомых данных сама собой напрашивается структура древовидного поиска.

  Ответить  
 
 автор: Саня   (21.08.2009 в 20:19)   письмо автору
 
   для: Trianon   (21.08.2009 в 18:09)
 

Ну в этом смысле да.

  Ответить  
 
 автор: simbel   (21.08.2009 в 11:22)   письмо автору
 
   для: Саня   (21.08.2009 в 09:56)
 

Спасибище ))))

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

Ещё раз, очень благодарен!

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования