LINUX.ORG.RU

работа с данными от nfdump


0

1

Здравствуйте! Может мне тут помогут, а то в админской ветке пока тихо =(

У меня в сети раздается инет через роутер mikrotik где поднят обычный nat. На роутере включен NetFlow для сбора статистики и все это добро отправляется на сервер. Сервер же представляет собой обычную ubuntu 10.10 версии и на ней крутится nfdump принимая netflow трафик от mikrotik-a. Все вроде хорошо, netflow принимается, складывается, через nfsen смотрится, глюков нет.

Но потребовалось решить такую задачу:
1. Каждый день сохранять полную статистику за предыдущий день
2. В полученном файле должны быть ip и имена хостов

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

Исходный файл дампа

Date flow start          Duration Proto      Src IP Addr:Port          Dst IP Addr:Port   Packets    Bytes Flows
1970-01-12 13:37:15.181     0.000 UDP     192.168.173.22:4004  ->   192.168.170.11:4003         1       51     1
1970-01-12 13:37:04.071    11.570 TCP    192.168.170.203:445   ->   192.168.173.43:2411        14     1854     1
1970-01-12 13:37:04.071    11.570 TCP     192.168.173.43:2411  ->  192.168.170.203:445         18     4141     1
1970-01-12 13:36:58.191    17.610 TCP     192.168.170.29:4542  ->      81.19.88.88:80           4      160     1
1970-01-12 13:37:15.941     0.000 UDP    192.168.173.102:13643 ->     208.88.187.9:33033        1       61     1
Summary: total flows: 5, total bytes: 6267, total packets: 38, avg bps: 2824, avg pps: 2, avg bpp: 164
Time window: 1970-01-12 13:36:58 - 1970-01-12 13:37:15
Total flows processed: 756, Blocks skipped: 0, Bytes read: 39340
Sys: 0.000s flows/second: 0.0        Wall: 0.000s flows/second: 1225283.6

Получаемый новый файл дампа

1970-01-12 13:37:15.181 0.000 UDP 192.168.173.22 (kataev.sit.local.minint-k2q30pt.) -> 192.168.170.11 (oktell.sit.local.) 1 51 1
1970-01-12 13:37:04.071 11.570 TCP 192.168.170.203 (192.168.170.203) -> 192.168.173.43 (1-94b7061353914.lena.) 14 1854 1
1970-01-12 13:37:04.071 11.570 TCP 192.168.173.43 (lena.1-94b7061353914.) -> 192.168.170.203 (192.168.170.203) 18 4141 1
1970-01-12 13:36:58.191 17.610 TCP 192.168.170.29 (egorov_a.sit.local.) -> 81.19.88.88 (www.afisha.ru.) 4 160 1
1970-01-12 13:37:15.941 0.000 UDP 192.168.173.102 (uch-klass3.sit.local.) -> 208.88.187.9 (187-009.static.quiettouch.com.) 1 61 1
Вот мой скрипт
#!/bin/bash
year=$1
month=$2
day=$3
cd /var/www/billing/nfdata/
nfdump -R /data/nfsen/profiles-data/live/mikrotik/$year/$month/$day > a$year$month$day.txt
afile1=a$year$month$day.txt
cfile1=c$year$month$day
num=`cat ${afile1} | wc -l`
num=`expr $num - 4`
nxdomain="3(NXDOMAIN)"
for ((i=2;i<=${num};i++))
do
  srcip=`head -n $i $afile1 | tail -n 1 | awk '{print $5}' | awk -F ':' '{print $1}'`
  srcdns=`host $srcip | awk '{printf $5}'`
  if [ "$srcdns" = "$nxdomain" ]; then
    srcdns=$srcip
  fi
  dstip=`head -n $i $afile1 | tail -n 1 | awk '{print $7}' | awk -F ':' '{print $1}'`
  dstdns=`host $dstip | awk '{printf $5}'`
  if [ "$dstdns" = "$nxdomain" ]; then
    dstdns=$dstip
  fi
  head -n "$i" "$afile1" | tail -n 1 | awk -v srcdns=" ($srcdns)" -v srcip="$srcip" -v dstdns=" ($dstdns)" -v dstip="$dstip" '{$5=srcip srcdns;$7=dstip dstdns;print}' >> $cfile1.txt
done
В данном примере приведен дамп из 5 flows, реальный дамп может быть более >100000 и мой способ конвертировать в имена оооочень медленный.

Подскажите пожалуйста что можно придумать в сложившейся ситуации =(


Ответ на: комментарий от arsi

конечно можно и на перле и на питоне. я думал вообще на С парсер написать, но хотелось обойтись.

Вот кстати новый вариант, уже без перезаписи построчно, а поиск первого попавшегося ip, конвертирование в имя и затем замена по всему файлу где совпадает с этим ip.

#!/bin/bash
year=$1
month=$2
day=$3
ipfile=dump$year$month$day.txt
cd /var/www/billing/nfdata/
clear
nfdump -R /data/nfsen/profiles-data/live/mikrotik/$year/$month/$day > $ipfile
cp $ipfile ip$ipfile
while true;
do
ipadr=`grep -Po -m 1 "[ ](\d{1,3}\.){3}\d{1,3}[:]" $ipfile | head -n 1 | rev | cut -c2- | rev`
if [ "$ipadr" = "" ]; then
  break
fi
echo "$ipadr"
ipdns=`host $ipadr | head -n 1 | awk '{printf $5}'`
ipadrdns="$ipadr($ipdns)"
echo "$ipadrdns"
sed "s/$ipadr/$ipadrdns/g" $ipfile > tmp$ipfile
cat tmp$ipfile > $ipfile
done
rm tmp$ipfile

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

Боюсь что бекрезолвы мало информативны, а лучше сказать не информативны для анализа.

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

> конечно можно и на перле и на питоне

#!/usr/bin/perl

use strict;

open my $fh, '<', 'my.log' or die $!;

my %cache;

sub resolve {
    my $ip = shift;
    $cache{$ip} = (`host $ip` =~ /domain name pointer ([\w-]+(\.[\w-]+)+)\./)[0] || $ip
        unless exists $cache{$ip};
    return $cache{$ip};
}

while (<$fh>) {
    s/(?<=\s)(\d{1,3}(?:\.\d{1,3}){3})(:\d+\s)/"$1$2(".resolve($1).') '/ge;
    print;
}

только регекспы для доменного имени и ипника заменить на более корректные…

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

спасибо за пример на перле! ща попробую и отпишусь. Для статистики скажу что второй вариант на bash-e обработал дамп весом в 27013754 байт (27Мб) за 5 часов и 30 минут, превратив файл в dns кашу весом в 39011174 байт (39Мб) =). Посмотрим как справится перл, я честно говоря возлагаю на него надежды, хотя мозг уже впадает в истерику, а руки рвутся писать парсер на С =(

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