Path MTU Discovery Black Hole
Embed This Widget
Add the script tag and a data attribute to embed this widget.
Embed via iframe for maximum compatibility.
<iframe src="https://ipfyi.com/iframe/entity//" width="420" height="400" frameborder="0" style="border:0;border-radius:10px;max-width:100%" loading="lazy"></iframe>
Paste this URL in WordPress, Medium, or any oEmbed-compatible platform.
https://ipfyi.com/entity//
Add a dynamic SVG badge to your README or docs.
[](https://ipfyi.com/entity//)
Use the native HTML custom element.
TCP connections appear to establish successfully but then hang or stall when transferring data larger than a certain size. This is the classic symptom of a Path MTU Discovery (PMTUD) black hole: ICMP 'Fragmentation Needed' messages are being discarded by an intermediate firewall, preventing the sender from learning the correct MTU and causing it to send oversized packets that are silently dropped.
Symptoms
- ⚠ Small HTTP requests (like pings or DNS) work fine, but large file downloads or web pages stall after the initial response
- ⚠ SSH connections establish but hang after authentication when shell output exceeds ~1400 bytes
- ⚠ VPN tunnels connect but pass only small packets — large transfers freeze completely
- ⚠ tcpdump shows TCP SYN/SYN-ACK completing, data flowing briefly, then retransmissions with no ICMP Type 3 Code 4 responses
- ⚠ The issue only occurs with specific remote hosts and not others, depending on the intermediate network path
- ⚠ Adding '?cachebust=1' to URLs or reducing MTU manually causes the connection to work
Possible Root Causes
- • A firewall between sender and receiver drops ICMP Type 3 Code 4 (Fragmentation Needed) messages, preventing PMTUD from functioning
- • VPN or tunnel encapsulation reduces the effective MTU (e.g., IPsec adds 50-60 bytes, reducing 1500-byte MTU to ~1440)
- • ISP or carrier network using MPLS labels that add overhead, reducing the available payload size for IP packets
- • Network equipment misconfigured with inconsistent MTU values on different interfaces of the same path
- • Stateful firewalls that allow ICMP echo but silently discard ICMP unreachable messages as a misguided security measure
Diagnosis Steps
Step 1: Test with different packet sizes
# Linux / macOS — ping with specific payload size and DF bit set
# The DF (Don't Fragment) bit triggers ICMP Fragmentation Needed responses
ping -c 4 -s 1472 -M do remote-host.example.com
# 1472 bytes payload + 28 bytes ICMP/IP header = 1500 bytes total (standard Ethernet MTU)
# Reduce size until ping succeeds:
ping -c 4 -s 1450 -M do remote-host.example.com
ping -c 4 -s 1400 -M do remote-host.example.com
ping -c 4 -s 1300 -M do remote-host.example.com
# Windows (DF bit is set by default with -f flag)
ping -f -l 1472 remote-host.example.com
ping -f -l 1450 remote-host.example.com
The largest size that succeeds without fragmentation is your effective path MTU.
Step 2: Capture traffic to confirm PMTUD blackhole
# On the sender, capture to see if ICMP Type 3 Code 4 messages are received
sudo tcpdump -i eth0 -n 'icmp and icmp[0] == 3 and icmp[1] == 4'
# Type 3 = Destination Unreachable
# Code 4 = Fragmentation Needed
# If no such ICMP messages appear during a stalled large transfer,
# the ICMP is being dropped by an intermediate firewall = PMTUD blackhole
Step 3: Identify where ICMP is being dropped
# Use traceroute with varying payload sizes to find the problematic hop
# Linux / macOS
traceroute -n remote-host.example.com
# Then manually send large UDP/ICMP packets to each hop to find where DF is blocked
# (Advanced: use scapy or hping3 for precise control)
# hping3 — send TCP packets with DF bit and varying sizes
sudo hping3 -S -p 443 -d 1450 -M 0 remote-host.example.com
# -S = SYN
# -d = data size
# -M 0 = set IP ID to 0 (DF bit behavior varies by implementation)
Step 4: Check the MSS (Maximum Segment Size) in TCP handshake
# Capture the TCP handshake and inspect MSS option
sudo tcpdump -i eth0 -n -w /tmp/capture.pcap host remote-host.example.com
# Open in Wireshark and filter: tcp.flags.syn == 1
# Inspect TCP Options > Maximum segment size
# Alternatively, use ss to check MSS on established connections
ss -i dst remote-host.example.com
# Look for "mss:" value in the output
Step 5: Check current interface MTU settings
# Linux — show MTU for all interfaces
ip link show | grep mtu
# macOS
ifconfig | grep mtu
# Windows
netsh interface ipv4 show interfaces
Pay attention to tunnel interfaces (tun0, ppp0) which often have reduced MTUs.
Step 6: Test with TCP MSS clamping simulation
# Use iptables to clamp MSS and test if it fixes the issue
# This is a test — apply to outbound traffic only temporarily
sudo iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
# If connections now work, PMTUD blackhole is confirmed
# Remove after testing:
sudo iptables -t mangle -D POSTROUTING -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
Solution
Solution A: TCP MSS clamping (recommended — fixes the symptom)
Add iptables rules to clamp the TCP Maximum Segment Size to the correct value, bypassing PMTUD entirely:
# On the Linux router or gateway, clamp MSS to 1452 (1500 MTU - 20 IP - 20 TCP - 8 ICMP)
# or use --clamp-mss-to-pmtu to auto-calculate
sudo iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
# For VPN interfaces where MTU is known:
sudo iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-o tun0 -j TCPMSS --set-mss 1360
# Make persistent (Debian/Ubuntu)
sudo apt install iptables-persistent
sudo netfilter-persistent save
Solution B: Reduce MTU on the interface (fixes the root cause locally)
# Linux — lower MTU to match the path maximum
sudo ip link set eth0 mtu 1400
# Make permanent in /etc/network/interfaces:
# mtu 1400
# Or via NetworkManager:
nmcli con mod "Wired connection 1" 802-3-ethernet.mtu 1400
nmcli con up "Wired connection 1"
Solution C: Allow ICMP unreachable messages through firewalls
# Linux — ensure ICMP Type 3 (unreachable) is never dropped
sudo iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
sudo iptables -A OUTPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
sudo iptables -A FORWARD -p icmp --icmp-type destination-unreachable -j ACCEPT
On network firewalls (Cisco, Palo Alto, pfSense), ensure ICMP unreachable (Type 3) and time exceeded (Type 11) are not blocked — they are essential for PMTUD and traceroute.
Solution D: Enable PMTUD on Windows
# Windows — enable PMTUD (may be disabled on some systems)
netsh interface ipv4 set subinterface "Local Area Connection" mtu=1500 store=persistent
netsh interface ipv4 set global mtu=1500
Prevention
- Never blindly block all ICMP traffic — always allow ICMP Type 3 (unreachable) and Type 11 (time exceeded) through firewalls, as these are required for PMTUD and traceroute
- Apply TCP MSS clamping as a standard policy on all routers with tunnel interfaces or PPPoE WAN connections
- Document the MTU of every network segment, especially VPN tunnels, and configure consistent values end-to-end
- Regularly test path MTU from your network to critical remote destinations, especially after adding new tunnels or changing ISPs
- When deploying IPsec or WireGuard VPNs, explicitly configure the interface MTU: IPsec typically needs 1400-1420; WireGuard needs 1420