63 lines
2.0 KiB
Python
Raw Normal View History

2025-05-08 09:49:17 +02:00
from scapy.all import *
import struct
# Define NetFlow v5 header and record formats
NETFLOW_V5_HEADER_LEN = 24
NETFLOW_V5_RECORD_LEN = 48
def parse_netflow_v5(packet):
if not packet.haslayer(UDP):
return
udp_payload = bytes(packet[UDP].payload)
if len(udp_payload) < NETFLOW_V5_HEADER_LEN:
print("Invalid NetFlow v5 header length")
return
# Parse header
header = struct.unpack('!HHIIIIBBH', udp_payload[:NETFLOW_V5_HEADER_LEN])
version, count, uptime, unix_secs, unix_nsecs, flow_seq, engine_type, engine_id, sampling = header
print(f"\n--- NetFlow v5 Packet ---")
print(f"Version: {version}, Record count: {count}, Sys uptime: {uptime}")
print(f"Unix secs: {unix_secs}, Flow sequence: {flow_seq}")
# Parse flow records
offset = NETFLOW_V5_HEADER_LEN
for i in range(count):
if offset + NETFLOW_V5_RECORD_LEN > len(udp_payload):
print("Incomplete record")
break
record = struct.unpack('!IIIHHIIIIHHBBBBHHBBH', udp_payload[offset:offset + NETFLOW_V5_RECORD_LEN])
src_addr = inet_ntoa(struct.pack('!I', record[0]))
dst_addr = inet_ntoa(struct.pack('!I', record[1]))
next_hop = inet_ntoa(struct.pack('!I', record[2]))
src_port = record[10]
dst_port = record[11]
packets = record[4]
bytes_ = record[5]
print(f"\nFlow #{i+1}")
print(f"Src IP: {src_addr}:{src_port} → Dst IP: {dst_addr}:{dst_port}")
print(f"Next hop: {next_hop}, Packets: {packets}, Bytes: {bytes_}")
offset += NETFLOW_V5_RECORD_LEN
# Sniff on a given interface or from a pcap file
def start_sniff(interface=None, pcap_file=None):
if pcap_file:
packets = rdpcap(pcap_file)
for pkt in packets:
parse_netflow_v5(pkt)
elif interface:
sniff(iface=interface, filter="udp port 2055", prn=parse_netflow_v5)
# Example usage
if __name__ == "__main__":
# Provide either an interface or a pcap file
start_sniff(pcap_file="netflowv5_sample.pcap")
# start_sniff(interface="eth0")