LINUX.ORG.RU

Странные значения адресов у последних потоков в пакете netflow


0

0

Написал софтинку, которая считает трафик по netflow. И всё вроде бы 
хорошо, но есть одно но...

Последние несколько потоков имеют странные адреса.

Вот пример:

time = 1225203441,src = 192.168.27.222, dst = 192.168.27.255, pkt = 3, oct = 234,in = 1, out = 0, first = 1523725680, last = 1523727180
...
time = 1225203441,src = 25.1.0.0, dst = 40.0.0.0, pkt = 524288, oct = 805306368,in = 5376, out = 31, first = 385875968, last = 352321544
time = 1225203441,src = 255.31.0.0, dst = 177.0.0.0, pkt = 234881024, oct = 352327424,in = 18432, out = 0, first = 203882496, last = 2969567232
time = 1225203441,src = 12.39.0.0, dst = 48.0.0.0, pkt = 100663296, oct = 671088640,in = 5376, out = 8, first = 335544320, last = 1157629440
time = 1225203441,src = 14.0.0.0, dst = 21.0.13.0, pkt = 234881024, oct = 1207959552,in = 45312, out = 0, first = 268435456, last = 352324096
time = 1225203441,src = 17.0.0.0, dst = 40.0.0.0, pkt = 4280221696, oct = 2969567232,in = 17664, out = 1792, first = 234881024, last = 1207959552
time = 1225203441,src = 14.0.0.0, dst = 72.0.0.0, pkt = 203882496, oct = 100663296,in = 5376, out = 1, first = 262144, last = 100663296
time = 1225203441,src = 57.0.0.0, dst = 192.168.25.1, pkt = 1346490970, oct = 1346490970,in = 24352, out = 17866, first = 16777216, last = 3589498337

То что адреса и прочие данные высчитываются правильно, я уверен, 
поскольку первые 20 потоков имеют правильные значения. А особенно 
меня смущает, особенно в приведённом блоке, так это то что у 
последнего потокока примера адрес назначения имеет правильное
значение равное адресу шлюза (циски).

Может кто то сможет разъяснить что это за адреса? Может где я 
напортачил?

Заранее спасибо!!!
★★★★★

...на различия time и first/last не обращайте внимание, просто time 
берётся с машины на которой собирается netflow, а first/last с циски.

cyclon ★★★★★
() автор топика
Ответ на: комментарий от cyclon

спросил whois про эти адреса, записи о них есть, но всё равно как то странно..

cyclon ★★★★★
() автор топика
Ответ на: комментарий от true_admin

тут ещё один вопрос, а почему у входящих и исходящих интерфейсов могут быть такие значения?

in = 5376, out = 1

ведь по идее их не может быть столько.

cyclon ★★★★★
() автор топика
Ответ на: комментарий от true_admin

не похоже..

select DISTINCT inf from netflow;
...
1314 rows in set (1.00 sec)

в столбце inf в таблице netflow пишутся порты.

cyclon ★★★★★
() автор топика

>То что адреса и прочие данные высчитываются правильно, я уверен, 
>поскольку первые 20 потоков имеют правильные значения.

А чему равно поле count в заголовке Netflow пакета?
Случайно не 20?

Анализируешь ли ты версию протокола?
В разных версиях формат пакетов отличается (а 9-я версия - фактически
другой протокол). 
Кстати, какая версия используется?

Описание форматов, по которым я писал парсеры Netflow:
http://netflow.caligare.com/netflow_format.htm

Хотелось бы посмотреть код, который парсит пакеты.

Krivenok_Dmitry
()
Ответ на: комментарий от Krivenok_Dmitry

Разумеется проверяю и версию и количество потоков в пакете и в зависимости от этого соответствующим образом обрабатываю пакет.

cyclon ★★★★★
() автор топика
Ответ на: комментарий от cyclon

хз что там с нетфлоу, но запрос лучше делать так: select DISTINCT count(inf) from netflow :)

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

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

Да у меня есть доступ к этим цискам. Там установлена 5-я версия... Моя
 софтина правильно определяет версию.

cyclon ★★★★★
() автор топика
Ответ на: комментарий от cyclon

Если ты не уверен в своем коде, то можно попробовать другой
ресивер/прасер (например flow-tools).

Если он покажет тот же мусор в конце пакета, то вероятно проблема
на железке.
Насколько я помню, можно прямо на циске посмотреть текущее состояние
кэша. 
Может лажа уже там? Хотя я сомневаюсь в этом :)

А какая ОС используется для запуска ресивера UDP дейтаграмм, в которые
инкапсулируются пакеты Netflow? 

Krivenok_Dmitry
()
Ответ на: комментарий от Krivenok_Dmitry

> А какая ОС используется для запуска ресивера UDP дейтаграмм, в которые
инкапсулируются пакеты Netflow?

использует linux

cyclon ★★★★★
() автор топика
Ответ на: комментарий от cyclon

int listen::nf5Version(const u_char *packet)
{
	int data_pos, h_offset, r_offset, count;
	struct ip *ip;
	struct udphdr *udp;
	NFv5H *nf5h;	// заголовок 5-ой версии netflow
	NFv5R *nf5r;	// данные 5-ой версии netflow

	// получаем заголовок ip
	ip = (struct ip *) (packet + ETH_H);
	// получаем заголовок tcp
	udp = (struct udphdr *) (packet + ETH_H + IP_H);

	// вычисляем позицию начала данных
	data_pos = ETH_H + IP_H + UDP_H;
	// вычисляем позицию начала заголовка netflow пакета
	h_offset = data_pos;
	// вычисляем позицию начала первого пакета данных netflow
	r_offset = data_pos + sizeof(NFv5H);

	// получаем заголовок пакета nteflow
	nf5h = (struct NFv5H *) (packet + h_offset);
	// получаем первый пакет данных netflow
	nf5r = (struct NFv5R *) (packet + r_offset);

	// получае количество потоков в пакете netflow
	count = ntohs(nf5h->Count);

	// перебираем все потоки включённые в поток
	for(int i = 0; i < count; i++){
	
		Flow flow;
		flow.from = ip->ip_src.s_addr;
		flow.srcaddr = nf5r->srcaddr;
		flow.dstaddr = nf5r->dstaddr;
// 		flow.nexthop = nf5r->nexthop;
		flow.input = ntohs(nf5r->input);
		flow.output = ntohs(nf5r->output);
		flow.dPkts = ntohl(nf5r->dPkts);
		flow.dOctets = ntohl(nf5r->dOctets);
		flow.dstport = ntohs(nf5r->dstport);
		flow.First = ntohl(nf5r->First);
		flow.Last = ntohl(nf5r->Last);
// 		flow.prot = ntohs(nf5r->prot);

		work(flow);

		// вычисляем позицию следующего потока
		r_offset = data_pos + (sizeof(NFv5R))*i + sizeof(NFv5H);
		// получаем следующий поток
		nf5r = (struct NFv5R *) (packet + r_offset);
	}
}

// обработка полученных пакетов
void listen::got_packet(pcap_t *handle)
{
	int data_pos = 0;
	NFversion *ver;

	// перебираем полученные пакеты
	while(1){
		// получаем пакет
		packet = pcap_next(handle,&header);

		// вычисляем начало данных
		data_pos = ETH_H + IP_H + UDP_H;

		// получаем версию пакета
		ver = (struct NFversion *) (packet + data_pos);

		switch(ntohs(ver->Version)){
			case 1:
				nf1Version(packet);
				break;
			case 5:
				nf5Version(packet);
				break;
                                ...
	}
}

cyclon ★★★★★
() автор топика
Ответ на: комментарий от cyclon

ntohs делаю поскольку у mysql и php функции inet_ntoa не изменяют порядок байтов

cyclon ★★★★★
() автор топика
Ответ на: комментарий от cyclon

В этом цикле помоему ошибка.

	for(int i = 0; i < count; i++){
	
		Flow flow;
		flow.from = ip->ip_src.s_addr;
		flow.srcaddr = nf5r->srcaddr;
		flow.dstaddr = nf5r->dstaddr;
// 		flow.nexthop = nf5r->nexthop;
		flow.input = ntohs(nf5r->input);
		flow.output = ntohs(nf5r->output);
		flow.dPkts = ntohl(nf5r->dPkts);
		flow.dOctets = ntohl(nf5r->dOctets);
		flow.dstport = ntohs(nf5r->dstport);
		flow.First = ntohl(nf5r->First);
		flow.Last = ntohl(nf5r->Last);
// 		flow.prot = ntohs(nf5r->prot);

		work(flow);

		// вычисляем позицию следующего потока
		r_offset = data_pos + (sizeof(NFv5R))*i + sizeof(NFv5H);
		// получаем следующий поток
		nf5r = (struct NFv5R *) (packet + r_offset);
	}

При i == 0 выражение
r_offset = data_pos + (sizeof(NFv5R))*i + sizeof(NFv5H);
сокращается до
r_offset = data_pos + sizeof(NFv5H);
и при i == 1 nf5r будет смотреть на 1-й, а не на 2-й пакет.

Krivenok_Dmitry
()
Ответ на: комментарий от cyclon

Я не работал с pcap'ом и не знаю какие плюсы в его использовании
в данной задаче.
На мой взгляд их нет.

Возможно ты сильно урезал код и просто не запостил все, но 
при обработке Netflow неплохо было бы анализировать 
sequence numbers пакетов, т.к. UDP - протокол ненадежный.

И в общем случае вызов типа
work(flow);
в цикле парсинга потоков - плохая идея.
Если функция work может надолго заблокироваться (например в
случае записи в БД), а поток пакетов очень большой, то ты просто 
напросто будешь терять UDP дейтаграммы.
А узнать теряешь ли ты их можно путем анализа flow_sequence.

Krivenok_Dmitry
()
Ответ на: комментарий от Krivenok_Dmitry

> При i == 0 выражение
> r_offset = data_pos + (sizeof(NFv5R))*i + sizeof(NFv5H);
> сокращается до
> r_offset = data_pos + sizeof(NFv5H);
> и при i == 1 nf5r будет смотреть на 1-й, а не на 2-й пакет.

так всё правильно, берётся первая запись из пакета, т.е. заголовок 
основных пакетов, плюс заголовок пакета netflow

cyclon ★★★★★
() автор топика
Ответ на: комментарий от Krivenok_Dmitry

> Если функция work может надолго заблокироваться (например в
> случае записи в БД), а поток пакетов очень большой, то ты просто 
> напросто будешь терять UDP дейтаграммы.

тут я хочу выкрутиться (пока не реализовал) использовать 
многопоточность (threads).

cyclon ★★★★★
() автор топика
Ответ на: комментарий от cyclon

Кажется понял, у меня два раза считывался 1-ый элемент, В цикле поправил для первого i вместо 0 поставил 1. Но вот только проблема осталась.

cyclon ★★★★★
() автор топика
Ответ на: комментарий от cyclon

Вот ещё раз кусок лога с нумерацией потоков в пакете

num = 0 time = 134516304, from = 192.168.25.1,src = x.x.x.x, dst = x.x.x.x, pkt = 5, oct = 969,in = 2, out = 1, first = 1691782828$
num = 1 time = 134516304, from = 192.168.25.1,src = 192.168.25.3, dst = x.x.x.x, pkt = 6, oct = 1231,in = 1, out = 2, first = 1691782836, l$
num = 2 time = 134516304, from = 192.168.25.1,src = x.x.x.x, dst = x.x.x.x, pkt = 5, oct = 4256,in = 2, out = 1, first = 1691782844$
num = 3 time = 134516304, from = 192.168.25.1,src = 192.168.25.3, dst = x.x.x.x, pkt = 5, oct = 868,in = 1, out = 2, first = 1691782848, l$
num = 4 time = 134516304, from = 192.168.25.1,src = 192.168.25.2, dst = x.x.x.x, pkt = 25, oct = 1585,in = 1, out = 2, first = 1691782856,$
num = 5 time = 134516304, from = 192.168.25.1,src = 192.168.25.2, dst = x.x.x.x, pkt = 8, oct = 989,in = 1, out = 2, first = 1691782868, l$
num = 6 time = 134516304, from = 192.168.25.1,src = 192.168.25.2, dst = x.x.x.x, pkt = 8, oct = 904,in = 1, out = 2, first = 1691782872, $
num = 7 time = 134516304, from = 192.168.25.1,src = x.x.x.x, dst = x.x.x.x, pkt = 5, oct = 717,in = 2, out = 1, first = 1691782876$
num = 8 time = 134516304, from = 192.168.25.1,src = x.x.x.x, dst = x.x.x.x, pkt = 25, oct = 30632,in = 2, out = 1, first = 1691782$
num = 9 time = 134516304, from = 192.168.25.1,src = x.x.x.x, dst = x.x.x.x, pkt = 8, oct = 6543,in = 2, out = 1, first = 169178289$
num = 10 time = 134516304, from = 192.168.25.1,src = x.x.x.x, dst = x.x.x.x, pkt = 8, oct = 7237,in = 2, out = 1, first = 1691782$
num = 11 time = 134516304, from = 192.168.25.1,src = x.x.x.x, dst = x.x.x.x, pkt = 6, oct = 3135,in = 2, out = 1, first = 16917717$
num = 12 time = 134516304, from = 192.168.25.1,src = 192.168.25.2, dst = x.x.x.x, pkt = 5, oct = 1196,in = 1, out = 2, first = 1691772160,$
num = 13 time = 134516304, from = 192.168.25.1,src = x.x.x.x, dst = x.x.x.x, pkt = 5, oct = 621,in = 2, out = 1, first = 169177224$
num = 14 time = 134516304, from = 192.168.25.1,src = 192.168.25.2, dst = x.x.x.x, pkt = 31, oct = 2542,in = 1, out = 2, first = 1691772352$
num = 15 time = 134516304, from = 192.168.25.1,src = x.x.x.x, dst = x.x.x.x, pkt = 39, oct = 49405,in = 2, out = 1, first = 169177$
num = 16 time = 134516304, from = 192.168.25.1,src = 192.168.25.3, dst = x.x.x.x, pkt = 2, oct = 106,in = 1, out = 2, first = 1691767828,$
num = 17 time = 134516304, from = 192.168.25.1,src = 192.168.25.3, dst = x.x.x.x, pkt = 7, oct = 990,in = 1, out = 2, first = 1691777988, la$
num = 18 time = 134516304, from = 192.168.25.1,src = x.x.x.x, dst = x.x.x.x, pkt = 6, oct = 996,in = 2, out = 1, first = 1691777996,$
num = 19 time = 134516304, from = 192.168.25.1,src = x.x.x.x, dst = x.x.x.x, pkt = 2, oct = 106,in = 2, out = 1, first = 16917680$
num = 20 time = 134516304, from = 192.168.25.1,src = 25.1.0.0, dst = 40.0.0.0, pkt = 524288, oct = 805306368,in = 5376, out = 31, first = 385875$
num = 21 time = 134516304, from = 192.168.25.1,src = 255.31.0.0, dst = 177.0.0.0, pkt = 234881024, oct = 352327424,in = 18432, out = 0, first = $
num = 22 time = 134516304, from = 192.168.25.1,src = 12.39.0.0, dst = 48.0.0.0, pkt = 100663296, oct = 671088640,in = 5376, out = 8, first = 335$
num = 23 time = 134516304, from = 192.168.25.1,src = 14.0.0.0, dst = 21.0.13.0, pkt = 234881024, oct = 1207959552,in = 45312, out = 0, first = 2$
num = 24 time = 134516304, from = 192.168.25.1,src = 17.0.0.0, dst = 40.0.0.0, pkt = 4280221696, oct = 2969567232,in = 17664, out = 1792, first $
num = 25 time = 134516304, from = 192.168.25.1,src = 14.0.0.0, dst = 72.0.0.0, pkt = 203882496, oct = 100663296,in = 5376, out = 1, first = 2621$
num = 26 time = 134516304, from = 192.168.25.1,src = 192.168.25.2, dst = x.x.x.x, pkt = 16777728, oct = 134217728,in = 16527, out = 54884$
num = 27 time = 134516304, from = 192.168.25.1,src = x.x.x.x, dst = x.x.x.x, pkt = 33554688, oct = 83886080,in = 9359, out = 54884$
num = 28 time = 134516304, from = 192.168.25.1,src = x.x.x.x, dst = x.x.x.x, pkt = 33554688, oct = 419430400,in = 13455, out = 548$

cyclon ★★★★★
() автор топика
Ответ на: комментарий от cyclon

> тут я хочу выкрутиться (пока не реализовал) использовать 
> многопоточность (threads).

Не думаю что здесь нужны треды.

Порождать тред на каждый пакет - безумие.
Overhead страшный.

Использовать пул заранее созданных тредов и диспетчеризировать
пакет на них не имеет смысла, т.к. если скорость прихода пакетов
значительно превышает скорость обработки (записи в БД), то что у
тебя 1 поток, что N - разницы никакой.

Я бы предложил разделить сбор и обработку данных на 2 приложения:
1) Чисто ресивер.
Считывает UDP дейтаграммы, анализирует адрес получателя и версию
протокола и поддерживает некий буфер (например 1000 дейтаграмм).
Когда буфер заполняется, ресивер сбрасывает буфер в файл.
При этом можно подобрать размер блока данных таким образом, чтобы
запись была максимально быстрой.
Очевидно, что файлы нужно нарезать с учетом времени (например за час).
В итоге ты получишь файлы вида:
192.168.65.1_v5_20081030_000000.cdr
192.168.65.1_v5_20081030_010000.cdr
192.168.65.1_v5_20081030_020000.cdr
192.168.65.1_v5_20081030_030000.cdr
192.168.65.1_v5_20081030_040000.cdr
192.168.65.1_v5_20081030_050000.cdr
192.168.65.1_v5_20081030_060000.cdr
192.168.65.1_v5_20081030_070000.cdr
192.168.65.1_v5_20081030_080000.cdr
192.168.65.1_v5_20081030_090000.cdr
192.168.65.1_v5_20081030_100000.cdr
192.168.65.1_v5_20081030_110000.cdr

Основная фишка - в файлах хранятся сырые пакеты Netflow (поток байт).
Время на парсинг (анализируется только версия - 1-е поле) и обработку
вообще не тратится.

2) Парсер
Парсер парсит файлы используя формат пакетов Netflow (в файлах ведь
сырые пакеты) и делает с ними что хочет.
Может в файл отписывать, может в БД, может отчет строить.

Естественно обработка в некотором роде офлайновая (на период нарезки
файлов + время обработки).
Но Netflow нельзя обрабатывать в online.

И еще совет - нельзя вставлять в БД информацию по каждому flow.
Нужно предварительно агрегировать.
База ляжет от нагрузки по вставкам на больших девайсах, где поток
Netflow безумный.

В моей практике встречались сырые файлы с часовой нарезкой размером
более 2Gb.

Сам считай
2GB = 2 * 1024 * 1024 * 1024
1 пакет = 24 + 48 * 30 = 1464 (на самом деле 30 - максимум, но обычно
он всегда достигается при больших нагрузках)
Записей в пакете - 30
В часе 3600 секунд.

Получаем:
(2 * 1024 * 1024 * 1024 / 1464) * 30 / 3600 = 12223

То есть более 12000 flow в секунду.
Какая БД выдержит столько INSERT'ов?

Krivenok_Dmitry
()
Ответ на: комментарий от cyclon

Обрати внимание на поля pkt и oct начиная с 20-го пакета.
Они явно левые.
А значения индексов интерфейсов.

Ты явно читаешь какой-то мусор и интерпретируешь его как пакет
Netflow.

Krivenok_Dmitry
()
Ответ на: комментарий от Krivenok_Dmitry

По поводу тредов... Я агргрегирую данные внутри сборщика и передаю их раз в минуту. Т.е. точноть записей в базе составляет одна минута.

cyclon ★★★★★
() автор топика
Ответ на: комментарий от cyclon

Кстати странно... у меня почему то count постоянно равно 30 видимо как раз отсюда и проблема. Или так и должно быть?

cyclon ★★★★★
() автор топика
Ответ на: комментарий от cyclon

>Кстати странно... у меня почему то count постоянно равно 30 видимо как
> раз отсюда и проблема. Или так и должно быть?

Так и должно быть.
Согласно спецификации максимальное количество flow в пакете NFv5 - 30.
Если железка нагружена, то она всегда посылает максимально полные
пакеты.

Почитай для чего изначально был придуман Netflow.
Узнаешь много интересного :)

Krivenok_Dmitry
()
Ответ на: комментарий от Krivenok_Dmitry

Сложно сказать...flow-tools выдаёт такое 

192.168.25.3     x.x.x.x  6     52371    80       1041        6
x.x.x.x      	 x.x.x.x  6     80       37710    9128        9
192.168.25.2     x.x.x.x  6     52468    80       720         6
194.67.45.98     x.x.x.x  6     80       36120    523         5
192.168.25.3     x.x.x.x  6     25       59985    173         3
192.168.25.3     x.x.x.x  6     52372    25       11383       24
x.x.x.x          x.x.x.x  6     80       52371    3944        5
x.x.x.x          x.x.x.x  6     80       52468    346         5
x.x.x.x          x.x.x.x  6     25       52372    1515        19
192.168.25.3     x.x.x.x  6     52373    80       892         5
192.168.25.2     x.x.x.x  6     55322    80       781         6
192.168.25.2     x.x.x.x  6     37002    80       963         6
192.168.25.3     x.x.x.x  6     52375    80       1489        6
192.168.25.3     x.x.x.x  6     52376    80       1491        6
192.168.25.2     x.x.x.x  6     36107    80       2614        42
x.x.x.x          x.x.x.x  6     80       52373    460         4
x.x.x.x          x.x.x.x  6     80       55322    510         5
x.x.x.x          x.x.x.x  6     80       37002    795         6
192.168.25.3     x.x.x.x  6     52377    80       904         5
x.x.x.x          x.x.x.x  6     80       52375    351         4
x.x.x.x          x.x.x.x  6     80       52376    351         4
192.168.25.3     x.x.x.x  6     51443    80       104         2
192.168.25.3     x.x.x.x  6     51444    80       104         2
x.x.x.x          x.x.x.x  6     80       36107    75640       55
x.x.x.x          x.x.x.x  6     80       52377    373         4
x.x.x.x          x.x.x.x  6     80       51443    52          1
x.x.x.x          x.x.x.x  6     80       51444    52          1
192.168.25.2     x.x.x.x  6     52356    80       104         2
192.168.25.2     x.x.x.x  6     44979    80       104         2
x.x.x.x          x.x.x.x  6     80       44979    104         2

cyclon ★★★★★
() автор топика
Ответ на: комментарий от cyclon

Проблема решена, была в том что pcap_open_live открывал перехват на 1024 байта, а пакет был 1506 :) Спасибо всем за помощь!

cyclon ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.