Marsh Notes

MTU headaches between tunnel endpoints

The classic symptom: a TCP connection from a client to a tunnel endpoint works, but a TLS connection stalls at exactly 300 seconds. The MTU is set to 1450 on the client side, but the path to the tunnel's peer has a 1300-byte hard limit.

Why 1450 fails

On Ethernet, the maximum packet size is 1500 bytes. When you add the tunnel's GRE/UDP/IP overhead (usually 50 bytes), you get 1450. The path's bottleneck link (a 3G/4G modem or a satellite link) has a hard MTU of 1300. The client's TCP stack sends packets sized to 1450, the first 500 packets pass, and the 501st packet is fragmented at 1300. If the path's DF bit is set, the packet is dropped. The TCP stack sees 1200 bytes of data, then 1200, then 1200 again, until the window shrinks and the connection stalls.

The 57-byte clue

Check the path's MTU with traceroute -M or mtr -m 1500. If the last hop is a PPPoE link or a PPPoE over 3G modem, the MTU is often 1300. If the client is behind a NAT gateway that rewrites the GRE header to a 57-byte tunnel header (a common pattern in openvpn or wireguard), the 57 bytes are added to the path's 1243-byte limit, giving 1299 — one byte short. The client's TCP stack sends a 1300-byte packet, the path drops it, and the 57-byte header is the culprit.

Fixes

On the client, set the tunnel's MTU to 1200. If the path's MTU is 1243, you can set it to 1243. The client's OS will then fragment packets to fit the path's limit. On the server side, tun0 devices need their own MTU set to the same value. A 57-byte difference is common, so start with 1200 and bump to 1243 if you see fragmentation on the server's tcpdump.

Rule of thumb: if a tunnel's client-side MTU is 1450, the path's MTU is likely 1300.