Nobody about something

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

Написано 8 сентября 2008 в 23:15 - Рубрики: *nix

Решил я завести у себя дома аналог статистики netflow для циски. То есть сбор данных о проходящих через сеть пакетах (откуда, куда, размер). Циски у меня нету, а статистику иметь охота.

Рассмотрим установку и эксплуатацию на FreeBSD 7.0

Для этого есть тулза ng_ipacct.

  1. Установка

    cd /usr/ports/net-mgmt/ng_ipacct/

    А вот установка во FreeBSD 7 отличается от make install
    При выполнении make компиляция обрывается с ошибкой

    ng_ipacct.c:905: error: too few arguments to function 'in_pcblookup_local'

    Гугл почти ничего об этом не знает, но ответ я нашёл. Смысл его таков:

    В седьмой фряхе изменили синтаксис этой системной функции. Непонятно, а нафига, но придётся с этим жить. А ещё более непонятно, как мэнтэйнер этого порта (чтоб ему руки оторвать) запихал собственно в порт заведомо нерабочую прогу

    О какой функции тут идёт речь тут понятно. Дело за малым – подправить код.

    make fetch extract
    vi work/ng_ipacct/ng_ipacct/ng_ipacct.c

    идём на 905-ю строку и заменяем

    --- pcb = in_pcblookup_local(pcbinfo, ina, port, 1);
    +++ pcb = in_pcblookup_local(pcbinfo, ina, port, 1, 1);
    

    Далее просто make install clean
    Установили

  2. Настройка
    Правим rc.conf. Добавляем ng_ipacct_enable="YES"
    Настраиваем конфиг /usr/local/etc/ng_ipacct.conf. Вот пример моего конфига с настройкой на один интерфейс

    # $FreeBSD: ports/net-mgmt/ng_ipacct/files/ng_ipacct.conf,v 1.6 2008/06/03 10:40:16 skv Exp $
    #
    # Please read and meditate on netgraph(4), ipacctctl(8) and ngctl(8).

    Мне нравится эта фраза. “читайте и медитируйте”

    # Enable ng_ipacct (i.e. enable run startup script "ng_ipacct.sh")
    #ng_ipacct_enable="YES"
    

    Аналог включения через /etc/rc.conf

    # Enable kernel modules loading.
    # On "ng_ipacct.sh start" all kernel modules specified
    # in ${ng_ipacct_modules_list} will be loaded.
    # Note: on "ng_ipacct.sh stop" only "ng_ipacct" will be unloaded.
    ng_ipacct_modules_load="YES"
    

    Разрешаем при запуске автоподгрузку необходимых модулей. Я один фиг подгрузил руками :)

    # Netgraph can load required ng_* modules automatically on the hook creation
    # - except for "ng_ether". Generally, modules preloading is recommended.
    # Do not add to this list modules which are statically compiled into kernel.
    #ng_ipacct_modules_list="netgraph ng_ether ng_cisco ng_socket ng_tee ng_ipacct"
    ng_ipacct_modules_list="netgraph ng_ether ng_ipacct"
    

    Указываем какие модули подружать, если включена автоподгрузка. Сделано во избежание подгрузки модулем чего-либо скомпилированого статически

    # List of monitored interfaces. For each interface additional vars must be
    # specified in corresponding variables 'ng_ipacct_IFACE_*'.
    # See examples below.
    #ng_ipacct_interfaces="xl0 cx0 vpn0"
    ng_ipacct_interfaces="vr0"
    

    Указываем на каких интерфейсах вести сбор статистики


    # Default start/stop scripts.
    #
    # Single quotes are required to preserve newlines.
    # '%%iface%%' will be automatically expanded with a relevant interface.
    # This feature should be applied to use indentical rules
    # for similar interfaces.
    ng_ipacct_default_ether_start='
    mkpeer %%iface%%: tee lower right
    name %%iface%%:lower %%iface%%_tee
    connect %%iface%%: lower upper left
     
    mkpeer %%iface%%_tee: ipacct right2left %%iface%%_in
    name %%iface%%_tee:right2left %%iface%%_ip_acct
    connect %%iface%%_tee: %%iface%%_ip_acct: left2right %%iface%%_out
    '
     
    ng_ipacct_default_ether_stop='
    shutdown %%iface%%_ip_acct:
    shutdown %%iface%%_tee:
    shutdown %%iface%%:
    '
     
    ng_ipacct_bpf_ether_start='
    mkpeer %%iface%%: tee lower right
    name %%iface%%:lower %%iface%%_tee
    connect %%iface%%: lower upper left
     
    mkpeer %%iface%%_tee: bpf right2left %%iface%%_in
    name %%iface%%_tee:right2left %%iface%%_bpf
    connect %%iface%%_tee: right2left left2right %%iface%%_out
     
    mkpeer %%iface%%_bpf: ipacct %%iface%%_match_in %%iface%%_in
    name %%iface%%_bpf:%%iface%%_match_in %%iface%%_ip_acct
    connect %%iface%%_bpf: %%iface%%_ip_acct: %%iface%%_match_out %%iface%%_out
    '
     
    ng_ipacct_bpf_ether_stop='
    shutdown %%iface%%_ip_acct:
    shutdown %%iface%%_bpf:
    shutdown %%iface%%_tee:
    shutdown %%iface%%:
    '

    Это лучше не трогать. Это скрипты запуска по умолчанию. Я в них ничего не понял и оставил как есть. Далее идут настройки конкретно под интерфейс


    # Configuration for 'vr0_ip_acct' node:
     
    ng_ipacct_vr0_dlt="EN10MB" # required line; see ipacctctl(8)

    Немного загадочная строка. Оставил как есть. Для ethernet интерфейса вроде как такая должна быть.


    ng_ipacct_vr0_threshold="5000" # '5000' by default

    Максимальное количество записей в буфере. Работает сбор инфомации в памяти ядра, и если размера ОЗУ, выделенного под ядро ядро системы не будет хватать, то система просто грохнется. Во избежание этого, сделана опция. При превышении указанной длинны новая статистика собираться не будет до обнуления буфера


    ng_ipacct_vr0_verbose="yes" # 'yes' by default

    Подробный режим


    ng_ipacct_vr0_saveuid="yes" # 'no' by default
    ng_ipacct_vr0_savetime="no" # 'no' by default
    ng_ipacct_vr0_start=${ng_ipacct_default_ether_start}
    ng_ipacct_vr0_stop=${ng_ipacct_default_ether_stop}
    ng_ipacct_vr0_checkpoint_script="/root/ng.sh"
    # this script is called on "stop" (to save accumulated
    # data) or via "rc.d/ng_ipacct.sh checkpoint"

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

  3. Использование
    Для начала запустим

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

    Через некоторое время( как накопится статистика) её можно снять. Для этого служит ipacctctl

    ipacctctl $IFACE_ip_acct:IFCAE checkpoint

    Снять статистику с модуля ядра во временный буфер

    ipacctctl $IFACE_ip_acct:IFCAE show

    Показать эту статистику. Если включён подробный режим, то формат спика такой:
    IP_источника порт_источника IP_получателя порт_получателя номер_протокола число_пакетов число_байт какая_то_фигня

    ipacctctl $IFACE_ip_acct:IFCAE clear

    Очищает временный буфер. Без очистки нелья вызвать checkpoint

    Что теперь со всем этим можно делать. Я сделал 2 скрипта. Один раз в 5 минут сбрасывает статистику во временный файл. Другой скрипт раз в полчаса переносит всё это в другой файл, больший по размеру.

    Скрипт 1. Тот что раз в пять минут:

    #!/bin/sh
    DATE=`date +"%Y %m %d %H %M"`
    YEAR=`echo $DATE | awk '{print $1}'`
    MONTH=`echo $DATE | awk '{print $2}'`
    DAY=`echo $DATE | awk '{print $3}'`
    HOUR=`echo $DATE | awk '{print $4}'`
    MINUTE=`echo $DATE | awk '{print $5}'`
    /usr/local/sbin/ipacctctl vr0_ip_acct:vr0 checkpoint
    /usr/local/sbin/ipacctctl vr0_ip_acct:vr0 show > /var/log/ngraph/tmp/$YEAR-$MONTH-$DAY-$HOUR-$MINUTE.log
    /usr/local/sbin/ipacctctl vr0_ip_acct:vr0 clear
    

    Директория /var/log/ngraph/tmp/ предварительно создана.

    Скрипт 2. Тот, что “архивирует”

    #!/bin/sh
    DATE=`date +"%Y %m %d %H %M"`
    YEAR=`echo $DATE | awk '{print $1}'`
    MONTH=`echo $DATE | awk '{print $2}'`
    DAY=`echo $DATE | awk '{print $3}'`
    HOUR=`echo $DATE | awk '{print $4}'`
    MINUTE=`echo $DATE | awk '{print $5}'`
    MINUTE=`expr $MINUTE - 1`
    if [ ! -d /var/log/ngraph/$YEAR ]; then
      mkdir /var/log/ngraph/$YEAR
    fi
    if [ ! -d /var/log/ngraph/$YEAR/$MONTH ]; then
      mkdir /var/log/ngraph/$YEAR/$MONTH
    fi
    if [ ! -d /var/log/ngraph/$YEAR/$MONTH/$DAY ]; then
      mkdir /var/log/ngraph/$YEAR/$MONTH/$DAY
    fi
    DNAME=/var/log/ngraph/$YEAR/$MONTH/$DAY
    for NAME in `ls /var/log/ngraph/tmp/ | grep log`; do
      echo $DNAME/$HOUR-$MINUTE.log
      cat /var/log/ngraph/tmp/$NAME >> $DNAME/$HOUR-$MINUTE.log
      rm /var/log/ngraph/tmp/$NAME
    done
    

    Запускается он каждую 1-ю и 31-ю минуты часа

    Также необходимо сделать ротацию всего этого хозяйства. За неделю на канале 256 кбит/с при средней загрузке канала, набралось на 210 мегабайт статистики.

  4. Для чего это
    Вопрос дня. А для чего это нужно?

    Ну например для подсчёта траффика на IP. Например для биллинга, или ещё для чего-либо. Также можно использовать для поиска сетевых аномалий (флуд или ещё что-нить), ну и просто для красоты и выпендрёжу :)

    Мне эта статистика помогла определить почему не до конца выделяется канал одному пользователю, при простое другого. Выяснилось, что выделяется-то он весь. Но CPU “не успевает” пакеты в очередь пихать и дропает их. Буду апгрейдить шлюз.

    Кстати. Очень важное замечание. Netgraph (через который и берётся статистика) работает на уровне ядра FreeBSD и перед файрволом. То есть пакет вначале считается нетграфом, а потом только обрабатывается файрволом. В этом есть плюс. В статистику попадают все пакеты на интерфейсе, невжно дропнуты они были или нет. Есть и минус. Он в том, что статистика на шлюзе будет в этом случае отличаться от статистики на удалённой машине, или на файрволле.

Метки:

Комментарии (3) на запись “Считаем траффик во FreeBSD”

  1. aksel пишет 2 марта 2009 в 15:02

    Нармальная статейка у меня получилось …
    только ng_ipacct_modules_load=”YES” это выключил ибо ошибки сыпались

    хотелось бы все это с продолжением т.е. со складыванием в мускуль и т.д.

  2. tuupic пишет 8 марта 2009 в 10:13

    Хм. А что именно в мускуле хранить?
    Если сами “логи”, то это имхо не имеет смысла. Так как во-первых, неудобно обрабатывать данные проихвольным методом (cat файл | что угодно), а во вторых это нерационально с точки зрения диска. Файлы можно просто архивировать, либо удалять устаревшие (сомневаюсь, что могут понадобиться подобные “сырые” данные годовалой давности, к примеру).
    А если хранить в мускуле результаты обработки, то для начала надо придумать что собственно считать. А цели считать что-либо периодически у меня не было. Была цель получить подобную статистику о пакетах. Конечно, периодически, я считаю кое-что, но это разовые подсчёты, для решения разовых вопросов.

  3. tit пишет 26 марта 2009 в 12:59

    а зачем секс с awk?
    date +”%Y-%m-%d-%H-%M”

    а зачем поминутные файлы?
    cat ~/bin/get_data
    #!/bin/sh
    now=`/bin/date +%Y%m%d`
    INTERFACES=”vr0 ng0″
    IPACCTCTL=”/usr/local/sbin/ipacctctl”
    log=”/var/log/ng_ipacct/$now”

    for IFACE in $INTERFACES; do
    $IPACCTCTL ${IFACE}_ip_acct:$IFACE checkpoint
    $IPACCTCTL ${IFACE}_ip_acct:$IFACE show v | /usr/bin/sort -nk 8 >> $log.$IFACE
    $IPACCTCTL ${IFACE}_ip_acct:$IFACE clear
    done

Оставить комментарий