Loading learning content...
Every packet traversing the Internet begins with a critical piece of information packed into a single byte—the Version and Internet Header Length (IHL) fields. These 8 bits, split evenly between two 4-bit fields, establish the fundamental identity and structure of every IPv4 packet that flows across the global network.
This might seem like a trivial starting point. After all, what's so important about knowing it's version 4 and how long the header is? But consider this: every router, firewall, load balancer, and network interface card on the planet examines these exact bits to determine how to process the packet. A single misinterpretation here means the entire packet becomes unintelligible garbage. The elegance and constraints of these first 8 bits reveal deep truths about protocol design that have persisted for over four decades.
By the end of this page, you will master the Version and IHL fields completely: their exact bit positions, encoding schemes, valid values, edge cases, and the engineering rationale behind each design decision. You'll understand why IPv4 allocates 4 bits for version (allowing 16 versions) yet only two have ever been deployed, and why the IHL field measures in 32-bit words rather than bytes.
The IPv4 header, defined in RFC 791 (September 1981), begins with a fixed structure that has remained unchanged since its inception. The Version and IHL fields occupy the very first byte—bits 0 through 7—of every IPv4 packet.
Let us visualize the exact positioning:
| Bit Positions | 0-3 | 4-7 | 8-15 | 16-18 | 19-31 |
|---|---|---|---|---|---|
| Field Name | Version | IHL | Type of Service | Flags (partial) | Various |
| Size | 4 bits | 4 bits | 8 bits | 3 bits | Varies |
| Byte Position | Byte 0 (upper) | Byte 0 (lower) | Byte 1 | Byte 2 (partial) | Bytes 2-3 |
Why These Fields Come First:
The positioning of Version and IHL at the header's start is no accident. Network devices process packets in a strictly sequential, byte-by-byte manner:
Version MUST come first because a device cannot interpret subsequent fields without knowing which protocol version applies. An IPv6 header has a completely different structure after the version field.
IHL immediately follows because the device needs to know where the header ends and the payload begins before it can do anything meaningful with the packet.
This ordering principle—identification before parsing—is a fundamental pattern in protocol design. You cannot interpret data until you know its format, and you cannot locate data until you know its boundaries.
IPv4, like all Internet protocols, uses network byte order (big-endian). This means the most significant bit (MSB) is transmitted first. The Version field occupies bits 0-3 (the most significant 4 bits of the first byte), not bits 4-7. When examining raw packet dumps, the Version value appears in the upper nibble of the first byte.
The Version field is a 4-bit unsigned integer that identifies the IP protocol version used to create the packet. While 4 bits theoretically allow values from 0 to 15 (16 possible versions), the practical landscape is far more constrained.
Complete Version Number Assignments:
The Internet Assigned Numbers Authority (IANA) maintains the official registry of IP version numbers. Here is the complete, authoritative list:
| Version | Description | Status | Reference |
|---|---|---|---|
| 0 | Reserved | Not for use | RFC 791 |
| 1-3 | Unassigned | Never defined | — |
| 4 | Internet Protocol version 4 (IPv4) | Active, ubiquitous | RFC 791 |
| 5 | Internet Stream Protocol (ST) | Experimental, obsolete | RFC 1190 |
| 6 | Internet Protocol version 6 (IPv6) | Active, growing | RFC 8200 |
| 7 | TP/IX | Obsolete proposal | RFC 1475 |
| 8 | PIP (P Internet Protocol) | Obsolete proposal | RFC 1621 |
| 9 | TUBA (TCP/UDP over CLNP) | Obsolete proposal | RFC 1347 |
| 10-14 | Unassigned | Reserved for future | — |
| 15 | Reserved | Not for use | — |
Why Version 5 (ST) Exists:
A common interview question concerns the missing version 5. The Internet Stream Protocol (ST) was an experimental protocol developed for real-time multimedia applications in the late 1970s and 1980s. It was assigned version number 5 but never achieved widespread deployment. ST2 (ST-II) was documented in RFC 1819 as an experimental protocol for resource reservation, but it was ultimately superseded by other approaches like RSVP. This is why IPv4 was followed directly by IPv6—version 5 was already allocated.
Engineering Insight:
The 4-bit allocation for version numbers reflects the confidence of early Internet architects. With 16 possible values, they assumed major protocol revisions would be infrequent. This has proven accurate—only two versions (4 and 6) have achieved production status in over 40 years.
Network devices receiving a packet with an unrecognized version number (anything other than 4 or 6, depending on the interface) MUST discard the packet silently. There is no error response—the packet simply disappears. This is why protocol version fields are validated as the absolute first step in packet processing.
The Internet Header Length (IHL) field is a 4-bit unsigned integer that specifies the total length of the IPv4 header in 32-bit words (4-byte units). This field is essential because the IPv4 header has variable length due to the optional Options field.
Header Length in Bytes = IHL × 4Why 32-Bit Words Instead of Bytes?
This design decision often puzzles newcomers. Why not simply express the header length in bytes? The answer lies in bit efficiency and alignment requirements:
4-bit constraint: With only 4 bits available, direct byte counts would limit the maximum header to 15 bytes—insufficient even for the mandatory 20-byte minimum header.
32-bit alignment: The Internet Protocol was designed for 32-bit CPUs. All IP options must be padded to 32-bit boundaries anyway, so measuring in 32-bit words loses no precision.
Extended range: Measuring in 4-byte words gives an effective range of 20-60 bytes (5-15 words × 4 bytes/word), which covers all possible IPv4 headers.
| IHL Value | Header Bytes | Options Bytes | Description |
|---|---|---|---|
| < 5 | (Invalid) | — | Values 0-4 are invalid; packet must be discarded |
| 5 | 20 bytes | 0 bytes | Standard header, no options (most common) |
| 6 | 24 bytes | 4 bytes | Header with 4 bytes of options |
| 7 | 28 bytes | 8 bytes | Header with 8 bytes of options |
| 8 | 32 bytes | 12 bytes | Header with 12 bytes of options |
| ... | ... | ... | Each increment adds 4 bytes |
| 15 | 60 bytes | 40 bytes | Maximum header; 40 bytes of options |
The Significance of Minimum IHL = 5:
The IPv4 header has exactly 20 bytes of mandatory fields (5 × 32-bit words). These 20 bytes contain:
Total: 20 bytes = 5 × 4-byte words
Any IHL value less than 5 is physically impossible and indicates a corrupted or malicious packet.
To find where the payload (data) begins in an IPv4 packet, multiply IHL by 4. If IHL = 5, the data starts at byte 20. If IHL = 8, the data starts at byte 32. This calculation is performed billions of times per second across all Internet infrastructure.
Understanding how Version and IHL appear in actual packet captures is essential for network analysis. Let's examine the first byte in various scenarios:
12345678910111213141516171819202122232425262728
# First byte of IPv4 header combines Version and IHL# Byte value = (Version << 4) | IHL # Example 1: Standard IPv4 packet, no options# Version = 4 (binary: 0100)# IHL = 5 (binary: 0101)# Combined byte = 0100 0101 = 0x45 = 69 decimal First byte: 0x45├── Upper nibble: 0x4 = Version 4 (IPv4)└── Lower nibble: 0x5 = IHL 5 (20-byte header) # Example 2: IPv4 packet with options# Version = 4 (binary: 0100)# IHL = 7 (binary: 0111)# Combined byte = 0100 0111 = 0x47 = 71 decimal First byte: 0x47├── Upper nibble: 0x4 = Version 4 (IPv4)└── Lower nibble: 0x7 = IHL 7 (28-byte header) # Example 3: IPv6 for comparison# Version = 6 (binary: 0110)# Note: IPv6 has no IHL field; next nibble is Traffic Class First byte: 0x60 (typical IPv6)├── Upper nibble: 0x6 = Version 6 (IPv6)└── Lower nibble: Part of Traffic Class fieldExtracting Values in Code:
Network programming often requires extracting these nibbles from raw packet bytes. Here's how it's done in various languages:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
def extract_version_ihl(first_byte: int) -> tuple[int, int]: """ Extract Version and IHL from the first byte of an IPv4 header. Args: first_byte: The first byte of the IP header (0-255) Returns: Tuple of (version, ihl) """ version = (first_byte >> 4) & 0x0F # Upper nibble ihl = first_byte & 0x0F # Lower nibble return version, ihl def validate_ipv4_header(packet: bytes) -> dict: """ Validate and parse the first byte of an alleged IPv4 packet. Returns parsed info or raises ValueError for invalid packets. """ if len(packet) < 1: raise ValueError("Packet too short") version, ihl = extract_version_ihl(packet[0]) # Validate version if version != 4: raise ValueError(f"Not IPv4: version = {version}") # Validate IHL if ihl < 5: raise ValueError(f"Invalid IHL: {ihl} (must be >= 5)") header_length = ihl * 4 options_length = (ihl - 5) * 4 # Ensure packet is long enough for the claimed header if len(packet) < header_length: raise ValueError( f"Packet truncated: need {header_length} bytes, have {len(packet)}" ) return { 'version': version, 'ihl': ihl, 'header_length_bytes': header_length, 'options_length_bytes': options_length, 'has_options': ihl > 5, 'data_offset': header_length } # Example usagepacket = bytes([0x45, 0x00, 0x00, 0x3c]) # Typical IPv4 header startinfo = validate_ipv4_header(packet)print(f"IPv{info['version']} packet, header={info['header_length_bytes']} bytes")# Output: IPv4 packet, header=20 bytesThe hexadecimal value 0x45 is so common in packet analysis that experienced network engineers recognize it instantly. Seeing 0x45 at the start of a packet immediately identifies it as a standard IPv4 packet with no options. Values like 0x46, 0x47, or 0x48 indicate IPv4 with options—relatively rare in modern traffic.
The Version and IHL fields, despite their simplicity, have been vectors for various attacks and implementation bugs over the years. Understanding these edge cases is essential for robust network programming.
Security Implications:
1. Fragmentation Evasion Attacks: Attackers have used unusual IHL values combined with fragmentation to evade intrusion detection systems (IDS). The IDS and the target system might interpret the packet boundaries differently, allowing malicious payloads to slip through.
2. Header Length Overflow: When calculating buffer sizes for header copying, multiplying IHL by 4 can overflow in poorly written code if IHL somehow exceeds expected bounds (shouldn't be possible with 4 bits, but type promotion bugs occur).
3. Options-Based Attacks: Packets with IHL > 5 indicate the presence of IP options. Options parsing has historically been a source of vulnerabilities. Some security policies reject all packets with IHL > 5 to avoid options-related bugs entirely.
Never trust header fields at face value. Validate: (1) Version is exactly 4, (2) IHL is at least 5, (3) IHL × 4 ≤ packet length, (4) IHL × 4 ≤ Total Length field. These four checks prevent the majority of malformed-packet attacks targeting these fields.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
def secure_ipv4_validation(packet: bytes) -> bool: """ Security-focused validation of IPv4 Version and IHL fields. Returns True only if the packet passes all sanity checks. """ # Check 1: Minimum packet length if len(packet) < 20: return False # Can't even hold minimum IPv4 header first_byte = packet[0] version = (first_byte >> 4) & 0x0F ihl = first_byte & 0x0F # Check 2: Version must be exactly 4 if version != 4: return False # Check 3: IHL must be at least 5 (20 bytes) if ihl < 5: return False # Check 4: IHL cannot exceed 15 (60 bytes) # This is guaranteed by 4-bit size, but explicit is better if ihl > 15: return False header_length = ihl * 4 # Check 5: Packet must be at least as long as claimed header if len(packet) < header_length: return False # Check 6: Cross-validate with Total Length field # Total Length is bytes 2-3, big-endian if len(packet) >= 4: total_length = (packet[2] << 8) | packet[3] # Total Length must be at least header length if total_length < header_length: return False # Total Length must not exceed packet size # (might be less due to Ethernet padding) if total_length > len(packet): return False return TrueThe Version and IHL fields were defined in RFC 791 (Internet Protocol, September 1981) by Jon Postel and the RFC 791 working group. Understanding the historical context illuminates why certain design choices were made.
Why Version is 4 Bits:
When IPv4 was designed in the late 1970s, the architects anticipated that the Internet Protocol might undergo significant revisions as networking technology evolved. Allocating 4 bits allowed for 16 possible protocol versions—a seemingly generous allowance for future evolution.
In practice, the Internet's growth proved that changing the IP layer is extraordinarily difficult. Once billions of devices implement a particular version, migration becomes a multi-decade undertaking. IPv6 was standardized in 1998 (RFC 2460), yet global IPv6 adoption only reached approximately 40% by 2024. The difficulty of transitions means that the 4-bit version field has proven more than sufficient.
Why IHL Uses 32-bit Words:
The late 1970s and early 1980s saw the transition from 8-bit and 16-bit to 32-bit computing architectures. The designers of IPv4 made a prescient choice to align on 32-bit boundaries:
CPU efficiency: 32-bit aligned data could be loaded and processed in single operations on then-emerging 32-bit processors.
Future-proofing: Even as 64-bit architectures arrived, 32-bit alignment remained compatible and efficient.
Range maximization: Using 4-byte units extended the expressible range from 0-15 bytes to 0-60 bytes—enough to accommodate all foreseeable options.
IPv6 eliminated the IHL field entirely. The IPv6 base header is always exactly 40 bytes. Variable-length options are handled through Extension Headers, a chain of fixed-format headers following the base header. This simplification eliminates an entire class of parsing complexity and security issues that plagued IPv4.
The Enduring Legacy:
The Version/IHL byte format has processed literally quintillions of packets since 1981. The design has proven remarkably robust:
When engineers today design new protocols, they often study IPv4's field layouts as examples of efficient, long-lived design.
Let's examine how Version and IHL appear in actual network traffic using common analysis tools. These examples will prepare you for hands-on packet analysis.
12345678910111213141516171819202122232425262728
# Wireshark display of an IPv4 header (typical HTTP request)Frame 1: 74 bytes on wire Ethernet II, Src: 00:11:22:33:44:55, Dst: 66:77:88:99:aa:bbInternet Protocol Version 4, Src: 192.168.1.100, Dst: 93.184.216.34 0100 .... = Version: 4 .... 0101 = Header Length: 20 bytes (5) ← No options Differentiated Services Field: 0x00 Total Length: 60 ... # Same packet in raw hex:0000 45 00 00 3c 1a 2b 40 00 40 06 ... │ │ │ └─ IHL = 5 (20 bytes) └──── Version = 4 # IPv4 packet WITH options (Record Route option):Frame 2: 94 bytes on wireInternet Protocol Version 4, Src: 192.168.1.100, Dst: 10.0.0.1 0100 .... = Version: 4 .... 1000 = Header Length: 32 bytes (8) ← Has 12 bytes of options Options: (12 bytes), Record Route ... # Raw hex:0000 48 00 00 5e 1a 2c 40 00 40 01 ... │ └──── 0x48 = Version 4, IHL 8 (32-byte header)Using tcpdump for Field Extraction:
1234567891011121314151617181920212223242526
# Basic tcpdump showing IP version$ tcpdump -n -v iptcpdump: listening on eth0, link-type EN10MBIP (tos 0x0, ttl 64, id 12345, offset 0, flags [DF], proto TCP (6), length 60) 192.168.1.100.43210 > 93.184.216.34.80: ... # Note: tcpdump shows "IP" for IPv4, not "IPv4"# The version and IHL are parsed but not explicitly shown in default verbose mode # To see raw hex including first byte:$ tcpdump -n -X ip and host 192.168.1.1000x0000: 4500 003c 1a2b 4000 4006 xxxx c0a8 0164 │ └── 0x45 = IPv4, IHL=5 # Using Berkeley Packet Filter to match Version/IHL:# Match only IPv4 packets with options (IHL > 5)$ tcpdump -n 'ip[0] & 0x0f > 5' # Match only standard IPv4 packets (IHL = 5)$ tcpdump -n 'ip[0] & 0x0f = 5' # Breakdown of the BPF expression:# ip[0] - first byte of IP header# & 0x0f - mask to extract lower nibble (IHL)# > 5 or = 5 - compare IHL valueStudies of Internet traffic consistently show that >99% of IPv4 packets have IHL=5 (no options). IP options are rarely used in modern networks because: (1) they add processing overhead at every hop, (2) many routers drop packets with options for security reasons, (3) alternative mechanisms (like ICMPv6, extension headers) handle similar functions better.
We've conducted a comprehensive analysis of the first byte of every IPv4 packet. Let's consolidate the essential knowledge:
What's Next:
With the Version and IHL fields mastered, we move to the second byte of the IPv4 header: the Type of Service (ToS) field. This 8-bit field has undergone significant evolution—from its original RFC 791 definition through the Differentiated Services (DiffServ) architecture to modern ECN (Explicit Congestion Notification) usage. Understanding ToS reveals how quality-of-service and congestion control mechanisms operate at the IP layer.
You now possess deep understanding of the Version and IHL fields—their exact encoding, valid values, security implications, and practical analysis techniques. This knowledge forms the foundation for parsing any IPv4 packet correctly and securely.