ipfw и ipacctd. Считаем трафик во FreeBSD

Существует достаточно готовых систем подсчета трафика, но большая часть из них черезчур навороченная для небольшого оффиса и часто не стоят того времени, которое нужно на их внедрение. Маленький биллинг легко создать самому. В принципе нам нужны 2 составляющие для учета трафика. 1-я это система сбора данных по трафику и вторая – система которая посчитает трафик.

Для сбора трафика воспользуемся файерволом, ipacctd и небольшим перловым скриптом, который будет импортировать данные по трафику в базу MySQL.

В первую очередь создадим правила файерволла. Мы воспользуемся tee для копирования всех пакетов проходящих через внутренний интерфейс. Выглядит это так:

ipfw="/sbin/ipfw -q"

${ipfw} flush

${ipfw} add 1 tee 500 ip from any to any via em0

Это правило говорит копировать весь проходящий трафик через интерфейс em0 в divert порт 500.

Теперь нужно установить ipacctd и настроить его на этот порт. Ставим ipacctd из портов:

cd /usr/ports/net-mgmt/ipacctd/

make install clean

Установка проходит быстро без всяких там дополнительных диалогов настройкт. А настройка ipacctd производится непосредственно в стартовом скрипте, через флаги командной строки. Открываем /usr/local/etc/rc.d/ipacctd и добавляем такие строки:

ipacctd_rules="em0"

ipacctd_rule_em0_flags="-p 500 -t -s -w -v"

ipacctd_rule_em0_pid="/var/run/ipacctd_em0.pid"

А в /etc/rc.conf добавим:

echo 'ipacctd_enable="YES"' >> /etc/rc.conf

и запустим его:

/usr/local/etc/rc.d/ipacctd start

Проверяем наличие запущенного ipacctd:

ps afx|grep ipacctd

Если увидим примерно такое:

96053 ?? Ss 0:00,00 /usr/local/sbin/ipacctd -p 500 -t -s -w -v -r /var/run/ipacctd_em0.pid

то все запустилось нормально.

И проверим как у нас обстоит дело с открытыми сокетами ipacctd:

sockstat -l|grep ipacctd

Должно появится:

root ipacctd 96053 5 div4 *:500 *:*

root ipacctd 96053 6 stream /tmp/ipacct/ipacct.500

Первая строка это открытый диверт сокет, через который ipacctd получает копию всех проходящих через файерволл пакетов и вторая строка – unix сокет через который ipacctd будет отдавать накопленную информацию.

Проверяем – есть ли накопленная информация:

cat -f /tmp/ipacct/ipacct.500

должны увидеть информацию о прошедших пакетах.

Можно переходить к созданию базы MySQL в которую будем скриптом импортировать данные по пакетам.

mysql -uroot -p

create database ipacctd;

grant all on ipacctd.* to 'ipacctd'@'localhost' identified by 'ipacctd-777';

И создадим таблицу такого вида:

use ipacctd;

CREATE TABLE `traff` (

`timestamp` int(11) NOT NULL default '0',

`src` varchar(15) NOT NULL default '0.0.0.0',

`src_p` int(5) NOT NULL default '1',

`dst` varchar(15) NOT NULL default '0.0.0.0',

`dst_p` int(5) NOT NULL default '1',

`proto` varchar(4) NOT NULL default '',

`bytes` bigint(20) NOT NULL default '0',

`num` bigint(20) NOT NULL default '0',

KEY `traff_src` (`src`),

KEY `traff_dst` (`dst`),

KEY `traff_timestamp` (`timestamp`));

Теперь можно переходить к разработке скрипта, который будет импортировать прошедший трафик в базу.

Скрипт напишем на перле, поэтому нужно установить библиотеку для работы с MySQL:

cd /usr/ports/databases/p5-DBD-mysql50/

make install clean

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

#!/usr/bin/perl -w

use DBI;

$dbh=DBI->connect("dbi:mysql:ipacctd","ipacctd","ipacctd-777") or die "can't connect MySQL $!";

@traff=`/bin/cat /tmp/ipacct/ipacct.500`;

foreach(@traff)

{

@tmp=split(" ",$_);

$query="insert into traff set src='$tmp[0]', src_p='$tmp[1]', dst='$tmp[2]', dst_p='$tmp[3]', proto='$tmp[4]', bytes='$tmp[5]', num='$tmp

$dbh->do($query);

}

И поставим его(этот скрипт) на cron:

crontab -e

и в нем вносим строку:

*/5 * * * * /root/bin/import.pl

И теперь скрипт подсчета статистики. У меня он выглядит так:

#!/usr/bin/perl -w

use DBI;

if(!$ARGV[0] or !$ARGV[1] or !$ARGV[2])

{

print "Usage stat.pl ip.add.re.ss 01-01-2009 01-02-2009 ";

exit;

}

$dbh=DBI->connect("dbi:mysql:ipacctd","ipacctd","ipacctd-777") or die "can't connect MySQL $!";

$date_b_t=$ARGV[1];

chomp $date_b_t;

$date_e_t=$ARGV[2];

@date_b=split('-', $date_b_t);

@date_e=split("-",$date_e_t);

$timestamp_begin=`/bin/date -v$date_b[0]d -v$date_b[1]m -v$date_b[2]y -v0H -v0M -v0S +%s`;

$timestamp_end=`/bin/date -v$date_e[0]d -v$date_e[1]m -v$date_e[2]y -v0H -v0M -v0S +%s`;

chomp $timestamp_begin;

chomp $timestamp_end;

$ip=$ARGV[0];

chomp $ip;

$query="select sum(bytes)/1024/1024 from traff where timestamp>='$timestamp_begin' and timestamp<'$timestamp_end' and (src='$ip' or dst='$i

$sth=$dbh->prepare($query);

$sth->execute();

($traff)=$sth->fetchrow_array();

if(!$traff)

{

print "Traffic ip $ip с $date_b_t по $date_e_t не найден ";

}

else

{

print "Traffic ip $ip с $date_b_t по $date_e_t $traff Mb ";

}

Вызывается он так:

./stat.pl 192.168.1.1 01-01-2009 01-05-2009

В нашем примере, мы пытаемся посчитать трафик абонента 192.168.1.1 с 1 января 2009 года по 1-е мая 2009 года.

То есть за 4 месяца.

http://www.hilik.org.ua/ipfw-и-ipacctd-считаем-трафик/

Обновлено: 12.03.2015