Overview
This guide covers common MTU/MSS scenarios for WireGuard. For complex network topologies or carrier-specific issues, consult your network engineering team.
Purpose:
This is a complete troubleshooting guide focused on solving MTU (Maximum Transmission Unit) and MSS (Maximum Segment Size) problems in WireGuard VPN setups. These issues often cause symptoms like stalled large file transfers, partial web page loads, SSH working but SCP failing, or intermittent connectivity — even when the VPN handshake succeeds.
For very complex networks or carrier-specific quirks, involve your network engineering team.
Quick Reference
Provides safe starting MTU values depending on the user’s internet connection type:
| Path Type | Recommended MTU | Notes |
|---|---|---|
| Standard internet | 1420 | Safe default for most deployments |
| PPPoE (DSL/Fiber) | 1412 | PPPoE adds 8-byte overhead |
| Mobile/LTE | 1400 | Conservative for variable paths |
| Satellite | 1400 | High latency, avoid fragmentation |
| Data center (jumbo frames) | 1420 | WireGuard overhead still applies |
| Double NAT | 1400 | Extra encapsulation possible |
Decision Tree
The guide gives a logical flowchart to quickly determine whether your issue is MTU-related:
START: User reports connectivity issues
│
▼
┌─────────────────────────────────────────┐
│ Can user establish handshake? │
│ Check: wg show wg0 latest-handshakes │
└─────────────────────────────────────────┘
│
├── NO ──► Handshake Issues (not MTU)
│ - Check firewall (UDP 51820)
│ - Check endpoint resolution
│ - Check key configuration
│
▼ YES
┌─────────────────────────────────────────┐
│ Can user ping gateway (small packets)? │
│ ping -c 3 -s 64 <gateway_ip> │
└─────────────────────────────────────────┘
│
├── NO ──► Routing Issues (not MTU)
│ - Check AllowedIPs
│ - Check server-side routing
│
▼ YES
┌─────────────────────────────────────────┐
│ Do large transfers fail or stall? │
│ - Web pages partially load │
│ - SSH works, SCP fails │
│ - Small pings OK, large pings timeout │
└─────────────────────────────────────────┘
│
├── NO ──► Not an MTU issue
│ - Check bandwidth limits
│ - Check application issues
│
▼ YES
┌─────────────────────────────────────────┐
│ ══════════════════════════════════════ │
│ LIKELY MTU PROBLEM │
│ ══════════════════════════════════════ │
└─────────────────────────────────────────┘
│
▼
Proceed to MTU Discovery below
MTU Discovery Procedure
Step-by-step process to empirically find the maximum safe packet size through the tunnel.
Step 1: Find Working MTU (Client Side)
Test from client through VPN tunnel to a host on the other side:
# Linux/macOS - Start high, decrease until success
# -M do = don't fragment (Linux)
# -D = don't fragment (macOS)
# Linux - Start with 1472 (1500 - 28), decrease by 10s until success
ping -c 3 -M do -s 1472 <target_ip>
# macOS - Start with 1472
ping -c 3 -D -s 1472 <target_ip>
# Windows - Start with 1472
ping -n 3 -f -l 1472 <target_ip>
Step 2: Binary Search for Optimal MTU
# If 1472 fails, try progressively smaller values
ping -c 3 -M do -s 1462 <target_ip> # Try 10 bytes smaller
# If that works, try larger values to find the boundary
ping -c 3 -M do -s 1468 <target_ip> # Try 6 bytes larger
# Continue testing in 2-4 byte increments until you find the exact boundary
Step 3: Calculate Interface MTU
Interface MTU = Successful ping size + 28 (IP + ICMP headers)
Example: ping -s 1372 works
Interface MTU = 1372 + 28 = 1400
MTU Overhead Breakdown
Shows exactly where the overhead comes from in a WireGuard packet:
- Outer: IP (20 IPv4 / 40 IPv6) + UDP (8) = 28 / 48 bytes
- WireGuard: Header (32) + Authentication tag (16) = 48 bytes
- Total overhead: 60 bytes (IPv4) or 80 bytes (IPv6)
┌─────────────────────────────────────────────────────────┐
│ Standard Ethernet Frame (1500 bytes) │
├─────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Outer IP Header (20 bytes) │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ UDP Header (8 bytes) │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ WireGuard Header (32 bytes) │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ ┌─────────────────────────────────────────────────┐ │ │
│ │ │ Inner Packet (max 1440 bytes) │ │ │
│ │ │ - Inner IP Header (20 bytes) │ │ │
│ │ │ - Inner TCP Header (20 bytes) │ │ │
│ │ │ - Payload (max 1400 bytes) │ │ │
│ │ └─────────────────────────────────────────────────┘ │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ WireGuard Auth Tag (16 bytes) │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
WireGuard overhead: 20 + 8 + 32 + 16 = 60 bytes (IPv4)
40 + 8 + 32 + 16 = 80 bytes (IPv6)
Safe WireGuard MTU: 1500 - 80 = 1420 (conservative, works for both IPv4 and IPv6)
Configuration Examples
WireGuard Interface MTU
Set MTU directly in WireGuard config (recommended):
# /etc/wireguard/wg0.conf
[Interface]
PrivateKey = <key>
Address = 10.0.0.2/24
MTU = 1400 # Conservative setting
[Peer]
PublicKey = <key>
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0
Linux: Set MTU on Running Interface
Change MTU on a running interface (temporary):
# Temporary (until restart)
ip link set wg0 mtu 1400
# Verify
ip link show wg0 | grep mtu
MSS Clamping(alternative when you can’t/won’t change client MTU):
- On the server, use iptables to clamp TCP MSS during handshake:
- Automatic (best):
bash--clamp-mss-to-pmtu - Manual example (for MTU 1420):
bash--set-mss 1380(1420 – 40 for TCP+IP headers)
When you cannot change client MTU, clamp MSS on the server to prevent TCP segmentation issues:
# On WireGuard server - Option 1: Automatic clamping to PMTU
iptables -t mangle -A FORWARD -i wg0 -p tcp \
--tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
# Option 2: Set explicit MSS (WireGuard MTU - 40 bytes for TCP/IP headers)
# For standard IPv4 WireGuard MTU 1420: MSS = 1420 - 40 = 1380
iptables -t mangle -A FORWARD -i wg0 -p tcp \
--tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1380
Common Scenarios
Scenario 1: PPPoE Connection
Problem: User on DSL/Fiber with PPPoE cannot load large pages Cause: PPPoE adds 8-byte overhead, reducing path MTU to 1492
Solution:
- Set WireGuard MTU to 1412 (1492 - 80)
- Or use MSS clamping to 1372 (1412 - 40)
Scenario 2: Mobile User
Problem: Laptop user reports intermittent failures on mobile hotspot Cause: Mobile carriers often have variable/reduced MTU
Solution:
- Set WireGuard MTU to 1280 (minimum IPv6 MTU, always works)
- Or use 1400 as reasonable compromise
Scenario 3: Double NAT / CGNAT
Problem: User behind carrier-grade NAT has connectivity issues Cause: Additional encapsulation in carrier network
Solution:
- Reduce MTU to 1380 or lower
- Test empirically with ping method above
Scenario 4: Corporate Firewall
Problem: User behind corporate proxy/firewall drops large packets (Cause: Firewall may filter or fragment oversized UDP).
Solution:
- Test MTU from inside corporate network
- May need MTU as low as 1280
- Consider if firewall blocks UDP entirely (use TCP fallback if available)
Troubleshooting Commands
Check Current MTU
# Linux
ip link show wg0 | grep mtu
# macOS
ifconfig utun3 | grep mtu # utun number varies
# Windows (PowerShell)
Get-NetIPInterface | Where-Object {$_.InterfaceAlias -like "*WireGuard*"}
Check Path MTU
# Linux - trace with MTU discovery
tracepath <destination>
# Check for ICMP fragmentation needed messages
tcpdump -i eth0 'icmp[0] == 3 and icmp[1] == 4'
Verify MSS Clamping
# Capture TCP SYN to see MSS option
tcpdump -i wg0 'tcp[tcpflags] & tcp-syn != 0' -v
Best Practices
- Start conservative: Use 1400 or lower initially, optimize later
- Test from affected client: MTU issues are path-specific
- Document per-location settings: Different offices may need different MTU
- Consider MSS clamping: Often easier than changing client configs
- Monitor for regressions: ISP changes can alter path MTU
Quick Fix Cheat Sheet
| Symptom | Quick Fix | Permanent Fix |
|---|---|---|
| Large transfers stall | Lower MTU to 1280 | Find optimal MTU with ping test |
| Random disconnects | Lower MTU to 1400 | Test path MTU, set precisely |
| Works on some networks | Set MTU to 1280 | Create per-network profiles |
| VoIP/video issues | Check MTU + QoS | Ensure MTU consistent both ends |
Core takeaway:
Most WireGuard “connectivity but no large traffic” problems are MTU-related. Use the decision tree first, then discover the real path MTU with ping tests, set a safe value (often 1400 or lower), or apply server-side MSS clamping as a simpler fix.

