Computer Network 📂 Network Layer · 1 of 6 51 min read

The IPv4 Header Explained Field by Field: Version, IHL, DSCP, TTL

A complete walkthrough of every field in the IPv4 header defined by Jon Postel in RFC 791 (Sept 1981). Learn the purpose of Version, IHL, DSCP + ECN, Total Length, Identification, Flags (DF/MF), Fragment Offset, TTL, Protocol, Header Checksum, and Source/Destination IP addresses — with animated diagrams, fragmentation math, traceroute's TTL trick, DSCP QoS values used by Microsoft Teams, and real CVEs from the news.

Section 01

The Envelope Every Internet Packet Wears

Twelve Fields, Twenty Bytes, Forty-Five Years of Service
Every time you load a webpage, send a message, or stream a video, your data is chopped into little chunks called packets. Each packet needs an envelope: an address to reach, a return address for replies, and instructions for the mailmen (routers) along the way. That envelope is the IPv4 header.

Jon Postel finalised its design in RFC 791, September 1981, at the Information Sciences Institute in Marina del Rey. He specified exactly twelve fields spread across the first twenty bytes of every IP packet. Every field had to earn its place — on the ARPANET a single bit was expensive. Postel wrote his three-word philosophy into RFC 761: "Be liberal in what you accept, and conservative in what you send."

Trillions of packets per second still carry this exact 20-byte envelope in 2026. Understanding what each field does — from the humble 4-bit Version to the once-controversial ECN congestion bits — is what separates someone who uses a network from someone who runs one. This tutorial walks you through every single field, with animated diagrams, real captured values, and the practical purpose of each.
📍
Where the IP Header Lives

Every packet on the Internet has this structure from the outside in: Ethernet frame → IP header → TCP/UDP header → application data. The IP header is the second thing every router touches after peeling off the Ethernet frame. It is the only part of the packet the router must understand to forward it. Nothing about the application, the URL, or the file being transferred is required — just the IP header.


Section 02

The Full Picture — All Twelve Fields at a Glance

Here is the entire IPv4 header laid out as it actually appears on the wire. Twenty bytes minimum, organized into five 32-bit words. Each field is highlighted in sequence in the animation below to give a visual tour before we dissect them one by one.

IPv4 Header Layout — 20 bytes / 160 bits (option-free) 0 4 8 16 19 24 31 bit→ byte 0-3 Ver (4b) IHL (4b) DSCP + ECN (8b) Total Length (16b) byte 4-7 Identification (16b) Flags (3b) Fragment Offset (13b) byte 8-11 TTL (8b) Protocol (8b) Header Checksum (16b) byte 12-15 Source IP Address (32 bits) byte 16-19 Destination IP Address (32 bits) byte 20+ Options + Padding (0 – 40 bytes) — rarely used Payload (TCP / UDP / ICMP data) — up to 65,515 bytes
The five mandatory rows above the dashed line total exactly 20 bytes. Watch the amber glow travel through the fields — that's the order we'll examine them in Sections 03 through 14.
📈
One Header, Two Ways to Read It

Networking books often show these fields in a 32-bit-wide table (as above) because that matches how the header is laid out in memory. Wireshark and tcpdump show them as a vertical list. Both views describe the same 20 bytes — use whichever matches the tool in front of you.


Section 03

Field 1 — Version (4 bits)

🔧 Field 1 — Version
Size
4 bits (nibble). Bits 0-3 of the header.
Values
4 = IPv4. 6 = IPv6. All other numbers are historical or unused (5 was ST-II Stream Protocol).
Purpose
Tells every router which version of the IP protocol this packet uses before parsing the rest of the header. IPv4 and IPv6 headers have completely different layouts — the router must know which one it's reading.
Wire value
For every IPv4 packet, the very first nibble is 0100 (binary) = 0x4.
Real trick
A dual-stack device peeks only at this nibble to decide "hand this off to the IPv4 stack or the IPv6 stack." One line of C code: if ((packet[0] >> 4) == 4) parse_ipv4();

Section 04

Field 2 — IHL / Internet Header Length (4 bits)

🔧 Field 2 — IHL (Internet Header Length)
Size
4 bits. Bits 4-7 of the header.
Values
Counts the header size in 32-bit words, not bytes. Minimum = 5 (5 × 4 = 20 bytes, no options). Maximum = 15 (15 × 4 = 60 bytes, options fill 40 bytes).
Purpose
Tells the router "the payload starts here" — skip this many 32-bit words from the start of the IP header. Without IHL, the router wouldn't know where options end and payload begins.
Wire value
Almost every packet you'll ever capture has IHL = 0101 (5) = no options, 20-byte header.
Why 32-bit words?
Ancient minicomputers processed memory in 32-bit words. A 4-bit counter that measures bytes would only reach 15 bytes — not enough. Counting words gets 15 × 4 = 60 bytes with the same 4 bits.
⚠️
The Only IHL Value You'll Ever See

In practice, IHL is always 5. IP options are rare, deprecated, and often blocked by firewalls (RFC 7126). Packet-processing hardware in routers is optimized for the 20-byte fast path. If you capture a packet with IHL > 5, treat it as suspicious — it's either legacy source routing, a network experiment, or a probe.


Section 05

Field 3 — DSCP + ECN (8 bits, formerly Type of Service)

This 8-bit field is the QoS control panel of the IP header. Originally called Type of Service (ToS) in RFC 791, it was redefined in 1998 by RFC 2474 as two sub-fields: DSCP (Differentiated Services Code Point, 6 bits) for traffic classification and ECN (Explicit Congestion Notification, 2 bits) for congestion signalling.

The 8-bit DSCP + ECN field — example value: EF (Expedited Forwarding) for voice 1 0 1 1 1 0 0 0 DSCP (6 bits) — 1011102 = 4610 = EF tells routers how important this packet is ECN (2 bits) — 00 = not-capable lets routers signal congestion Common DSCP values seen in the wild EF (46) = Voice  •  AF41 (34) = Video conferencing  •  CS4 (32) = Streaming video  •  AF11 (10) = Bulk data  •  0 = Best Effort
DSCP marks the packet's priority class; ECN carries per-hop congestion state. A VoIP phone typically stamps every audio packet with DSCP 46 so switches know to service it first.
🔧 Field 3 — DSCP + ECN
Size
8 bits total = 6 bits DSCP + 2 bits ECN. Bits 8-15 of the header.
Purpose
DSCP classifies traffic (voice, video, best-effort, bulk). ECN lets a router mark "I'm congested" instead of dropping the packet, so TCP can slow down without waiting for a timeout.
Real use
Microsoft Teams stamps voice with DSCP 46 and video with DSCP 34. The standard DSCP value for VoIP voice traffic is 46, known as Expedited Forwarding (EF). This marking ensures voice packets receive priority treatment across routers and switches, minimizing latency and jitter.
Warning
Consumer ISPs usually ignore or zero-out DSCP at their edge. QoS marking only helps inside enterprise or MPLS networks where administrators actually honour it.

Section 06

Field 4 — Total Length (16 bits)

🔧 Field 4 — Total Length
Size
16 bits (2 bytes). Bits 16-31 of the header.
Values
Minimum = 20 (an empty header). Maximum = 65,535 bytes (216 − 1). Real-world packets are almost always < 1500 bytes because that's the Ethernet MTU.
Purpose
Tells the receiver "the entire packet — header + payload — is this many bytes long." Without it, the receiver couldn't know where one packet ended and the next began on a byte-stream link.
Payload size
Payload bytes = Total Length − (IHL × 4). For a typical packet: 1500 − 20 = 1480 bytes of payload.
MTU link
Every link on the Internet has a Maximum Transmission Unit (MTU). Ethernet = 1500, WiFi = 2304, PPPoE = 1492, GRE tunnel = 1476. If Total Length > MTU, the router either fragments the packet (Section 09) or drops it and sends back an ICMP "Fragmentation Needed" message.

Section 07

Field 5 — Identification (16 bits)

🔧 Field 5 — Identification (IPID)
Size
16 bits (2 bytes). Bits 32-47 of the header.
Values
0 to 65,535. The sender picks a value; on Linux it's a per-destination counter, on Windows it was historically a global monotonic counter (a huge privacy leak until fixed).
Purpose
Uniquely identifies a datagram from a given source so that all fragments of the same original packet share the same ID. The receiver uses this to know "these three fragments belong together — reassemble them."
Security note
Predictable IPIDs enable idle-scanning attacks (nmap's -sI) where an attacker can probe a target without ever sending a packet from their own IP. Modern OSes randomize per-flow.
If unfragmented
The value is still filled in but never consulted — only fragmentation uses it.

Section 08

Field 6 — Flags (3 bits)

Three flag bits — only two of them do anything Bit 0 — Reserved Must be 0. Ignored. "Evil bit" joke (RFC 3514) Bit 1 — DF Don't Fragment 1 = drop, don't split Bit 2 — MF More Fragments 1 = more coming, 0 = last Unfragmented packet: DF=0 or 1, MF=0 Middle fragment: DF=0, MF=1  •  Last fragment: DF=0, MF=0
DF controls whether routers may split the packet. MF distinguishes middle fragments (more coming) from the last fragment (or an unfragmented packet).
🔧 Field 6 — Flags
Bit 0
Reserved, must be zero. RFC 3514 famously proposed it as the "Evil Bit" (April 1st joke) — malicious packets should set it to 1.
DF (bit 1)
Don't Fragment. If set, routers must NEVER fragment this packet. If it exceeds the outgoing link MTU, the router drops it and returns an ICMP "Fragmentation Needed" error. This drives Path MTU Discovery (PMTUD).
MF (bit 2)
More Fragments. Set on every fragment except the last. Reads: "there are more fragments after this one." Combined with Fragment Offset, this tells the receiver when to stop waiting.
Real use
Modern TCP stacks set DF=1 on every packet and use PMTUD to find the smallest MTU on the path, then size TCP segments to fit. IPv6 drops fragmentation entirely — there's no equivalent DF/MF, and routers must drop oversized packets.

Section 09

Field 7 — Fragment Offset (13 bits) + Full Fragmentation Deep Dive

🔧 Field 7 — Fragment Offset
Size
13 bits. Bits 51-63 of the header. Values 0 – 8191.
Values
Offset of this fragment's data in the original packet, measured in 8-byte units. So offset 185 means "my data starts at byte 1480 of the original packet."
Purpose
Tells the receiver where in the reassembly buffer this fragment's bytes belong. Fragments can arrive out of order — the offset places each one correctly.
Why 8-byte units?
Only 13 bits available but the max packet is 65,535 bytes. Multiplying by 8 gets 213 × 8 = 65,536 — exactly enough range. The trade-off: every fragment (except the last) must be a multiple of 8 bytes.

Animated Fragmentation Example — 4000-byte Packet on a 1500-MTU Link

Original 4000-byte packet → three fragments, each ≤ 1500 bytes MTU Original Hdr 20 Payload 3980 bytes — Total Length = 4000 router chops on 8-byte multiples Frag 1 Hdr 20 1480 bytes of data ID=X   MF=1   Offset=0   TotLen=1500 Frag 2 Hdr 20 1480 bytes of data ID=X   MF=1   Offset=185   TotLen=1500 Frag 3 Hdr 20 1020 bytes ID=X   MF=0   Offset=370   TotLen=1040 The math a router just performed: 3980 payload ÷ 1480 per fragment → 2 full fragments (1480 each) + 1 remainder (1020 bytes) Offsets in 8-byte units: 0, 1480÷8=185, (1480+1480)÷8=370. Same ID glues them together at the receiver.
All three fragments share the same Identification. MF=1 on the first two, MF=0 on the last. The receiver reassembles based on offset once all fragments arrive.
🔫
Why Fragmentation is Dangerous

Malicious fragments have caused decades of security incidents: Past issues include Windows kernel panics, Cisco router crashes, and Linux kernel panics due to fragments. Common techniques used in fragmentation attacks include tiny 1-8 byte fragments, overlapping offsets, and invalid flag combinations. The Teardrop attack (1997) crashed Windows 95 and NT with overlapping fragments; CVE-1999-0015 is its permanent record. That's why IPv6 removed fragmentation entirely and modern firewalls often drop fragmented packets outright.


Section 10

Field 8 — TTL / Time To Live (8 bits)

🔧 Field 8 — TTL (Time To Live)
Size
8 bits (1 byte). Values 0 to 255.
Values
Original OS defaults: Linux/macOS/Android = 64, Windows = 128, some routers = 255. Solaris used 30 historically.
Purpose
Prevents packets from looping forever if routing goes wrong. Every router that forwards the packet decrements TTL by 1. When TTL hits 0, the router drops the packet and sends back an ICMP "Time Exceeded" message.
History
RFC 791 defined TTL as seconds. In practice every router treated it as a hop count from day one, and RFC 1122 formalised this in 1989. The name stuck even though it counts hops.

Animated TTL Decrement — Packet Hopping Across Five Routers

Packet leaves Linux host with TTL = 64 — each router decrements by 1 Source Linux R1 gateway TTL=63 R2 ISP edge TTL=62 R3 core TTL=61 R4 peering TTL=60 Dest server TTL=59 PKT If TTL ever hits 0, the router drops the packet and returns ICMP "Time Exceeded" to the source. This is exactly how the traceroute command discovers every router on the path.
Van Jacobson's clever 1988 hack: send probes with TTL=1, TTL=2, TTL=3... Each router returns an ICMP error revealing itself. You've just mapped every hop between you and the destination.
📡
Van Jacobson & the Birth of traceroute

Traceroute, implemented in 1989 based on a suggestion by Steve Deering, discovers packet paths by incrementing the Time-to-Live (TTL) field in IP headers, provoking ICMP time-exceeded responses from intermediate routers to reveal hop-by-hop paths. Every network engineer who has ever typed tracert or traceroute is exploiting a field designed to prevent packet loops — turning a safety mechanism into the most-used diagnostic tool ever invented.


Section 11

Field 9 — Protocol (8 bits)

When the packet arrives at its destination, the OS needs to know what to do with the payload. Is it a TCP segment? A UDP datagram? An ICMP echo? The Protocol field is the single byte that tells the network stack which upper-layer handler to call.

Protocol field = 8-bit number that selects the upper-layer handler IP hdr Protocol = 6 / 17 / 1 Payload DEMUX TCP handler Protocol = 6 UDP handler Protocol = 17 ICMP handler Protocol = 1 Other important values: 2 = IGMP  •  41 = IPv6 encap  •  47 = GRE  •  50 = ESP  •  51 = AH  •  89 = OSPF
The 8-bit Protocol field carries an IANA-assigned number that tells the OS "hand the payload to this handler." Same idea as EtherType at Layer 2.
🔧 Field 9 — Protocol Numbers to Memorise
1
ICMP — ping, traceroute, error reports
2
IGMP — multicast group management
6
TCP — connection-oriented, reliable byte-stream
17
UDP — connectionless datagrams
41
IPv6-in-IPv4 — used by 6to4 tunnels
47
GRE — Generic Routing Encapsulation
50 / 51
ESP / AH — IPsec payload / authentication
89
OSPF — link-state routing protocol between routers
132
SCTP — Stream Control Transmission Protocol (VoIP signalling)

Section 12

Field 10 — Header Checksum (16 bits)

🔧 Field 10 — Header Checksum
Size
16 bits. Bits 80-95 of the header.
Purpose
Detects corruption in the IP header only (not the payload — TCP and UDP have their own checksums covering the payload).
Algorithm
16-bit one's-complement sum of all 16-bit words in the header, treating the checksum field itself as zero during calculation.
Recomputed at every hop
Every router changes the TTL (and sometimes DSCP), which changes the checksum. Each router must recompute it after decrementing TTL — a small but real per-packet cost.
If invalid
Packet is silently dropped. No ICMP error — the header itself might have been corrupted, so replying to the source could send an error to the wrong destination.
IPv6 lesson
IPv6 removed this field entirely. Ethernet CRCs already catch corruption on each link; recomputing at every router was a waste of CPU. IPv6 trusts lower and upper layers to detect errors.

Section 13

Fields 11 & 12 — Source & Destination IP Addresses (32 bits each)

🔧 Field 11 — Source IP Address
Size
32 bits (4 bytes). Bytes 12-15 of the header.
Purpose
Return address for the packet. The receiver replies to this IP. It also lets middleboxes (firewalls, load balancers) apply source-based policy.
NAT reality
Behind a home router, your device's private IP (e.g. 192.168.1.5) is rewritten to your router's public IP before the packet leaves your house. The server never sees your real source.
Spoofing
Nothing in IPv4 prevents forging the source address. This enables reflection/amplification DDoS: attacker sends a small UDP request to a DNS server with a spoofed source = victim, and the DNS server floods the victim with the large reply.
🔧 Field 12 — Destination IP Address
Size
32 bits (4 bytes). Bytes 16-19 of the header.
Purpose
The only field a router truly cares about. It looks this up in its routing table (longest-prefix match) and forwards the packet toward the next hop.
Special values
255.255.255.255 = limited broadcast (this subnet). 224.0.0.0 – 239.255.255.255 = multicast (group). 127.0.0.1 = loopback (never leaves the sending host).
Not rewritten by NAT
Unlike source, the destination usually stays intact end-to-end — the packet needs to reach a specific server. (Exception: DNAT for port-forwarding.)

Section 14

Fields 13 & 14 — Options and Padding (variable, usually absent)

🔧 Optional trailing fields
Options
Up to 40 bytes of variable-length options: Record Route (log routers along path), Loose/Strict Source Routing (dictate the path), Timestamp, Router Alert. Almost universally deprecated in modern networks.
Padding
If options don't end on a 32-bit boundary, zero bytes are added so the header total is a multiple of 4 bytes.
In practice
>99.9% of packets have no options, so IHL = 5 and the header is exactly 20 bytes. Fast-path silicon in modern routers is optimised for this case.
Security note
RFC 7126 recommends dropping packets that carry Loose or Strict Source Routing options at Internet borders — they were used in real attacks to bypass firewalls by routing packets around them.

Section 15

Complete Wire Example — What a Real Packet Looks Like

Here is a captured IPv4 header for a ping request. Each byte position is annotated with the field it belongs to.

Byte(s)Hex ValueFieldDecoded Meaning
0 (high nibble)4VersionIPv4
0 (low nibble)5IHL5 × 4 = 20-byte header, no options
100DSCP + ECNBest-effort (no QoS marking)
2-300 54Total Length84 bytes (20 IP + 8 ICMP + 56 data)
4-51c 46Identification0x1c46 = 7238 — kernel-picked ID
6 (high 3 bits)010FlagsDF=1, MF=0 (Don't Fragment set)
6 (low 5) + 70 0000Fragment Offset0 (not a fragment)
840TTL64 (Linux default)
901Protocol1 = ICMP
10-11d6 08Header Checksum0xd608 (verified)
12-15c0 a8 01 05Source IP192.168.1.5
16-1908 08 08 08Destination IP8.8.8.8 (Google DNS)
🔊
Try It Yourself

Run tcpdump -i any -X icmp on any Linux/macOS machine and send a ping. You'll see the exact 20 bytes above scroll by. Wireshark decodes them into a beautiful tree — but remember, every field there maps directly to one of the twelve fields we just covered.


Section 16

Real-World Cases from the News

🔌
Teardrop and Its Descendants
Overlapping-fragment attacks have crashed operating systems for a quarter century. Imperva reports: Past issues include Windows kernel panics, Cisco router crashes, and Linux kernel panics due to fragments. Every one exploited how the target OS reassembled the Identification, Flags, and Fragment Offset fields. CVE-1999-0015 (Teardrop), CVE-1999-0104 (Nestea), CVE-1999-0257 (Bonk) all abused the same three fields.
CVE-1999-0015  /  the fragment three
🔫
14% of Top Sites Still Vulnerable
A 2022 NDSS Symposium paper measured live web traffic: 1,407 websites among the Alexa top 10k websites are vulnerable to the forged ICMP "Fragmentation Needed" messages sent from our vantage point in California, which can be tricked into fragmenting their TCP segments even if the PMTUD mechanism is enabled. Attackers can then inject forged fragments into a legitimate TCP stream by exploiting the IPID field.
NDSS 2022 measurement
📡
Van Jacobson's TTL Hack
Traceroute wasn't invented for path discovery — it was invented to exploit a safety field: Van Jacobson created the original traceroute in 1987 using the IP Time To Live (TTL) field. This field specifies the maximum number of routers a packet can pass through. Each time it's routed, the field is decremented. When it reaches 0, an error message (ICMP TTL Exceeded for IPv4 or Hop Limit Exceeded for IPv6) is sent back. Nearly forty years later, every network engineer's first debugging move still relies on that trick.
1987 — TTL as diagnostic
📱
Microsoft Teams & the DSCP Field
Microsoft's own documentation instructs enterprise admins: QoS uses Differentiated Services Code Point (DSCP) markings together with port-based Access Control Lists (ACLs) to identify, mark, and classify all packets in real-time streams. This implementation ensures that voice, video, and screen share streams receive preferential treatment at the expense of other types of traffic. Teams marks audio with DSCP 46 (EF) and video with DSCP 34 (AF41) — the same values Cisco recommended twenty years earlier.
DSCP 46 for audio, 34 for video
🔐
QUIC vs the ICMP-PMTU Attack
CVE-2024-53259 hit the popular quic-go library: An attacker can inject false ICMP "Packet Too Big" messages that reduce the MTU below the minimum QUIC packet size of 1200 bytes, thereby effectively blocking the connection. A single forged ICMP fragmentation-needed message can shrink a victim's effective MTU — a manipulation attack that pivots off the DF flag and Total Length field.
CVE-2024-53259 — PMTUD abuse
🌐
Every Packet, Every Second, Still This Envelope
Despite 45 years passing since RFC 791, and despite IPv6 being available on 40%+ of major networks, IPv4 still routes the majority of Internet traffic. Every DNS query, every video frame, every messaging notification passes through the twelve fields you just learned. Understanding the IP header is not a legacy skill — it is the working vocabulary of running any modern network.
RFC 791 → 2026

Section 17

Golden Rules for the IPv4 Header

🏆 Non-Negotiable Rules for Working with the IP Header
1
The router only needs three fields to forward a packet: Destination IP, TTL, and Header Checksum. Everything else the packet carries for the endpoint. Optimise your routers to touch these three quickly — that's the fast path.
2
Set DF=1 on all TCP traffic and use Path MTU Discovery. Fragmentation at intermediate routers is slow, brittle, and abused by attackers. Let the endpoints negotiate the right packet size instead.
3
Drop fragmented packets at Internet-facing firewalls unless you have a specific reason to accept them. Real modern traffic is virtually never fragmented. Fragments arriving from outside your network are far more likely to be an attack than legitimate traffic.
4
Mark voice with DSCP 46 (EF) and video with DSCP 34 (AF41) at the source. Then honour those markings inside your network. On the public Internet, expect them to be wiped — DSCP is only useful when the whole path trusts and honours it.
5
Set TTL to 64 or 128 for hosts, 255 for routers. A TTL that starts too low breaks distant destinations. A TTL of 255 lets a router quickly detect malicious packets arriving with TTL < 254 (they must have crossed hops, so they didn't originate on the local link — a technique called GTSM, RFC 5082).
6
Never trust the source IP for authentication. Anyone can spoof it. If you need to know who sent a packet, use TLS, IPsec, or cryptographic tokens — not the IP header.
7
The header is 20 bytes. Full stop. If you see IHL > 5 or any IP options, treat the packet as suspicious and log it. Legitimate traffic has stopped using options since the 1990s.
🌈
The Whole Header in One Sentence

Version says which IP, IHL says how long, DSCP+ECN say how important and how congested, Total Length says how big, Identification+Flags+Offset handle fragmentation, TTL prevents loops, Protocol says who gets the payload, Checksum catches corruption, and Source and Destination IPs say where from and where to — and those twelve fields have been enough to run the Internet since 1981.