Chapter 15 — MTU: the maximum size of a packet
In one sentence
Every link has a maximum packet size (usually 1500 bytes), and when a packet is too big for the next link, something has to give — this causes one of the most confusing bugs in networking.
The problem
You send a 1 MB file. It can't go as one packet — Ethernet's payload maxes out at 1500 bytes (Chapter 5). So it's split into ~700 packets. Fine. But what if a link somewhere along the path has a smaller limit than yours?
The key numbers
MTU (Maximum Transmission Unit) = the biggest IP packet a link will carry
MSS (Maximum Segment Size) = the biggest chunk of DATA inside it
Standard Ethernet: MTU = 1500
- 20 bytes IP header
- 20 bytes TCP header
---------------------
MSS = 1460 bytes of your actual data
Common MTUs you'll meet:
| Link | MTU |
|---|---|
| Standard Ethernet / Wi-Fi | 1500 |
| PPPoE (some DSL) | 1492 |
| WireGuard VPN | 1420 |
| IPsec VPN | ~1400 |
| Cloud overlay networks (VXLAN) | 1450 |
| Data-centre "jumbo frames" | 9000 |
| IPv6 minimum every link must support | 1280 |
Notice the VPN entries. A VPN wraps your packet inside another packet, and that wrapper costs bytes. This is why VPNs cause MTU problems so often.
What happens when a packet is too big
Two possibilities:
CASE 1: the sender said "you may split this" (DF bit not set)
-> the router chops it into FRAGMENTS
-> slow, fragile, and often blocked by firewalls
CASE 2: the sender said "DO NOT FRAGMENT" (DF bit set -- TCP always does this)
-> the router DROPS the packet
-> and sends back ICMP "Fragmentation Needed", saying the correct size
-> the sender shrinks its packets and retries
Case 2 is called Path MTU Discovery (PMTUD), and it works well — as long as that ICMP message gets through.
The classic bug: the PMTU black hole
Someone blocks all ICMP on a firewall "for security" (Chapter 14). Now:
1. TCP handshake works fine (those packets are tiny)
2. Your request works fine (also small)
3. The server sends a full-size 1500-byte response packet
4. A router on the path can't fit it, drops it, sends ICMP...
5. ...which is BLOCKED. The sender never learns.
6. The sender retransmits the same too-big packet. Forever.
RESULT: the connection CONNECTS and then HANGS.
Learn this fingerprint. It is one of the most common "impossible" bugs:
"SSH connects then freezes." "Small web pages load, big ones hang." "
git clonestalls at a few KB." "It works on the office Wi-Fi but not over the VPN."
All four are usually MTU.
How to diagnose it in 30 seconds
ping can send a specific size with "don't fragment" set:
# Linux
ping -M do -s 1472 -c 2 example.com # 1472 + 8 (ICMP) + 20 (IP) = 1500
# macOS
ping -D -s 1472 -c 2 example.com
- Works? Path MTU is at least 1500. Good.
- "Message too long" / "Frag needed"? Something on the path is smaller.
Now binary search for the real limit:
for s in 1472 1452 1422 1372 1272; do
echo -n "payload $s: "
ping -M do -s $s -c 1 -W 2 example.com >/dev/null 2>&1 && echo OK || echo TOO BIG
done
The largest size that works, plus 28, is your path MTU.
Or just use:
tracepath example.com # Linux -- reports the MTU per hop, no root needed
How to fix it
| Fix | When |
|---|---|
| Allow ICMP type 3 through your firewalls | Always. This is the correct fix. |
| MSS clamping on the router/VPN — rewrite the MSS in the handshake so both ends agree to smaller packets | Standard on VPN gateways |
Lower the interface MTU on the affected machine (ip link set eth0 mtu 1400) |
Quick local workaround |
Enable tcp_mtu_probing (Linux) so TCP finds the limit itself without ICMP |
Good defensive setting |
Practice (25 min)
A. Find your own path MTU to three destinations: your router, a nearby site, a distant site. Record them.
B. Break it on purpose (safe, and instructive):
# Linux -- lower your MTU, see what happens, then put it back
ip link show eth0 | grep mtu # note the current value
sudo ip link set eth0 mtu 1200
curl -s -o /dev/null -w '%{http_code}\n' https://example.com
sudo ip link set eth0 mtu 1500 # PUT IT BACK
Small MTU still works (just less efficiently) because PMTUD is functioning. The breakage comes from a mismatch plus blocked ICMP.
C. See fragmentation:
sudo tcpdump -i any -n 'ip[6:2] & 0x3fff != 0' # captures only fragments
# in another terminal:
ping -s 4000 -c 1 192.168.1.1 # a 4000-byte ping must be fragmented
D. If you use a VPN, run the MTU test with the VPN on and off. Compare.
Common confusions
- "Bigger MTU is always better." Only if every device on the path agrees. Jumbo frames (9000) are great inside a data centre and useless across the internet, where something will be 1500.
- "MTU vs MSS?" MTU is the whole packet including headers; MSS is just the
data.
MSS = MTU − 40for normal TCP over IPv4. - "Why doesn't this fix itself?" It does — via PMTUD — unless someone blocks the ICMP that makes PMTUD work.
Check yourself
- What's the standard Ethernet MTU, and what's the resulting TCP MSS?
- What does a router do with a too-big packet that has the DF bit set?
- Describe the symptoms of a PMTU black hole.
- Why do VPNs so often cause MTU problems?
Further reading
- Article (excellent): "Path MTU Discovery" — Cloudflare blog, and their post on "Fixing an old hack" about MTU issues in the wild.
- Video: "MTU and MSS Explained" — Practical Networking.
- Blog: search "MTU black hole troubleshooting" — many good war stories; reading a few builds pattern recognition fast.