2 Learning
Watersrc-stack edited this page 2026-10-14 04:00:21 +02:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Learning: what a packet is made of

A packet on the wire is a stack of headers, each wrapping the next, like envelopes inside envelopes. Each layer reads its own header, then hands the rest to the layer above. This section takes real packets apart, byte by byte, layer by layer.

Page Layer One line
Ethernet link Delivers a frame to a machine on the same network, by MAC address. Includes ARP.
IPv4 network Delivers a packet across networks, by 32-bit address.
IPv6 network The same with 128-bit addresses, a fixed header and extension headers.
TCP transport A reliable, ordered byte stream between two ports.
UDP transport Single datagrams between two ports, nothing more.
DNS application Names to addresses, and back.
QUIC transport, over UDP Encrypted, multiplexed connections: HTTP/3.
Traffic anomalies many packets at once Scans, floods, errors, beaconing, spikes, protocol misuse and DNS tunnels: patterns no single packet shows.

One packet, all layers

Here is a whole frame: a DNS query asking for the address of example.com, as it left the machine.

0000  00 00 5e 00 53 02 00 00 5e 00 53 01 08 00 45 00
0010  00 50 09 52 00 00 40 11 ed 47 c0 00 02 01 c0 00
0020  02 02 93 0f 00 35 00 3c 84 51 9e 28 01 20 00 01
0030  00 00 00 00 00 01 07 65 78 61 6d 70 6c 65 03 63
0040  6f 6d 00 00 01 00 01 00 00 29 04 d0 00 00 00 00
0050  00 0c 00 0a 00 08 41 f8 43 a3 bc b7 57 11
flowchart LR
  eth["Ethernet header<br/>14 bytes<br/>0x00–0x0d"] --> ip["IPv4 header<br/>20 bytes<br/>0x0e–0x21"]
  ip --> udp["UDP header<br/>8 bytes<br/>0x22–0x29"]
  udp --> dns["DNS message<br/>52 bytes<br/>0x2a–0x5d"]
Bytes Layer What they say
00 00 5e 00 53 02 00 00 5e 00 53 01 08 00 Ethernet to MAC …:02, from MAC …:01; what follows is IPv4 (0x0800)
45 00 00 50 … 11 … c0 00 02 01 c0 00 02 02 IPv4 version 4, 80 bytes long, protocol 17 (UDP), from 192.0.2.1 to 192.0.2.2
93 0f 00 35 00 3c 84 51 UDP from port 37647 to port 53 (DNS), 60 bytes
9e 28 01 20 00 01 … 07 example 03 com 00 00 01 00 01 … DNS query 0x9e28: what is the A record of example.com?

Each header names the next layer:

  • Ethernet says "IPv4" with its EtherType (0x0800).
  • IPv4 says "UDP" with its protocol number (17).
  • UDP says nothing about its content, but port 53 is DNS by convention.

Read the pages in order, and you'll be able to read this dump by eye.

NetOtter's l shows this packet as one line:

#19    [veth0]     4.322547  192.0.2.1:37647       -> 192.0.2.2:53          ttl 64  UDP     60 B  [DNS A?]

How these examples were made

Every capture in this section comes from an isolated test network made of two Linux network namespaces joined by a virtual Ethernet cable:

  • the "client" uses 192.0.2.1 / 2001:db8::1 and MAC 00:00:5e:00:53:01;
  • the "server" uses 192.0.2.2 / 2001:db8::2 and MAC 00:00:5e:00:53:02.

These are the ranges reserved for documentation (RFC 5737, RFC 3849, RFC 7042), and example.com is reserved too (RFC 2606). The server ran a small DNS server and a web server. The client used ping, dig, curl and curl --http3. NetOtter captured everything on the client's interface, veth0.

tools/lab/learning.sh in the repository makes this capture again, without root (see the anomaly lab): it writes tools/lab/samples/learning.nto, which NetOtter opens with -I, and a .pcap file of the whole frames, where the hexdumps on these pages come from. Run again, it gives other ports, ids and random values, but the same packets.

Reading hexdumps

  • Offsets are in hexadecimal: 0x10 is 16, 0x22 is 34.
  • Multi-byte numbers are big-endian ("network byte order"): 00 50 is 0x0050 = 80, the most significant byte first.
  • Fields smaller than a byte are read in bits: the byte 45 is 0100 0101, so 4 in the high half and 5 in the low half.