Understanding MTU and Path MTU Discovery
Introduction¶
A connection that completes its handshake and then freezes on the first real
data — a large HTTP response, an SSH banner, a git clone — is almost always
an MTU problem. It's counter-intuitive because small packets (ping, the
handshake) work fine. This post explains why and how to fix it.
Concepts¶
- MTU (Maximum Transmission Unit) — the largest IP packet an interface will send in one piece. Standard Ethernet is 1500 bytes. PPPoE knocks it to 1492, a typical IPsec/WireGuard tunnel to ~1400, GRE to 1476.
- MSS (Maximum Segment Size) — the largest chunk of TCP payload per
packet, advertised by each side in the SYN. It's
MTU - 40(IPv4: 20-byte IP header + 20-byte TCP header), so 1460 on standard Ethernet. - Path MTU — the smallest MTU along the entire path. A packet bigger than this must be fragmented or dropped.
Path MTU Discovery (PMTUD)¶
IPv4 hosts set the Don't Fragment (DF) bit and rely on routers to send back an ICMP "fragmentation needed" (type 3, code 4) message when a packet is too big. The sender then lowers its packet size and retries.
PMTUD breaks when that ICMP message is filtered — which many firewalls do, blanket-blocking all ICMP. Now the oversized packet is silently dropped, the sender never learns, and it keeps retransmitting the same too-big packet forever. That's the hang. This is called a PMTUD black hole.
IPv6 has no fragmentation by routers at all — PMTUD is mandatory, and blocking ICMPv6 "Packet Too Big" breaks IPv6 entirely.
Hands-on¶
Find the path MTU¶
ping with DF set and a payload size, binary-searching:
# Linux: -M do sets DF; -s is payload (add 28 for the ICMP+IP headers)
ping -M do -s 1472 example.com # 1472 + 28 = 1500, standard Ethernet
ping -M do -s 1400 example.com # if 1472 fails, try smaller
# The largest -s that doesn't say "Message too long" or hang,
# plus 28, is your path MTU.
macOS: ping -D -s 1472 example.com. Windows: ping -f -l 1472 example.com.
tracepath example.com (Linux) does the search automatically and prints the
MTU at each hop.
Fix 1: MSS clamping (on the router/gateway)¶
Rewrite the MSS in passing SYN packets to match the path:
# iptables (nftables equivalent: 'tcp option maxseg size set rt mtu')
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
This is the right fix on a NAT gateway / VPN concentrator — it doesn't touch
endpoints. Nginx has proxy_pass equivalents; OpenVPN has mssfix; strongSwan
has mss in the config.
Fix 2: Lower the interface MTU (on the endpoint or tunnel)¶
ip link set dev wg0 mtu 1380
# persist it in the interface config (netplan, NetworkManager, ifcfg)
Use this when you control the tunnel interface and can't clamp on a middlebox.
Fix 3 (least good): allow the ICMP¶
If you own the firewall, don't blanket-drop ICMP:
iptables -A INPUT -p icmp --icmp-type fragmentation-needed -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type packet-too-big -j ACCEPT
Verification and troubleshooting¶
- Small requests work, big ones hang — textbook PMTUD black hole. Do the
ping -M dosearch; the failing size tells you the path MTU. git clone/apt updatestalls at a percentage — same thing; the large data packets can't get through.- Works over IPv4, IPv6 totally broken — ICMPv6 "Packet Too Big" is being filtered somewhere. This is not optional for IPv6.
- Fixed with MTU 1400, still occasional stalls — the path MTU is even lower (double tunnel, some mobile networks are ~1358). Lower it more or clamp.
- After a WireGuard/IPsec setup, everything is slow/broken — set the tunnel MTU explicitly; the defaults are often too optimistic.
tcpdumpshows repeated identical large packets from your host — the sender never got the ICMP and is retransmitting blindly.
Related tools and reading¶
- On-site: Ping, Traceroute, Port Checker.
- Related posts: The TCP three-way handshake, What happens when you type a URL.
Stuck on something this site can't fix?Reach out to Prabath directly on LinkedIn.More in Network Protocols
DHCP DORA: How a Host Gets Its Address
The four DHCP packets, the renewal timers, why relays exist, and the tcpdump filter to watch it happen.
October 24, 2026SMB Versions and Signing, Demystified
SMB1 is a security liability, SMB3 encrypts and signs. Here's how dialect negotiation works and how to tell which one a connection actually used.
October 24, 2026DNS over TLS and DNS over HTTPS
Plain DNS is unencrypted and unauthenticated. DoT and DoH fix the transport — here's how each works, and the trade-off between privacy and network visibility.
October 24, 2026