понедельник, марта 27, 2006

Пример простой системы учета трафика

У многих начинающих системных администраторов часто стоит вопрос, а как организовать систему учета трафика? С подобными вопросами вы сталкнетесь на многих форумах в интернете.
В рамках данной статьи мы рассмотрим простую систему учета трафика, которая должна будет обладать следующими характеристика:
Учет всего трафика проходящего через маршрутизатор работающий под ОС Linux;
Возможностью быстрого изменения конфигурации без внесения изменений в код;
Данные о трафике должны храниться в базе данных, в нашем случае мы в качестве
сервера баз данных будем использовать MySQL.
В рассматриваемом примере будем считать, что все IP адреса в нашей сети реальные.
Начнем с создания конфигурационного файла, назовем его billing.conf. Пусть он имеет следующий вид:
<******* billing.conf **************>
# Формируем список IP адресов машин или сетей, для которых мы будем считать
трафик
# Рабочее место WS1="192.168.0.1"
# Ceть нашего клиента NET="192.168.1.0/24"
# Объединим объединим все сети и адреса в один список.
ALLNETS="$WS1 $NET"
<**********************************>

В принципе формировать списки для каждого адреса или сети нет необходимости, т.к. рассматриваемая система использует только список ALLNETS, однако они могут понадобиться в случае если вам нужно будет обрабатывать статистику о каждомпользователе. Данный конфигурационный файл является единой для всей нашей системы, состоящей как минимум из трех программ:
· Программы формирования правил учета для firewall, с использованием iptables;
· Программы снятия статистики;
· Программы отображения статистики;
Рассмотрим программу формирования правил учета для firewall, названную в нашем случае rc.firewall, которую нужно будет добавить в один из файлов, который будет выполняться при загрузке системы.
Для начала немного теории, в ядрах Linux серии 2.4.X используется firewall NetFilter интерфейсом к которому является программа iptables. В NetFilter cущестуют несколько цепочек:
INPUT - все входящии пакеты, адресованные маршрутизатору,
OUTPUT - все исходящии из маршрутизатора пакеты,
FORWARD - все пересланные маршрутизатором пакеты во внешнюю сеть.
<******* rc.firewall **************>
#!/bin/bash
# Подключаем конфигурационный файл.
/etc/lbiling.conf IPTABLES="/sbin/iptables"
# Задаем путь к программе iptables ###################################
# Учет трафика ###################################
# Функция для создания правила учета addrule(){ $IPTABLES -N ACCT_IN_$1
# Создаем правило для учета входяшего трафика $IPTABLES -N ACCT_OUT_$1
# Создаем правило для учета изходяшего трафика
$IPTABLES -F ACCT_IN_$1 # Обнулим полученные цепочки
$IPTABLES -F ACCT_OUT_$1
$IPTABLES -A INPUT -j ACCT_IN_$1
# Включим учет по цепочкам $IPTABLES -A FORWARD -j ACCT_IN_$1
$IPTABLES -A FORWARD -j ACCT_OUT_$1
$IPTABLES -A OUTPUT -j ACCT_OUT_$1
$IPTABLES -A ACCT_IN_$1 -s $2 # Считать входящим трафик у которого источник адрес $2
$IPTABLES -A ACCT_OUT_$1 -d $2 # Считать исходящим трафик у которого получатель адрес $2 }
# Создаем правила для учета трафика
for NET in $ALLNETS;
do # Для всех сетей в списке $ALLNET создать правила учета трафика
addrule $NET $NET
done
<**********************************>
После выполниния нашей программы rc.firewall, набрав в консоле:
# iptables -L
Вы должны будете увидеть нечто подобное:
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCT_IN_192.168.0.1 all -- anywhere anywhere
ACCT_IN_192.168.1.0/24 all -- anywhere anywhere
Chain FORWARD (policy ACCEPT) target prot opt source destination
ACCT_IN_192.168.0.1 all -- anywhere anywhere
ACCT_OUT_192.168.0.1 all -- anywhere anywhere
ACCT_IN_192.168.1.0/24 all -- anywhere anywhere
ACCT_OUT_192.168.1.0/24 all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ACCT_OUT_192.168.0.1 all -- anywhere anywhere
ACCT_OUT_192.168.1.0/24 all -- anywhere anywhere
Chain ACCT_IN_192.168.0.1 (2 references)
target prot opt source destination all -- 192.168.0.1 anywhere
Chain ACCT_IN_192.168.1.0/24 (2 references)
target prot opt source destination all -- 192.168.1.0/24 anywhere
Chain ACCT_OUT_192.168.0.1 (2 references)
target prot opt source destination all -- anywhere 192.168.0.1
Chain ACCT_OUT_192.168.1.0/24 (2 references)
target prot opt source destination all -- anywhere 192.168.1.0/24
Создадим базу данных в MySQL с названием trafficbd, для этого необходимо будет
выполнить следующий SQL запрос (как это сделать не входит в рамки нашей статьи, обратитесь к документации MySQL):
<***** База данных trafficbd.sql *****>
CREATE DATABASE IF NOT EXISTS trafficbd;
use trafficbd;
#
# Структура таблицы `traffic`
#
CREATE TABLE traffic (
id int(11) NOT NULL auto_increment,
date datetime NOT NULL default '0000-00-00 00:00:00',
ip varchar(20) NOT NULL default '',
inb int(11) NOT NULL default '0',
outb int(11) NOT NULL default '0',
KEY id (id)
) TYPE=MyISAM;
<**********************************>
Итак, подведем итоги, мы создали базу данных, написали правила учета трафика,
теперь нам надо паписать программу, которая бы снимала полученную статистику, заносила её в базуданных и после этого обнуляла бы счетчики. Ниже приведен пример такой программы, её можно прописать в CRON и вызывать с некоторым периодом.
<**********************************>
<#!/usr/bin/perl
# Функция занимающаяся сбором и внесением данных в БД.
sub account {
$name=$_[0];
# Имя правила
$IP_IN=0;
# Инициализация счетчиков
$IP_OUT=0;
# Командная строка MySQL для внесения данных в таблицу.
$mysqlcommand="/usr/bin/mysql -hlocalhost trafficbd -e";
# Снимем данные со счетчика входящего трафика и обнулим
$ipstuff=`/sbin/iptables -L -Z ACCT_IN_$name -v -x`;
# Выделим из вывода предыдущей команды значение счетчика
@IPTBMASS=split(/\n/,$ipstuff);
chomp $IPTBMASS[2];
$string=$IPTBMASS[2];
$string=~ s/\s{1,}/ /g;
@INFOMASS=split(//,$string);
$IP_IN=$INFOMASS[2];
# Снимем данные со счетчика исходящего трафика и обнулим
$ipstuff=`/sbin/iptables -L -Z ACCT_OUT_$name -v -x`;
# Выделим из вывода предыдущей команды значение счетчика
@IPTBMASS=split(/\n/,$ipstuff);
$string=$IPTBMASS[2]; $string=~ s/\s{1,}/ /g;
@INFOMASS2=split(/ /,$string);
$IP_OUT=$INFOMASS2[2];
# Получим текущее время
($min, $hours, $day, $mounth,$year) = (localtime)[1,2,3,4,5];
$time=$hours.":".$min.":00";
$mounth=$mounth+1; $year=$year+1900;
$date=$year."-".$mounth."-".$day;
# Формируем SQL запрос
$sql="insert into traffic values('','".$date."
".$time."','".$name."','".$IP_IN."','".$IP_OUT."');";
# Выполняем его `$mysqlcommand "$sql"`;
}
# На этом функция account заканчивается:)
# Основая программа $config=`./lconfreader.sh`;
# Прочитаем конфигурационный файл.

Ниже приводится текст скрипта lconfreader.sh:
#
#!/bin/bash # . ./lbiling.conf
# Включить конфигурационный файл
echo $ALLNETS
# Вывести в stdout список всех сетей, покоторым ведется учет .
chomp $config;
@NETMASS=split(/ /,$config);
foreach $nets(@NETMASS)
{
# Для каждого элемента списка, выполнить функцию
account account $nets;
}

<**********************************>
Вот собственно и вся биллинговая система:)

Комментариев нет: