Платформы * Linux
Описание
Модуль CTT позволяет подсчитывать трафик, проходящий через определенный интерфейс. С помощью специальных счетчиков-фильтров можно задать правила отбора пакетов на основе IP-адреса и маски подсети. Фильтрация пакетов может выполняться на основе информации об источнике или о назначении.
Модуль работает по принципу сниффера: соответствующий интерфейс переводится в режим PROMISCUOUS, после этого становятся доступными пакеты сегмента подсети, в который выведен интерфейс.
ВНИМАНИЕ!
* Учтите, что для перевода интерфейса в "разнородный" режим необходимо обладать правами привелегированного пользователя.
* С помощью модуля вы не сможете контролировать прохождение пакетов низкого уровня - только IP-протоколов.
* Модуль так же не обращает внимание на пакеты IP-версии отличной от 4.
* Будьте внимательны, если рядом свитч.
Настоящая версия (0.1) позволяет
* Использовать интерфейсы стандарта Ethernet IEEE 802.3.
* Накапливать информацию о проходящих пакетах в 32-разрядных счетчиках (в пределах 4Gb).
* Устанавливать правила фильтрации пакетов по адресам источника и назначения, маскировать недейственные биты адреса, с возможностью отрицания условия (условная инверсия).
* Устанавливать для каждого фильтра объем трафика (входящего, исходящего или общего), после прохождения которого будет вызываться специальный обработчик. Код обработчика может быть произвольно переопределен.
Установка модуля
Для установки модуля распакуйте тарбол и перейдите к корневой каталог пакета. Наберите команду
perl Makefile.PL
После этого в текущем каталоге и в подкаталоге _lib будут созданы файлы Makefile для сборки проекта. Наберите команду
make
Выполнение этой команды приведет к сборке проекта: в подкаталоге _lib будет создана библиотека, необходимая для функционарования модуля, а в текущем каталоге появится подкаталог blib, в котором и будут размещены готовые файлы модуля.
Тестовая программа пока не реализована, по этому в случае успешной сборки можете сразу установить модуль командой
make install
После этого каталог проекта можно удалить.
ПРИМЕЧАНИЕ
По умолчанию модуль CTT предполагает использование не более 256 счетчиков. Однако вы можете перед сборкой модуля переопределить константу MAX_FILTER и, сопоставив ей требуемое значение, увеличить количество фильтров.
Пример использования модуля
use CTT; $ctt = new CTT; $ctt->Enable("eth0") or die "Ошибка установки разнородного режима"; $fi1 = $ctt->AddFilter("192.168.1.90","255.255.255.255", "!192.168.0.0","255.255.0.0"); # Фильтровать все с 192.168.1.90 # отправленное за пределы сети $ctt->StopOn($fi1,20000,20000,0); # Сигнализировать по достижении # 20000 байт $fi2 = $ctt->AddFilter("192.168.1.90","255.255.255.255", "!192.168.1.90","255.255.255.255");# Фильтровать все с 192.168.1.90 # адресованное другим хостам $ctt->StopOn($fi2,40000,40000,0); # Сигнализировать по достижении # 40000 байт while ($ctt->Read()){ @filters = $ctt->GetFilters(); unless (@fi){ print "Нечего фильтровать.\n"; last; } } sub CTT::OnOverflow{ my ($self,$fi) = @_; print "Счетчик $fi переполнен. Текущее значение: ", scalar(self->GetCurrBytes($fi)),"\n"; $self->DelFilter($fi); }
Интерфейс класса CTT
Модуль имеет объектно ориентированный интерфейс. Один экземпляр может быть привязан только к одному сетевому интерфейсу. Однако это не означает, что одному интерфейсу нельзя сопоставить несколько объектов CTT.
Фильтр определяет условия отбора пакетов а так же сохраняет промежуточные значения счетчиков. Фильтры определяются по индексам, но различные экземпляры CTT никак не связаны между собой. Это значит, что одинаковые индексы фильтров для каждого экземпляра объекта CTT будут указывать на абсолютно несвязанные данные.
new
Конструктор не принимает аргументов. Возвращает ссылку на экземпляр класса или неопределенное значение в случае неудачи.
$ctt = new CTT;
Enable
Метод Enable в качестве аргумента принимает идентификатор интерфейса и пытается перевести его в "неразборчивый" режим. В случае успеха возвращает знаечние истина, в противном случае - ложь.
$ctt->Enable("eth0");
Вы не сможете вызвать метод Read для объекта пока не укажете на какой интерфейс нужно поставить сниффер. В этом случае метод Read всегда будет возвращать значение 0.
Disable
Метод Disable останавливает процесс чтения пакетов. Этот метод не принимает аргументов. Все счетчики остаются в состоянии, в котором они находились после последнего вызова метода Read. Повторный вызов метода Enable так же не приведет к сбросу счетчиков, но будьте внимательны в случае назначения другого сетевого интерфейса.
Read
Метод Read приводит к чтению очередной порции данных. После чтения выполняется сравнение пакета с каждым заданным фильтром и, в случае необходимости, вызывается виртуальный метод OnOverflow. Естественно что вызов Read представляется бессмысленным, если не задано ни одно правило отбора пакетов. Если выполнить чтение не удается (предварительно не вызван метод Enable) то в качестве результата работы метод возвращает 0. Таким образом, если в обработчике OnOverflow определить код, вызывающий метод Disable можно организовать цикл чтения пакетов следующим образом
while ($ctt->Read()){ ... }
AddFilter
Метод AddFilter позволяет задать новое правило отбора пакетов. В качестве аргументов принимает IP-адрес источника, маску адреса источника, IP-адрес назначения и маску адреса назначения.
$fi2 = $ctt->AddFilter("192.168.1.90","255.255.255.255", "!192.168.0.0","255.255.0.0");
В качестве результата работы метод возвращает индекс добавленного фильтра или -1, в случае если добавить фильтр не удалось. Ошибочная ситуация при добавлении фильтра может возникнуть например в случае отсутствия места для нового фильтра. Для хранения информации счетчиков используется массив фиксированных размеров. По умолчанию каждый объект CTT может иметь не более 256 фильтров. Как правило этого должно хватить для большинства задач (см. параграф Установка модуля если хотите увеличить это значение).
Обратите внимание на способ задания адреса назначения. Восклицательный знак перед адресом указывает на отрицание адреса. Это значит, что в отбор попадут все пакеты, один из адресов которых (источник или назначение) не совпадает с указанным, то есть не входит в сеть 192.168.0.0/16.
ВНИМАНИЕ!
На самом деле, не имеет значения какой из заданных адресов источник, а какой назначение. Условием отбора является совпадение (или несовпадение в случае указания "!") одного из указанных адресов с адресом источника, а другого с адресом назначения, определяемым по заголовку пакета. Но обязательно совпадать должны оба адреса. И если в процессе анализа пакета выяснилось, что источник и назначение попадают под указанное условие, но поменялись местами то выполняется инкремент счетчика полученных байт. В случае совпадения адресов в указанном порядке инкрементируется счетчик отправленных байт. Учтите, что вы имеете возможность задать такое условие отбора, при котором суммарный трафик превысит фактический в два раза. Например при сети 192.168.1.0
# Все адреса в сети попадают как под первое условие, так и под второе $ctt->AddFilter("192.168.1.0","255.255.255.0", "192.168.0.0","255.255.0.0");
DelFilter
Метод DelFilter удаляет фильтр-счетчик. В качестве аргумента принимает индекс удаляемого фильтра. После удаления слот, в котором хранился счетчик, освобождается и может быть использовать самим модулем для размещения нового фильтра. Метод не возвращает значений.
$fi = $ctt->AddFilter("192.168.1.0","255.255.255.0", "!192.168.0.0","255.255.0.0"); $ctt->DelFilter($fi);
StopOn
Метод StopOn позволяет установить предел сигнализации, то есть указать объем входящего, исходящего и общего трафика, по достижении которого будет вызван виртуальный обработчик OnOverflow (например если вы хотите не просто считать трафик, а на основе этой информации еще и чем то управлять). В качестве аргументов принимает индекс фильтра, значение исходящего, входящего и общего трафика, определяющие границы сигнализации. Значение 0 отменяет контроль над трафиком конкретного типа
$fi = $ctt->AddFilter("192.168.1.0","255.255.255.0", "!192.168.0.0","255.255.0.0"); $ctt->StopOn($fi,1000,2000,10*1024*1024); # Сигнализировать при # исходящем 1000B, входящем 2000B # и общем трафике более 10MB. $ctt->StopOn($fi,0,0,10*1024*1024); # Контролировать только общий трафик # при прежнем условии 10MB.
IfName
Метод IfName позволяет получить идентификатор интерфейса, так как он был передан в функцию Enable.
print $ctt->IfName();
GetCurrBytes
Метод GetCurrBytes позволяет получить значение счетчика байт конкретного фильтра. В качестве аргументов принимает индекс фильтра, полученный в результаты вызова метода AddFilter. В скалярном контексте метод возвращает строку представления счетчика байт, а в списковом - массив из двух элементов: количества отправленных и полученных байт.
$str = $ctt->GetCurrBytes($fi); ($sent,$recv) = $ctt->GetCurrBytes($fi);
GetCurrPackets
Метод GetCurrBytes позволяет получить значение счетчика пакетов конкретного фильтра. В качестве аргументов принимает индекс фильтра. В скалярном контексте метод возвращает строку представления счетчика пакетов, а в списковом - массив из двух элементов: количества отправленных и полученных пакетов.
ResetCounter
Этот метод позволяет сбросить значения счетчиков определенного фильтра. В качестве аргумента метод принимает индекс фильтра.
GetFilters
Метод GetFilters позволяет получить список индексов всех заданных фильтров данного объекта. Если ни один фильтр не задан, то возвращается пустой список.
while ($ctt->Read() && @fi = $ctt->GetFilters()){ ... }
IsUsed
Метод позволяет проверить, определен ли фильтр с указанным индексом. В качестве аргумента принимает индекс фильтра. Возвращает 0, если фильтр неопределен или 1, если такой фильтр есть.
if ($ctt->IsUsed(0)){ ... }
OnOverflow
Метод OnOverflow вызывается каждый раз, когда существует фильтр, значения счетчиков которого превысили одну из указанных границ сигнализации (см. метод StopOn). Вы можете переопределить этот метод в производном классе, или же просто перекрыть существующий метод CTT::OnOverflow как это сделано в примере.
Планы
* Процедуры тестирования
* POD-документация