ICMP Explained — How ping and traceroute Work and What the Message Types Mean thumbnail

ICMP Explained — How ping and traceroute Work and What the Message Types Mean

⏱ approx. 15 min views 183 likes 0 LOG_DATE:2026-05-09
TOC

ICMP (Internet Control Message Protocol) is the control protocol that signals errors and path conditions on IP networks. It doesn't carry data itself; instead it returns information like "couldn't deliver", "TTL expired", "the port is closed" back to the sender, so hosts and routers can figure out what is going on. ping and traceroute are built on top of it. ICMP is defined in RFC 792 (IPv4); the IPv6 redesign is ICMPv6 (RFC 4443).

01

How to read an ICMP message #

ICMP runs as an upper-layer protocol over IP (Protocol Number 1 in IPv4, 58 in IPv6). It has no port numbers like TCP / UDP, so it doesn't show up in connection listings like ss or netstat.

The header is very simple.

Field Size Role
Type 1 byte Message type (Echo Request / Destination Unreachable, etc.)
Code 1 byte Sub-type within Type (e.g. Type 3 Code 1 = Host Unreachable)
Checksum 2 bytes Verification over the whole ICMP message
Rest of Header 4 bytes Per-Type field (Identifier+Sequence for Echo, etc.)
Data Variable Error-notification messages echo back "the IP header of the failed packet + the first 8 bytes"
▸ The "original failed packet" in the Data section is the key to root-causing

Because error-notification messages return part of the original packet that failed, the sender can tell exactly which of its packets failed and how. When reading ICMP in tcpdump, look not only at Type/Code but also at the inner IP header (Source/Dest IP, TCP/UDP ports) embedded inside — that is what reveals the cause.

02

What ping and traceroute actually do #

ping = Echo Request (Type 8) / Echo Reply (Type 0) #

ping simply sends a Type 8 and measures how long it takes a Type 0 to come back. The Identifier + Sequence Number distinguish multiple pings, so simultaneous pings from the same host are still correctly correlated.

When nothing comes back, the typical interpretations:

  • Nothing returns → ICMP is dropped somewhere on the path, or at the destination firewall
  • Destination Unreachable (Type 3) returns → someone on the path is saying "I can't deliver this." Code tells you why
  • TTL exceeded (Type 11) returns → routing loop, or you set the TTL absurdly low
▸ "ping doesn't return" ≠ "the host is dead"

It's perfectly normal for a web server to block only ICMP. Even with no Echo Reply, TCP 443 is often perfectly alive.

traceroute increments TTL by 1 and collects Time Exceeded #

traceroute probes with TTL=1, 2, 3, ..., ratcheting up the TTL, and collects the Time Exceeded (Type 11) messages each intermediate router returns to draw the path. The final host doesn't return Type 11, so it's detected by a different signal.

1. Send a probe with TTL=1
The first router decrements TTL from 1 to 0 and returns a Time Exceeded (Type 11). The sender records that IP as hop 1.
2. Repeat with TTL=2, 3, 4 ...
Each subsequent hop returns Time Exceeded in turn, so the routers along the path become visible one by one.
3. Detecting the final host
UDP-high-port variant (Linux/macOS default): the final host returning Port Unreachable (Type 3 Code 3) means we arrived. Echo variant (Windows tracert / Linux -I): Echo Reply (Type 0) means we arrived. TCP SYN variant (-T / tcptraceroute): probe 80/443 to pierce firewalls and trace the route.

Try it yourself — increase the TTL by one each round and watch each router along the path reveal itself with a Time Exceeded, one hop at a time.

A run of * * * in the output means that hop's router didn't return Time Exceeded (or is rate-limited). Plenty of routers rate-limit ICMP generation, so missing hops are not unusual.

03

Messages you'll read in the field #

Destination Unreachable (Type 3) — read by Code #

Code Meaning Field interpretation
0 Network Unreachable No route to that network in the routing table
1 Host Unreachable The last router on the path can't resolve a MAC via ARP
3 Port Unreachable UDP: no service on that port / signal that UDP traceroute reached the end
4 Fragmentation Needed and DF Set Required for PMTUD (next section)
9 Network Administratively Prohibited Network-level deny by ACL
10 Host Administratively Prohibited Host-level deny by ACL
13 Communication Administratively Prohibited Blocked by firewall

Code 3 (Port Unreachable) is commonly seen as the response to a UDP probe, and is a common cause of "name resolution silently fails" with dig. Code 13 is an explicit "the firewall said no," so you need to check with whoever owns the network configuration.

Time Exceeded (Type 11) #

Code Meaning
0 TTL Exceeded in Transit (hit TTL=0 at a hop)
1 Fragment Reassembly Time Exceeded (timed out reassembling fragments)

Code 0 is also the signal traceroute relies on, but a steady stream of Code 0 in operations suggests a routing loop.

Redirect (Type 5) #

A router tells a host "there's a better route." Because it can be spoofed to enable a MITM attack, modern OSes refuse it by default (see below).

▸ Obsoleted or safely ignorable
  • Source Quench (Type 4) — deprecated by RFC 6633 (2012). Congestion control is TCP ECN's job
  • Timestamp (Type 13/14) — replaced by NTP. Abused for uptime fingerprinting, so the standard is to drop these outbound
  • Address Mask Request (Type 17/18) — superseded by DHCP
04

PMTUD black holes — the canonical disaster when ICMP is fully blocked #

If the path includes a section with a smaller MTU, a router that receives an IP packet with the DF (Don't Fragment) bit returns Destination Unreachable Code 4 (Fragmentation Needed). The sender takes that signal and lowers its TCP MSS — that is Path MTU Discovery (PMTUD).

If a firewall blocks "all ICMP," Code 4 doesn't get through, and only the large TCP segments silently disappear.

  • Small HTTP requests work
  • Large POSTs / large responses suddenly hang
  • Ordinary ping (small echoes) works, so it superficially looks fine

This is the PMTUD black hole — the textbook cause of the absolute worst kind of incident: "only some traffic over the VPN gets stuck," "only certain API responses time out."

▸ Type 3 Code 4 must always be allowed

"Block all ICMP for safety" is the configuration that produces the nastiest faults. Type 3 Code 4 (Fragmentation Needed) must be allowed in both directions — this is non-negotiable. A workaround is TCP MSS Clamping (forcing the SYN's MSS to a lower value at the router) — close to mandatory in VPN and PPPoE environments.

05

ICMPv6 — in IPv6, blocking it stops the network #

In IPv6 the role of ICMP was greatly expanded; it is essential to the operation of IPv6 itself. ARP, IGMP, and Router Discovery all moved into ICMPv6.

Function Type Role
Neighbor Solicitation 135 IPv4 ARP equivalent — resolves a neighbour's MAC
Neighbor Advertisement 136 The response to the above
Router Solicitation 133 Host asks "are there any routers?"
Router Advertisement 134 Router announces itself + advertises prefixes (the heart of SLAAC)
MLD 130-132, 143 Multicast management, the IGMP equivalent for IPv6
▸ Wholesale-blocking ICMPv6 in IPv6 means no communication at all

NDP and RA both stop working. The mandatory reading for filtering policy is RFC 4890 — it tabulates which Types may be dropped and which must always be allowed. The safe operating model is blocklist-based (declare what is dropped).

06

Security points worth knowing #

Historically Smurf and Ping of Death drew the headlines, but modern OSes and routers have those covered. The four things to think about today are:

ICMP Redirect spoofing #

An on-segment attacker sends fake ICMP Redirects to lure a host into routing through them — a classic MITM. On Linux, lock this down explicitly:

Disable Redirect reception and emission
$ sysctl -w net.ipv4.conf.all.accept_redirects=0 $ sysctl -w net.ipv4.conf.all.send_redirects=0 $ sysctl -w net.ipv6.conf.all.accept_redirects=0

ICMP tunneling (covert channel) #

Stuff arbitrary data into Echo Request / Reply payloads to disguise TCP/UDP traffic as ICMP and slip past the firewall. icmpsh and ptunnel are well-known; APT actors have used variants for C2.

Detection signals:

  • Unusually large / continuous Echo packets (normal ping is ~64 bytes)
  • One-way Echo with no reply (e.g., heavy outbound only)
  • Monitor outbound ICMP from servers at the egress firewall

OS fingerprinting #

Small details in ICMP responses (initial TTL, Code choice, whether they respond at all) carry OS-specific fingerprints that nmap -O keys on. On internet-facing hosts, dropping Timestamp (Type 13/14) alone reduces useful reconnaissance.

Ping flood / rate limiting #

The simple DoS of pelting a host with ICMP Echo. Set icmp_ratelimit in the Linux kernel and on routers, and put Echo Request behind a limit module on the firewall — that's the standard recipe.

07

Filtering strategy — both blanket allow and blanket deny are wrong #

"Block all ICMP for safety" is wrong: PMTUD breaks and you lose diagnostic ability. The correct posture is selective allow.

Type Allow / drop Reason
Destination Unreachable Code 4 Always allow (in/out) Required for PMTUD
Other Destination Unreachable codes Allowing simplifies operations Useful for diagnosis
Time Exceeded (Type 11) Allow traceroute / diagnosis
Echo Request (Type 8) Allow with rate limit Outright blocking destroys diagnosability
Echo Reply (Type 0) Allow Responses to your own pings
Redirect (Type 5) Drop MITM risk
Timestamp (Type 13/14) Drop Used in reconnaissance
Address Mask Request (Type 17/18) Drop No use case
Source Quench (Type 4) Drop Deprecated
iptables — rate-limit Echo, allow the essential messages
# Cap Echo Request at 5 per second $ iptables -A INPUT -p icmp --icmp-type echo-request \ -m limit --limit 5/sec -j ACCEPT $ iptables -A INPUT -p icmp --icmp-type echo-request -j DROP # Allow Destination Unreachable and Time Exceeded outright $ iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT $ iptables -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT # Drop Redirect / Timestamp $ iptables -A INPUT -p icmp --icmp-type redirect -j DROP $ iptables -A INPUT -p icmp --icmp-type timestamp-request -j DROP
▸ Summary — Type 3 Code 4 and Time Exceeded must always pass

ICMP feels low-key, but it's the protocol that carries the first piece of information you get the moment communication breaks. When you're cutting up a problem with ping / traceroute / mtr, just looking at "is the response Type 3 or 11, and what is the Code?" closes the distance to the root cause enormously. Switching from "block ICMP just in case" to a design that always lets through Code 4 (PMTUD) and Time Exceeded is the first step toward operations and security pulling in the same direction.

𝕏 Post B! Hatena