|
|
|
| Здравствуйте.
Есть список диапазонов 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 ?
извиняюсь , если вопрос наивный | |
|
|
|
|
|
|
|
для: annonymоus
(21.08.2009 в 06:53)
| | > что означает цифра после слэша ?
Количество единиц в битовом представлении маски. | |
|
|
|
|
|
|
|
для: 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($x, 8, '0', STR_PAD_LEFT);
// получаем маску в битовом представлении
$mask = str_repeat('1', $mask);
$mask = str_pad($mask, 32, 0);
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;
}
}
|
| |
|
|
|
|
|
|
|
для: Саня
(21.08.2009 в 09:56)
| | :-( | |
|
|
|
|
|
|
|
для: 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 дают одну и ту-же цифру
, а должны вроде как разные ;) где я ошибся? | |
|
|
|
|
|
|
|
для: annonymоus
(21.08.2009 в 10:28)
| |
<?
$ip = '8.2.144.200';
$mask = -1 << 32 - 24;
$long = ip2long('8.2.144.200');
print 'CIDR-адрес: '.$ip.'/24<br/>'
.'Маска: '.long2ip($mask).'<br/>'
.'Подсеть: '.long2ip($long & $mask);
|
| |
|
|
|
|
|
|
|
для: Саня
(21.08.2009 в 10:18)
| | эффективность .... | |
|
|
|
|
|
|
|
для: 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);
?> | |
|
|
|
|
 3.3 Кб |
|
|
для: annonymоus
(21.08.2009 в 12:45)
| | Отличаются несильно. При параметрах теста "ab -n 100000 -c 5 http://localhost/test.php" мой скрипт показал 1688.21 запросов/сек, ваш — 1570.55. Всё же сказывается разница между стандартной, специально заточенной для IP функцией и регвырами. | |
|
|
|
|
|
|
|
для: Саня
(21.08.2009 в 11:31)
| | :-( | |
|
|
|
|
|
|
|
для: Trianon
(21.08.2009 в 14:55)
| | Что? | |
|
|
|
|
|
|
|
для: Саня
(21.08.2009 в 15:03)
| | Эффективность... | |
|
|
|
|
|
|
|
для: Trianon
(21.08.2009 в 17:02)
| | Не могу придумать ничего эффективнее. Разве что вызов сторонней программы, написанной на асме. | |
|
|
|
|
|
|
|
для: Саня
(21.08.2009 в 17:15)
| | Собственно, при тестировании только одного IP-адреса, можно оставить и так.
Но если проверить нужно целый пакет - стоит изменить структуру хранения набора подсетей.
Вообще же для искомых данных сама собой напрашивается структура древовидного поиска. | |
|
|
|
|
|
|
|
для: Trianon
(21.08.2009 в 18:09)
| | Ну в этом смысле да. | |
|
|
|
|
|
|
|
для: Саня
(21.08.2009 в 09:56)
| | Спасибище ))))
Мне самому, прежде чем написать такой скрипт, долго пришлось бы разбираться с особенностями IP, диапазонов, масок и т.д..
Ещё раз, очень благодарен! | |
|
|
|