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()
В файл складируется вот такая информация:
Формат записи очень простой и позволит легко составлять отчеты, либо экспортировать в БД.
- IP-адрес роутера с которого пришел запрос
- номер пакета
- время захвата пакета
- IP-адрес источника
- маска подсети источника
- порт источника
- интерфейс источника
- IP-адрес приёмника
- маска подсети приемника
- порт приемника
- интерфейс приемника
- получено пакетов
- получено байт
- протокол
Номер пакета позволяет узнать о потере пакетов. А так же количество пропавших пакетов. В дальнейшем, на основании этой информации, будет производиться корректировка данных о трафике.
Маска подсети в нашем случае является лишней, но я её оставил для красоты, тем более она занимает мизерный обьем.
На текущий момент появилась идея всю самую затрантую по ресурсам задачу повешать на анализатор. В конечном итоге в базу данных попадет уже скомпилированная и сжатая по времени информация о прошедшем трафике. Если будет большой объём трафика с одного и того же IP-адреса, то информация сожмётся до пары кортежей в БД.
Судя по всему в Netflow трафик попадают даже данные которые убиваются на входе в интерфейс. Это надо проверять дополнительно, но данное поведение позволит выявлять атаки на оборудование.
Недавно возникли вопросы о необходимости или бесполезности записывать адрес роутера с которого приходит Netflow траффик. Я считаю, что это необходимо. Во-первых, мало ли кто поверх вашего трафика начнет кидать свой. Во-вторых, чтобы гарантировать правильность полученных данных. Во-третьих, при смене интерфейса с которого приходит трафик изменится и адрес роутера. В-четвертых, он поможет понять направление генерируемого трафика.
На текущий момент у меня запущено несколько таких коллекторов для дальнейших экспериментов.
Тэги: ИТ, Cisco, программирование, Питон
Отредактировано:2021-02-17 12:59:52