Что же представляет собой netgraph?
Если в двух словах, то netgraph это как высокоуровневый Basic для сетевых сервисов по сравнению с машинным кодом. Идеология netgraph позволяет путем создания визуальных графов из "кубиков" протоколов, портов и сервисов как бы строить взаимодействие сетевых компонентов простым созданием связей между "кубиками".
Надо отметить что netgraph работает на уровне ядра, и, как сказали бы англоязычные братья, this is god damn fast.Надо сказать что к осознанию netgraph я подходил несколько раз. И каждый раз найденная в небольшом количестве рускоязычная документация не раскрывала темы, да и в общем не давала полного понимания принципов работы.
Из моего примера вы почерпнете технику создания связей для узлов (nodes) сетевых протоколов и интерфейсов и научитесь при помощи модуля
ng_netflow отправлять статистику сетевых соединений в формате
Cisco на обрабатывающий хост, в моем случае это
Netflow Analyzer 4 от AdventNet Inc.
Что нам потребуется для реализации статистики по структуре трафика:
1. FreeBSD роутер (192.168.0.1), с которого будем собирать статистику, ядро скомпилировано с поддержкой netgraph.
2. Windows хост (192.168.0.12), на который будут приходить пакеты в формате Cisco netflow.
3. установленный модуль ng_netflow (/usr/ports/net/ng_netflow)
4. установленный Netflow Analyzer 4 на windows хост, прослушивающий UDP пакеты на порту 9996
Опишем "кубики" 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.0.12:9996).
Создать узел можно при помощи команды mkpeer, при чем создание узла всегда происходит с подключением одного из хуков создаваемого узла
к хуку родительского узла, и правда, зачем нам создавать неподключенный узел? :)
Соединение хуков происходит при помощи команды connect, синтаксис которой таков:
connect перваянода втораянода хукпервойноды хуквторойноды.
Именование хуков и нод следующее. Каждый создаваемый нод безымянный, но имеет индекс, который мы можем увидеть командой list.
Пример:
Name: ngctl27877 Type: socket ID: 00000009 Num hooks: 0
Name: <unnamed> 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 <unnamed> 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.0.12 начнет получать netflow пакеты на UDP порт 9996.
Если все прошло не как следует мы вполне можем получить непингуемую машину, которую прийдется лечить перезагрузкой.
Настройка netflow analyzer не представляет никакого интереса, ибо нечего там настраивать ;)
В завершение приведу несколько скриншотов с работающей системы учета трафика.
Следует отметить, что netgraph исключительно мощная система, что доказывает очень известный и популярный продукт MPD VPN для PPTP, который полностью работает на netgraph.
Ведь использовать netgraph можно не только для подсчета трафика ;)
P.S. Так и напрашивается на изготовление графический модуль для "рисования" кубиков и связей netgraph в Visio, или другой cad системе.
Также обнаружил в ngctl интересную команду .dot, эта команда выдает листинг узлов и связей в формате, пригодном для графического построения графов netgraph пакетом graphviz. Скриншот прилагается.
Но об этом уже другая история.
Комментариев: 4