Memra

Five fields, and the header they live in

◈ 6 cards

The IPv4 header drawn to scale, the five fields a packet filter reads, and why a first fragment that is too small gets the whole packet thrown away.

A choke point, and what it can see

Host-by-host defence has an arithmetic problem. When a flaw is announced, every affected machine has to be patched, and a mid-sized organisation has thousands of them spread across several operating-system versions. A firewall answers that by being a boundary system separating two security domains — a single choke point where policy and auditing are imposed once instead of everywhere at once. It may be a single device or a set of cooperating ones.

That only works if three design goals hold:

  1. All traffic in both directions passes through the firewall. This is an architectural claim about the network, not about the device, and it is achieved by physically removing every other path.
  2. Only traffic authorised by the local security policy passes.
  3. The firewall itself resists penetration, which implies a hardened, secured operating system underneath it.

The simplest firewall is a packet-filtering firewall. It applies a list of rules to every IP packet, inbound and outbound, and forwards or discards each one. It remembers nothing about the packets that came before. So its entire world is the set of fields it can read off a single packet in isolation — and that is a question about the shape of the IPv4 header.

The IPv4 header, to scale

A header with no options is 20 bytes — 160 bits — laid out in five 32-bit words:

  • Version (4 bits) — always 4 here.
  • IHL (4 bits) — Internet Header Length, counted in 32-bit words, not bytes. The minimum legal value is 5, which is the 20-byte header; anything larger says options follow. Multiply by 4 to get bytes.
  • DSCP/ECN (8 bits) — differentiated services and congestion notification. A filter almost never looks here.
  • Total Length (16 bits) — the length of the whole datagram in bytes, header included. Sixteen bits is why an IPv4 datagram cannot exceed 65,535 bytes.
  • Identification (16 bits) — the tag shared by every fragment of one original datagram.
  • Flags (3 bits) — reserved, Don't Fragment, More Fragments.
  • Fragment Offset (13 bits) — where this fragment's payload sits in the original, counted in 8-byte units.
  • TTL (8 bits) — hop count.
  • Protocol (8 bits) — which transport protocol follows: 6 is TCP, 17 is UDP, 1 is ICMP.
  • Header Checksum (16 bits) — over the header only.
  • Source Address (32 bits) and Destination Address (32 bits) — the two addresses, and together a quarter of the entire header.

Notice the shape. Four bits here, sixteen there, three fragment flags wedged in front of a thirteen-bit offset: the reason the header is hard to hold in your head is precisely that the fields are not the same size. A diagram that draws them equal has deleted the only thing worth learning.

The five fields a filter reads

A packet-filtering firewall makes its decision from five pieces of information, and the exam wants all five by name:

  1. Source IP address — the address the packet claims to have come from. It is a claim, not a fact, which is exactly why spoofing works and why anti-spoofing rules exist.
  2. Destination IP address — the address of the system the packet is going to.
  3. Source and destination transport-level address — the TCP or UDP port numbers, which is what identifies the application: 25 for mail, 80 and 443 for the web, 22 for SSH.
  4. IP protocol field — which transport protocol is in use.
  5. Interface — for a firewall with three or more ports, which interface the packet arrived on or is leaving by.

Only items 1, 2 and 4 are in the IP header. Item 3 is in the transport header that follows it, and item 5 is not in the packet at all — it is a fact the device knows about itself. That split looks like pedantry until fragmentation gets involved, at which point it becomes an attack.

Rules are applied top to bottom, first match decides, and a default action applies when nothing matches.

Worked example — the tiny fragment attack

Take a first fragment whose header reads IHL = 5 and Total Length = 36. The header occupies 4 x 5 = 20 bytes, so the payload is

payload = Total Length - 4 x IHL = 36 - 20 = 16 bytes

A TCP header without options is 20 bytes, and the source and destination ports are its first four bytes. Sixteen bytes of payload is not a whole TCP header — but it is more than enough to hold the ports, so why is that a problem?

It is a problem because an attacker chooses the split. Set the fragment boundary deliberately low enough and the TCP header is cut before the port numbers, so they arrive in fragment two. A stateless filter examines the first fragment and forwards later fragments on the strength of that decision; reassembly happens only at the destination. So the filter is asked to judge a packet whose ports are simply not present in it. A rule that says deny inbound TCP to port 23 has nothing to match on, and the fragment sails through. When the destination reassembles, the TELNET connection the rule forbade is complete. That is the tiny fragment attack.

The countermeasure has two halves, and an answer that gives only the first loses marks. Require the first fragment to carry a minimum amount of the transport header — enough that the ports are always present, so there is always something to match. And when a first fragment is rejected, remember it and discard every subsequent fragment of that datagram too: the later fragments are useless on their own, and letting them through would leave the destination holding a partial datagram assembled from traffic the policy refused. The whole packet goes, not just the offending fragment.

This is the same shape as the other two classic attacks on packet filters. IP address spoofing sends an outside packet carrying an inside source address, and is answered by discarding packets whose source address is internal when they arrive on an external interface — a rule that needs field 5, the interface. Source routing lets the sender dictate the path in order to skirt a filter, and is answered by discarding every packet that uses the option rather than by trying to analyse where it claims to be going.

024681012141618202224262830Version=44IHLwords4DSCP/ECN8Total Lengthbytes16Identification16FlagsDF MF3Fragment Offset8-byte units13TTL8Protocol6=TCP8Header Checksum16Source Address32Dest Address32IHL > 5 means options follow.
Version 4, IHL 4, DSCP/ECN 8, Total Length 16, Identification 16, Flags 3, Fragment Offset 13, TTL 8, Protocol 8, Header Checksum 16, and two 32-bit addresses: 160 bits in all. The shaded fields are three of the five a filter decides on; the ports are in the transport header past the end of this figure, and the interface is not in the packet at all.

source EXT - RFC 791 section 3.1 (Internet Header Format)

Filtering fieldWhere it livesWhat a rule does with itSource IP addressIP headertrust or reject the senderDestination IP addressIP headername the protected hostSource/dest transportaddressTCP or UDP headerpick the service: 25, 80,443IP protocol fieldIP headerTCP or UDP or ICMPInterfacethe device itselfinside or outside arrivalOnly the ports sit past the IP header.
Three of the five come out of the IP header, one out of the transport header behind it, and one out of the device itself. Losing the third row to fragmentation is the tiny fragment attack.

source EXT - RFC 791 section 3.1 (Internet Header Format)

source Stallings & Brown, Computer Security 5e, ch9 section 9.3; EXT - RFC 791 section 3.1

NORMAL ~/memra/learn/comp-400/what-a-packet-filter-reads-and-the-ipv4-header utf-8 LF