Документация по ОС FreeBSD Четверг, 02.05.2024, 00:38
Приветствую Вас Гость | RSS
Меню сайта

Категории каталога
Apache [58]
DNS [25]
FTP [27]
Mail [74]
Samba [24]
Squid [46]
SSH [23]
VPN [35]
РРР [20]
Net [173]

Главная » Статьи » Сеть » Net

Сага о биллинге, или Считаем трафик на FreeBSD (ng_ipacct + perl+ MySQL) Часть 3
В предыдущей части статьи мы рассмотрели, как установить и запустить ng_ipacct, а также создание своих собственных скриптов для запуска и остановки разрабатываемой системы учета трафика.

Дальнейшая цель ? получить статистику и поместить ее в базу. Что нам для этого нужно? В первой части статьи, когда описывался ng_ipacct, указывалось, что для снятия статистики необходимо последовательно проделать следующее: передать данные в checkpoint базу, потом вывести данные при помощи show (перенаправить в файл) и очистить checkpoint, для получения следующей порции данных.

Таким образом, мы сразу же определили, что нам нужно сложить статистику в файл при помощи перенаправления вывода show. А после этого, уже считывая из файла данные, отправить в базу. Для того чтобы не было смешивания всех интерфейсов в одном файле, мы так же должны условиться заранее, что для каждого интерефейса будет создан свой собственный файл статистики, а так же один общий, куда будет складываться статистика со всех интерфейсов. В этих файлах будет указанно, имя хоста, время получения порции записей, дата и самое главное - интерфейс. Почему так акцентируется внимание на интерфейсе? Очень просто. У нас могут быть каналы на одной машине, где локальный трафик считается, а так же где он бесплатный. У честь нам необходимо платный. Соответственно, нужно знать какой интерфейс принял или отправил пакет. 

Что ж основная установка сделана. Остальное - по ходу повествования.

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

Создаем базу данных:

        mysql> create database ng_stat;
        Query OK, 1 row affected (0.04 sec)
        mysql> grant insert,create,update,select,delete on ng_stat.* to nguser@'%' identifiedby 'ngpassword';
        Query OK, 0 rows affected (0.08 sec)
        mysql>

Одновременно были даны права пользователю nguser  на добавление, обновление, удаление записей и их выборку, а так же на создание таблиц. Для чего проделано последнее? Чтобы не вести учет того, создана таблица за текущий месяц или нет, а создавать по мере необходимости. 

Итак, вновь возвращаемся к написанию скриптов:

        skif@ostwest : touch ng_stat_in.pl

И начинаем вносить данные. 

Первым делом необходимо подключить два модуля perl, которые будут использоваться: 

        #!/usr/bin/perl -w
        use DBI;
        use Time::localtime;

Последний у вас должен быть по умолчанию в системе, а вот присутствие DBI  необходимо проверить. Самый простой способ - отправить на исполнение скрипт уже в таком виде ? выдаст ошибку ? значит, нет или не соответствует текущей версии perl (например, вы обновили perl, а все сопутствующие модули нет). Что ж, это поправимо:

        root@ostwest : cd /usr/ports/databases/p5-DBI/
        root@ostwest : make && make install && make clean && rehash
        root@ostwest : cd /usr/ports/databases/p5-DBD-mysql
        root@ostwest : make && make install && make clean && rehash

Если у вас стоит MySQL не версии 3.23, а 4-й и выше, то выберите соответствующий вариант,  вместо  p5-DBD-mysql. После этого можно смело приступать к дальнейшим манипуляциям. 

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

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

Все это описано в конфигурационном файле (смотрите первую часть статьи).
Но сначала опять нужно задать основные переменные.

        #########################
        # Список основных переменных
        #########################
        my $serverdb = "test";
        my $dbname = "test";
        my $dbuser = "test";
        my $dbpass = "test";
        my $table_auth = "test";
        my $table_proto = "test";
        my $listen_host = "test";
        my @listen_interf;
        my @ng_modules;
        my $ng_modules_def = "netgraph,ng_ether,ng_socket,ng_tee,ng_ipacct";
        my $threshold = 5000;
        my $ipacct_log = '/usr/local/script/ng_stat/log/ng.log';

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

Самое важное в этом списке my $ipacct_log = '/usr/local/script/ng_stat/log/ng.log' - мы указали расположение основного файла статистики, куда по умолчанию будет записываться ВСЯ статистика (с интерфейсами, временем и т.д.).

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

Проверяем время на машине. Именно это время и будет записываться в базу: 

        #########################
        # Проверяем время.
        #########################
        $gm = localtime();
        $year = ($gm->year()) + 1900;
        $mounth = ($gm->mon()) + 1;
        $mday = $gm->mday();
        $date = "$mday-$mounth-$year";
        $hour = $gm->hour();
        $min = $gm->min();
        $sec = $gm->sec();
        $hour=sprintf("%02d",$hour);
        $min=sprintf("%02d",$min);
        $sec=sprintf("%02d",$sec);
        $time = "$hour\:$min\:$sec";
        $table_date = "$year\_$mounth";

Почему в переменной $year мы добавляем 1900? Очень просто - она ведет отсчет от 1900 года. Почему в месяцах прибавляем единицу - переменная возвращает значения от 0 до 11. 

Функция sprintf вернет значения переменных $hour, $sec и $min числом из двух цифр, если полученное значение будет меньше 10. Например, одна секунда, после получения ее значения, будет 1, а нужно 01. 

Последний параметр $table_date определяет имя таблицы в базе данных. 

Далее идет конструкция для проверки, установлены интерфейсы или нет. Если все в порядке, начинаем подготовку к тому, что бы закачивать данные на сервер.

Первым делом необходимо получить данные с интерфейсов и записать во временные файлы.

        #
        while (@listen_interf){
        $interface = shift @listen_interf;
        my $pid;
        $pid = fork;
        if (defined $pid) {
        if ($pid == 0){
        #$IPACCTCTL ${IFACE}_ip_acct:$IFACE checkpoint
        exec "/usr/local/sbin/ipacctctl $interface\_ip_acct:$interface checkpoint"
or die "Ошибка передачи записи в checkpoint-базу!\n";
        exit;
        }
        }
        else {
        print "Фатальная ошибка ветвления!\n.................\n";
        die "Разделение на процессы не возможно.\n Принудительный выход из дочернего процесса: $!\n";
        }
        do {
        $kid = waitpid $pid,0;
        if ($kid == -1) {
        print "Дочерних процессов в системе нет или система не поддерживает их.\n Ошибка!" and die "Выход!\n";
        } elsif ($kid == 0) {
        print "Задан не блокирующий вызов и процесс еще не завершен!\n";
        }
        } until $kid=$pid;

        undef $pid;

        $pid = fork;
        if (defined $pid) {
        if ($pid == 0){
        #$IPACCTCTL ${IFACE}_ip_acct:$IFACE show >> $DIR/$SDIR/$NAME
        exec "/usr/local/sbin/ipacctctl $interface\_ip_acct:$interface show >> $ipacct_log\.$interface"
or die "Ошибка передачи записей из checkpoint-базы в файл!\n";
        exit;
        }
        }
        else {
        print "Фатальная ошибка ветвления!\n.................\n";
        die "Разделение на процессы не возможно.\n Принудительный выход из дочернего процесса: $!\n";
        }
        do {
        $kid = waitpid $pid,0;
        if ($kid == -1) {
        print "Дочерних процессов в системе нет или система не поддерживает их.\n Ошибка!" and die "Выход!\n";
        } elsif ($kid == 0) {
        print "Задан не блокирующий вызов и процесс еще не завершен!\n";
        }
        } until $kid=$pid;

        undef $pid;

        $pid = fork;
        if (defined $pid) {
        if ($pid == 0){
        #$IPACCTCTL ${IFACE}_ip_acct:$IFACE clear
        exec "/usr/local/sbin/ipacctctl $interface\_ip_acct:$interface clear"
           or die "Ошибка при очистке checkpoint-базы! \n
База не очищена. Возможно переполнение. Очистите базу в ручную\n";
        exit;
        }
        }
        else {
        print "Фатальная ошибка ветвления!\n.................\n";
        die "Разделение на процессы не возможно.\n Принудительный выход из дочернего процесса: $!\n";
        }
        do {
        $kid = waitpid $pid,0;
        if ($kid == -1) {
        print "Дочерних процессов в системе нет или система не поддерживает их.\n Ошибка!" and die "Выход!\n";
        } elsif ($kid == 0) {
        print "Задан не блокирующий вызов и процесс еще не завершен!\n";
        }
        } until $kid=$pid;

        undef $pid;

        $TMPLOG= "$ipacct_log\.$interface";
        open (TMPLOG, "$TMPLOG");
        $TMPLOG =~ s/\||`|&&|<|>//gi; #Очистка ряда символов | ` && < > из пути к файлу.
        while (){
        $tmp_log_line=$_;
        chomp $tmp_log_line;
        $tmp_log_line = "$tmp_log_line $date $time $listen_host $interface";
        push @ipacct_arr,$tmp_log_line;
        }
        close (TMPLOG);
        truncate ($TMPLOG,0);

        undef $pid;
        }

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

Как видите, первыми идут checkpoint, show, clear. На этапе show  мы перенаправляем данные во временный файл. Временный файл определяется основным файлом статистики с приставкой имени интерфейса, то есть для rl0 он будет выглядеть как /usr/local/script/ng_stat/log/ng.log.rl0. И так поочередно для каждого из интерфейсов.

После занесение данных эти файлы считываются. Каждая строка из них будет дополнена необходимой информацией (дата, время, имя хоста, интерфейс) и занесена в массив.

        $tmp_log_line = "$tmp_log_line $date $time $listen_host $interface";
        push @ipacct_arr,$tmp_log_line;

После того, как временный файл считан до конца, мы его очищаем (можно, в принципе и удалить, хотя это не эффективно). 

        truncate(?$TMPLOG?,0);

так поочередно мы заполним данными со всех интерфейсов массив @ipacct_arr. Его, кстати, необходимо внести в список основных переменных, которые были объявлены в начале скрипта.

        my @ipacct_arr;
        my @ipacct_arr_in;

Я указал кроме него еще один массив - он сейчас тоже потребуется. 

        open (IPCTLOG,">>$ipacct_log");
        while (@ipacct_arr){
        $line_arr = shift @ipacct_arr;
        $line_arr = "$line_arr\n";
        print IPCTLOG $line_arr;
        }
        close(IPCTLOG); 

Этим действием все содержимое массива, полученного на предыдущем шаге, заносится в основной файл статистики. Теперь в случае любых перипетий (недоступность сервера, отсутствие созданной базы или неправильный логин/пароль) вся статистика будет накапливаться в нем. Именно по этому и было указано, то, что в случае пополнения записей они должны дописываться в конец файла.

         open (IPCTLOG,">>$ipacct_log"). 

Статистика получена. Теперь наступил самый ответственный этап. Необходимо привести к нужному виду каждую строку в файле статистики. Проверить доступность сервера и необходимой базы и таблицы. Если все в полном порядке, то внести данные. Вот как полностью будет выглядеть этот блок:

        #
        while (@listen_interf){
        $interface = shift @listen_interf;
        my $pid;
        $pid = fork;
        if (defined $pid) {
        if ($pid == 0){
        #$IPACCTCTL ${IFACE}_ip_acct:$IFACE checkpoint
        exec "/usr/local/sbin/ipacctctl $interface\_ip_acct:$interface checkpoint"
or die "Ошибка передачи записи в checkpoint-базу!\n";
        exit;
        }
        }
        else {
        print "Фатальная ошибка ветвления!\n.................\n";
        die "Разделение на процессы не возможно.\n Принудительный выход из дочернего процесса: $!\n";
        }
        do {
        $kid = waitpid $pid,0;
        if ($kid == -1) {
        print "Дочерних процессов в системе нет или система не поддерживает их.\n Ошибка!" and die "Выход!\n";
        } elsif ($kid == 0) {
        print "Задан не блокирующий вызов и процесс еще не завершен!\n";
        }
        } until $kid=$pid;

        undef $pid;

        $pid = fork;
        if (defined $pid) {
        if ($pid == 0){
        #$IPACCTCTL ${IFACE}_ip_acct:$IFACE show >> $DIR/$SDIR/$NAME
        exec "/usr/local/sbin/ipacctctl $interface\_ip_acct:$interface show >> $ipacct_log\.$interface"
or die "Ошибка передачи записей из checkpoint-базы в файл!\n";
        exit;
        }
        }
        else {
        print "Фатальная ошибка ветвления!\n.................\n";
        die "Разделение на процессы не возможно.\n Принудительный выход из дочернего процесса: $!\n";
        }
        do {
        $kid = waitpid $pid,0;
        if ($kid == -1) {
        print "Дочерних процессов в системе нет или система не поддерживает их.\n Ошибка!" and die "Выход!\n";
        } elsif ($kid == 0) {
        print "Задан не блокирующий вызов и процесс еще не завершен!\n";
        }
        } until $kid=$pid;

        undef $pid;

        $pid = fork;
        if (defined $pid) {
        if ($pid == 0){
        #$IPACCTCTL ${IFACE}_ip_acct:$IFACE clear
        exec "/usr/local/sbin/ipacctctl $interface\_ip_acct:$interface clear"
           or die "Ошибка при очистке checkpoint-базы! \n
База не очищена. Возможно переполнение. Очистите базу в ручную\n";
        exit;
        }
        }
        else {
        print "Фатальная ошибка ветвления!\n.................\n";
        die "Разделение на процессы не возможно.\n Принудительный выход из дочернего процесса: $!\n";
        }
        do {
        $kid = waitpid $pid,0;
        if ($kid == -1) {
        print "Дочерних процессов в системе нет или система не поддерживает их.\n Ошибка!" and die "Выход!\n";
        } elsif ($kid == 0) {
        print "Задан не блокирующий вызов и процесс еще не завершен!\n";
        }
        } until $kid=$pid;

        undef $pid;

        $TMPLOG= "$ipacct_log\.$interface";
        open (TMPLOG, "$TMPLOG");
        $TMPLOG =~ s/\||`|&&|<|>//gi; #Очистка ряда символов | ` && < > из пути к файлу.
        while (){
        $tmp_log_line=$_;
        chomp $tmp_log_line;
        $tmp_log_line = "$tmp_log_line $date $time $listen_host $interface";
        push @ipacct_arr,$tmp_log_line;
        }
        close (TMPLOG);
        truncate ($TMPLOG,0);

        undef $pid;
        }

        open (IPCTLOG,">>$ipacct_log");
        while (@ipacct_arr){

        $line_arr = shift @ipacct_arr;
        $line_arr = "$line_arr\n";
        print IPCTLOG $line_arr;

        }
        close(IPCTLOG);

        &parse_log_file;
        &check_in_mysql;
        &insert_data_db;
        }

Как видно из кода, присутствует  вызов трех подпрограмм. Выполняемые ими функции интуитивно понятны из названия(&parse_log_file; &check_in_mysql; &insert_data_db;).

Рассмотрим их поочередно.

        sub parse_log_file {
        open (PARSFILE, "$ipacct_log");
        while ($line_parse=) {
                chomp $line_parse;
                $line_parse =~ s/[\s\t]+/\t/g;
                push @ipacct_arr_in, $line_parse;
        }
        close (PARSFILE);
        truncate ("$ipacct_log",0);
        }

Все, что мы делаем здесь, - производим разбор строки основного файла.  И все имеющиеся символы пробела или табуляции заменяем на единичные символы табуляции. И вносим данные в объявленный выше массив @ipacct_arr_in .  После того как все данные из фала были внесены в массив, этот файл обнуляется для записи последующей порции данных.

Что ж, проверим  доступность mysql и наличия таблиц: 

        my ($dbh,$sth,$count);
        $dbh = DBI->connect("DBI:mysql:host=$serverdb;database=$dbname", "$dbuser", "$dbpass")
                        or &error_connection;
        $sth = $dbh->prepare("SHOW tables");
        $sth->execute ();

Первой строкой мы объявили переменные, которые будут использоваться для соединения. Второй устанавливаем соединение с MySQL. В ней указываем, что необходимо использовать драйвер mysql DBI, так же расположение сервера, БД, имя и пароль, которые получили из файла настройки. В случае если произойдут ошибки, будет выполнена подпрограмма &error_connection. Ее опишем несколько позже, а пока условимся, что соединение прошло успешно. Следующим пунктом будет запрос. В данном случае проверяется наличие необходимых таблиц в базе (SHOW TABLES), а последняя строка означает выполнение запроса.

Теперь полученный результат занесем в массив:

        my @row;
        my $tables;
        while (@row = $sth->fetchrow_array) {
        foreach $tables (@row){
        push @dbtables, $tables;
        }
        }

Самое интересное во всем этом ? оператор foreach, который присваивает переменной $table значения массива @row. Значения этой переменной заносятся в @tables.

        $crt_tbl="yes";
        while (@dbtables) {
        $table = shift @dbtables;
        if (defined $table) {
        if ($table eq $table_date) {
        $crt_tbl="no";
        }
        }
        }

В данном блоке устанавливается значение переменной $crt_tbl в yes, что бы в случае необходимости создать таблицу, определенную в переменной $table_date. Последующие действия как раз и описывают этап сравнения элементов массива с переменной. Если таблица с таким именем присутствует, то $crt_tbl принимает значение no.

        if ($crt_tbl eq "yes") {
        # print "Создаем таблицу\n";
        &crt_table_log;
        }
        $sth->finish;
        $dbh->disconnect;

Если такой таблицы нет, она будет создана при вызове подпрограммы &crt_table_log.

В этом модуле встречаются две новые подпрограммы. Опишем первую,  так как она используется еще  в нескольких местах. Итак, в случае ошибки соединения необходимо срочно остановить выполнение скрипта и сбросить данные обратно в файл.

        sub error_connection {

        print "Проверьте правильность имени и пароля на базу в MySQL, ее существование\n";
        print "Возможной причиной ошибки так же может являться то, что сервер временно не доступен\n";
        print "Будет произведено копирование всех данных в файл:\n\n$ipacct_log \n\n";
        print "Накопление статистики в файл не лимитипровано, но это может повлечь за собой";
        print " всплеск нагрузки на сеть и сервера. По этому обратите внимание на данное";
        print " сообщение и выясните конкретную причину.\n";
        foreach $line_arr(@ipacct_arr_in) {
        open (DUMPFILE, ">>$ipacct_log");
        $line_arr = "$line_arr\n";
        print DUMPFILE $line_arr;
        close (DUMPFILE);
        }
        die "Выход.\n";
        }

Вторая создает таблицу, в которую будет производиться запись данных.

        sub crt_table_log {
        my ($dbh,$sth,$count);
        $dbh = DBI->connect("DBI:mysql:host=$serverdb;database=$dbname", "$dbuser", "$dbpass") 
        or &error_connection;
        $select = "CREATE  TABLE $table_date (ip_from varchar(255),s_port varchar(128),ip_to varchar(255),
                 d_port   varchar(128), proto varchar(32), packets int(8), bytes int(16) default 0,
         date_ins varchar(32), time_ins time,host  varchar(128), interface varchar(8),
         index (ip_from),index (ip_to),index (proto),index (packets), index (bytes),
         index (host), index (time_ins), index (date_ins), index (interface))";

        $sth = $dbh->prepare("$select");
        $sth->execute ();
        $sth->finish;
        $dbh->disconnect;

        }

Ну и наконец последнее - заносим данные в базу:

        sub insert_data_db {
        my ($dbh,$sth,$count);
        $dbh = DBI->connect("DBI:mysql:host=$serverdb;database=$dbname","$dbuser","$dbpass")
                        or &error_connection_in;
        $insert = "INSERT INTO $table_date (ip_from,s_port,ip_to,d_port,proto,packets,bytes,
date_ins,time_ins,host,interface)
VALUES (?,?,?,?,?,?,?,?,?,?,?)";
        $sth = $dbh->prepare("$insert");
        print "$insert\n";
        while (@ipacct_arr_in) {
        $line_in = shift @ipacct_arr_in; ($ip_from,$s_port,$ip_to,$d_port,$proto,$packets,$bytes,
$date_ins,$time_ins,$host,$interface)=split(/[\s\t]+/,$line_in);
        if (!defined $proto){
        $proto="0";
        }
        if (!defined $packets){
        $packets="0";
        }
        if (!defined $bytes){
        $bytes="0";
        }
        $sth->execute ($ip_from,$s_port,$ip_to,$d_port,$proto,$packets,$bytes,$date_ins,$time_ins,$host,$interface);
        }
        $sth->finish;
        $dbh->disconnect;
        }

Как видите, снова идет пошаговое считывание данных из массива. Полученные строки разбиваются на составляющие при помощи split. Если значения в этих переменных отсутствуют, им присваивается значение равное нулю.

Вот в принципе все. Мы занесли данные в таблицу.

Теперь можно извлекать нужные данные соответствующими запросами на выборку.

Полностью одержимое можно посмотреть в ng_stat_in.pl

Последние штрихи ? помещение созданного сценария в /usr/local/etc/rc.d и добавление подобной записи в /etc/crontab

        */15 * * * * root /usr/local/script/ng_stat/bin/ng_stat_in.pl

Наша система готова к сбору статистики. 

Конечно, данная система не лишена ряда недостатков. Таковыми можно считать то, что работает она именно от пользователя root, и не имеет возможности на лету менять конфигурацию. 

Самое главное ее преимущество - простота.  Она предоставляет самое удобное хранилище данных, откуда их можно вытянуть и при помощи web, и с консоли, и даже с машины под управлением Windows. Я думаю, оттолкнуться от этого и поплыть (думаю лучше оставить как есть ? все такие это часто употребляемый фразеологизм ?оттолкнуться и поплыть?, так что разночтений не будет)сможет каждый.  

Итак,  были выполнены практически все требования к биллингу. Мы остановимся пока на этом, ибо не маленький объем вышел, для трех простеньких скриптов. Если у читателей появится желание, приведу дополнительный набор скриптов и их описание, систему авторизации через web-интерфейс и, если необходимо, графические клиенты под X-Window и MS Windows. 

В принципе вы и сами можете написать самые простые запросы уже сейчас.
Приведу еще раз заголовки таблицы:

        mysql> show columns from 2004_10;
        +-----------+--------------+------+-----+---------+-------+
        | Field     | Type         | Null | Key | Default | Extra |
        +-----------+--------------+------+-----+---------+-------+
        | ip_from   | varchar(255) | YES  | MUL | NULL    |       |
        | s_port    | varchar(128) | YES  |     | NULL    |       |
        | ip_to     | varchar(255) | YES  | MUL | NULL    |       |
        | d_port    | varchar(128) | YES  |     | NULL    |       |
        | proto     | varchar(32)  | YES  | MUL | NULL    |       |
        | packets   | int(8)       | YES  | MUL | NULL    |       |
        | bytes     | int(16)      | YES  | MUL | 0       |       |
        | date_ins  | varchar(32)  | YES  | MUL | NULL    |       |
        | time_ins  | time         | YES  | MUL | NULL    |       |
        | host      | varchar(128) | YES  | MUL | NULL    |       |
        | interface | varchar(8)   | YES  | MUL | NULL    |       |
        +-----------+--------------+------+-----+---------+-------+
        11 rows in set (0.00 sec)

        mysql>

И простенький запрос к базе на выборку за 10 месяц 2004 года сумы прошедшего трафика через интерфейс rl0 сервера freebsd2:

        mysql> select sum(bytes) from 2004_10 where host='freebsd2' and interface='rl0';
        +-----------+
        |sum(bytes) |
        +-----------+
        |993453162  |
        +-----------+
        1 row in set (0.12 sec)

        mysql>

Все остальные скрипты, вне зависимости от своего назначения, являются вариациями на тему запроса.


Подведем итоги.

Разобранные выше примеры написания системы учета трафика не полноценный биллинг, так как для такой системы нужно хорошо просчитать структуру самой БД, ее нагрузку, выбрать оптимальные типы полей в таблицах. Для примера, в более серьезном и нагруженнном варианте(сервер провайдера и порядка 20 хостов), необходимо изменить типы полей  s_port, d_port, ip_from, ip_to на тип int(преобразование ip-адреса выполняется встроенными функциями MySQL), одним словом уделить очень большое внимание настройке оптимальной производительности самой СУБД ? здесь она станет узким местом, и возможно перейти на альтернативную СУБД.

Но подводя итоги этой статьи можно с увереностью сказать самое главное:
ng_ipacct является очень удобный программным пакетом для сбора полной и детализированной статистики. Причем он не требует каких-то особых заоблочных знаний и предоставляет удобную в отображении информацию. Он единолично может заменить вам систему учета трафика, даже если вы будете каждый день мигрировать с одного типа брендмауера на другой. При этом особо не нагрузит ваш сервер. 

Так же можно добавить, что сам процесс сбора статистики и запись полученных данных, средствами perl не представляет особой сложности ? весь необходимый набор инструментов встроен в perl либо присутствует в виде портов и пакетов.

Большую часть подпрограмм (например чтение конфигурационного файла) можно вынести в отдельный модуль/пакет.

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

Архив со скриптами находиться по адресу:
http://www.samag.ru/source/f0205-1.zip
а так же
http://skif.in.ua/soft/ng_stat_script.tar.gz
http://www.opennet.ru/soft/ng_stat_script.tar.gz

P.S.: Касательно скриптов расположенных на SKIF.IN.UA - эти скрипты время от времени дорабатываются, так что там может быть разночтенние с базовыми и приведенным в статье кодом.

P.P.S: Так как статья писалась достаточно давно, то там отображен период, когда ng_ipacct не входил в порты, на данный момент он там наличиствует

P.P.S: Nfr

Благодарности: Особая благодарность Глебу Смирнову (Gleb Smirnoff) из UAFUG рассылки за  подробное объяснение того как дышит netgraph. К сожалению благодарности из статьи были вырезаны редакторами журнала и мне было несколько не удобно за сей прискорбный факт, думаю теперь я себя реабилитировал.
 
Автор: Skif ( http://skif.in.ua )
Категория: Net | Добавил: oleg (15.11.2007)
Просмотров: 1122 | Рейтинг: 0.0/0 |
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Форма входа

Beastie

Друзья сайта

Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0
links

Copyright MyCorp © 2024