All IP packets have at least one header, which is known as the IP header; sometimes this header is also called a Layer 3 or network header. The IP header is simply a series of bits which have been grouped into fields of a set size. All IP headers have the same structure; the only difference will be which bits have been set to “1” to either turn on a field’s value or to represent a binary number within a field. Let’s take a closer look at the fields in an IP header:
|Ver.||IHL||Type of service||Total length|
|Time to live||Protocol||Header checksum|
|Option + Padding|
Here is one example packet between my computer and www.neti.ee webpage:
An IP packet has 14 fields; let’s go through these fields one at a time.
This is a 4-bit field that indicates the IP version, written in binary. For example if you are using IPv4, the bits will be set to 0100; if you are using IPv6, the bits will be set to 0110.
IHL or header length
This 4-bit field indicates how long the IP packet header is; this value is used to distinguish which part of the IP packet is the header, and which part is the actual data. If you take a look at the picture of the IP packet, you’ll notice that it is 32 bits wide. Now take a look at the length of the packet: the data is not part of the header, the options are optional, but all other fields are required. This means that the minimum header length is five 32-bit words, or binary 0101. You’ll sometimes see these words translated into bytes; that is, five words multiplied by 4 bytes (32 bits divided by 8 bits to make a byte) equals a header length of 20 bytes. If the options are used, the header length will be at least six 32-bit words. Since this is a 4-bit field, the maximum length will be 2 to the power of 4 minus 1, or 15. This effectively limits the size of an IP header to 60 bytes (15 words multiplied by 4 bytes).
Type of Service (sometimes called TOS) flags
This field is 8 bits long; the first 3 bits are called precedence bits and the last 5 bits represent the type of service flags. These flags were originally created to prioritize which packets should be delivered and which packets could be dropped if a router became congested. Since then, other protocols have been invented to prioritize traffic and most routers ignore these flags even if they have been set.
Total length; also called packet length or datagram length
This 16-bit field represents the total length of the IP packet, meaning both the data and the header. The minimum size is 21 bytes (default header size plus one byte of data). Since this field is 16 bits long, the maximum packet size is 2 to the power of 16 minus one, or 65,535 bytes. (The minus one represents the illegal length value of 0.)
Every IP packet is given an identification number when it is created; that number is contained within this 16-bit field. It is possible for an IP packet to be separated into smaller “fragments” before it reaches its final destination; each fragment still belongs to the original IP packet, so each fragment will have the same identification number.
This field contains three flags as follows:
reserved flag: must always be 0
don’t fragment flag: if set to 0, this flag is off, meaning you can fragment the IP packet; if set to 1, this flag is on, meaning you don’t fragment this IP packet
more fragments flag: if set to 0, there are no more fragments; if set to 1, there are more fragments of this IP packet yet to arrive
If an IP packet has been fragmented, each fragment will have a value in this 13-bit field indicating where this fragment’s data fits into the original IP packet. For example, let’s pretend an IP packet containing 128 bytes of data was fragmented into two fragments each containing 64 bytes of data. The fragment containing the first 64 bytes of data would have a fragment offset of 0 as its data belongs at the very beginning of the original IP packet. The fragment containing the last 64 bytes of data needs to indicate that its data starts after the first 64 bytes. Since the number in this field represents an 8-byte multiple, its fragment offset will be 8 (8 multiplied by 8 = 64 bytes).
Time to Live (often called TTL)
Whenever an IP packet passes through a router, the router will decrease the TTL by one; if the TTL ever reaches 0, the packet will be thrown away under the assumption that it must be undeliverable as it hasn’t been delivered by now. The original TTL value depends upon the operating system; your FreeBSD system uses a default TTL of 64. Since this is an 8-bit field, the maximum allowable TTL is 255 (2 to the power of 8 minus 1; the minus 1 is for the non-allowable TTL of 0).
This 8-bit value specifies which protocol’s data is contained within the IP packet and gives a good indication of what type of information will be contained within the data portion of the packet. The protocol numbers that appear in this field are found in the “/etc/protocols” file on your FreeBSD system.
For example, the protocol number 1 represents the ICMP protocol. This means that this IP packet does not contain any data from an application; instead, it contains a small amount of ICMP data. We’ll be taking an in-depth look at ICMP and how it affects your firewall in a separate article.
A protocol number of 6 indicates the TCP protocol. You may remember from earlier articles that TCP is a connection-oriented transport. This IP packet will have an additional header known as a TCP header that will be located just after the IP header and before the beginning of the actual data that is being delivered.
A protocol number of 17 indicates the UDP protocol, which is the connectionless transport. This IP packet will have a UDP header located just after the IP header and before the beginning of the data that is being delivered.
Whenever an IP header is created or modified, a CRC (cyclic redundancy check) is run on the bits contained within the IP header. Basically, some math (the CRC algorithm) is done which results in an answer known as the checksum. When the IP packet is received, the same CRC is repeated on the header; if this results in the same answer (checksum), all of the bits of the IP header must have arrived in the correct order. If the CRC results in a different checksum, some of the bits in the header didn’t arrive, meaning the IP packet was somehow damaged during transit.
This will be the IP address of the host that sent the IP packet.
This will be the IP address of the host that is to receive the data contained within the IP packet.
Options and Padding
This is the only field in an IP packet which is optional, as all other fields are mandatory. This field is used to provide special delivery instructions not covered by the other fields in an IP header. It can allow for up to 40 bytes worth of extra instructions; these instructions must be in 32-bit words. If an instruction doesn’t quite fill up a 32-bit word, the missing bits will be filled in with “padding” bits.
The last field in an IP packet is called the data field. This will be the actual data that is being sent from one host to another. The data field may start with a Layer 4 header, which will give additional instructions to the application that will be receiving the data; alternately, it may be an ICMP header and not contain any user data at all.