аукцион / donate / услуги / RSS / распечатать / вход 
Мой мир
Вконтакте
Одноклассники

[16 февраля 2021 | 17 февраля 2021 | 24 февраля 2021]

NetFlow v5 Python (часть 2)

Написание собственного коллектора для Netflow на Python продолжается. Текущий вариант коллектора «ловит» входящий трафик и пишет его в файлы каждую минуту. Потом можно будет написать парсер, который будет «разбирать» собранные нами данные и сортировать как нам захочется. Для себя я пока пишу немного другой коллектор который пишет в файлы двоичный код, что многократно уменьшит объём хранимой информации. В принципе, метод хранения не принципиален, так как в дальнейшем эта информация будет записываться в БД, а на диске будет удалёна. Дисковое хранение требуется для гарантированной записи и ускорения работы скрипта, у меня используется SSD диск для временного хранения данных.

Текущий код для коллектора теперь выглядит вот так:

#!/usr/bin/python3
# -*- Mode: Python; tab-width: 4 -*-
#       Id: collect.py, v 1.06 2021
#       Author: Ivan Kurilko 
#       https://orcinus.ru
# ======================================================================
# Copyright 2020 by Ivan Kurilko aka Orcinus Orca
#
#                         All Rights Reserved
#
# Permission to use, copy, modify, and distribute this software and
# its documentation for any purpose and without fee is hereby
# granted, provided that the above copyright notice appear in all
# copies and that both that copyright notice and this permission
# notice appear in supporting documentation, and that the name of Ivan
# Kurilko not be used in advertising or publicity pertaining to
# distribution of the software without specific, written prior
# permission.
#
# IVAN KURILKO DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
# NO EVENT SHALL IVAN KURILKO BE LIABLE FOR ANY SPECIAL, INDIRECT OR
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# ======================================================================

import socket, struct, time

from socket import inet_ntoa
# Netflow v5
SIZE_OF_HEADER = 24
SIZE_OF_RECORD = 48
# Netflow v1
#SIZE_OF_HEADER = 17
#SIZE_OF_RECORD = 49


sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('0.0.0.0', 9996))

while True:
   buf, addr = sock.recvfrom(1500)

   (version, count) = struct.unpack('!HH',buf[0:4])

   # Проверяем версию протокола
   if version != 5:
      print ("Not NetFlow v5!")
      continue

   # По стандарту в этом пакете не может быть больше 30 записей
   if count <= 0 or count > 30:
      print ("Invalid count %s" % count)
      continue

   # Считываем заголовок
   (sys_uptime, unix_secs, unix_nsecs, flow_sequence) = struct.unpack('!IIII',buf[4:20])

   # Время старта оборудования, к нему будем плюсовать пакеты
   starttime = unix_secs-sys_uptime//1000

   # упаковываем IP-адрес роутера
   iprouter = struct.unpack('!I', socket.inet_aton(addr[0]))[0]
   # Обнуляем байтовую строку
   outpacket = ''

   for i in range(0, count):
      try:
         # Точка смещения пакета
         offset = SIZE_OF_HEADER+(i*SIZE_OF_RECORD)
         # Заполняем переменные
         (srcaddr, dstaddr, nexthop, if_input, if_output,
            dpkts, doсtets, first, last, srcport, dstport,
            pad1, tcp_flags, prot, tos, src_as, dst_as,
            src_mask, dst_mask) = struct.unpack('!IIIHHIIIIHHBBBBHHBB',buf[offset+0:offset+46])
         # UNIX время создания пакета
         startpkt = starttime+first//1000
         
         outpacket += socket.inet_ntoa(struct.pack('!I', iprouter))

         outpacket += '\t'+str(flow_sequence+i)
         outpacket += '\t'+time.ctime(startpkt)

         outpacket += '\t'+socket.inet_ntoa(struct.pack('!I', srcaddr))
         outpacket += '\t'+str(src_mask)
         outpacket += '\t'+str(srcport)
         outpacket += '\t'+str(if_input)

         outpacket += '\t'+socket.inet_ntoa(struct.pack('!I', dstaddr))
         outpacket += '\t'+str(dst_mask)
         outpacket += '\t'+str(dstport)
         outpacket += '\t'+str(if_output)

         outpacket += '\t'+str(dpkts)
         outpacket += '\t'+str(doсtets)
         outpacket += '\t'+str(prot)+'\n'

      except:
         continue

   # дописываем в файл
   with open(addr[0]+'-'+str(unix_secs//60)+'.txt', 'a') as file:
      file.write(outpacket)
      file.close()

В файл складируется вот такая информация:

Netflow database on ssd.

Формат записи очень простой и позволит легко составлять отчеты, либо экспортировать в БД.

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

Маска подсети в нашем случае является лишней, но я её оставил для красоты, тем более она занимает мизерный обьем.

На текущий момент появилась идея всю самую затрантую по ресурсам задачу повешать на анализатор. В конечном итоге в базу данных попадет уже скомпилированная и сжатая по времени информация о прошедшем трафике. Если будет большой объём трафика с одного и того же IP-адреса, то информация сожмётся до пары кортежей в БД.

Судя по всему в Netflow трафик попадают даже данные которые убиваются на входе в интерфейс. Это надо проверять дополнительно, но данное поведение позволит выявлять атаки на оборудование.

Недавно возникли вопросы о необходимости или бесполезности записывать адрес роутера с которого приходит Netflow траффик. Я считаю, что это необходимо. Во-первых, мало ли кто поверх вашего трафика начнет кидать свой. Во-вторых, чтобы гарантировать правильность полученных данных. Во-третьих, при смене интерфейса с которого приходит трафик изменится и адрес роутера. В-четвертых, он поможет понять направление генерируемого трафика.

На текущий момент у меня запущено несколько таких коллекторов для дальнейших экспериментов.

Тэги: ИТ, Cisco, программирование, Питон

Отредактировано:2021-02-17 12:59:52


Этот сайт использует файлы cookies, чтобы упростить вашу навигацию по сайту, предлагать только интересную информацию и упростить заполнение форм. Я предполагаю, что, если вы продолжаете использовать мой сайт, то вы согласны с использованием мной файлов cookies. Вы в любое время можете удалить и/или запретить их использование изменив настройки своего интернет-браузера.

Сообщайте мне о замеченных ошибках на: web@orcinus.ru. Все пожелания и советы будут учтены при дальнейшем проектировании сайта. Я готов сотрудничать со всеми желающими. В некоторых случаях, мнение автора может не совпадать с мнением автора! Phone: +7-902-924-70-49.

Top.Mail.Ru
Top.Mail.Ru LiveInternet Rambler's Top100 Яндекс.Метрика