Мы — долго запрягаем, быстро ездим, и сильно тормозим.

FreeBSD
  настройка
  подсчёт трафика
  trafd & MySQL
  WEB-морда к траффику
  SNMP
  ipacctd
  pfctl
  ntop 3.2
  NeTAMS
  NeTAMS 2
  SQUID+SAMS +Rejik-(NCSA)
  ng_ipacct + squid
  SQUID+SAMS +Rejik-(NTLM)
  SQUID+SAMS +Rejik-(LDAP)
  mpd5 + radius + ng_car + Abills
  darkstat
  Netams 3.4.5
  программы
  почтовые системы
  Шелезяки
  Мелочи
  Файловая система
  WWW
  Security
  system
  Games Servers
  X11
  Programming
Очумелые Ручки
OpenBSD
Cisco
www.lissyara.su —> статьи —> FreeBSD —> подсчёт трафика —> ipacctd

ipacctd - подсчёт траффика через IPFW

Автор: lissyara.


    Купили новый сервант, на AMD64 - (AMD - форева!) - под архивацию пользовательских документов, и прочего подобного хламу. Накатил на него, разумеется, фряху - 6-ю версию, платформа - x64. В-общем-то всё хорошо, но, как оказалось некоторые злостные программеры пишут строго под определённую архитектуру - x86 и всё тут... Первым таким приложением стал trafd - он компилился, запускался, но вот вместо статистики в файлы сохранялся какой-то бред... Пересобрал - бесполезно... Тогда собрал пакет на другой машине, тоже 6-я FreeBSD, но x86. Раскатал на AMD64 - не запускается... Что и ожидал (однако где-то в глубине души копошилась надежда - вдруг поднимется :))). Полез в порты - искать чем считать. Нашёл - bpft, сайт проекта мёртв, но вещщь родственная trafd. К сожалению родство оказалось слишком близким - у них одна наследственная болезнь - бред в логах. Снёс, полез дальше. Нашёл - ipacctd - сайт не указан.... Фомат логов очень похож на тот, что у trafd - потому переделки будут мелкими.
   Ставим из портов:
/usr/home/lissyara/>cd /usr/ports
/usr/ports/>make search name=ipacctd
Port:   ipacctd-1.46_1
Path:   /usr/ports/net-mgmt/ipacctd
Info:   IP accounting using divert socket
Maint:  skv@FreeBSD.org
B-deps:
R-deps:
WWW:

/usr/ports/>cd /usr/ports/net-mgmt/ipacctd
/usr/ports/net-mgmt/ipacctd/>make && make install && make clean

Программа абсолютно копеечного размера (15кб), но самый главный плюс оказался не в этом - если у Вы удосужились прикрутить русский язык к консоли, то сможете лицезреть ман по этой программе на русском :) Собственно по этой причине не буду расписывать ключи, и прочее.
  Работает через IPFW - пришлось пересобрать ядро и поднять файрволл. Извращаться особо не стал, забил совсем немного правил - машина с одним интерфейсом, смотрящим в локалку:
/etc/rc.firewall
#!/bin/sh -xv

# переменные
FwCMD="/sbin/ipfw"

${FwCMD} -f flush

${FwCMD} add divert 10001 ip from any to any via sk0
${FwCMD} add divert 10002 ip from any to any via lo0
#${FwCMD} add deny ip from not 192.168.0.0/16 to me
${FwCMD} add allow ip from any to any

Учтите, что правила надо добавлять в самом верху файрволла до остальных (сразу после -f flush). Также добавляем следующие строки в /etc/rc.conf (для двух интерфейсов - lo0 и sk0)
ipacctd_enable="YES"
ipacctd_flags="-v"
ipacctd_rules="sk0 lo0"
ipacctd_rule_sk0_flags="-p 10001 -f /var/log/traffic_sk0.log"
ipacctd_rule_sk0_pid="/var/run/ipacctd.sk0"
ipacctd_rule_lo0_flags="-p 10002 -f /var/log/traffic_lo0.log"
ipacctd_rule_lo0_pid="/var/run/ipacctd.lo0"

После чего запускаем ipacctd:
/usr/local/etc/rc.d/>./ipacctd.sh start

и перезагружаем правила файрволла:
/usr/local/etc/rc.d/>sh /etc/rc.firewall > /dev/null &
[1] 16480
/usr/local/etc/rc.d/>
[1]    Done                          sh /etc/rc.firewall > /dev/null
/usr/local/etc/rc.d/>

Всё. Траффик считается. Осталось привенуть скрипт, который, будет всё это складывать в БД. Я чуть-чуть модифицировал свой скрипт, написанный для trafd:
#!/bin/sh -xv
#
#
##########   Вводим данные для подключения к MySQL серверу   ##################
# IP адрес MySQL сервера
IP_MySQL_servera="localhost"
# Имя пользователя для доступа к БД в которой храниться траффик
username="ipacctd"
# Пароль пользователя MySQL
user_passw="ipacctd"
# Имя базы данных
db_name="ipacctd"

##########

# Сегодяшний день
day="`date +%Y-%m-%d`"
# Текущий год
year="`date +%Y`"
# Текущий месяц
month="`date +%m`"
# Текущее время (секунды специально сделаны 00 - иногда cron запускает скрипт не
# в 00 секунд а позже (максимум что я видел - в 13), если машина очень загружена -
# как итог в логах начинает фигурировать разное число секунд.
# Мне это непонравилось :)
curr_time="`date +%H:%M:00`"
# Директория в которой будут храниться текстовые файлы с логами trafd
NewDir="/var/traffic/${year}/${month}"
# Пытаемся создать эту самую директорию на случай если это первый запуск
# или произошла смена месяца (года)
mkdir -p ${NewDir}
# Ну и топаем туда
cd ${NewDir}

# Местоположение исполняемого файла клиента MySQL
mysql="/usr/local/bin/mysql"
# Префикс для команд (лень же каждый раз набивать параметры подключения)
sql_preffix="${mysql} --host=${IP_MySQL_servera} \
--user=${username} --password=${user_passw} --database=${db_name}"

# Считываем все переменные из файла /etc/rc.conf с целью извлечь оттуда
# строчку с названиями интерфейсов по которым работает trafd
# (У меня три сетевых платы и lo0 - просто интереса ради)
. /etc/rc.conf

# Сохраняем статистику по всем интерфейсам
# sleep введён по причине, что иногда не успевает траффик
# в текстовый файл сохраниться - подумываю ещё sync воткнуть
killall -1 ipacctd && sleep 1

# Для всех интерфейсов выковырнутых из rc.conf (висят в ${trafd_ifaces})
# выполняем один и тот же набор действий по разбору логов и запихиванию
# их в базу данных
for iface in ${ipacctd_rules}
do

# Дозаписываем логи в текстовый файл (пусть лежат на всякий случай...)
echo '' >> /var/log/traffic_${iface}.log
cat /var/log/traffic_${iface}.log >> ${NewDir}/summary.${iface}
# Далее - загоняем траффик в БД
#
${sql_preffix} --execute="CREATE TABLE \`traffic_tmp\` \
(\`date\` DATE NOT NULL, \`time\` TIME NOT NULL, \
\`from_IP\` CHAR(16) NOT NULL, \`port_from_IP\` CHAR(8) NOT NULL, \
\`to_IP\` CHAR(16) NOT NULL, \`port_to_IP\` CHAR(8) NOT NULL, \
\`protocol\` ENUM('icmp','tcp','udp') NOT NULL, \`bytes\` CHAR(16) NOT NULL, \
\`paketov\` CHAR(16) NOT NULL) TYPE=MyISAM COMMENT='tmp_table'" 2>/dev/null

########### Лопатим данные для интерфейса ${iface}  #####################
# Очищаем временную таблицу
${sql_preffix} --execute="DELETE FROM \`traffic_tmp\`"
# Построчно превращаем файл со статистикой в набор переменных
cat /var/log/traffic_${iface}.log |
{
while read stroka
do
from_IP=`echo "${stroka}" | awk '{print $1}'`
port_from_IP=`echo "${stroka}" | awk '{print $2}'`
to_IP=`echo "${stroka}" | awk '{print $3}'`
port_to_IP=`echo "${stroka}" | awk '{print $4}'`
protocol=`echo "${stroka}" | awk '{print $5}'`
bytes=`echo "${stroka}" | awk '{print $6}'`
paketov=`echo "${stroka}" | awk '{print $7}'`
# Загоняем полученный набор во временную таблицу
${sql_preffix} --execute="insert into \`traffic_tmp\` (date, time, from_IP, \
port_from_IP, to_IP, port_to_IP, protocol, bytes, paketov) \
values ('${day}', '${curr_time}', '${from_IP}', \
'${port_from_IP}', '${to_IP}', '${port_to_IP}', \
'${protocol}', '${bytes}', '${paketov}')"
done
}
# Стираем пустые строки (а вот откуда они вылазиют я так и непонял....)
${sql_preffix} --execute="DELETE FROM \`traffic_tmp\` WHERE from_IP='' AND \
port_from_IP='' AND to_IP='' AND port_to_IP='' AND protocol=''"
# Стираем строки в которых полное число байт (вместе с технической инфой)
# равно нулю (тоже непойми откуда берутся - раз в статистику trafd попали -
# значит соединение было и байты должны были б быть...)
${sql_preffix} --execute="DELETE FROM \`traffic_tmp\` WHERE paketov='0'"
# Создаём таблицу для окончательного хранения траффика
# (на тот случай если она не создана - хотя конечно тоже дурацкий вариант -
# пытаться создать таблицу при каждом запуске скрипта, но другой вариант -
# проверять существование и если нету её - то создавать. А какая разница? Так
# как сделано сейчас - проще и менее ресурсоёмко)
${sql_preffix} --execute="CREATE TABLE \`${iface}_${year}\` \
(\`date\` DATE NOT NULL, \`time\` TIME NOT NULL, \
\`from_IP\` CHAR(16) NOT NULL, \`port_from_IP\` CHAR(8) NOT NULL, \
\`to_IP\` CHAR(16) NOT NULL, \`port_to_IP\` CHAR(8) NOT NULL, \
\`protocol\` ENUM('icmp','tcp','udp') NOT NULL, \`bytes\` CHAR(16) NOT NULL, \
\`paketov\` CHAR(16) NOT NULL) TYPE=MyISAM COMMENT='База \
данных траффика по (${iface}) интерфейсу за ${year} год'" 2>/dev/null
# Перекидываем траффик из временной таблицы в окончательную, при этом
# объединяем строки в которых совпадает ВСЁ кроме числа байт.
${sql_preffix} --execute="INSERT INTO \`${iface}_${year}\` (date, time, from_IP, \
port_from_IP, to_IP, port_to_IP, protocol, bytes, paketov) \
SELECT date, time, from_IP, port_from_IP, to_IP, port_to_IP, \
protocol, sum(bytes) as bytes, sum(paketov) as paketov FROM \
traffic_tmp GROUP BY date, time, from_IP, port_from_IP, to_IP, \
port_to_IP, protocol"

# Очищаем файл c логами о том когда и по какому интерфейсу сохранялась статистика
cat /dev/null > /var/log/traffic_${iface}.log


done

Доработки минимальны - изменилась команда сохранения траффика, и одна колонка сменилась - вместо `all_bytes` стало `paketov`... После чего пихаем скрипт в планировщик - я всунул его на запуск раз в минуту (все звёздочки, кроме команды)...

P.S. По прошествии нескольких дней обратил внимание, что в моменты пиковой загрузки (когда всех припёрло лезть в инет) скрипт работает долго - 20-30 секунд на нененагруженной машине... Пару раз, когда машина была загруженна, даже не успевал отработать. Причина нашлась быстро - сильно возросло число строк в логах - trafd все порты больше 10000 обзывал client а ipacctd честно их писал... Подумавши, настругал такой скрипт на перл:
#!/usr/bin/perl -w

# вводим переменные
# MySQL - хост где БД
$db_host = 'localhost';
# MySQL юзер
$db_user = 'ipacctd';
# MySQL пароль
$db_password = 'ipacctd';
# MySQL база данных
$db_database = 'ipacctd';
# подрубаем модуль для работы с MySQL
use Mysql;
# время - тока чтоб год достать...
use Time::localtime;

# достаём время
# Год
$year = localtime->year() + 1900;
# Месяц (идиотский язык, чтобы достать месяц в виде
# двузначного числа приходиться изгаляться через жопу...)
# Если знаете способ лучше - подскажите, поменяю...
$month = `date '+%m'`;
$month = substr($month,0,2);

# Коннектимся к MySQL
$dbh = Mysql->Connect($db_host,$db_database,$db_user,$db_password);

# Вызываем внешние программы по сохранению траффика
system("killall -1 ipacctd && sleep 2");

#use strict;
if(open(RC_CONF,"/etc/rc.conf")){
my @data = reverse <RC_CONF>;
chomp @data;
close RC_CONF;
foreach my $str (@data)
    {
    # разбираем rc.conf
    next if $str =~ /^#/ or $str =~ /^\s*$/;
    $str =~ /^\s+/;
    $str =~ /\s+$/;
    my($var_name,$var_value) = split(/=/, $str);
    if($var_name eq 'ipacctd_rules')
        {
        $var_value =~ s#^\s*(['"]?)(.*)\1#$2#;
        foreach my $interface (split (/\s+/, $var_value))
            {
            # шуршим по интерфейсам
            # Создаём таблицу для постоянного хранения траффика
            # строим кверю к MySQL
$MySQL_query = "CREATE TABLE IF NOT EXISTS `" . $interface . "_" . $year . "`(
            `unic_id` INT(16) NOT NULL auto_increment,
            `date` DATE NOT NULL,
            `time` TIME NOT NULL,
            `unix_time` INT(12) NOT NULL,
            `from_IP` CHAR(16) NOT NULL,
            `port_from_IP` INT(8) NOT NULL,
            `to_IP` CHAR(16) NOT NULL,
            `port_to_IP` INT(8) NOT NULL,
            `protocol` CHAR(12) NOT NULL,
            `bytes` INT(16) NOT NULL,
            `paketov` INT(8) NOT NULL,
            PRIMARY KEY (`unic_id`),
            KEY `date`(`date`),
            KEY `unix_time`(`unix_time`)
            ) ENGINE=MyISAM COMMENT='Traffic for " . $interface . "-interface'";
            # Делаем запрос к БД, если неудачный - помираем с ошибкой
            $dbh->Query("$MySQL_query") or die $Mysql::db_errstr;
            # строим путь к файлу с траффиком
            $file_path = "/var/log/traffic_" . $interface . ".log";
            # открываем файло
            open TRAFFIC,"$file_path";
            # Разбираем построчно
            while (<TRAFFIC>)
                {
                # убираем лишние пробелы
                #tr/\s+/ /s;
                # Разбиваем по пробелам на переменные
                ($from_IP,$port_from_IP,$to_IP,$port_to_IP,$protocol,
                $bytes,$paketov) = split(/\s+/,$_);
                # пихаем траффик в БД

                $MySQL_query = "INSERT INTO `" . $interface . "_" . $year . "`
                (`date`,`time`,`unix_time`,`from_IP`,`port_from_IP`,`to_IP`,
                `port_to_IP`,`protocol`,`bytes`,`paketov`) VALUES (DATE(NOW()),
                TIME(NOW()),UNIX_TIMESTAMP(),'" . $from_IP . "',
                '" . $port_from_IP . "','" . $to_IP . "','" . $port_to_IP . "',
                '" . $protocol . "','" . $bytes . "','" . $paketov . "')";
                # Делаем запрос к БД, если неудачный - помираем с ошибкой
                $dbh->Query("$MySQL_query") or die $Mysql::db_errstr;
                }
            # создаём директории
            system("mkdir -p /var/traffic/" . $year . "/" . $month);
            # переносим траффик
            $otkuda = "/var/log/traffic_" . $interface . ".log";
        $kuda = "/var/traffic/" . $year . "/" . $month . "/summary." . $interface;
            system("cat $otkuda >> $kuda");
            # очищаем файло
            system("cat /dev/null > $otkuda");


            # создаём таблицу, где будет храниться траффик

            }
        }
    }
}

# выходим
1;

Он прекрасно заменяет тот же шелловый скрипт. Тока работает раз в 10-15 быстрей :))) Также есть и нововведения (колонка unix_time и unic_id) - понадобились для работы. Если заменять существующий shell скрипт колонку unix_time надо добавить, а если с нуля - то сам всё создаст. Также убрана временная таблица. Тут она не нужна.

P.S. Ненавижу перл.



размещено: 2006-02-01,
последнее обновление: 2006-05-31,
автор: lissyara

оценить статью:





Хостинг HOST-FOOD

2010-08-25, manefesto
freebsd lvm

Использование linux_lvm для работы с LVM разделами из-под FreeBSD. Проблемы которые возники при монтирование lvm раздела
2010-04-30, gonzo111
proftpd file auth&quota

Proftpd - квоты и авторизация из файлов, без использования базы данных и/или системных пользователей
2010-04-22, lissyara
tw_cli

Пошаговая инструкция по восстановлению RAID на контроллере 3ware, из которого выпал один диск. Настройка мониторинга состояния рейда и отчётов о его состоянии на email.
2010-04-14, fox
MySQL Master+Master

MySQL (Master Master) and (Master Slave) Как настроить репликацию…
2010-03-22, Mufanu
named 9.7.0

Система доменных имен (Domain Name Service, DNS) - одна из тех незаметных, закулисных программ, которым не уделяется и половины того внимания, которого они заслуживают.
2010-03-09, terminus
DNS zones

Краткий ликбез про управление DNS зонами. Примеры проведения делегирования прямых и обратных DNS зон.
2010-03-09, aspera
Squid+AD (group access)

Настройка прокси сервера SQUID с автроризацией пользователей в AD. Разделение пользователей на группы
2010-03-02, BlackCat
Шлюз: Часть 4

Настройка дополнительных сервисов: синхронизация времени (OpenNTPD), клиент DynDNS.org.
2010-03-01, BlackCat
Шлюз: Часть 3

Настройка DHCP и DNS серверов для работы внутри частной сети, c поддержкой внутренних (частных зон) DNS, а так же интеграция DHCP и DNS сервисов.
2010-03-01, BlackCat
Шлюз: Часть 2

Конфигурация МСЭ pf для проброса портов с изменением порта назначения и без, а так же поддержки активного режима FTP и ограничения максимального размера сегмента
2010-03-01, BlackCat
Шлюз: Часть 1

Быстрая настройка шлюза/маршрутизатора с установлением PPPoE-соединения, поддержкой NAT и DNS-forwarding.
2010-02-23, Morty
darkstat

Простая считалка траффика, со встроенным веб-сервером. Очень маленькая, может делать отчеты трафика по хостам, портам, протоколам, а также строить графики
2010-01-23, gonzo111
squid+sams+sqstat

Пилим squid и sams - примеры конфигов с объяснениями. Установка SqStat.
2009-12-19, schizoid
mpd5 + radius + ng_car + Abills

Настройка pppoe-сервера с биллинговой системой Abills и шейпером ng_car
2009-11-16, lissyara
UFS->ZFS

Удалённая миграция с UFS на ZFS. Загрузка с раздела zfs. Настройка для работы с малым количеством памяти под архитектурой i386.
2009-11-13, gx_ua
fusefs-ntfs

Установка, настройка и использование fusefs-ntfs, драйвер NTFS, предназанченного для монтирования NTFS разделов под FreeBSD
2009-11-12, Morty
LiveCD

Создание собственного LiveCD с необходимыми вам изменениями, автоматизирование данного процесса, а так же вариант скоростной сборки СД.
2009-09-27, lissyara
Samba как PDC

Контроллер домена - аналог M$ NT4 домена под самбой, без использования LDAP и прочей хиромантии. Просто и быстро =)
2009-08-30, terminus
Подробное руководство по ipfw nat

Подробное руководство по ipfw nat, сложные случаи конфигурации.
2009-08-24, levantuev
HotSpot

Установка Hotspot системы в общественное заведение.
2009-08-18, lissyara
diskless

Создание бездисковых терминалов под управлением FreeBSD - с загрузкой по сети. Используются для старта rdesktop и подключения к виндовому серверу терминалов.
2009-07-29, BAV_Lug
Видеонаблюдение

Настройка бюджетного варианта видеонаблюдения на удаленном объекте
2009-07-22, Cancer
OpenLDAP адресная книга

Настройка и создание адресной книги на базе OpenLDAP + phpLDAPadmin
2009-06-30, SergeySL
AimSniff

Руководство по созданию системы мониторинга ICQ-переписки на базе AimSniff, использующей базу данных MySQL для хранения и Web-интерфейс WAS (Web Aim Sniff) для просмотра перехваченных сообщений
2009-06-25, atrium
Управление правами доступа

Полномочия пользователей и файлов, принадлежащих им, формирует концепцию ОС UNIX.
2009-06-16, DNK
Exim+PgSQL

Установка почтовой системы exim+pgsql на FreeBSD 7.1
2009-05-30, mvalery
HDD(mbr) -> HDD(gpt)

Как разбить диск размером более 2TB на разделы, сделать загрузочным, а затем перенести на него информацию с рабочей системы — донора.
2009-05-22, Cancer
SendXMPP

Отправка сообщений на Джаббер сервер по средствам SendXMPP
2009-05-11, Raven2000
Network UPS Tools

Network UPS Tools представляет собой набор программ, которые обеспечивают общий интерфейс для мониторинга и администрирование UPS оборудования.
2009-04-29, m0ps
IPSEC over GRE with RIP

Пример IPSEC over GRE и динамическим роутингом (RIP), с ADSL в качестве последней мили на оборудовании Cisco.
2009-04-24, WhiteBear777
qemu network

Появилась необходимость поставить на БСД эмулятор(qemu) и настроить в качестве гостевой ОС Windows XP, предоставив ей выход в локалку и в сеть internet...
2009-04-22, vp
freebsd + huawei 162 gsm modem

В статье описывается простой способ подключения модема huawei 162 к freebsd + первичная настройка smstools
2009-04-12, mvalery
Мониторинг RAID

Мониторинг из командной строки RAID компаний AMCC 3ware, HighPoint, Dell (Perc 5/i и PERC 6/i) и LSI (MegaRAID SAS 8408E и SAS1078)
2009-04-09, texnotronic
RAID1 via LAN

Функциональности DRBD во FreeBSD можно добиться примонтировав блочное устройство по сети при помощи GEOM Gate (ggate) и добавив его в зеркало с локальным диском средствами gmirror.
подписка

    вверх      
Статистика сайта
Сейчас на сайте находится: 45 чел.
За последние 30 мин было: 223 человек
За сегодня было
15693 показов,
1743 уникальных IP
 

  Этот информационный блок появился по той простой причине, что многие считают нормальным, брать чужую информацию не уведомляя автора (что не так страшно), и не оставляя линк на оригинал и автора — что более существенно. Я не против распространения информации — только за. Только условие простое — извольте подписывать автора, и оставлять линк на оригинальную страницу в виде прямой, активной, нескриптовой, незакрытой от индексирования, и не запрещенной для следования роботов ссылки.
  Если соизволите поставить автора в известность — то вообще почёт вам и уважение.

© lissyara 2006-10-24 08:47 MSK

Время генерации страницы 0.194 секунд
Из них PHP: 70%; SQL: 30%; Число SQL-запросов: 77 шт.
Исходный размер: 120841; Сжатая: 26018