Vadim Goncharov wrote:
22.06.11 @ 18:53 Oleg Cherevko wrote:

На данный момент ng_netflow, в силу его внутреннего устройства, до этого идеала далеко. У него проблемы с broadcast- и multicast-трафиком, с пакетами, отсеяными firewall'ом, с ipfw fwd, с локальным трафиком и,

С fwd можно справляться, навешивая ноду непосредственно на ng_ether, а не через файрвол, и включая соответствующие флаги в конфигурации узла, чтобы не считало дважды тот же трафик.

Да, можно. Но это будет полноценным решением лишь в том случае, если в картине
отсутствует ipfw nat, а у меня он предполагается присутствующим. Если собирать
netflow на выходе через ng_ether, невозможно будет увидеть детализацию трафика
по внутренним ip (которые раньше по пути движения пакета переписывает NAT).

возможно, еще с чем-то, до чего я пока не добрался. Справедливости ради следует сказать, что все вышеперечисленное обычно не является определяющим в общем объеме трафика, так что ng_netflow для основного трафика на машине без особых изысков в конфигурации -- вполне рабочий инструмент. Но мне хочется перевести его из фазы "make it work" в фазу "make it right", (ну а затем и в "make it fast", если понадобится).

Боюст, это опять потребует архитектурных изменений :)

Чтобы совсем все идеально правильно работало -- наверное, да. Но чтобы выправить
ряд текущих косяков с broadcast'ами, multicast'ами и ipfw fwd, как оказалось,
нужно не так уж много всего менять. Совсем скромный патч для ng_ipfw (чтобы он
сохранял oif в mbuf tag'е). Чуть менее скромный патч для составляющих ng_netflow
(чтобы доставать этот oif, а также next_hop от ipfw fwd из соответсвующих tag'ов
+ еще кой-чего) и voila!

Было так (default смотрит в сторону vlan3):
#flowctl netflow show
SrcIf         SrcIPaddress    DstIf         DstIPaddress    Pr SrcP DstP  Pkts
vlan2         192.168.1.140   vlan3         224.0.0.5       89 0000 0000      2
(null)        192.168.1.141   vlan3         224.0.0.6       89 0000 0000      1
(null)        192.168.1.141   vlan3         224.0.0.5       89 0000 0000      7
vlan2         192.168.1.142   vlan3         224.0.0.5       89 0000 0000      7
vlan3         10.1.0.5        vlan3         10.1.15.255     17 445c 445c      1
vlan3         10.1.0.5        vlan3         255.255.255.255 17 445c 445c      1
(null)        127.0.0.1       lo0           127.0.0.1        1 0000 0000      6
lo0           127.0.0.1       lo0           127.0.0.1        1 0000 0000      6
vlan3         10.1.0.3        vlan3         10.1.15.255     17 0089 0089      3

Стало так:
#flowctl netflow show
SrcIf         SrcIPaddress    DstIf         DstIPaddress    Pr SrcP DstP  Pkts
vlan2         192.168.1.140   (null)        224.0.0.5       89 0000 0000      2
(null)        192.168.1.141   vlan2         224.0.0.6       89 0000 0000      1
(null)        192.168.1.141   vlan2         224.0.0.5       89 0000 0000      7
vlan2         192.168.1.142   (null)        224.0.0.5       89 0000 0000      7
vlan3         10.1.0.5        (null)        10.1.15.255     17 445c 445c      1
vlan3         10.1.0.5        (null)        255.255.255.255 17 445c 445c      1
(null)        127.0.0.1       lo0           127.0.0.1        1 0000 0000      8
lo0           127.0.0.1       (null)        127.0.0.1        1 0000 0000      8
vlan3         10.1.0.3        (null)        10.1.15.255     17 0089 0089      2

В новом варианте четко видно, какие пакеты приняты, какие отправлены и через
какой именно интерфейс. (На приведенном примере можно разглядеть выправление
ситуации с broadcast'ами, multicast'ами и некоторое перемены с локальным
траффиком, но учет ipfw fwd, которого тут не видно, тоже работает -- уже на
соседней машине, которая в production).

Сначала в ng_netflow попадает out-пакет идущий на 127.0.0.1, у него SrcIf=(null), как и положено out-пакетам, потом он уходит в lo0 и тут же снова принимается из lo0, но SrcIf уже, понятное дело, lo0, а поскольку SrcIf входит в определение того, что такое flow, то вот и образуется

Нет, вот в этом месте неправильно.

Да, согласен, тут было не додумано. Значит, все-таки, не зря в рассылку написал.

второй flow для того же пакета, что формально правильно, но по сути неправильно, ибо в результате такой трафик учитывается дважды. Теперь вопрос, что можно с этим сделать? Ну, кроме как просто не отправлять в ng_netflow out-пакеты, идущие на lo0? Может у кого есть какие идеи?

Там на самом деле происходит следующее: у узла в конфигурации включен флаг NG_NETFLOW_CONF_ONCE (conf=7), и узел честно помечает прошедший через него пакет mbuf-тегом "пакет уже побывал на netflow-узле с id=..."; в норме это приведет к тому, что в следующий раз этот пакет будет отсеян еще до разбора, с какого он интерфейса, и с какого flow.

Однако далее пакет с этим тегом отправляется в if_lo, а там основная функция обработчик начинается вот так:

int
if_simloop(struct ifnet *ifp, struct mbuf *m, int af, int hlen)
{
        int isr;

        M_ASSERTPKTHDR(m);
        m_tag_delete_nonpersistent(m);

То есть, почти все теги первым делом удаляются, пакет как бы становится чистым, и потом "поступает на вход". И дальше, когда он снова попадает в ng_netflow, тот уже не обнаруживает на нем своей метки, и вот только тогда вступает в действие то правило, что интерфейс у flow другой.

Не знаю, насколько это архитектурная особенность :) т.е. насколько повредит сделать тег постоянным. Можно попробовать (эффекты, если что, вылезут в других частях системы), если хочется, то вот решение:

исправить в /usr/src/sys/netgraph/netflow/ng_netflow.с и заменить строчку

                mtag = m_tag_alloc(MTAG_NETFLOW, MTAG_NETFLOW_CALLED,

на

mtag = m_tag_alloc(MTAG_NETFLOW, MTAG_NETFLOW_CALLED | MTAG_PERSISTENT,

Ну и как обычно, send-pr с соответствующим полем fix, особенно если ничего не сломается.

Спасибо за идею. Я поэкспериментирую.

--
Olwi


Ответить