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

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


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

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

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

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

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, "/usr/local/script/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;
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);

Обсуждение

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