Симптом всегда один и тот же: маленькие пакеты ходят, большие пропадают. Страница открывается наполовину, SSH соединяется и виснет, VPN поднимается но не передаёт данные.
Что такое MTU
MTU — максимальный размер пакета, который интерфейс передаёт без разбиения. Для Ethernet это 1500 байт. Если пакет больше, его либо фрагментируют, либо отбрасывают с ICMP-сообщением «нужна фрагментация».
Проблема возникает, когда это ICMP-сообщение блокируется межсетевым экраном. Отправитель не узнаёт о проблеме и продолжает слать слишком большие пакеты в пустоту. Это называется «чёрная дыра PMTUD».
Шаг 1: текущий MTU интерфейсов
ip link show | grep -E "^[0-9]+:|mtu"
Компактнее:
ip -br link show
Windows:
Get-NetIPInterface | Select-Object InterfaceAlias, AddressFamily, NlMtu
Шаг 2: определить рабочий MTU до узла
Отправляем ping с запретом фрагментации и подбираем максимальный проходящий размер.
Linux:
ping -M do -s 1472 -c 2 8.8.8.8
Здесь 1472 — это полезная нагрузка. Полный размер пакета получается 1472 + 8 байт заголовка ICMP + 20 байт заголовка IP = 1500.
Если проходит — MTU не меньше 1500. Если видите Frag needed and DF set или Message too long — уменьшайте:
ping -M do -s 1464 -c 2 8.8.8.8 # MTU 1492, типично для PPPoE
ping -M do -s 1422 -c 2 8.8.8.8 # MTU 1450, типично для VPN
ping -M do -s 1372 -c 2 8.8.8.8 # MTU 1400
Windows:
ping -f -l 1472 8.8.8.8
Совет. Не подбирайте вручную по одному байту. Двоичный поиск быстрее: попробуйте 1472, при неудаче 1272, потом середину между рабочим и нерабочим значением.
Шаг 3: автоматический подбор
for size in 1472 1464 1452 1442 1422 1392 1372; do
if ping -M do -s $size -c 1 -W 2 8.8.8.8 &>/dev/null; then
echo "Проходит payload $size → MTU $((size + 28))"
break
else
echo "Не проходит payload $size"
fi
done
Шаг 4: где теряется
Трассировка с фиксированным размером пакета покажет узел, на котором начинаются потери:
sudo traceroute --mtu 8.8.8.8
Утилита tracepath делает то же и специально ищет изменения MTU по пути:
tracepath 8.8.8.8
В выводе строка pmtu 1450 означает, что на этом участке максимальный размер снижается до 1450.
Шаг 5: исправление
Временно, до перезагрузки:
sudo ip link set dev eth0 mtu 1450
Постоянно через netplan — файл /etc/netplan/01-netcfg.yaml:
network:
version: 2
ethernets:
eth0:
mtu: 1450
sudo netplan try
sudo netplan apply
Команда netplan try откатит изменения через 120 секунд, если вы не подтвердите — страховка от потери доступа к серверу.
Windows:
Set-NetIPInterface -InterfaceAlias "Ethernet" -NlMtuBytes 1450
Типичные значения MTU
| Среда | MTU |
|---|---|
| Ethernet | 1500 |
| PPPoE (DSL) | 1492 |
| WireGuard | 1420 |
| OpenVPN UDP | 1500 минус накладные, обычно 1450 |
| IPsec | 1400–1438 |
| GRE | 1476 |
| Jumbo frames (LAN) | 9000 |
Обходной путь: MSS clamping
Если вы управляете шлюзом, но не можете менять MTU на клиентах, ограничьте размер TCP-сегмента на маршрутизаторе:
sudo iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
Это заставит стороны договориться о подходящем размере сегмента при установке соединения.
Предупреждение. MSS clamping работает только для TCP. UDP-трафик — включая DNS, QUIC и большинство VPN — он не затрагивает. Для них нужно правильное значение MTU.
Проверка результата
ip -br link show
ping -M do -s $((MTU - 28)) -c 3 8.8.8.8
curl -sI https://example.com | head -1
Практическая проверка — скачать что-то крупное:
curl -o /dev/null -w "%{speed_download}\n" https://speed.cloudflare.com/__down?bytes=10000000
Итог
Признак проблемы — маленькие пакеты проходят, большие нет. Диагностика: ping -M do -s РАЗМЕР с подбором значения. Формула: MTU = payload + 28. Исправление — выставить найденное значение на интерфейсе, для TCP дополнительно помогает MSS clamping на шлюзе.