SSH works but large transfers hang intermittently. Diagnose the probes below.
Over a site-to-site VPN, SSH logs in and small API calls succeed, but larger downloads stall and time out. Diagnose from the probes below; name the fault and give one fix.
$ ssh user@10.9.0.5 # connects, prompt appears
$ curl -sS https://10.9.0.5/small.json # 200 OK, instant
$ curl -sS https://10.9.0.5/report.csv # hangs, then times out
$ ping -c1 10.9.0.5 # 0% packet loss
$ ping -M do -s 1472 -c1 10.9.0.5
ping: local error: message too long, mtu=1400
What is the fault, and how do you fix it?
Small requests pass but large transfers hang, and ping -M do -s 1472 fails with mtu=1400 — a PMTU black hole. A VPN lowered the path MTU to 1400; DF-set packets are dropped, but the ICMP fragmentation needed is filtered, so the sender never learns and stalls. Fix: allow that ICMP, or clamp TCP MSS to the PMTU.
- ✗Reading a clean small
pingas proof the whole path is healthy - ✗Blaming random packet loss when only large, DF-set packets are dropped
- ✗Missing that filtered ICMP
fragmentation neededis what creates the black hole
- →Why do small requests succeed while only large transfers hit the black hole?
- →How does clamping TCP MSS avoid relying on ICMP getting through?
The symptom pattern names the fault: small requests succeed, large transfers hang. That asymmetry is the signature of a PMTU black hole. The ping -M do -s 1472 probe (1472 bytes payload + 28 bytes headers = a 1500-byte frame with Don't-Fragment set) fails locally with mtu=1400 — the VPN's encapsulation overhead has lowered the path MTU to 1400.
Here is the mechanism: a full-size TCP segment on an established connection is 1500 bytes with DF set. On the 1400-byte link it is too big to forward, so the router drops it and should return an ICMP fragmentation needed (type 3, code 4) telling the sender to shrink. If a firewall filters that ICMP, the sender never learns — it keeps resending the same oversized segment, which keeps getting dropped. Small packets fit under 1400 and sail through, so logins and tiny responses work while any large transfer stalls.
Two durable fixes:
# 1) Let PMTUD work: permit the ICMP that carries the smaller MTU.
# (allow ICMPv4 type 3 code 4 / ICMPv6 type 2 through the firewall)
# 2) MSS clamping — the robust fix that does not depend on ICMP arriving.
$ sudo iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
MSS clamping rewrites the TCP MSS in the SYN so both ends agree to send segments that already fit the path — no oversized packet is ever produced. As a last resort, lower the interface MTU to 1400.