Инструменты пользователя

Инструменты сайта


doc:os:freebsd:ng_ipacct:ng_ipacct

Подсчет траффика с помощью ng_ipacct

Советую для начала прочитать, что такое netgraph. Например, вот здесь.

Среда окружения:

  • ОС FreeBSD 8.2-Stable
  • MySQL server 5.1
  • обновленное дерево портов
  • Пересобранное ядро с опциями:
options    NETGRAPH
options    NETGRAPH_ETHER
options    NETGRAPH_IFACE
options    NETGRAPH_KSOCKET
options    NETGRAPH_SOCKET

Порядок действий

1. Устанавливаем порты:

/usr/ports/databases/p5-DBI
/usr/ports/databases/p5-DBD-mysql51
/usr/ports/net-mgmt/ng_ipacct

Порт p5-DBD-mysql51 должен согласовываться с вашей установленной версией MySQL server.

2. Создаем необходимые каталоги:

mkdir -p /var/scripts/ng_stat/etc
mkdir /var/scripts/ng_stat/bin
mkdir /var/scripts/ng_stat/log

3. Создаем БД, которая будет хранить сведения по траффику, пользователя nguser с паролем pass:

# mysql -p
create database ng_stat;
grant insert,create,update,select,delete on ng_stat.* to nguser@'localhost' identified by 'pass';

4. В /var/scripts/ng_stat/etc создаем файл ng_stat.conf следующего содержания:

# Имя сервера, где находиться база данных статистики
server_db = localhost
# Имя базы данных, где будет сохраняться статистика
db_name = ng_stat
# Имя пользователи для доступа к базе
db_user = nguser
# Пароль для доступа к базе
db_pass = pass
# Таблица для авторизации пользователей через WEB.
table_auth = ipacct_auth
# Таблица со списком протоколов, эквивалент /etc/protocols
table_protocols = protocols
# Имя хоста с которого снимается статистика
listen_host = localhost
# Имена интерфейсов, которые прослушиваются на компьютере.
# Указывать через запятую
listen_interfaces = xl0,xl1
# Загружаемые модули NETGRAPH, необходимые для интерфейсов,
# которые будет обслуживать программа
# По умолчанию загружаются следующие модули: netgraph,
# ng_ether,ng_socket,ng_tee,ng_ipacct
ng_modules = netgraph,ng_ether,ng_socket,ng_tee,ng_ipacct
# Какой трешхолд необходимо установить для работы системы.
# Отнеситесь внимательно к выбору этого параметра. Он
# означает сколько записей будет храниться в буфере
# По умолчанию значение равно 5000, но если у вас меньше
# 128 Мегабайт памяти  - уменьште его.
threshold = 10000

5. В папке bin создадим свой скрипт ng_stat_start.pl:

#!/usr/bin/perl -w

use DBI;
use POSIX ":sys_wait_h";
#use strict;
#########################
# Список основных переменных
#########################
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 $iface_set = "no";
my @ng_modules;
my $ng_modules_def = "netgraph,ng_ether,ng_socket,ng_tee,ng_ipacct";
my $threshold = 5000;
#########################
# Читаем конфиг. файл.
#########################
open (CONFIG, "/var/scripts/ng_stat/etc/ng_stat.conf");

while (<CONFIG>) {
    $comment = '#';
    if(/^$comment/) {
#    print "Коментарий\n";
    }
    else {
    ($param,$arg) = split("=",$_);
    chomp $param;
    chomp $arg;
    my $razdel = "";
    $param =~ s/[\s\t]+/$razdel/g;
    $arg =~ s/[\s\t]+/$razdel/g;
    if ($param eq "server_db"){
	$serverdb = $arg;
    }
    if ($param eq "db_name"){
    	$dbname = $arg;
    }
    if ($param eq "db_user") {
    	$dbuser = $arg;
    }
    if ($param eq "db_pass") {
        $dbpass = $arg;
    }
    if ($param eq "table_auth") {
        $table_auth = $arg;
    }
    if ($param eq "table_protocols") {
        $table_proto = $arg;
    }
    if ($param eq "listen_host") {
        $listen_host = $arg;
    }
    if ($param eq "listen_interfaces") {
	my $coma = ',';
	if (defined $arg) {
		$iface_set = "ok";
		if ($arg ne ""){
			if ($arg =~ m/$coma/ ) {
				@listen_interf=split($coma,$arg);
			}
			else {
				@listen_interf = $arg;
			}
		}
	}
    }
    if ($param eq "ng_modules") {
    
	my $coma = ',';
	if ($arg =~ m/$coma/ ){
		@ng_modules = split($coma,$arg);
	} 
	else {
	
	    @ng_modules = split ($coma,$ng_modules_def);
	}
    
    }
    if ($param eq "threshold") {
	$threshold = $arg;
    }

    }
}
close (CONFIG);

if (!defined $listen_interf[0]) {
    print "Установите пожалуйста в режим прослушивания хотя бы один интерфейс.\n";
}
else {

    &check_kld_modules;
    &listening;
    
}

sub check_kld_modules {
    my @modules;
    my $pid;
    my $ng_module_cfg;
    my $chk_ng_file = "/tmp/ng_file";
    my $check_ng = 'kldstat -v | grep ng';
    $check_ng = "$check_ng";# " > $chk_ng_file";
    my $check_netgraph = 'kldstat -v | grep netgraph';
    $check_netgraph = "$check_netgraph";#" >> $chk_ng_file";
#    $pid = fork;

@modules =split ("\n", `$check_ng && $check_netgraph`);
my $mod;
$mod = "";
if (defined $modules[0]) {
	foreach my $modules (@modules) {
		$modules=~ s/\d+//g;
		if ($modules =~ s/.ko//g) {
		#
		}
		else {
			$modules =~ s/[\s\t]+//g;
			$mod = "$mod $modules ";
		}
	}
	chop $mod;
	
	foreach my $ng_modules (@ng_modules) {
		if ($mod=~m/$ng_modules/g){
		#	print "$mod содержит $ng_modules\n";
		}
		else {
			my ($pid,$kid);
			
			$pid = fork;
			if (defined $pid) {
				if ($pid == 0){
					print "Загрузка необходимого модуля ",$ng_modules,"\n";
					exec "/sbin/kldload $ng_modules > /dev/null 2>&1"  or die "Ошибка загрузки модуля $ng_modules !\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;
		}
	}
}
else {
	foreach my $ng_modules (@ng_modules) {
		my ($pid,$kid);
			
		$pid = fork;
		if (defined $pid) {
			if ($pid == 0){
				print "Загрузка необходимого модуля ",$ng_modules,"\n";
				exec "/sbin/kldload $ng_modules > /dev/null 2>&1"  or die "Ошибка загрузки модуля $ng_modules !\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;
		undef $pid;
	}
	
}
}

sub listening {
	my $pid;
    $ngctl = "/usr/sbin/ngctl";
	$ipacctctl = "/usr/local/sbin/ipacctctl";
    while (@listen_interf){
    
	$interface = shift @listen_interf;
#/usr/sbin/ngctl mkpeer ${IFACE}: tee lower right
        $mkpeer = "$ngctl mkpeer $interface\: tee lower right";
	$pid = fork;
	if (defined $pid) {
		if ($pid == 0){
			print "Создание и подключение нового NETGRAPH-узла к уже существующему:\n $mkpeer\n";
			exec "$mkpeer" or die "Ошибка создания нового узла NETGRAPH!\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;
	
#/usr/sbin/ngctl connect ${IFACE}: lower upper left	
        $connect = "$ngctl connect $interface\: lower upper left";
	
	$pid = fork;
        if (defined $pid) {
                if ($pid == 0){
			print "Соединение двух NETGRAPH-узлов на интерфейсе:\n$connect\n";
        		exec "$connect" or die "Ошибка соединения двух NETGRAPH-узлов!\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;
	
#/usr/sbin/ngctl name ${IFACE}:lower ${IFACE}_acct_tee	
        $name = "$ngctl name $interface\:lower $interface\_acct_tee ";
	
	$pid = fork;
        if (defined $pid) {
                if ($pid == 0){
			print "Присвоение имени созданному узлу:\n$name\n";
        		exec "$name" or die "Ошибка на этапе присвоения имени созданному узлу!\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;

#/usr/sbin/ngctl mkpeer ${IFACE}_acct_tee: ipacct right2left ${IFACE}_in	
        $mkpeer = "$ngctl mkpeer $interface\_acct_tee: ipacct right2left $interface\_in";
	
	$pid = fork;
        if (defined $pid) {
                if ($pid == 0){
			print "Создание и подключение нового NETGRAPH-узла к уже существующему:\n $mkpeer\n";
			exec "$mkpeer" or die "Ошибка создания нового узла NETGRAPH!\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;
	
#/usr/sbin/ngctl name ${IFACE}_acct_tee:right2left ${IFACE}_ip_acct	
        $name = "$ngctl name $interface\_acct_tee:right2left $interface\_ip_acct";
	
	$pid = fork;
        if (defined $pid) {
                if ($pid == 0){
			print "Присвоение имени созданному узлу:\n$name\n";
        		exec "$name" or die "Ошибка на этапе присвоения имени созданному узлу!\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;
	
#/usr/sbin/ngctl connect ${IFACE}_acct_tee: ${IFACE}_ip_acct: left2right ${IFACE}_out
	$connect = "$ngctl connect $interface\_acct_tee: $interface\_ip_acct: left2right $interface\_out";
	
	$pid = fork;
        if (defined $pid) {
                if ($pid == 0){
			print "Соединение двух NETGRAPH-узлов на интерфейсе:\n$connect\n";
        		exec "$connect" or die "Ошибка соединения двух NETGRAPH-узлов!\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;
	
#$IPACCTCTL ${IFACE}_ip_acct:$IFACE verbose $VERBOSE	
        $verbose = "$ipacctctl $interface\_ip_acct:$interface verbose 1";

	$pid = fork;
        if (defined $pid) {
                if ($pid == 0){
			print "Установка режима вывода информации:\n$verbose\n";
        		exec "$verbose" or die "Ошибка установки режима вывода информации\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;
	
#$IPACCTCTL ${IFACE}_ip_acct:$IFACE threshold $THRESHOLD	
        $set_threshold = "$ipacctctl $interface\_ip_acct:$interface threshold $threshold";

	$pid = fork;
        if (defined $pid) {
                if ($pid == 0){
			print "Установка THRESHOLD:\n$set_threshold\n";
        		exec "$set_threshold" or die "Ошибка установки параметра THRESHOLD\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;
    }

}

exit(0);

5.1 Даем права на запуск:

chmod a+x ng_stat_start.pl

5.2 Выполняем скрипт ng_stat_start.pl. Смотрим на ошибки, если есть. Мой вывод:

Загрузка необходимого модуля ng_ether
Создание и подключение нового NETGRAPH-узла к уже существующему:
 /usr/sbin/ngctl mkpeer bge0: tee lower right
ngctl: send msg: File exists
Соединение двух NETGRAPH-узлов на интерфейсе:
/usr/sbin/ngctl connect bge0: lower upper left
ngctl: send msg: File exists
Присвоение имени созданному узлу:
/usr/sbin/ngctl name bge0:lower bge0_acct_tee
ngctl: send msg: Address already in use
Создание и подключение нового NETGRAPH-узла к уже существующему:
 /usr/sbin/ngctl mkpeer bge0_acct_tee: ipacct right2left bge0_in
ngctl: send msg: File exists
Присвоение имени созданному узлу:
/usr/sbin/ngctl name bge0_acct_tee:right2left bge0_ip_acct
ngctl: send msg: Address already in use
Соединение двух NETGRAPH-узлов на интерфейсе:
/usr/sbin/ngctl connect bge0_acct_tee: bge0_ip_acct: left2right bge0_out
ngctl: send msg: File exists
Установка режима вывода информации:
/usr/local/sbin/ipacctctl bge0_ip_acct:bge0 verbose 1
Установка THRESHOLD:
/usr/local/sbin/ipacctctl bge0_ip_acct:bge0 threshold 10000

6. Создаем в каталоге /usr/local/etc/rc.d стартовый скрипт ng_stat.sh:

#!/bin/sh 

case "$1" in 
start) 
/var/scripts/ng_stat/bin/ng_stat_start.pl 
;; 
stop) 
/var/scripts/ng_stat/bin/ng_stat_stop.pl 
;; 
*) 
echo "" 
echo "Usage: `basename $0` { start | stop }" 
echo ""
;;
esac

7. Создаем скрипт /var/scripts/ng_stat/bin/ng_stat_stop.pl:

#!/usr/bin/perl -w

use DBI;
use POSIX ":sys_wait_h";
#########################
# Список основных переменных
#########################
my $ngctl = "/usr/sbin/ngctl";
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 $iface_set = "no";

#########################
# Читаем конфиг. файл.
#########################
open (CONFIG, "/var/scripts/ng_stat/etc/ng_stat.conf");
while (<CONFIG>) {
    $comment = '#';
    if(/^$comment/) {
#    print "Коментарий\n";
    }
    else {
    ($param,$arg) = split("=",$_);
    chomp $param;
    chomp $arg;
    my $razdel = "";
    $param =~ s/[\s\t]+/$razdel/g;
    $arg =~ s/[\s\t]+/$razdel/g;
    if ($param eq "server_db"){
	$serverdb = $arg;
    }
    if ($param eq "db_name"){
    	$dbname = $arg;
    }
    if ($param eq "db_user") {
    	$dbuser = $arg;
    }
    if ($param eq "db_pass") {
        $dbpass = $arg;
    }
    if ($param eq "table_auth") {
        $table_auth = $arg;
    }
    if ($param eq "table_protocols") {
        $table_proto = $arg;
    }
    if ($param eq "listen_host") {
        $listen_host = $arg;
    }
    if ($param eq "listen_interfaces") {
	my $coma = ',';
	if (defined $arg) {
		if ($arg ne ""){
			if ($arg =~ m/$coma/ ) {
				@listen_interf=split($coma,$arg);
			}
			else {
				@listen_interf = $arg;
			}
		}
	}
    }
    }
}
close (CONFIG);

if (!defined $listen_interf[0]) {
    print "Установите пожалуйста в режим прослушивания хотя бы один интерфейс.\n";
}
else {

   foreach my $interface (@listen_interf){
#/usr/sbin/ngctl shutdown ${IFACE}_acct_tee:
        $shutdown = "$ngctl shutdown $interface\_acct_tee:";
	my $pid;
	$pid = fork;
        if (defined $pid) {
                if ($pid == 0){
			print "Отключение созданных узлов на интерфейсе:\n$shutdown\n";
			exec "$shutdown";
			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;
#	sleep 1;
	$shutdown = "$ngctl shutdown $interface\:";
	$pid = fork;
        if (defined $pid) {
                if ($pid == 0){
			print "Отключение NETGRAPH на интерфейсе:\n$shutdown\n";
			exec "$shutdown";
				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;
    }
}

exit(0);

7.1 Даем скрипту ng_stat_stop.pl права на выполнение.

7.2 Проверяем работу скрипта.

8. Cоздаем скрипт /var/scripts/ng_stat/bin/ng_stat_in.pl:

#!/usr/bin/perl -w

use DBI;
use Time::localtime;
use POSIX ":sys_wait_h";

#########################
# Список основных переменных
#########################
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 $iface_set = "no";
my @ng_modules;
my $ng_modules_def = "netgraph,ng_ether,ng_socket,ng_tee,ng_ipacct";
my $threshold = 5000;
my $ipacct_log = '/var/scripts/ng_stat/log/ng.log';
my @ipacct_arr;
my @ipacct_arr_in;
##########################
# Читаем конфиг. файл.
#########################
open (CONFIG, "/var/scripts/ng_stat/etc/ng_stat.conf");

while (<CONFIG>) {
    $comment = '#';
    if(/^$comment/) {
#    print "Коментарий\n";
    }
    else {
    my ($param,$arg) = split("=",$_);
    chomp $param;
    chomp $arg;
    $param =~ s/[\s\t]+//g;
    $arg =~ s/[\s\t]+//g;
    if ($param eq "server_db"){
        $serverdb = $arg;
    }
    if ($param eq "db_name"){
        $dbname = $arg;
    }
    if ($param eq "db_user") {
        $dbuser = $arg;
    }
    if ($param eq "db_pass") {
        $dbpass = $arg;
    }
    if ($param eq "table_auth") {
        $table_auth = $arg;
    }
    if ($param eq "table_protocols") {
        $table_proto = $arg;
    }
    if ($param eq "stat_file") {
        $ipacct_log = $arg;
    }
    if ($param eq "listen_host") {
        $listen_host = $arg;
    }
    if ($param eq "listen_interfaces") {
        my $coma = ',';
        if ($arg =~ m/$coma/ ) {
            @listen_interf=split($coma,$arg);
            }
        else {
        @listen_interf = $arg;
        }
    }
    if ($param eq "ng_modules") {
	my $coma = ',';
        if ($arg =~ m/$coma/ ){
            @ng_modules = split($coma,$arg);
        } else {

            @ng_modules = split ($coma,$ng_modules_def);
        }

    }
    if ($param eq "threshold") {
        $threshold = $arg;
    }

    }
}
close (CONFIG);

#########################
# Проверяем время.
#########################
$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";

if (!defined $listen_interf[0]) {
    print "Установите пожалуйста в режим прослушивания хотя бы один интерфейс.\n";
}
else {

	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 (<TMPLOG>){
			$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;
}

sub check_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 ();
my @row;
my $tables;
while (@row = $sth->fetchrow_array) {
	foreach $tables (@row){
		push @dbtables, $tables;
	}
}
$crt_tbl="yes";
while (@dbtables) {
	$table = shift @dbtables;
	if (defined $table) {
		if ($table eq $table_date) {
			$crt_tbl="no";
		}
	}
}

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

$sth->finish;
$dbh->disconnect;

}

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;
}

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

exit(0);

8.1 Делаем скрипт исполняемым.

8.2 Выполняем скрипт. Смотрим на ошибки.

Итак, за каждый месяц должна автоматически создаваться табличка со столбцами:

+-----------------+--------+-----------------+--------+-------+---------+---------+----------+----------+-----------+-----------+
| ip_from         | s_port | ip_to           | d_port | proto | packets | bytes   | date_ins | time_ins | host      | interface |
+-----------------+--------+-----------------+--------+-------+---------+---------+----------+----------+-----------+-----------+

8.3 Помещаем вызов скрипта ng_stat_in.pl в крон:

*/15 * * * *	root	/var/scripts/ng_stat/bin/ng_stat_in.pl

TAG:

Обсуждение

, d.m.Y H:i

With thanks, Numerous facts. casino en ligne Very good data Many thanks! casino en ligne You actually said it really well. casino en ligne Really a good deal of very good knowledge. casino en ligne fiable With thanks! I appreciate it! casino en ligne This is nicely said. ! casino en ligne France You revealed this effectively. casino en ligne Wow all kinds of great information. casino en ligne francais Incredible all kinds of excellent material. casino en ligne Seriously tons of superb data. casino en ligne

, d.m.Y H:i

With thanks, Numerous facts. casino en ligne Very good data Many thanks! casino en ligne You actually said it really well. casino en ligne Really a good deal of very good knowledge.

casino en ligne fiable With thanks! I appreciate it! casino en ligne This is nicely said. ! casino en ligne France You revealed this effectively. casino en ligne Wow all kinds of great information. casino en ligne francais Incredible all kinds of excellent material.

casino en ligne Seriously tons of superb data. casino en ligne

Ваш комментарий. Вики-синтаксис разрешён:
 
/var/www/wiki.itcall.ru/data/pages/doc/os/freebsd/ng_ipacct/ng_ipacct.txt · Последнее изменение: d.m.Y H:i — 127.0.0.1