Frequently Asked Questions

Question
Netflow на FreeBSD подсчет трафика

Answer
Netflow - один из самых удобных способов сбора трафика для никс систем. С учетом того что он совместим с флоу протоколом Cisco и способен собирать\отдавать данные по сети, система представляет собой особый интерес. Вот неплохая ссылка с описанием нетграф: www.opennet.ru

Если в двух словах, то идеология netgraph позволяет путем создания визуальных графов из "кубиков" протоколов, портов и сервисов как бы строить взаимодействие сетевых компонентов простым созданием связей между "кубиками".
Что нужно чтобы установить это все на FreeBSD? Для начала набор включений в ядро для обеспречения поддержки netgraph. Полная версия (она на самом деле не нужна в таком количестве, для подсчета трафика достаточно меньшего):

options         NETGRAPH                #netgraph(4) system
        options         NETGRAPH_ASYNC
        options         NETGRAPH_BPF
        options         NETGRAPH_CISCO
        options         NETGRAPH_ECHO
        options         NETGRAPH_ETHER
        options         NETGRAPH_FRAME_RELAY
        options         NETGRAPH_HOLE
        options         NETGRAPH_IFACE
        options         NETGRAPH_KSOCKET
        options         NETGRAPH_L2TP
        options         NETGRAPH_LMI
        # MPPC compression requires proprietary files (not included)
        #options        NETGRAPH_MPPC_COMPRESSION
        options         NETGRAPH_MPPC_ENCRYPTION
        options         NETGRAPH_ONE2MANY
        options         NETGRAPH_PPP
        options         NETGRAPH_PPPOE
        options         NETGRAPH_PPTPGRE
        options         NETGRAPH_RFC1490
        options         NETGRAPH_SOCKET
        options         NETGRAPH_TEE
        options         NETGRAPH_TTY
        options         NETGRAPH_UI
        options         NETGRAPH_VJC


Минимально достаточно вот этого:

        options         NETGRAPH   
        options         NETGRAPH_ETHER
        options         NETGRAPH_SOCKET
        options         NETGRAPH_TEE


После того как ядро будет перекомпилировано и все заработает после перезагрузки, можно заняться настройкой конкретики.
Вот пример с описанием, задача - собирать трафик с некоего интерфейса (fxp0) и отправлять его на удаленную систему. Этот пример очень хорошо описывает каждое действие, хотя для реального сервера неприменимо т.к. имеет исключительно познавательный вид (куски с описанием взяты с сайта nexus.org.ua):

Опишем "кубики" netgraph, которые нам потребуются:

1. кубик сетевого интерфейса, в нашем случае fxp0, он создается автоматически. Имеет для хука: lower и upper.
Lower означает работу с протоколами низкого уровня, upper - соответственно верхнего. Нас будет интересовать как раз сетевой поток,
проходящий от нижнего сетевого уровня к верхнему.
2. кубик tee. Его нам потребуется создать вручную. Имеет четыре хука: left, right, left2right и right2left.
Назначение этого кубика - пропускать пакеты с left в right (и наоборот) и дублировать проходящий поток данных в хуки
left2right если нужны данные, которые идут слева направо (исходящий трафик), и right2left если данные идут справа налево(входящий трафик).
3. кубик one2many, название говорит само за себя. Принимает от многих хуков (many0,many1,many2 и т.д.) и передает "собирая" потоки в один хук one.
4. кубик netflow, который будет принимать на себя сетевые потоки снятые при помощи tee у сетевых интерфейсов через хуки iface0, iface1,iface2 и т.д.
Этот кубик будет формировать cisco netflow пакеты, содержащие агреггированную информацию о прошедшем трафике и передавать в хук export.
5. кубик ksocket, стандартный модуль netgraph для отправки пакетов определенному хосту. В нашем случае на хук inet/dgram/udp будут поступать от netflow пакеты для передачи хосту. Управляющим сообщением msg мы зададим хост и порт, на который будут уходить наши пакеты (192.168.1.10:2055).

Создать узел можно при помощи команды mkpeer, при чем создание узла всегда происходит с подключением одного из хуков создаваемого узла
к хуку родительского узла, и правда, зачем нам создавать неподключенный узел?

Соединение хуков происходит при помощи команды connect, синтаксис которой таков:
connect перваянода втораянода хукпервойноды хуквторойноды.

Именование хуков и нод следующее. Каждый создаваемый нод безымянный, но имеет индекс, который мы можем увидеть командой list.

Пример:

Name: ngctl27877 Type: socket ID: 00000009 Num hooks: 0
Name: Type: ksocket ID: 00000008 Num hooks: 1


Мы можем обратиться к узлу ksocket через его номер (ID) так [8]:
Двоеточие указывает на то, что это нода Мы можем дать название ноде.
К примеру, назовем этот же узел как ksocket1.

name [8]: ksocket1


И далее мы уже можем обращаться к нему как к ksocket1:

Полезна команда show, которая нам покажет соединенные хуки

+ show netflow:
Name: netflow Type: netflow ID: 00000007 Num hooks: 2
Local hook Peer name Peer type Peer ID Peer hook
---------- --------- --------- ------- ---------
export ksocket 00000008 inet/dgram/udp
iface0 one2many0 one2many 00000006 one


Здесь видны какие хуки есть, сколько их, и к каким узлам подключены.

К нодам и хукам мы можем обратиться разными способами. Например, у нас есть два узла: tee (хуки left, right,right2left, left2right) с названием tee1 и one2many (хуки many0,many1,one) с названием one2many1.
Допустим мы хотим соединить tee1 через хук left к хуку many0 узла one2many1, и хук right tee1 к хуку many1 узла one2many1.
Хук left от узла tee1 адресуем как tee1:left. Хук many0 адресуем как one2many1:many0.

+ connect tee1: one2many1: left many0


после того как ноды соединены мы имеем возможность использовать альтернативную адресацию, к примеру, к ноде one2many1 мы можем обратиться через ноду tee1 следующим образом: tee1:left, да-да, как буд-то мы адресуем хук Эту конструкцию можно использовать в свежесозданных, еще не именованных узлах.

Итак, начнем.

Подгрузим в ядро модуль netflow:

:~#kldload ng_netgraph


запускаем ngctl

:~#ngctl


и попадаем в командную строку netgraph.
следует проверить, что "кубик" netflow был корректно подгружен:

+ types
There are 20 total types:
      Type name   Number of living nodes
      ---------   ----------------------
        netflow       0
+ mkpeer fxp0: tee lower left
#### создать узел типа tee соединяя их хуки lower и left
+ name fxp0:lower tee0
#### назвать созданный узел tee0
+ connect fxp0: fxp0:lower upper right
#### соединяем хуки upper и right
+ mkpeer tee0: one2many left2right many0
#### создаем узел типа one2many соединяя хуки left2right и many0
+ name tee0:left2right one2many0
#### называем узел one2many0
+ connect tee0:  one2many0: right2left many1
+ mkpeer one2many0: netflow one iface0
#### создаем netflow узел
+ name one2many0:one netflow
+ mkpeer netflow: ksocket export inet/dgram/udp
#### создание узла ksocket, соединяем с netgraph на хук iten/dgram/udp
+ msg netflow: setifindex { iface=0 index=4 }
#### задаем индекс интерфейса (я так понимаю это что-то вроде порядкового номера, под которым он идет в ifconfig)
+ msg netflow:export connect inet/192.168.0.12:9996
### говорим отправлять пакеты на хост сбора статистики


В этом примере рассмотрено подключение к статистике одного интерфейса. Подключение нескольких интерфейсов происходит аналогично, через tee, one2many и один из свободных хуков ng_netflow (iface1,iface2, ...) Если все прошло как следует, то 192.168.1.10 начнет получать netflow пакеты на UDP порт 2055.

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

nep63-57# more FlowStart

Внутри ничего нового, как раз реализована отдача трафика на 2 хоста, собственно на себя (127.0.0.1) и на некий 91.123.123.3 по портам 2055. Запускается этот скрипт с командной строки или при загрузке например вот так:

FlowStart start vlan998
FlowStart start vlan277
FlowStart start vlan997


В комплекте с написанным мной биллингом ProvAdmin (ищите здесь же на сайте) запуск прослушки интерфейсов происходит в процессе создания списка vlan для клиентов при запуске сервера. Напомню только один нюанс, созданный конфиг для данного vlan будет слушать на нем трафик только до момента пересоздания этого влан. Так же могут меняться индексы созданных влан в системе нетграф. Это может вызвать прекращение прослушки и потерю данных. Естественно, с физическими итерфейсами такое не происходит. Чтобы избежать подобных проблем, если вам необходимо слушать именно vlan, сделайте их до запуска клиентских интерфейсов, например правкой rc.conf:

cloned_interfaces="vlan2 vlan997 vlan998"
ifconfig_vlan2="inet 192.168.254.1 netmask 255.255.255.0 vlan 2 vlandev vr0"            #Upravlenie
ifconfig_vlan997="inet 91.123.123.123 netmask 255.255.255.248 vlan 997 vlandev fxp0" 
ifconfig_vlan998="inet 84.123.123.123 netmask 255.255.255.252 vlan 998 vlandev fxp0" 


Тогда любые изменения в клиентских влан интерфейсах не затронут индексы ваших прослушиваемых интерфейсов и не вызовут потерю данных.

Теперь что касается части "сервер". Как и чем принимать то что приходит по порту 2055? Для этого существует набор flow-tools (/usr/ports/net-mgmt/flow-tools) из портов FreeBSD. При помощи этого набора вы сможете создать коллектор, принимающий трафик от любого устройства, направляющего на него поток в формате flow 5 или 4. Среди них описанный выше рутер и Cisco например. Устанавливаете толсы из портов, затем существует несколько вариантов коллектора. Мне больше нравится "скриптовый" вариант, он позволяет контролировать по cron состояние прослушки портов и управлять параметрами. Создается 2 скрипта, 1 - для запуска и контроля:

nep63-57# more flow-capture-recovery.sh


Этот просто каждый час превращает принятые данные из бинарного вида в тексточитаемый, готовый к обработке всякими разными биллингами. Собственно, и все...

Есть один маленький нюанс... Если сервер слишком загружен, flow-capture может напрочь потерять связь с "реальностью" и перестать собирать трафик. Об этом упоминается в его манах. На этот случай может помочь другой подход, который описан вот здесь: Запись трафика на FreeBSD, аналогично NetFlow


Details
Info Sunday 14 March 2010 - 18:29:17 by




Vampyr`s House!


Protected by Copyscape DMCA Plagiarism Check