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

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


doc:os:freebsd:ng_ipacct:ng_ipacct

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Предыдущая версия справа и слеваПредыдущая версия
Следующая версия
Предыдущая версия
doc:os:freebsd:ng_ipacct:ng_ipacct [d.m.Y H:i] dbehterevdoc:os:freebsd:ng_ipacct:ng_ipacct [d.m.Y H:i] (текущий) – внешнее изменение 127.0.0.1
Строка 1: Строка 1:
 ====== Подсчет траффика с помощью ng_ipacct ====== ====== Подсчет траффика с помощью ng_ipacct ======
  
-Советую для начала прочитать, что такое netgraph.+Советую для начала прочитать, что такое netgraph. Например, вот [[http://www.opennet.ru/base/net/all_about_netgraph.txt.html|здесь]].
  
 Среда окружения: Среда окружения:
Строка 16: Строка 16:
 </code> </code>
  
-Порядок действий:+===== Порядок действий =====
  
 **1.** Устанавливаем порты: **1.** Устанавливаем порты:
Строка 22: Строка 22:
 /usr/ports/databases/p5-DBI /usr/ports/databases/p5-DBI
 /usr/ports/databases/p5-DBD-mysql51 /usr/ports/databases/p5-DBD-mysql51
 +/usr/ports/net-mgmt/ng_ipacct
 </code> </code>
 Порт p5-DBD-mysql51 должен согласовываться с вашей установленной версией MySQL server. Порт p5-DBD-mysql51 должен согласовываться с вашей установленной версией MySQL server.
Строка 27: Строка 28:
 **2.** Создаем необходимые каталоги: **2.** Создаем необходимые каталоги:
 <code> <code>
 +mkdir -p /var/scripts/ng_stat/etc
 +mkdir /var/scripts/ng_stat/bin
 +mkdir /var/scripts/ng_stat/log
 +</code>
  
 +**3.** Создаем БД, которая будет хранить сведения по траффику, пользователя nguser с паролем pass:
 +<code>
 +# mysql -p
 +create database ng_stat;
 +grant insert,create,update,select,delete on ng_stat.* to nguser@'localhost' identified by 'pass';
 </code> </code>
 +
 +**4.** В /var/scripts/ng_stat/etc создаем файл ng_stat.conf следующего содержания:
 +<code>
 +# Имя сервера, где находиться база данных статистики
 +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
 +</code>
 +
 +**5.** В папке bin создадим свой скрипт ng_stat_start.pl:
 +<code>
 +#!/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);
 +</code>
 +**5.1** Даем права на запуск:
 +<code>
 +chmod a+x ng_stat_start.pl
 +</code>
 +
 +**5.2** Выполняем скрипт ng_stat_start.pl. Смотрим на ошибки, если есть.
 +Мой вывод:
 +<code>
 +Загрузка необходимого модуля 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
 +</code>
 +
 +**6.** Создаем в каталоге /usr/local/etc/rc.d стартовый скрипт ng_stat.sh:
 +<code>
 +#!/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
 +</code>
 +
 +**7.** Создаем скрипт /var/scripts/ng_stat/bin/ng_stat_stop.pl:
 +<code>
 +#!/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);
 +
 +</code>
 +
 +**7.1** Даем скрипту ng_stat_stop.pl права на выполнение.
 +
 +**7.2** Проверяем работу скрипта.
 +
 +**8.** Cоздаем скрипт /var/scripts/ng_stat/bin/ng_stat_in.pl:
 +<code>
 +#!/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);
 +</code>
 +
 +**8.1** Делаем скрипт исполняемым.
 +
 +**8.2** Выполняем скрипт. Смотрим на ошибки. 
 +
 +Итак, за каждый месяц должна автоматически создаваться табличка со столбцами:
 +<code>
 ++-----------------+--------+-----------------+--------+-------+---------+---------+----------+----------+-----------+-----------+
 +| ip_from         | s_port | ip_to           | d_port | proto | packets | bytes   | date_ins | time_ins | host      | interface |
 ++-----------------+--------+-----------------+--------+-------+---------+---------+----------+----------+-----------+-----------+
 +</code>
 +
 +**8.3** Помещаем вызов скрипта ng_stat_in.pl в крон:
 +<code>
 +*/15 * * * * root /var/scripts/ng_stat/bin/ng_stat_in.pl
 +</code>
 +
 +TAG: {{tag> ng_ipacct FreeBSD}} 
 +
 +~~DISCUSSION~~
/var/www/wiki.itcall.ru/data/attic/doc/os/freebsd/ng_ipacct/ng_ipacct.1302366200.txt.gz · Последнее изменение: d.m.Y H:i (внешнее изменение)