Lately, we are working with Netflow quite a bit for our upcoming release of Trisul Network Metering. Here is a tiny script we find invaluable while looking at network captures containing Netflow traffic.
Often while troubleshooting issues we need to look at the raw Netflow records.
For example : You may want to see all the Netflow records sent for IP = 10.22.1.29
Display filters wont get you far because you will still be left with individual packets. These packets themselves can contain dozens of records of which only one or two match.
We turned to Unsniff Scripting and wrote a simple Ruby script that allows you to query for netflow records matching any field value. We use this script heavily for our internal testing and wish to share it on the blog.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# ------------------------------------------------------------------ # nfquery Print matching netflow records # ------------------------------------------------------------------ require 'win32ole' USAGE = "nfquery <capture-filename> <fieldname>=<value>" EXAMPLE = "nfquery c:\temp\nfcap.usnf SrcAddress=209.209.1.200" if ARGV.length != 2 puts USAGE exit 1 end # Set up input InputFile = ARGV[0] UnsniffDB = WIN32OLE.new("Unsniff.Database") QueryFieldName = ARGV[1].split('=')[0] QueryFieldValue = ARGV[1].split('=')[1] # Open capfile and get packet index UnsniffDB.OpenForRead(InputFile) PacketIndex = UnsniffDB.PacketIndex # Scan each packet looking for netflow protocol id (0..PacketIndex.Count-1).each do |idx| pkt = PacketIndex.Item(idx) nf_layer = pkt.FindLayerByGUID("{DF2428E1-4843-48CF-B7DD-CCC9E5AE4BC1}") next if nf_layer.nil? pdu_count=nf_layer.FindField("Count").Value.to_i (0..pdu_count-1).each do |pduidx| nf_pdu = nf_layer.FindField(">NetflowRecord>pdu[#{pduidx}]") next if nf_pdu.nil? target_field=nf_pdu.FindField(QueryFieldName) if target_field.Value == QueryFieldValue duration_ms = nf_pdu.FindField("End Time").Value.to_i - nf_pdu.FindField("Start Time").Value.to_i s_ip = nf_pdu.FindField("SrcAddress").Value d_ip = nf_pdu.FindField("DstAddress").Value s_port = nf_pdu.FindField("SrcPort").Value d_port = nf_pdu.FindField("DstPort").Value octets = nf_pdu.FindField("Octets").Value proto = nf_pdu.FindField("Protocol").Value print pkt.ID.to_s.ljust(6) + " " [s_ip,d_ip,s_port,d_port,octets,proto,duration_ms].each do |item| print item.to_s.ljust(16) + " " end print "\n" end end end UnsniffDB.Close() |
To use this script.
1. Import the capture file in tcpdump format into Unsniff (or capture off a live interface)
2. Save the file as USNF format
3. Start querying using the script
More :