DevTools Hub

Search tools

Search for a developer tool

VPN MTU and Fragmentation Explained

Part of the VPN Toolkit

"The VPN connects fine, but large file transfers hang or SSH sessions freeze the moment I do anything beyond typing" is one of the most common VPN complaints, and it's almost always the same underlying cause: the tunnel's effective MTU is smaller than what the connection is actually trying to send, and something in the path isn't handling that gracefully. This post covers why VPNs shrink the usable packet size at all, why the failure mode looks exactly like this, and how to compute a safe MTU instead of guessing.

What MTU actually limits

MTU (Maximum Transmission Unit) is the largest packet a given network link will carry without fragmenting it. Standard Ethernet uses 1500 bytes, a number so ubiquitous it's easy to forget it was ever a deliberate choice rather than a law of physics. A VPN adds its own encapsulation on top of every packet it carries — an outer IP header, a transport header (UDP or TCP), and the VPN protocol's own framing — which means a packet that fit perfectly on the underlying network no longer fits once it's wrapped for the tunnel, unless the VPN interface's own MTU is set smaller to compensate.

Where the overhead actually comes from

Every layer adds a fixed cost, and they stack:

  • Outer IP header: 20 bytes for IPv4, 40 for IPv6 — the packet carrying the VPN traffic itself needs its own addressing.
  • Outer transport header: 8 bytes for UDP, 20 for TCP.
  • The VPN protocol's own framing: WireGuard adds a fixed 32 bytes (a type field, receiver index, counter, and authentication tag, specified precisely by its protocol format). OpenVPN and IPsec vary depending on cipher — an AEAD cipher like AES-GCM adds meaningfully less overhead than an older CBC-mode cipher paired with a separate HMAC, since CBC needs an IV and padding on top of the authentication tag.

Add an outer PPPoE connection (common on DSL) and there's another 8 bytes on top of all of it, squeezed in before the packet even reaches the internet-facing router. A connection already near the edge on plain Ethernet can end up genuinely too tight once PPPoE and a VPN are both in the picture.

Why the symptom is always "works small, fails large"

A DNS lookup, a short HTTP request, an SSH login banner — none of these come close to 1500 bytes, so they sail through regardless of how badly the MTU math is off. The failure only shows up once something tries to send a packet close to the interface's stated MTU: a large file download, a bulk SCP transfer, or an SSH session the moment you run a command with substantial output. What should happen at that point is either successful fragmentation or Path MTU Discovery quietly negotiating a smaller size going forward; what actually happens when either mechanism is broken is the oversized packet simply disappearing, with the connection stalling until a timeout — a confusing failure mode precisely because everything looked fine right up until that point.

Why fragmentation and Path MTU Discovery both commonly fail

IPv6 doesn't allow routers along the path to fragment a packet at all — only the original sender can, which requires the sender to already know the correct size in advance. IPv4 permits router fragmentation in principle, but modern stacks commonly set the "Don't Fragment" bit on outgoing packets specifically so Path MTU Discovery can work: a router that can't forward an oversized, DF-marked packet is supposed to send back an ICMP "Fragmentation Needed" message, letting the sender learn the correct size and resend smaller. The common failure: a firewall somewhere along the path blocks that ICMP message outright (a long-standing, still common misconfiguration often justified as a security hardening measure), and the sender never learns anything is wrong — it just keeps sending packets that silently vanish.

TCP MSS clamping: fixing it proactively instead of relying on discovery

# Linux iptables example: clamp MSS to the tunnel's MTU
iptables -t mangle -A FORWARD -o wg0 -p tcp --tcp-flags SYN,RST SYN \
  -j TCPMSS --clamp-mss-to-pmtu

Rather than relying on Path MTU Discovery to eventually work, MSS clamping rewrites the Maximum Segment Size a TCP connection announces during its own handshake, so it never tries to send a segment too large for the tunnel in the first place. This only affects TCP — a protocol with its own explicit segment-size negotiation. UDP has no equivalent mechanism; a UDP-based application that cares about this has to size its own packets conservatively, which is part of why VPN protocols carrying UDP control traffic (like WireGuard's own handshake messages) are deliberately kept well under any plausible MTU limit.

Setting the interface MTU directly

Rather than relying purely on MSS clamping (which only helps TCP), setting the VPN interface's own MTU correctly fixes the problem at the source for all traffic, UDP included. The calculation is exactly the overhead breakdown above, subtracted from the underlying link's MTU: a 1500-byte Ethernet link running WireGuard over IPv4 UDP supports a 1440-byte WireGuard interface MTU (1500 − 20 IP − 8 UDP − 32 WireGuard); the same setup over an IPv6 outer transport only supports 1420, which is exactly why WireGuard's own documented default is 1420 — a deliberately conservative choice that works regardless of which outer IP version actually carries the traffic.

Common mistakes

  • Leaving the VPN interface at the underlying link's full MTU. The single most common root cause — the VPN's own overhead is never subtracted at all.
  • Blocking ICMP outright at the firewall. This breaks Path MTU Discovery for every connection through that firewall, not just VPN traffic — a much larger blast radius than intended.
  • Forgetting PPPoE's extra 8 bytes. A calculation that accounts for the VPN's overhead but not the underlying connection type can still come up short.
  • Assuming MSS clamping alone is a complete fix. It only helps TCP; UDP traffic still needs a correctly sized interface MTU.

FAQ

Why does a VPN with a bad MTU work for small requests but fail on large ones?

A small request — a DNS lookup, a short HTTP request, an SSH login prompt — fits easily within even a badly undersized MTU, so nothing looks wrong. A large transfer eventually sends a packet that doesn't fit, and if fragmentation or Path MTU Discovery isn't working correctly for that connection, that specific packet is what silently disappears — which is why the symptom always shows up as "works for small stuff, hangs on anything substantial" rather than an immediate, obvious failure.

Why can't the network just fragment the oversized packet automatically?

It often tries to, but two things commonly break it: IPv6 doesn't support fragmentation by routers at all (only by the original sender), and even on IPv4, the "Don't Fragment" bit is commonly set on packets by default and by Path MTU Discovery itself — precisely so an oversized packet triggers an informative ICMP error back to the sender instead of being silently fragmented, letting the sender adjust down. If that ICMP message gets blocked by a firewall along the path (a very common misconfiguration), the sender never learns to adjust, and the packet is simply dropped every time instead.

Is TCP MSS clamping the same thing as setting the VPN interface's MTU?

Related but different layers. The VPN interface's MTU is the actual size limit enforced on that interface. MSS clamping is a separate mechanism (often implemented by rewriting packets in transit, e.g. iptables' TCPMSS target) that tells TCP connections what maximum segment size to use during their handshake, so TCP itself never tries to send a segment too large for the tunnel — a proactive fix specifically for TCP, on top of whatever the interface MTU is set to.

Does UDP traffic benefit from MSS clamping too?

No — MSS is a TCP-specific concept negotiated during the TCP handshake. UDP has no equivalent negotiation; a UDP application that wants to avoid fragmentation has to know the effective path MTU itself and size its own packets accordingly, which is part of why some UDP-based protocols (including WireGuard's own control traffic) are deliberately conservative about packet sizes.

If I'm not sure about my exact cipher's overhead, what's a safe default?

Err toward a slightly smaller MTU than the calculated minimum — a slightly conservative MTU costs a small, constant amount of efficiency on every packet; an MTU that's even a few bytes too large causes fragmentation or drops that can be far more disruptive than the efficiency loss from being conservative. WireGuard's own default of 1420 exists for exactly this reason — it's deliberately sized for the worst realistic case rather than the best one.

Try it yourself

VPN MTU / TCP MSS Calculator computes the recommended interface MTU and MSS clamp for WireGuard, OpenVPN, or IPsec from your actual setup, entirely in your browser.

Related tools