Privacy Tools Guide

If you’ve ever experienced a VPN connection that works for some websites but fails for others, or one that drops frequently with no apparent reason, you may be dealing with Maximum Segment Size (MSS) related issues. This technical guide explains how MSS clamping works in VPN contexts and provides practical solutions for fixing packet size related connection problems.

Understanding MSS and Packet Fragmentation

When data travels over a network, it gets broken down into smaller chunks called packets. Each packet has a maximum size determined by the network’s Maximum Transmission Unit (MTU). For standard Ethernet connections, the default MTU is 1500 bytes.

The Maximum Segment Size is the largest amount of data that can be carried in a single TCP segment, excluding the TCP and IP headers. By default, MSS is set to 1460 bytes (1500 - 20 bytes IP header - 20 bytes TCP header).

The Problem: VPN Tunnel Overhead

When you connect to a VPN, your original packets get encapsulated inside new packets. This adds overhead:

This means a 1500-byte packet from your computer becomes 1544+ bytes when wrapped in a VPN tunnel, exceeding the path MTU and causing fragmentation or drops.

How MSS Clamping Works

MSS clamping solves this problem by modifying the MSS value in TCP handshake packets. When properly configured, the VPN server or firewall tells the client “don’t send packets larger than X bytes” during the connection establishment.

The Three-Way Handshake Problem

TCP MSS values are set during the three-way handshake (SYN, SYN-ACK, ACK packets). The client advertises its MSS, the server responds with its MSS, and they agree on the smaller value. For MSS clamping to work in a VPN, it must intercept and modify these SYN packets.

Implementing MSS Clamping

Option 1: Server-Side MSS Clamping with iptables

On your VPN server, you can use iptables to automatically clamp MSS:

# For OpenVPN (via TUN interface)
iptables -A FORWARD -i tun+ -o eth0 -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1400:1500 -j TCPMSS --clamp-mss-to-pmtu

# For WireGuard
iptables -A FORWARD -i wg0 -o eth0 -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1400:1500 -j TCPMSS --clamp-mss-to-pmtu

The --clamp-mss-to-pmtu option automatically calculates the correct MSS based on the path MTU discovery.

Option 2: Client-Side Clamping

If you control the client configuration, you can set MSS directly:

# Using iptables on client
iptables -A OUTPUT -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1400:1500 -j TCPMSS --clamp-mss-to-pmtu

Option 3: OpenVPN Configuration

In your OpenVPN server configuration, you can enable MSS clamping:

# Add to server.conf
mssfix 1400

This automatically clamps MSS for all TCP connections through the VPN.

Option 4: WireGuard Configuration

WireGuard doesn’t have built-in MSS clamping, but you can combine it with iptables:

# In your WireGuard post-up script
iptables -A FORWARD -i wg0 -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1400:1500 -j TCPMSS --clamp-mss-to-pmtu

Diagnosing MSS Issues

Symptom Checklist

MSS-related problems typically show these symptoms:

Diagnostic Commands

Use these commands to identify MSS issues:

# Check current interface MTU
ip link show

# Test path MTU to a specific host
tracepath -m 10 example.com

# Capture SYN packets to see actual MSS values
tcpdump -i tun0 'tcp[13] & 2 != 0' -nn

# Check for fragmentation
netstat -s | grep -i fragment

The Ping Test

Test for MTU issues by sending large ICMP packets:

# This should work (within normal MTU)
ping -s 1472 -M do example.com

# This may fail (exceeds path MTU)
ping -s 1500 -M do example.com

If small pings work but large ones fail, you have an MTU problem.

PMTUD Black Hole Problem

Path MTU Discovery (PMTUD) sometimes fails due to blocking of ICMP “packet too big” messages. This creates a “black hole” where the sender never learns about the smaller path MTU.

Solution: Enable MSS Clamping

The most reliable solution is to always clamp MSS to a safe value (typically 1400 bytes) rather than relying on PMTUD:

# Permanent iptables rule
iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

Common Configuration Values

VPN Type Recommended MSS Notes
OpenVPN (UDP) 1400 Accounts for UDP + OpenVPN overhead
OpenVPN (TCP) 1350 TCP has additional overhead
WireGuard 1420 Minimal overhead
IPsec 1350-1400 Depends on encryption
PPTP 1460 Minimal overhead

Advanced: IPv6 Considerations

If you’re running IPv6 over your VPN, you need separate rules:

# IPv6 MSS clamping
ip6tables -A FORWARD -i tun+ -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1400:1500 -j TCPMSS --clamp-mss-to-pmtu

Troubleshooting Checklist

  1. Verify MTU on all interfaces: Check both your physical interface and VPN tunnel
  2. Test with smaller MSS: Try 1400 or even 1300 to isolate the problem
  3. Check firewall logs: Look for blocked fragments or ICMP packets
  4. Verify TCP timestamps: Some networks filter these, affecting PMTUD
  5. Test without VPN: Determine if the problem is VPN-related or network-related

Advanced Diagnostic Tools and Techniques

For persistent MSS issues, use specialized debugging tools:

# Using tcpdump to capture and analyze SYN packets
tcpdump -i tun0 'tcp[13] & 2 != 0' -w syn_packets.pcap

# Analyze captured packets with tshark
tshark -r syn_packets.pcap -T fields -e tcp.options.mss -e ip.dst

# Expected output shows MSS values (e.g., 1400, 1460)
# If all packets show same small MSS, clamping is working
# If MSS varies or is too large, fragmentation will occur

This captures actual TCP handshake packets and reveals the exact MSS negotiation happening.

Wireshark Analysis for MTU Problems

Visual packet analysis with Wireshark reveals fragmentation:

# Capture traffic through VPN tunnel
wireshark -i tun0 &

# Apply display filter to find fragmented packets
# In Wireshark filter bar: ip.flags.mf == 1 or ip.flags.rf == 1

# Look for:
# - Packets larger than interface MTU
# - Fragmented packets (indicates MTU exceeded)
# - Retransmitted packets (sign of packet loss)

Wireshark’s graphical interface makes it easy to identify packet fragmentation patterns.

MTU Discovery and Configuration by VPN Type

Different VPN protocols handle MTU differently:

WireGuard: The most modern approach

OpenVPN: Flexible but requires attention

IPsec: Complex but powerful

PPTP: Legacy, avoid when possible

Persistent Configuration for Long-Term MSS Clamping

Rather than temporary iptables rules, make MSS clamping permanent:

# For Linux systems with systemd (permanent configuration)
cat > /etc/systemd/system/mss-clamp.service <<'EOF'
[Unit]
Description=MSS Clamping for VPN
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/sbin/iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
ExecStart=/usr/sbin/ip6tables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

systemctl enable mss-clamp.service
systemctl start mss-clamp.service

This configuration persists across reboots.

Understanding the TCP Window and MSS Relationship

MSS affects TCP window scaling and throughput:

TCP Segment Relationship:
├─ MTU: 1500 bytes (Ethernet frame)
├─ IP Header: 20 bytes
├─ TCP Header: 20 bytes
└─ MSS: 1460 bytes (1500 - 40)

With VPN (OpenVPN UDP):
├─ Original MSS: 1460
├─ VPN Overhead: 28 bytes (IP + UDP)
├─ OpenVPN Overhead: 26 bytes
├─ New effective MSS: ~1406 bytes
└─ Recommended clamp: 1400 bytes (safety margin)

The TCP window size determines how much unacknowledged data can be in flight. Smaller MSS values reduce maximum bandwidth but ensure reliability.

Set up proactive monitoring:

#!/bin/bash
# mss-monitor.sh - Alert on potential MSS issues

ALERT_THRESHOLD=100  # packets

check_fragmentation() {
    fragments=$(netstat -s | grep "fragments generated" | awk '{print $1}')
    if [ "$fragments" -gt "$ALERT_THRESHOLD" ]; then
        echo "WARNING: High fragmentation detected ($fragments packets)"
        # Send alert
        echo "MSS clamping may not be working correctly" | \
            mail -s "VPN MTU Alert" admin@example.com
    fi
}

check_retransmits() {
    retransmits=$(netstat -s | grep "segments retransmitted" | awk '{print $1}')
    if [ "$retransmits" -gt "$ALERT_THRESHOLD" ]; then
        echo "WARNING: High retransmission rate ($retransmits segments)"
    fi
}

# Run checks hourly via cron
check_fragmentation
check_retransmits

Add this to your monitoring infrastructure to proactively identify MSS problems.

Performance Tuning with MSS Clamping

MSS clamping impacts performance. Tune for optimal throughput:

# Baseline test without VPN
iperf3 -c 8.8.8.8 -t 60

# Test with VPN and MSS clamping
iperf3 -c 8.8.8.8 -t 60 -B [vpn-interface-ip]

# Results comparison
# Without VPN: baseline (e.g., 100 Mbps)
# With VPN + clamping: slightly reduced (e.g., 95-98 Mbps)
# If much lower (e.g., 50 Mbps), increase MSS or investigate other issues

Small MTU values reduce throughput. Find the largest MSS that avoids fragmentation.

Troubleshooting Specific Applications

Some applications are particularly sensitive to MSS issues:

Large file transfers (FTP, rsync):

Video streaming:

Voice/VoIP:

Web browsing:

Each application has different tolerance for packet loss and latency.

Built by theluckystrike — More at zovo.one