Learn · Network forensics

Flows: the phone bill of the network

A flow record says who talked to whom, when, for how long and how much, but not what was said. Flows are cheap enough to keep for months and to collect at every router, which often makes them the only network evidence left by the time an incident is noticed.

1 What a flow is

A router or sensor groups packets by their 5-tuple: source address, destination address, source port, destination port, protocol. Packets with the same key are counted into one record until the flow ends (a TCP FIN or RST), stays idle for the inactive timeout (often 15 s), or has run for the active timeout (often 30 min). A long transfer can therefore appear as several consecutive records.

The tool below groups the packets of the sample capture from the Packets page both ways:

From packets to flows

2 NetFlow v5 byte by byte

A NetFlow v5 export is a UDP packet from the router to a collector: a 24-byte header and up to 30 fixed records of 48 bytes, all big-endian. Record times are milliseconds of router uptime, not clock times. The header gives the uptime and the router's clock at export; together they turn every record time into a real time:

time = unix_secs − (sys_uptime − First) / 1000

Records 1 and 2 are the web request from the sample capture, one record per direction; compare their packets and bytes with the flow builder above. Record 4 is the TLS connection from the same capture, but the router kept counting after the capture ended: the client sent 88 MB to port 443 within five minutes, the TCP flags contain SYN but no FIN, and it ended 1.2 s before the export. The connection was probably still running and was exported by the active timeout or a cache flush: look for the next record with the same 5-tuple.

NetFlow v9 and IPFIX (sometimes called v10) replace the fixed layout by templates sent by the exporter, which allows extra fields such as application names or bidirectional counters. The principle stays the same.

3 Zeek conn.log

Zeek (formerly Bro) writes one line per connection to conn.log, tab-separated, with a header that lists the fields. The uid links the line to the same connection in dns.log, http.log, ssl.log or files.log.

FieldMeaning
tsfirst packet, Unix epoch (UTC)
id.orig_h / id.orig_poriginator (who sent the first packet) and its port
id.resp_h / id.resp_presponder and port
serviceprotocol Zeek recognised in the payload (dns, http, ssl, smb, …), whatever the port
duration, orig_bytes, resp_byteslength and payload bytes in each direction
conn_statehow it went: SF normal open and close, S0 SYN without answer, REJ rejected, RSTO/RSTR reset by originator/responder, S1 still open
historypacket letters: S SYN, h SYN-ACK, A ACK, D data, F FIN, R RST; upper case = originator, lower case = responder

4 Using flows in an investigation

5 Try it yourself

Answer from the hex views and the flow table above.

How many flow records does the export packet announce?

Header offset 2, two bytes, big-endian.

00 04 = 4. The packet is 24 + 4 × 48 = 216 bytes long, which matches.

How many bytes did the client send in flow record 4?

Record offset 20 (+14), four bytes.

05 49 EF 08 = 88,731,400 bytes (IP layer, client → server only). What came back is in a separate record, not shown in this packet.

Records 1 and 2 are the two directions of the same web request. How many IP bytes did the connection carry in total?

Add the byte counters of both records.

340 + 294 = 634 bytes. Switch the flow builder to "bidirectional": the HTTP connection on port 51514 shows the same numbers as originator and responder bytes, because these records describe the sample capture.

Record 4's TCP flags are 0x1A (SYN, ACK, PSH, no FIN or RST). What does that tell you?

The flags are OR-ed over all packets of the record.

There was a handshake (SYN, ACK) and data (PSH), but no FIN or RST yet: the connection was still open. The router exported it because of a timeout, so the transfer may continue in later records.

These are the 24 header bytes. Edit them and watch the decoded header:

  • Set the sampling field (the last two bytes) to 40 64. What do you now have to do with every byte and packet counter in the records?
  • Change the uptime (bytes 4–7) to 00 37 0E 80, i.e. 2 s longer. By how much do the real start times of all records move?