Course outline · 0% complete

0/30 lessons0%

Course overview →

What a router does to a packet, and how traceroute exploits it

lesson 5-2 · ~13 min · 14/30

Nine steps, repeated at every hop

A router is not mysterious. For every frame that arrives it performs the same short procedure.

1. Receive the frame and verify the FCS. Corrupt frame, drop it, count it. 2. Check the destination MAC. If it is not the router's own MAC or a broadcast, ignore the frame entirely. 3. Strip the layer 2 header and read the EtherType to find that the payload is an IP packet. 4. Verify the IP header checksum. Bad checksum, drop silently. 5. Look up the destination IP in the routing table, longest prefix match. No match and no default route, drop and send ICMP destination unreachable. 6. Decrement the TTL by one. If the TTL becomes 0, drop the packet and send ICMP time exceeded back to the source. 7. Recompute the IP header checksum, because the TTL just changed. 8. Find the next hop's MAC, from the ARP table or with a fresh ARP request. 9. Build a brand new layer 2 frame with the router's outgoing MAC as source and the next hop's MAC as destination, and transmit it.

Two things never change along the path: the source IP and the destination IP. Two things change at every hop: the layer 2 addresses and the TTL. If you remember only that, you can reason about almost any routing problem.

Notice what a router does not do. It does not look at ports, it does not track connections, and it does not care whether the payload is TCP or UDP. Those are transport concerns, one layer up. A device that does look at ports and track connections is a firewall or a NAT gateway, which is Unit 6.

TTL, the loop insurance

TTL (time to live) is an 8 bit field in the IP header, so it ranges from 0 to 255. It is a hop counter, not a timer, despite the name. Common starting values are 64 on Linux and macOS, 128 on Windows, and 255 on many routers.

Why does it exist? Because routing tables are built independently by many devices, and a temporary disagreement can point two routers at each other. A packet caught in that loop would circulate forever, and thousands of them would saturate the link. TTL guarantees the packet dies after at most 255 hops.

When a router decrements TTL to 0 it does two things: it drops the packet, and it sends an ICMP time exceeded message back to the source address. That courtesy message is what makes the next section possible.

TTL is also a fingerprint. A ping reply arriving with TTL 57 most likely started at 64 and crossed 7 routers. A reply with TTL 121 probably started at 128 on a Windows host. This is a quick sanity check on how far away something is.

ICMP, the network layer's message channel

ICMP (internet control message protocol) carries errors and diagnostics for IP. It rides directly inside IP with protocol number 1, and it has no ports, because it is not a transport protocol. It is IP talking about itself.

TypeCodeNameWhen you see it
00echo replythe answer to a ping
30net unreachableno route to that network
31host unreachableroute exists, ARP for the host failed
33port unreachablehost is up, nothing listening on that UDP port
34fragmentation neededthe path MTU problem from Lesson 3-3
50redirect"use a better router on this link, not me"
80echo requesta ping going out
110time exceededTTL hit zero at some hop
111reassembly timeoutfragments never all arrived

ping is two of those rows and nothing more. It sends an echo request and waits for an echo reply, timing the gap.

ping -c 2 192.168.1.1
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=1.21 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=1.08 ms

Two warnings about reading ping results. A failed ping does not prove a host is down, because plenty of hosts and firewalls are configured to ignore echo requests. And a successful ping does not prove an application works, it only proves layers 1 to 3 are functional. Both mistakes appear in real incident calls constantly.

youR1R2targetTTL 1TTL 2TTL 3TTL 0 hereTTL 0 hereprobe arriveseach reply reveals one hop's address, so the path is mapped one row at a time
Traceroute sends probes with TTL 1, then 2, then 3. Each router in turn kills a probe and identifies itself in the ICMP time exceeded reply.

Traceroute, a clever abuse of TTL

traceroute maps the path without any special protocol. It sends a probe with TTL 1, so the first router kills it and reveals itself in the time exceeded reply. Then TTL 2, so the second router replies. Then 3, and so on, until a probe survives to the destination. Three probes per hop give three timings.

On Linux the probes are UDP packets to unusual high ports, so the final host answers with ICMP port unreachable instead of time exceeded, which is how traceroute knows it arrived. traceroute -I uses ICMP echo instead, and traceroute -T uses TCP SYN, which often gets through firewalls that block the others.

traceroute -n example.com
 1  192.168.1.1     1.104 ms   1.021 ms   0.998 ms
 2  100.64.0.1      9.882 ms  10.114 ms   9.771 ms
 3  * * *
 4  62.115.120.7   14.302 ms  14.771 ms  14.219 ms
 5  93.184.216.34  15.006 ms  14.882 ms  15.114 ms

How to read it, including the parts that mislead people:

- Hop 2 in 100.64.0.0/10 is carrier grade NAT, from the table in Lesson 4-2. - *` ` does not mean a broken hop. It means that router chose not to send ICMP, or rate limited it. Traffic still passes through fine, which you can see because hops 4 and 5 answered. - Latency that jumps then settles is normal. Routers generate ICMP errors on a slow control path, so a busy core router may answer its own probes late while forwarding real traffic at full speed. Only a rise that persists through every later hop indicates a real problem. - The path shown is the forward** path only, and the return path can be completely different. Asymmetric routing is the norm on the internet, so a one sided traceroute never tells the whole story.