Network triage with flows and DNS

Read NetFlow and Zeek conn and dns logs to answer who talked to whom, how much and how regularly. Spot beaconing, DNS tunnelling and egress anomalies, and know when a pcap is worth asking for and what it adds.

FREELesson·13 min read·Beginner → Intermediate
networkZeekNetFlowDNSC2

01Flows: who talked to whom

✓What you will learn
  • Read NetFlow and Zeek conn.log fields fluently
  • Recognise beaconing from timing and size regularity
  • Spot DNS tunnelling and odd egress in dns.log and flow data
  • Know what a pcap adds and when it is worth asking for

Flow records are the network's call log: no content, just who, where, when, how long and how much. They are cheap to keep for months, which makes them the best source for "did anything else talk to this IP?" long after packets are gone.

Zeek conn.log, one workstationtext
#fields ts                 uid      id.orig_h   id.orig_p id.resp_h      id.resp_p proto service duration orig_bytes resp_bytes conn_state
1763024401.112  CkX9a1  10.20.4.17  51122     185.220.101.4  443       tcp   ssl     0.41     512        1840       SF
1763024461.098  Cj2Lq8  10.20.4.17  51130     185.220.101.4  443       tcp   ssl     0.39     512        1840       SF
1763024521.140  CbT7m3  10.20.4.17  51141     185.220.101.4  443       tcp   ssl     0.42     512        1840       SF
1763024533.502  CqP0z6  10.20.4.17  51149     10.20.0.5      53        udp   dns     0.01     44         120        SF
1763024581.087  CwE4h2  10.20.4.17  51150     185.220.101.4  443       tcp   ssl     0.40     512        1840       SF
FieldMeaningAnalyst use
id.orig_h / id.resp_hInitiator and responderDirection: who started it matters more than who sent more
durationConnection length in secondsLong-lived sessions (tunnels) vs short repeated ones (beacons)
orig_bytes / resp_bytesPayload each wayUploads where orig_bytes dwarfs resp_bytes: exfil candidates
conn_stateHow it ended (SF normal, S0 no reply, REJ refused)Lots of S0/REJ: scanning or dead C2
uidZeek connection IDJoins conn to dns, ssl, http and files logs for the same session

Read the sample above: every 60 seconds, the same host opens a short TLS connection to the same external IP, sends exactly 512 bytes and gets exactly 1840 back. People do not browse like that. Software on a timer does.

02Beaconing

A beacon is implant software checking in with its C2 server: "any tasks for me?". Most frameworks add jitter (random variation in the interval) to hide, but the pattern survives statistics: many connections, regular gaps, similar sizes, to a destination few other hosts talk to.

Finding regular check-inskql
// Hosts with regular, small, repeated outbound connections (Zeek conn in Sentinel)
Zeek_Conn
| where TimeGenerated > ago(24h) and not(ipv4_is_private(id_resp_h))
| sort by id_orig_h, id_resp_h, TimeGenerated asc
| extend gap = datetime_diff('second', TimeGenerated, prev(TimeGenerated))
| where id_orig_h == prev(id_orig_h) and id_resp_h == prev(id_resp_h)
| summarize conns=count(), avg_gap=avg(gap), sd_gap=stdev(gap), sizes=dcount(orig_bytes) by id_orig_h, id_resp_h
| where conns > 50 and sd_gap < avg_gap * 0.2 and sizes < 5
| order by conns desc

// id_orig_h    id_resp_h       conns avg_gap sd_gap sizes
// 10.20.4.17   185.220.101.4   1438  60.1    3.8    1
// 10.20.9.30   52.168.112.66   2880  30.0    0.2    2     <- Defender telemetry endpoint
SignalBeacon-likeUsually benign
IntervalFixed or jittered around a value (60 s ± 10%)Irregular, clustered in working hours
Destination prevalenceOne or two internal hosts talk to itHundreds of hosts (update, AV, SaaS)
SizeNear-identical request and response sizesVaried sizes
Time of dayContinues at 03:00 with nobody logged onFollows user activity
Destination ageDomain registered last week, cheap TLD, no reputationLong-lived vendor domain
!Lots of legitimate software beacons

EDR agents, AV updates, chat clients and telemetry all check in on timers. Combine regularity with rarity: a beacon to an endpoint 4,000 hosts also contact is almost always your own tooling. The second result above is Defender, which is why prevalence is the next filter.

Test yourself

Which pair of signals most strongly suggests C2 beaconing rather than legitimate telemetry?

03DNS: tunnelling and odd resolution

DNS is allowed out of almost every network, so attackers use it as a transport: data is encoded into subdomain labels on queries, and replies carry commands in TXT, NULL or CNAME records. The traffic looks nothing like a person browsing.

Zeek dns.log: which line is not like the others?text
#fields ts              id.orig_h   query                                                                  qtype_name rcode_name answers
1763031002.21  10.20.4.17  a3f9c2e1b07d4e55a1c9.0e7b2d4f61a8c3e9b1d2.x1.cdn-sync-api.top         TXT        NOERROR    "dGFzazpzbGVlcCA2MA=="
1763031002.84  10.20.4.17  b81d0c77e2a945f0be13.94c6a1e0f3b72d58c4a6.x2.cdn-sync-api.top         TXT        NOERROR    "b2s="
1763031003.40  10.20.4.17  5c2e9a1f04b8d3e7c6a2.f1b0e9d84c27a3b5e061.x3.cdn-sync-api.top         TXT        NOERROR    "b2s="
1763031004.07  10.20.4.17  e7d14b2a9c3f0815d6e4.2a9e7c1b5f3d08e4a7c6.x4.cdn-sync-api.top         TXT        NOERROR    "b2s="
1763031010.55  10.20.6.12  outlook.office365.com                                                  A          NOERROR    52.97.146.178
Tunnelling signWhy it stands out
Long, high-entropy labels (hex or base32)Humans and CDNs do not query 40 random characters
Many unique subdomains under one parent domainEach query carries a new chunk of data, so nothing repeats
TXT, NULL or unusual qtypes at volumeNormal clients mostly ask for A, AAAA and HTTPS records
One internal host, huge query count to one domainPrevalence and volume both wrong
Queries bypassing the corporate resolverDirect port 53 or DoH to the internet avoids your logging
Count unique names per parent domainbash
# Unique subdomains per parent domain, top talkers (zeek-cut on dns.log)
zcat dns.*.log.gz | zeek-cut id.orig_h query \
  | awk '{n=split($2,a,"."); if(n>=2) print $1, a[n-1]"."a[n], $2}' \
  | sort -u | awk '{print $1, $2}' | sort | uniq -c | sort -rn | head

#  9412 10.20.4.17 cdn-sync-api.top
#   311 10.20.6.12 office365.com
iRead the answers too

The TXT answers above are base64: dGFzazpzbGVlcCA2MA== decodes to task:sleep 60. You rarely get it that easy, but decoding a few answers often turns "suspicious" into "confirmed C2" in one step.

04Egress anomalies and what a pcap adds

Exfiltration shows up in flows as direction and volume: an internal host sending far more than it receives, to a destination it has never used, often outside working hours. Compare against that host's own history, not a global average.

Egress anomaly with a staging steptext
src          dst              dport  start(UTC)  dur     bytes_out     bytes_in   first_seen(dst)
10.30.2.44   45.137.21.9      443    02:11       47m     18.6 GB       41 MB      today
10.30.2.44   10.30.0.10       445    01:05-02:09 64m     12 MB         17.9 GB    -           (file server)

Read it as a sequence: between 01:05 and 02:09 the host pulled almost 18 GB from the file server over SMB, then at 02:11 pushed 18.6 GB to an external IP it had never contacted. That is collection then exfiltration, and the flow data alone is enough to escalate.

SourceGives youDoes not give you
NetFlow / IPFIX5-tuple, bytes, packets, times; long retentionNames, content, TLS details
Zeek conn/dns/ssl/httpFlows plus DNS names, SNI, certificates, HTTP metadata, file hashesPayload of encrypted sessions
Full pcapEvery byte: payloads in clear protocols, exact handshakes, malformed trafficLong retention (days at best); decrypted TLS without keys
▭On the whiteboard · When a pcap is worth asking for3 points
01
clear-text protocol
HTTP, SMB, DNS, FTP: you can extract the files and commands themselves
02
protocol abuse
malformed or custom traffic on a standard port; you need the bytes to write a signature
03
skip it
modern TLS to the internet: flows, SNI, JA3/JA4 and certificate data tell you almost as much, at a fraction of the cost
“How to say it in the room

"I start with flows to scope who talked to the destination and when, use Zeek DNS and SSL logs to put names and certificates on it, and only ask for packets when the protocol is clear-text or abused, because a pcap of TLS mostly tells me what the flow already did."

Q1How do you catch DNS over HTTPS bypassing your resolver?+

Block or alert on known DoH endpoints and on direct outbound 53/853 from anything that is not a resolver; then dns.log stays complete. Browsers can be told to use enterprise DNS by policy.

Q2Why do flows matter more than pcap for most investigations?+

Retention. Flows are kept for months; packets for hours or days. Most investigations start days after the intrusion, when only flows remain.

Q3What is JA3 or JA4?+

A fingerprint of the TLS client hello. The same malware family tends to produce the same fingerprint regardless of destination, so it lets you pivot across IPs and domains without decrypting anything.

Test yourself

A host shows 18 GB inbound from a file server over SMB, then 18 GB outbound to a new external IP. What do you do next?

Finished this one?
Tick it and it shows as done on the roadmap and the course.