Netgraph ipfw и гибкий учет трафика через netflow

    И снова здравствуйте!

    Продолжим обзор модулей FreeBSD netgraph.
    Сегодня у нас в гостях ng_ipfw, ng_one2many и старый друг ng_netflow.
    С их помощью попробуем посчитать трафик по определенным условиям и посмотрим как это можно использовать на практике.

    Что за модули?


    ng_ipfw.gif

    ng_ipfw — модуль, создающий интерфейс для доступа к подсистеме netgraph из фаервола IPFW. При загрузке в ядро, модуль автоматически создает свой узел в пространстве подсистемы netgraph с именем «ipfw:», и может присутствовать только в единственном экземпляре. Ng_ipfw принимает подключения к произвольным номерным хукам, номера хуков указываются в правилах ipfw. Каждый входящий в модуль пакет тэгируется по нескольким параметрам (ipfw правило, интерфейс, направление), для того чтобы его можно было идентифицировать при возврате обратно в ipfw. Не тэгированные пакеты, возвращаемые в фаервол, уничтожаются. Контрольных сообщений модуль не принимает.

    ng_one2many.gifng_one2many — модуль, позволяющий распределять пакеты по нескольким подключениям. Он принимает подключения к одному хуку «one» и к многочисленным «many0», «many1», «manyN»… Пока существует два алгоритма распределения пакетов внутри модуля.

    1. Пакеты входящие в «one» поочередно выходят через разные «manyN» (xmit_roundrobin). Все пакеты входящие в «manyN» выходят в «one».
    2. Пакеты входящие в «one» выходят копиями через все «manyN» (xmit_all). Все пакеты входящие в «manyN» выходят в «one». (похоже на работу ng_hub).

    Так же существует алгоритмы определения up/down линков, и возможность их включения/выключения через команды, это нужно для специфичных задач, об этом подробнее в man ng_one2many.

    Ng_one2many принимает контрольные сообщения: setconfig, getconfig, getstats, clrstats, getclrstats. В принципе интуитивно понятно. Подробнее в man.

    Модуль ng_hole — делает элементарные действия, считает пакетики вошедшие к нему и уничтожает их.

    О модуле ng_netgraph я писал в своем прошлом топике FreeBSD Netgraph на примере Ethernet тоннеля..


    IPFW


    Системным администраторам работающим с FreeBSD рассказывать об ipfw смысла нет, а кто не знает что это может без проблем прочитать в Википедии, да и гугл выдаст тонны информации с примерами и готовыми наработками. Скажу лишь то, что для взаимодействия ipfw и netgraph в ipfw существует два правила ngtee и netgraph, пример:

    ipfw add netgraph 10 all from any to any — направит весь трафик попавший в правило в хук ipfw:10 модуля ng_ipfw

    ipfw add ngtee 20 ip from any to any — скопирует весь трафик попавший в правило в хук ipfw:20 модуля ng_ipfw

    Немного посчитаем


    Мы хотим посчитать трафик, проходящий через интерфейс каждого пользователя в обоих направлениях. При этом исключить подсети 192.168.5.0/24 и 192.168.10.0/24 из учета, т.к в них у нас живут бесплатные ресурсы. Пользователи терминируются на интерфейсы «ngX» демоном mpd.

    В ipfw это будет выглядеть так:
    ipfw table 1 flush
    ipfw table 1 add 192.168.5.0/24
    ipfw table 1 add 192.168.10.0/24

    ipfw add ngtee 10 ip from not "table(1)" to any in via "ng*"
    ipfw add ngtee 10 ip from any to not "table(1)" out via "ng*"

    Т.е мы копируем в ipfw:10 подсистемы netgraph весь трафик, не принадлежащий сетям, перечисленным в таблице 1.

    ng_ipfw_netflow.gif Нарисуем граф. Он достаточно прост.

    Создаем простую структуру из модулей ng_ipfw и ng_netflow и ng_ksocket. Т.к это сбор статистики, данные будут идти только в одну сторону, обрабатываться и отправляться в нужное место.

    Копируем весь трафик проходящий через IPFW правила в ng_ipfw, который в свою очередь подключим к ng_netflow, подключенный к ksocket и далее к netflow коллектору.

    Собираем в системе


    Создаем модуль netflow и подключаем его хук iface0 к хуку ipfw 10.
    ngctl mkpeer ipfw: netflow 10 iface0
    Называем созданный модуль нетфлоу «netflow», он находится по адресу создания «ipfw:10»
    ngctl name ipfw:10 netflow
    Отправляем модулю «netflow:» команду, принимать через iface0 чистые IP пакеты. (подробнее в моём прошлом топике о модуле ng_netflow)
    ngctl msg netflow: setdlt {iface=0 dlt=12}
    Созадем модуль ksocket и подключаем его хук inet/dgram/udp к «netflow:» хуку «export».
    ngctl mkpeer netflow: ksocket export inet/dgram/udp
    Называем созданный модуль «netflow_socket»
    ngctl name netflow:export netflow_socket
    Отправляем модулю «netflow_socket» команду подключиться к коллектору.
    ngctl msg netflow_socket: connect inet/3.3.3.3:9996

    Казалось бы все просто — это будет работать, но оказывается не совсем так, как нужно. Пакет вышедший с интерфейса пользователя и вошедший в интерфейс нашего соседнего пользователя посчитается дважды. Тут мы можем перестать считать, например, исходящий трафик… но к нам на помощь приходит модуль ng_one2many.

    Новый граф


    ng_ipfw_one2many_netflow.gif Т.к ng_one2many умеет работать в режиме roundrobin, и даже делает это по-умолчанию, мы можем вставить его между ng_ipfw и ng_netflow.

    Для разделения трафика пополам потребуется подключить one2many хуками many0 и many1 к ng_netflow и ng_hole, т.к обязательное условие распределения пакетов для one2many являются хуки в активном состоянии.

    Получится что в учет пойдет только половина пакетов, с маленькой погрешностью, а вторая часть будет уничтожена.

    Для второго графа будем использовать новый хук модуля ipfw — 20. Так же при создании графа нужно будет давать узлам новые имена, чтобы они не пересекались с уже созданным выше графом. Создание его аналогично, и подробно описывать его не буду.

    В итоге мы получаем итоговые скрипты для работы.


    Первый скрипт для сбора графа полного netflow.
    #!/bin/sh
    case "$1" in
    start)
    echo "Starting full netflow."
    ngctl mkpeer ipfw: netflow 10 iface0
    ngctl name ipfw:10 netflow
    ngctl msg netflow: setdlt {iface=0 dlt=12}
    ngctl mkpeer netflow: ksocket export inet/dgram/udp
    ngctl name netflow:export netflow_socket
    ngctl msg netflow_socket: connect inet/3.3.3.3:9996
    echo "Ok."
    exit 0
    ;;
    stop)
    echo "Stopping full netflow."
    ngctl shutdown netflow_socket:
    ngctl shutdown netflow:
    echo "Ok."
    exit 0
    ;;
    restart)
    sh $0 stop
    sh $0 start
    ;;
    *)
    echo "Usage: `basename $0` { start | stop | restart }"
    exit 64
    ;;
    esac


    Второй скрипт создает граф учета половины трафика.
    #!/bin/sh
    case "$1" in
    start)
    echo "Starting half netflow."
    ngctl mkpeer ipfw: one2many 20 one
    ngctl name ipfw:20 one2many
    ngctl mkpeer one2many: netflow many0 iface0
    ngctl name one2many:many0 netflow_half
    ngctl mkpeer one2many: hole many1 black
    ngctl name one2many:many1 blackhole
    ngctl mkpeer netflow_half: ksocket export inet/dgram/udp
    ngctl name netflow_half:export netflow_socket_half
    ngctl msg netflow_half: setdlt {iface=0 dlt=12}
    ngctl msg netflow_socket_half: connect inet/3.3.3.3:9996
    echo "Ok."
    exit 0
    ;;
    stop)
    echo "Stopping half netflow."
    ngctl shutdown netflow_socket_half:
    ngctl shutdown blackhole:
    ngctl shutdown netflow_half:
    ngctl shutdown one2many:
    echo "Ok."
    exit 0
    ;;
    restart)
    sh $0 stop
    sh $0 start
    ;;
    *)
    echo "Usage: `basename $0` { start | stop | restart }"
    exit 64
    ;;
    esac


    В IPFW мы получаем новую конструкцию. Во вторую табличку добавляем сети, трафик между которыми надо уменьшать в 2 раза.

    ipfw table 1 flush
    ipfw table 1 add 192.168.5.0/24
    ipfw table 1 add 192.168.10.0/24

    ipfw table 2 flush
    ipfw table 2 add 192.168.50.0/24
    ipfw table 2 add 192.168.51.0/24
    ipfw table 2 add 192.168.52.0/24
    ipfw table 2 add 192.168.53.0/24

    ipfw add ngtee 10 ip from not "table(1)" to any in via "ng*"
    ipfw add ngtee 10 ip from any to not "table(1)" out via "ng*"

    ipfw add ngtee 20 ip from "table(2)" to "table(2)" via "ng*"


    Вот и всё


    Спасибо всем, кто героически прочел всю статью.
    Метки:
    Поделиться публикацией
    Похожие публикации
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 26
    • –1
      В linux:
      modprobe ipt_NETFLOW hashsize=65536 active_timeout=300
      iptables -A FORWARD -s 192.168.0.0/24 -j NETFLOW

      • +2
        А у меня в сарае аэроплан. Я про BSD писал.

        А как через iptables только половину трафа в нетфлоу отправить?
        • 0
          Через настройку правил. Что не понятно? Модуль добавляет специальную задачу для лить в netflow.
          • 0
            А покажите пример, интересно, я немного далек от iptables.
            • 0
              В написанном выше примере, в netflow отправляется весь исходящий транзитный трафик от адресов сети 192.168.0.0/24
              • 0
                А половину как отправить? Я ж об этом спрашиваю.
            • 0
              iptables -A FORWARD -i ppp+ -o eth0 -j NETFLOW
              iptables -A FORWARD -o ppp+ -i eth0 -j NETFLOW

              для трафика междy ppp-интерфейсами

              iptables -A FORWARD -i ppp+ -o ppp+ -j NETFLOW

              Ну, дополнительные условия по вкусу.

              Всегда поражала тяга бздишников к усложнению простых вещей.
              • 0
                про половину — мы считаем в цепочке FORWARD — трафик проходит через нее один раз поэтому отсеивать дубликаты методом костылей и подпорок не нужно
                • 0
                  Не, просто для BSDшников это простые вещи.
                  • 0
                    27 команд вместо 3 — то же какое-то нездоровое красноглазие ;)
                    • 0
                      У всего свои плюсы и минусы. Я привел пример использования и сборки модулей, цель заставить людей делать именно так не преследую.
        • 0
          Возьмите лучше к себе на работу на пол ставочки ;)
          • 0
            СОРМ четать? ;)
            • 0
              А больше заниматься нечем? СОРМ читать можно вон индусов нанять :D.
              • 0
                На полставки только чтение СОРМ :]
                • 0
                  ыы, и скока платят?
                  • 0
                    это секретная информация :]
                    • 0
                      Понятно, значит копейки :(
                      • +1
                        Мигалку бы дали, можно и за копейки СОРМ читать…
          • 0
            в BSD есть pf, который с pflow/pfflowd экспортит нетфлоу, можно легко выбирать какой трафик учитывать, а какой нет правилами. так что наброс про иптаблес мимо тазика, «простые» варианты есть и в BSD.
            • 0
              А он равзе там модулем ядра это делает? К тому же насколько я помню у pf с производительностью было как-то не очень хорошо.
              • 0
                pflow — ядерный, pfflowd — нет, но последнему это не мешает выполнять свою работу. а сведения о производительности это часом не от источника ОБС (ОднаБабкаСказала)?
                • 0
                  Интернет можно считать за ОБС. Вообще если у вас есть подтверждение что оно работает хотя бы не хуже netgraph я с удовольствием почитаю.
          • 0
            Коллега, а Вы не хотите сделать доклад на РИТ++ (http://www.ritconf.ru/)?
            Если интересно, то я могу выслать подробную информацию.
            • 0
              Нет, извиняйте, не готов к такому :)

            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.