22.06.11 @ 18:53 Oleg Cherevko wrote:
На данный момент ng_netflow, в силу его внутреннего устройства, до этого
идеала далеко. У него проблемы с broadcast- и multicast-трафиком, с
пакетами, отсеяными firewall'ом, с ipfw fwd, с локальным трафиком и,
С fwd можно справляться, навешивая ноду непосредственно на ng_ether, а не
через файрвол, и включая соответствующие флаги в конфигурации узла, чтобы
не считало дважды тот же трафик.
возможно, еще с чем-то, до чего я пока не добрался. Справедливости ради
следует сказать, что все вышеперечисленное обычно не является
определяющим в общем объеме трафика, так что ng_netflow для основного
трафика на машине без особых изысков в конфигурации -- вполне рабочий
инструмент. Но мне хочется перевести его из фазы "make it work" в фазу
"make it right", (ну а затем и в "make it fast", если понадобится).
Боюст, это опять потребует архитектурных изменений :)
msg netflow: setconfig { iface=0 conf=7 }
msg netflow: setconfig { iface=1 conf=7 }
[...]
Посылаем 1 UDP пакет на 127.0.0.1:8192 (этот UDP-порт никто не слушает):
>traceroute -e -q1 -M5 -m5 -p8192 127.0.0.1
traceroute to 127.0.0.1 (127.0.0.1), 5 hops max, 40 byte packets
5 localhost (127.0.0.1) 0.062 ms
Смотрим, что появилось в netflow:
>flowctl netflow show | fgrep -e Src -e 127.0.0.1
SrcIf SrcIPaddress DstIf DstIPaddress Pr SrcP
DstP Pkts
(null) 127.0.0.1 lo0 127.0.0.1 17 b171
2000 1
lo0 127.0.0.1 lo0 127.0.0.1 17 b171
2000 1
(null) 127.0.0.1 lo0 127.0.0.1 1 0000
0000 1
lo0 127.0.0.1 lo0 127.0.0.1 1 0000
0000 1
Видим ушедший пакет и icmp port unreachable ему навстречу, но и то и
другое -- в виде 2-х flow, отличающихся source interface'ом.
Для сравнения, если проделать то же самое, но отправить пакет за пределы
машины, на другую машину, где порт тоже никто не слушает, такого эффекта
не будет:
>traceroute -e -q1 -M5 -m5 -p8192 10.1.0.7
traceroute to 10.1.0.7 (10.1.0.7), 5 hops max, 40 byte packets
5 10.1.0.7 (10.1.0.7) 0.182 ms
>flowctl netflow show | fgrep -e Src -e 10.1.0.7
SrcIf SrcIPaddress DstIf DstIPaddress Pr SrcP
DstP Pkts
(null) 10.1.0.14 vlan3 10.1.0.7 17 b17e
2000 1
vlan3 10.1.0.7 lo0 10.1.0.14 1 0000
0000 1
Для разнообразия отправим еще пакет по адресу, на котором нет никакой
машины:
>traceroute -e -q1 -M5 -m5 -p8192 10.1.0.15
traceroute to 10.1.0.15 (10.1.0.15), 5 hops max, 40 byte packets
5 *
>flowctl netflow show | fgrep -e Src -e 10.1.0.15
SrcIf SrcIPaddress DstIf DstIPaddress Pr SrcP
DstP Pkts
(null) 10.1.0.14 vlan3 10.1.0.15 17 b194
2000 1
Мда. Изначально я было хотел попросить прокомментировать эти мои
наблюдения, но так долго писал весь этот длинный текст, что аж сам
понял, почему оно так себя ведет. :)
Сначала в 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, особенно если ничего
не сломается.
--
WBR, Vadim Goncharov