63 lines
2.0 KiB
Python
63 lines
2.0 KiB
Python
![]() |
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")
|
||
|
|