The symptom was maddening because half of everything worked. SSH connected fine. Short commands returned. But scp of anything large hung, web pages loaded their HTML and then stalled forever waiting for an image, and apt would sit there pretending to think. Small packets through, big packets gone. No errors anywhere, just silence and a spinner.
That pattern, small works and large hangs, is MTU. I'd put a WireGuard tunnel between two homelab boxes and forgotten that tunnels add overhead, so a full 1500-byte packet no longer fit. The big packets were being dropped, and because path MTU discovery relies on ICMP that something upstream was helpfully eating, nobody got told to send smaller ones. The connection didn't fail. It just quietly refused to move bulk data.
The proof takes one command: send a large packet with don't-fragment set and watch it die.
ping -M do -s 1472 10.0.0.2
1472 plus 28 bytes of headers is 1500. That failed; dropping -s down until it succeeded told me the real ceiling. Setting the tunnel interface MTU to match (1420 for this WireGuard link) fixed everything at once. Bulk transfers flowed, images loaded, apt woke up.
MTU is a silent killer precisely because it doesn't announce itself. There's no log line that says "your packet was too big". Things just hang, you blame DNS or the application, and you lose an evening. Now, whenever something connects but won't move data, the don't-fragment ping is the second thing I reach for. Right after blaming DNS, which this time, for once, was innocent.