Skip to main content
RunBook Academy

← All runbooks in VyOS

medium riskservice affecting~40 min

Runbook: Investigate an MTU Issue

1 · Prerequisites

Confirm every item is in place before any state change.

2 · Pre-checks

Read-only diagnostic commands. If any of these don't match expected output, stop and investigate further.

  • · The symptom has been restated as a size rather than an adjective. "Large packets fail" is not evidence; "the TLS handshake completes and the first response body stalls, every time, on the same file" is a starting point and a sized ping turns it into a number
  • · A default-size ping to the destination succeeds. If it does not, this is not an MTU incident: the path is down and the entry point is a routing runbook, not this one
  • · The path is named end to end - which source, which destination, and every tunnel, VLAN and provider hand-off in between. MTU is a property of a path, not of an interface, and a runbook run against the wrong path produces a confident wrong answer
  • · The interface MTU of every interface on the path this router owns is on file: show interfaces, and show interfaces wireguard / show interfaces vti / show interfaces tunnel for any tunnel in the path
  • · Whether anything changed has been established: show system commit for the revision list, and show system commit diff N for what a given revision actually altered. A path MTU that was fine last week and is not today usually has a commit or a provider change behind it
  • · Out-of-band access is confirmed before any remediation. An interface MTU change bounces the link; if that link carries your session, you will not see whether the change worked
  • · Both address families are in scope. IPv4 and IPv6 do not share a path MTU, do not share an MSS, and do not share a firewall rule set. Testing one and fixing one is half a fix

3 · Procedure

Execute each step in order. Verify the expected output of a step before moving to the next.

  1. 1Confirm the path works at all: a default-size ping to the destination. This runbook only applies where small packets succeed and large ones do not.
  2. 2Convert the symptom into a number. Run a sized, do-not-fragment ping and bisect: ping DEST size 1472 do-not-fragment count 3, then halve the gap until you have the largest payload that succeeds. The IP packet is the payload plus 28 bytes, so payload 1472 is a 1500-byte packet.
  3. 3Run the same size again WITHOUT do-not-fragment. This second ping is what distinguishes the four outcomes, and it is the step operators skip.
  4. 4Classify: large DF succeeds (not an MTU fault); large DF returns an ICMP fragmentation-needed with an MTU value (PMTUD is working, the path MTU is now known); large DF hangs but the non-DF ping succeeds (PMTUD black hole, ICMP is being filtered); both hang (the path is broken at that size for another reason).
  5. 5Try to locate the constraining hop, and treat the number from step 2 as the answer if you cannot. VyOS ships traceroute and mtr, neither of which reports per-hop MTU; where PMTUD is working, the ICMP fragmentation-needed carries the next-hop MTU and a capture is what reads it.
  6. 6Decide ownership: is the constraining hop an interface this estate configures, or is it inside a provider or partner network? This single question selects the fix and cannot be skipped.
  7. 7If PMTUD is black-holed, check whether this router is the one filtering: show firewall ipv4 input filter, show firewall ipv4 forward filter and their IPv6 equivalents, reading the per-rule counters rather than the intent. ICMP fragmentation-needed and ICMPv6 packet-too-big must be permitted.
  8. 8Compute the target values before changing anything: inner MTU is wire MTU minus tunnel overhead; IPv4 MSS is MTU minus 40; IPv6 MSS is MTU minus 60. Write both numbers into the incident record so the reviewer can check the arithmetic.
  9. 9Choose one fix and name what it costs: permit the ICMP that PMTUD needs (restores the mechanism, only works where you own the filter); correct the interface MTU (right when a tunnel MTU is simply wrong, and it bounces the link); clamp MSS (cheapest, works through a filtering provider, and does nothing for UDP).
  10. 10Apply it with a net: compare, then commit-confirm 5, then leave configure mode and re-run the sized ping from the operational shell before you confirm. An MTU change on the interface carrying your session is the one that needs the timer most.
  11. 11Verify on traffic, not on configuration. Re-run the sized do-not-fragment ping at the new ceiling, confirm the clamped MSS on the wire with a SYN capture, and then confirm the ORIGINAL application symptom is gone. A ping that now passes is necessary and not sufficient.
  12. 12Run save, then record the measured path MTU, the constraining hop, the fix and its owner in the MTU inventory. A path MTU that was measured and not written down will be measured again by the next person under the same pressure.

4 · Verification

Confirm the procedure actually fixed the problem.

  • A sized do-not-fragment ping at the new working size succeeds three times out of three, in both directions of the path where a host at each end is available
  • The sized do-not-fragment ping now succeeds at the value the fix targeted, re-measured by the same bisection that produced the original number. This is the verification, not a hop-by-hop report - VyOS has no op-mode command that prints per-hop MTU
  • Where MSS clamping was applied: a SYN capture on the interface the clamp is bound to shows the clamped value, not 1460 - monitor traffic interface eth0 filter "tcp[tcpflags] & tcp-syn != 0"
  • Where a firewall rule was added for ICMP: the rule counter is non-zero under real traffic. A rule at zero packets has not been proved to be the rule in effect
  • The application symptom that produced the page is gone, tested against the same operation that failed - the large upload, the file copy, the backup job - and not against ping alone
  • IPv6 was tested separately from IPv4 - the same ping ADDR size N do-not-fragment count 3 bisection against an IPv6 destination - and either fixed or explicitly recorded as out of scope
  • compare from configure produces no output, and configure, load /config/config.boot, compare, discard produces no diff: the fix is saved, not only live
  • The measured path MTU, the constraining hop and the chosen fix are in the MTU inventory with a date

5 · Rollback

If verification fails, undo the procedure in reverse order.

  • Interface MTU change: set the node back to its previous value (or delete it to return to the interface default), compare, commit-confirm 5, then confirm. Restoring the MTU bounces the link a second time, so it is a change with the same blast radius as the original
  • MSS clamp: delete interfaces ethernet ethN ip adjust-mss (and the ipv6 adjust-mss node separately), then commit. Existing TCP connections keep the MSS they negotiated at SYN time and will not revert until they are re-established
  • Firewall rule for ICMP: delete the rule number you added and commit. Removing an accept rule from a default-deny chain is a security-relevant change, so it needs the same review as adding one
  • Do NOT reach for rollback N as the undo. VyOS documents it as applying the revision and triggering a system reboot, which on a router carrying traffic is an outage rather than a revert. Use compare N to READ what a revision changed, and undo the specific nodes yourself
  • If the router became unreachable at the moment of the commit, do nothing and let the commit-confirm timer expire. A second blind attempt from a different host usually makes the evidence worse
  • POINT OF NO RETURN: lowering an MTU or clamping an MSS does not reverse the transfers that already failed. Anything that timed out during the incident - a backup, a replication job, a batch upload - has to be re-driven by whoever owns it
  • POINT OF NO RETURN: an MTU raised on a link whose far end has not been raised too. The link comes up, small packets pass, and large ones are dropped silently by the far end. Rolling back this router restores service; it does not tell you the far end was the problem

6 · Escalation

When the runbook isn't enough, contact:

  • · Escalate to the provider or partner NOC when the constraining hop is outside the estate. Ask two specific questions - what is the MTU on that hop, and do you filter ICMP fragmentation-needed - because "our network is fine" answers neither
  • · Escalate to network engineering before changing the MTU on any link that is one half of a redundant pair. Lowering the MTU on one path and not the other converts a size problem into a failover problem
  • · Escalate to security before permitting ICMP through a default-deny chain, even for fragmentation-needed. Widening an inbound filter is a security decision with an availability justification, which is not the same as an availability decision
  • · Escalate to the application owner rather than clamping harder when the failing traffic is UDP - QUIC, a UDP-based VPN, NFS over UDP, media. MSS clamping is a TCP mechanism and will not touch it
  • · Escalate to the platform team if the interface will not accept the MTU you calculated, or comes back down after the change. That is a driver or hardware conversation, not a configuration one
  • · Escalate rather than guess if the path crosses a tunnel this team does not own. Changing the inner MTU on one end of a tunnel whose far end you cannot see produces an asymmetric MTU, which is harder to diagnose than what you started with

An MTU incident almost never arrives described as one. It arrives as four reports that read like four different problems:

  • The VPN is up, but the file share on the other side is unusable.
  • The site loads, and the login page hangs forever.
  • SSH is fine; copying anything large stalls at the same point every time.
  • The nightly replication to the DR site started failing on Tuesday, and nobody changed anything.

They are one fault. Something on the path cannot carry a packet above a certain size, and everything below that size works perfectly — which is precisely why none of the four reports mentions size, and why the first hour of these incidents is usually spent on DNS, on the application, and on the firewall.

The whole job of this runbook is to convert an adjective into a number in the first ten minutes. “Large packets fail” is not evidence. “1372 bytes of payload succeeds and 1373 does not” is evidence, and it is most of the diagnosis.

When to use this runbook

Small packets reach the destination and large ones do not, on a path that this estate has a router on. The classic tells are a protocol that completes its handshake and then stalls on the first substantial payload, and a failure that reproduces at exactly the same size every time.

When not to use it

  • A default-size ping already fails. Nothing here applies; the path is broken and the entry point is vyos-rb-troubleshoot-missing-route.
  • Loss is proportional at every size, or comes and goes. That is vyos-rb-investigate-packet-loss — MTU faults are a cliff, not a slope.
  • The tunnel is new and has never carried a large packet. Sizing the tunnel is part of turn-up: vyos-rb-configure-wireguard and vyos-rb-configure-ipsec both end with a sized ping for this reason.

Blast radius

Every step up to the fix is read-only and can be run during business hours from any session. The fix is not. An interface MTU change bounces the link, an MSS clamp changes every TCP connection that later crosses the interface, and permitting ICMP widens a filter. Treat the remediation as a change with its own review, on a path that has just proved it can surprise you.

Step 1: turn the adjective into a number

Read-only / Safebisect for the largest payload that gets through
ping 192.0.2.50 count 3
ping 192.0.2.50 size 1472 do-not-fragment count 3
ping 192.0.2.50 size 1372 do-not-fragment count 3
ping 192.0.2.50 size 1422 do-not-fragment count 3

size is the ICMP payload, not the packet. The IP packet is the payload plus 28 bytes — 20 of IP header and 8 of ICMP echo header — so payload 1472 is a 1500-byte packet and payload 1372 is a 1400-byte packet. Subtract 28 from the MTU you are testing for; this is the arithmetic operators most often get wrong, and getting it wrong shifts every conclusion by 28 bytes.

Four or five probes bisect the whole range. Start at 1472, and when it fails, halve the gap rather than stepping down by ten — a linear walk from 1472 is forty probes and an hour you do not have.

If you prefer the underlying tool, ping -M do -s 1472 192.0.2.50 is the same test; the course’s Part LI lessons use that form throughout.

Step 2: run the same size again without the DF bit

This is the step that gets skipped, and it is the step that tells you what kind of MTU fault you have.

Read-only / Safethe same packet, allowed to fragment
ping 192.0.2.50 size 1472 count 3

Two probes at one size produce four outcomes, and each one points at a different fix:

DF probeNon-DF probeWhat you haveWhere to go
SucceedsSucceedsPath MTU is at or above the size you testedNot an MTU fault. Look at the application
Returns ICMP fragmentation-needed with an MTU valueSucceedsPMTUD is working and has told you the answerStep 3, then decide whether anything needs changing at all
Hangs, no ICMP at allSucceedsPMTUD black hole: something drops the big packet and sends nothing backStep 3, then Step 4 — the fix is ICMP or MSS
HangsHangsThe path cannot carry that size in any formNot primarily MTU. Routing, filtering, or a hop that drops fragments

The second row is the benign case and it is worth pausing on. If the path returns an ICMP fragmentation-needed carrying a usable MTU, the mechanism is working: senders that respect Path MTU Discovery will size themselves correctly on their own. If an application is still failing, the application is not honouring PMTUD, and clamping MSS is a workaround for that application rather than a repair of the network.

The third row is the one that generates incidents. Nothing is broken visibly; a router or firewall somewhere silently discards the oversized packet without generating the ICMP that would have told the sender why.

Step 3: find the hop, or accept that you cannot

Where PMTUD is working — the second row of the Step 2 table — the path has already told you the number and the hop that owns it. The ICMP fragmentation-needed carries the next-hop MTU, and a capture is what reads it:

Read-only / Safethe ICMP that PMTUD depends on, if it is arriving at all
monitor traffic interface eth0 filter 'icmp or icmp6'
IP 198.51.100.9 > 198.51.100.1: ICMP 192.0.2.50 unreachable -
     need to frag (mtu 1450), length 556

Illustrative output

Two things come out of one line: the constraining MTU (1450) and the address of the hop that announced it (198.51.100.9). That is the part of a tracepath report you were actually going to act on — the binding constraint and its owner — read from the router you are already logged into. What it will not give you is the MTU of hops that are not currently the constraint, which is a real limitation only if you intend to raise the ceiling twice.

If nothing arrives, that is the black-hole case and it is a finding, not a failed test. Run traceroute to establish the topology — the hops, and where the path leaves your estate — and pair it with the measured number from Step

  1. Knowing “1372 fits, 1373 does not, and hop 4 is the provider’s” is enough to choose a fix and enough to open a ticket with.

Do IPv6 separately and expect a different answer. The two families do not share a path MTU, they do not share an MSS, and they do not share a firewall rule set. A fix applied to one leaves the other exactly as it was.

Step 4: is the constraining hop yours?

Everything after this depends on the answer, so answer it explicitly and write it into the incident record.

The hop is an interface this estate configures — a tunnel, a VLAN sub-interface, a link you own both ends of. The MTU is probably simply wrong, and correcting it is the honest fix. Check the arithmetic below before you change it.

The hop is inside a provider or partner network. You are not going to change it. Your options are to size your own traffic to fit, or to get the provider to stop filtering the ICMP that would let PMTUD do it for you. Both are legitimate; only one is under your control today.

The hop cannot be identified at all because the path goes dark partway. Then the measured number from Step 1 is still valid and still actionable — you know what fits, even if you do not know why. Clamp to what fits, record that the constraining hop is unknown, and open the provider ticket anyway.

If PMTUD is black-holed, check that this router is not the one doing the filtering before blaming anyone else:

Read-only / Safecounters, not intentions
show firewall ipv4 input filter
show firewall ipv4 forward filter
show firewall ipv6 input filter
show firewall ipv6 forward filter
show firewall statistics

A default-deny chain with no rule permitting ICMP fragmentation-needed (IPv4) or ICMPv6 packet-too-big is a PMTUD black hole that this team owns. Read the counters: an accept rule sitting at zero packets while the default-action counter climbs means your traffic is being matched by something other than the rule you believe is in effect.

The arithmetic, before you change anything

Path elementOverhead, IPv4 outerInner MTU from 1500IPv4 MSSIPv6 MSS
Plain Ethernet150014601440
802.1Q VLAN tag0 at layer 3150014601440
GRE24147614361416
WireGuard32146814281408
WireGuard, IPv6 outer80142013801360
VXLAN50145014101390
IPsec ESP over a VTI38–66, cipher dependentmeasure it — and the interface defaults to 1500measure itmeasure it

MSS is the TCP payload only: it excludes both the TCP header and the IP header. So IPv4 MSS is MTU minus 40, and IPv6 MSS is MTU minus 60. The twenty-byte difference between the families is the single most common arithmetic error in this whole subject, and its symptom is an IPv6 path that still stalls after “the MTU was fixed”.

IPsec is deliberately left as “measure it”. The overhead depends on the cipher, on whether NAT traversal has added its eight bytes of UDP encapsulation, and on the length of the integrity check value, which is why Part LI-02 lands on a conservative VTI MTU of 1438 rather than a computed one. Read the negotiated proposal out of the Proposal column of show vpn ipsec sa — that is the cipher actually in use, which is not necessarily the one at the top of your proposal list — and then measure.

The second half of that row matters as much as the arithmetic. A VTI comes up at MTU 1500. Nothing about set interfaces vti vti0 sizes it for the overhead the tunnel is about to add, so an IPsec tunnel that was built without an explicit mtu is not “probably fine” — it is the exact configuration this runbook exists to diagnose, and it will present as an application fault. Confirm it with show interfaces vti vti0 before theorising about the path beyond it.

Step 5: choose the fix, and say what it costs

Permit the ICMP that PMTUD needs. This repairs the mechanism rather than working around it, and it fixes every protocol at once rather than only TCP. It only works where you own the filter, and it widens an inbound chain, so it is a security-reviewed change.

Configuration changethe specific types, not all ICMP
set firewall ipv4 name WAN-IN rule 5 action accept
set firewall ipv4 name WAN-IN rule 5 protocol icmp
set firewall ipv4 name WAN-IN rule 5 icmp type 3
set firewall ipv4 name WAN-IN rule 5 icmp code 4

set firewall ipv6 name WAN6-IN rule 5 action accept
set firewall ipv6 name WAN6-IN rule 5 protocol icmpv6
set firewall ipv6 name WAN6-IN rule 5 icmpv6 type-name packet-too-big

compare
commit-confirm 5

Correct the interface MTU. The right fix when a tunnel or a link is simply configured wrong. It bounces the link — briefly for an Ethernet interface, and long enough to notice — and it is only correct if the far end agrees.

Clamp MSS. The cheapest fix and the one that works through a provider you cannot change, because it needs nothing from anybody else. It is TCP-only.

Configuration changeclamp on the interface the SYN crosses
set interfaces wireguard wg01 ip adjust-mss clamp-mss-to-pmtu
set interfaces wireguard wg01 ipv6 adjust-mss clamp-mss-to-pmtu

compare
commit-confirm 5

clamp-mss-to-pmtu derives the value from the interface MTU, which is why setting the interface MTU deliberately matters even when the clamp is doing the work. VyOS documents the derivation precisely: the MSS becomes the interface MTU minus 40 for IPv4 — 20 bytes of IP header and 20 of TCP — so an interface at 1468 advertises 1428. Where the underlay is itself constrained — PPPoE, a tunnel inside a tunnel — ip adjust-mss <value> takes an explicit number from your Step 1 measurement, which is safer than a derived one that is derived from the wrong MTU.

Note that ip adjust-mss and ipv6 adjust-mss are separate nodes on the same interface. Setting one does nothing for the other, which is the mechanical reason behind “fixed for IPv4, still broken for IPv6” appearing twice in this runbook.

Hold. A first-class option. If the path is degraded rather than down, and the change window is hours away, holding with a named owner and an end time is better than a rushed MTU change on a live provider link. Write the owner and the time into the incident record, not into somebody’s memory.

Step 6: apply it with a net, then verify on traffic

Service impact possibletest before you confirm, not after
compare
commit-confirm 5
exit
ping 192.0.2.50 size 1372 do-not-fragment count 3

Leave configure mode and test from the operational shell while the timer runs. If the result is right, go back in and confirm, then save. If it is not, do nothing and let the timer restore the previous state — the operator who has just been wrong once is not the best judge of the second attempt.

Read-only / Safeprove the clamp on the wire
monitor traffic interface eth0 filter 'tcp[tcpflags] & tcp-syn != 0'

monitor traffic is VyOS’s wrapper around tcpdump, so the filter syntax is tcpdump’s and the output is tcpdump’s; Ctrl-C stops it. The SYN carries the MSS option, and this capture is the only direct evidence that the clamp is on the interface the SYNs actually cross. A clamp bound to the wrong interface commits cleanly, validates cleanly, and does nothing.

The interface to watch is the one the SYN crosses, which is not always the one you clamped. On a tunnel the SYN enters on the LAN side and leaves on the tunnel; the clamp rewrites it on egress, so capture on the tunnel interface to see the clamped value and on the LAN interface to see what it was before.

Then verify the thing that was actually broken. Re-run the failed upload, the file copy, the backup job. A sized ping that now passes is necessary and not sufficient, and the gap between the two is where “we fixed it” turns into a second page an hour later.

Common patterns

SymptomLikely causeWhere to look
Handshake completes, first large response hangsPath MTU below what the sender is usingSized do-not-fragment ping, bisected
DF ping hangs, non-DF ping succeedsPMTUD black hole — ICMP filtered somewhereOwn firewall counters first, then the provider
Fixed for IPv4, still broken for IPv6Separate path MTU, separate MSS, separate filterThe same sized-ping bisection to an IPv6 destination, ipv6 adjust-mss, and the IPv6 rule set
Clamp committed, nothing changedWrong interface, or existing connectionsSYN capture on the interface the SYNs cross
Works one direction, fails the otherAsymmetric tunnel MTU — the two ends disagreeshow interfaces on both ends of the tunnel
Failing traffic is unaffected by the clampThe traffic is UDPProtocol of the failing flow, before tuning further
Path MTU reported below 1280 for IPv6Below the IPv6 minimum link MTUThe link itself — this is not a tuning problem
Everything passes now, breaks after a rebootCommitted and never saved/config/config.boot

Escalation

Escalate when:

  • The constraining hop is outside the estate.
  • The link is one half of a redundant pair.
  • The fix requires widening a default-deny chain.
  • The failing traffic is UDP and the clamp cannot reach it.
  • The interface refuses the MTU, or does not come back after the change.
  • The path crosses a tunnel whose far end this team cannot see.

References

  1. VyOS documentation - Ethernet interfaces (mtu, ip adjust-mss)
  2. VyOS documentation - IPv4 firewall
  3. VyOS documentation - WireGuard interfaces
  4. VyOS documentation - VTI interfaces (the IPsec tunnel interface and its default MTU)
  5. VyOS documentation - connectivity tests (ping size / do-not-fragment, traceroute, mtr)
  6. Linux man page - ping(8)
  7. Linux man page - tracepath(8) - the per-hop MTU tool VyOS does not ship
  8. RFC 1191 - Path MTU Discovery
  9. RFC 8201 - Path MTU Discovery for IPv6
  10. RFC 4821 - Packetization Layer Path MTU Discovery