MAATRIX / Блог / MTU и фрагментация: откуда берутся «загадочные» обрывы

MTU и фрагментация: откуда берутся «загадочные» обрывы

MAATRIX

Ping отвечает мгновенно, DNS резолвится, страница вроде бы начинает грузиться — а потом зависает на середине, SSH-сессия открывается и намертво замирает на выводе длинной команды, а копирование файла останавливается на одном и том же месте. В логах при этом пусто: ни ошибки, ни таймаута, ни разрыва соединения. Почти всегда за этим стоит не «плохая сеть» и не баг в приложении, а конфликт размеров пакетов на разных участках маршрута — MTU и то, что происходит, когда пакет в этот размер не помещается. Разбираемся, откуда берётся это ограничение и почему оно так незаметно и так неприятно ломает именно крупные передачи.

Что такое MTU и почему 1500 — не случайное число

MTU (Maximum Transmission Unit) — это максимальный размер пакета, который может пройти через конкретный сетевой интерфейс за один раз, без разбивки на части. Это не глобальная константа интернета, а параметр каждого отдельного линка — у вашего домашнего роутера может быть один MTU, у провайдера на входе в его сеть — другой, у сервера в дата-центре — третий, и пакет по пути проходит через все эти границы подряд.

Значение 1500 байт для Ethernet — историческое: оно зафиксировано ещё в спецификации Ethernet II и с тех пор осталось умолчанием почти везде, потому что менять его массово на всех устройствах сети практически невозможно — MTU должен не превышать самое узкое место на всём пути одновременно, иначе где-то в середине маршрута пакет всё равно упрётся в более тесный канал. Отсюда и живучесть числа 1500 — разумный компромисс между накладными расходами на заголовки и вероятностью фрагментации.

Но 1500 — это далеко не единственное встречающееся значение:

  • PPPoE-подключение (частая схема у домашних провайдеров, где нужен логин и пароль) добавляет собственный заголовок в 8 байт, поэтому реальный MTU канала — обычно 1492, а не 1500.
  • Jumbo-кадры в локальных сетях дата-центров и у части облачных провайдеров поднимают MTU до 9000 байт — это снижает накладные расходы на заголовки при передаче больших объёмов данных внутри одного сегмента, но требует, чтобы jumbo-кадры поддерживало вообще всё оборудование на пути, иначе пакеты крупнее 1500 начнут падать уже на границе сегмента.
  • VLAN-тегирование (802.1Q) добавляет 4 байта к заголовку Ethernet-кадра — на коммутаторах с жёстко прибитым MTU 1500 это иногда съедает те самые 4 байта у полезной нагрузки.
  • Wi-Fi, мобильные сети, спутниковые каналы нередко имеют собственный эффективный MTU меньше 1500 из-за особенностей радиоинтерфейса и дополнительной служебной инкапсуляции у оператора.

Важный нюанс: единого MTU в системе нет. У каждого интерфейса — физического (Ethernet, Wi-Fi) и виртуального (VPN-туннель, Docker-мост, VLAN-подынтерфейс) — своё значение, и трафик от приложения до адресата обычно проходит через несколько таких интерфейсов с разными лимитами подряд.

Что происходит при превышении MTU: фрагментация в IPv4 и IPv6

Когда пакет крупнее MTU канала, у сети есть ровно два варианта поведения, и они принципиально разные в IPv4 и IPv6.

В IPv4 пакет можно фрагментировать — разбить на несколько частей с одинаковым идентификатором и указанием смещения (fragment offset), которые получатель потом соберёт обратно в правильном порядке. Фрагментировать пакет может любой маршрутизатор на пути, если у пакета не выставлен флаг DF (Don't Fragment). Проблема в том, что фрагментация дорого стоит: она грузит CPU маршрутизаторов, а при потере хотя бы одного фрагмента приходится пересылать весь пакет заново, а не только потерянный кусок. Поэтому современные стеки TCP/IP массово выставляют DF-бит на TCP-трафике и вместо фрагментации полагаются на Path MTU Discovery (PMTUD, разобран в следующем разделе).

В IPv6 ситуация жёстче: промежуточные маршрутизаторы вообще не имеют права фрагментировать пакет — эта возможность убрана из протокола осознанно, ради производительности сетевого оборудования. Фрагментация в IPv6 возможна только на стороне отправителя, через отдельный расширяющий заголовок (Fragment Header), и то далеко не все реализации её включают. На практике это означает, что в IPv6-сети PMTUD — не опциональная оптимизация, а единственный рабочий механизм подбора размера пакета. Если он сломан (см. следующий раздел про чёрную дыру), в IPv6-сети крупные пакеты пропадают ещё увереннее, чем в IPv4, где хотя бы теоретически возможна фрагментация «на лету».

Отсюда и практический вывод: если у вас параллельно работают IPv4 и IPv6 до одного и того же сервера, и проблема с обрывами воспроизводится только на IPv6-адресе — это почти наверняка PMTUD с более узким запасом по накладным расходам, а не что-то более экзотическое.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

ICMP «Fragmentation Needed», DF-бит и чёрная дыра PMTUD

Path MTU Discovery работает так: отправитель посылает пакет с флагом DF, и если этот пакет не помещается в MTU какого-то канала на пути, маршрутизатор на этом участке обязан отбросить пакет и отправить обратно ICMP-сообщение — в IPv4 это «Fragmentation Needed» (тип 3, код 4, с указанием, каким должен быть следующий размер), в IPv6 — «Packet Too Big» (тип 2). Получив это сообщение, отправитель узнаёт реальный MTU узкого места и в следующий раз шлёт пакеты меньшего размера. В теории — элегантный самонастраивающийся механизм.

На практике он ломается на ровном месте: множество домашних роутеров, корпоративных фаерволов и облачных security groups по умолчанию блокируют весь ICMP как «потенциально опасный» трафик — либо целиком, либо избирательно режут именно нужные типы сообщений. В результате маршрутизатор честно отбрасывает слишком крупный пакет, честно шлёт ICMP с сигналом «уменьшите размер» — а этот сигнал до отправителя просто не доходит, потому что его срезал фаервол где-то по пути назад. Отправитель никогда не узнаёт, что пакет потерян, и продолжает слать пакеты того же «слишком большого» размера снова и снова. Это состояние и называют чёрной дырой PMTUD (PMTUD black hole): соединение технически установлено, маленькие пакеты через него ходят, а крупные пропадают в тишине без единого сообщения об ошибке — именно поэтому проблема выглядит настолько загадочно и не оставляет следов в логах приложения.

Отличить чёрную дыру PMTUD от обычной потери пакетов можно по одному признаку: потеря обычно «плавающая» и задевает пакеты вперемешку, а чёрная дыра PMTUD стабильно режет пакеты одного и того же размера — проблема воспроизводится на 100% при одинаковой нагрузке и никогда не встречается на маленьких запросах.

Почему туннели уменьшают эффективный MTU

Отдельная и очень частая причина проблем с MTU — любая инкапсуляция трафика: VPN (WireGuard, OpenVPN), GRE-туннели между офисами или дата-центрами, VXLAN в оверлейных сетях контейнерной инфраструктуры. Механизм всегда один: туннель оборачивает исходный пакет в собственный заголовок, и этот заголовок «съедает» часть доступного места, оставляя меньше байт для полезной нагрузки при том же физическом MTU канала.

Порядок величин по протоколам:

ТехнологияТипичный overheadКомментарий
WireGuard (IPv4-транспорт)60 байт20 IP + 8 UDP + 32 заголовок WireGuard
OpenVPN40–60 байтзависит от режима (UDP/TCP, шифр, сжатие)
GRE24 байта20 байт внешний IP-заголовок + 4 байта заголовок GRE
VXLAN (оверлейные сети контейнеров)около 50 байт20 IP + 8 UDP + 8 VXLAN + инкапсулированный Ethernet-заголовок

Если физический канал даёт MTU 1500, а поверх него поднят WireGuard-туннель без понижения MTU на самом туннельном интерфейсе, приложение внутри туннеля продолжает готовить пакеты по 1500 байт, поверх которых туннель добавляет ещё 60 — итоговый пакет в 1560 байт уже не помещается в исходный канал и либо фрагментируется, либо упирается в чёрную дыру PMTUD, если на пакете стоит DF. Отдельно стоит помнить про двойное туннелирование — например, VPN поверх PPPoE или VPN внутри VPN, — где overhead складывается с каждым дополнительным слоем инкапсуляции, и MTU нужно понижать соответственно ниже. Подробный разбор именно для WireGuard, с формулами и готовыми значениями под PPPoE и двойные туннели, — в статье MTU для WireGuard: как настроить правильно. Похожая логика фрагментации, но с фокусом на диагностику по симптомам и на MSS clamping, разобрана в статье VPN и MTU: проблема фрагментации и как подобрать значение. Если вы столкнулись с той же картиной в оверлейной сети Docker или Kubernetes, а не в классическом VPN, — общее устройство таких сетей и их типовые проблемы разобраны в статье Docker network: типы bridge, host, overlay.

Классический симптом: мелкое летает, крупное зависает

Проблема с MTU почти никогда не выглядит как «сеть не работает» — она выглядит как «сеть работает через раз», и это главная причина, по которой её долго ищут не там. Характерный набор симптомов:

  • ping до сервера и до интернета проходит идеально, без потерь и с нормальной задержкой — обычный ICMP-запрос весит 56–64 байта полезной нагрузки и укладывается в любой мыслимый MTU.
  • SSH подключается, показывает приглашение, но зависает на конкретной команде — сам логин и обмен ключами укладываются в мелкие пакеты, а вывод ls -la в большой директории, cat длинного файла или прокрутка less генерирует пакеты, которые упираются в реальный MTU канала.
  • Небольшие сайты и текстовые страницы открываются нормально, а крупные — зависают на середине или обрываются — HTML-разметка обычно укладывается в один-два пакета, а вот крупные изображения, шрифты или сам процесс установки TLS-соединения (сертификаты часто крупнее 1400 байт) утыкаются в проблему.
  • Копирование файлов по SCP/rsync замирает на одном и том же проценте при каждой попытке — это тоже признак упора в конкретный размер пакета, а не случайной сетевой нестабильности.
  • Проблема воспроизводится стабильно — если повторить одно и то же действие несколько раз, оно ломается каждый раз в одном и том же месте, в отличие от обычной нестабильной сети, где сбои плавают.

Если же не проходит вообще ничего, включая маленький ping, — дело не в MTU, а в более базовой проблеме: маршрутизации, NAT или firewall, который режет соединение целиком, а не по размеру пакета.

Как найти рабочий MTU и где его поправить

Не нужно гадать между условными 1400, 1420 и 1450 — точное значение канала находится обычным бинарным поиском с помощью ping, если использовать флаг, запрещающий фрагментацию (аналог DF-бита):

# Linux
ping -M do -s 1472 8.8.8.8

# macOS
ping -D -s 1472 8.8.8.8

# Windows (PowerShell/cmd)
ping -f -l 1472 8.8.8.8

Число после -s (или -l на Windows) — это размер полезной нагрузки ICMP без заголовков IP и ICMP (в сумме 28 байт для IPv4). Значение 1472 проверяет пакет размером ровно 1500 байт целиком — стандартный Ethernet MTU. Если ответ пришёл — пакет такого размера проходит; если видите Frag needed and DF set, sendto: Message too long или сообщение о необходимости фрагментации при запрещающем бите — размер нужно уменьшать. Дальше — обычный бинарный поиск: пробуете среднее между последним успешным и последним неудачным значением, пока не найдёте точную границу с шагом в один байт. К найденному числу прибавьте 28 — это и есть реальный MTU канала (для IPv6 добавляется 48 байт вместо 28, так как заголовки крупнее).

Проверять стоит на каждом интересующем вас участке отдельно: на «чистом» физическом интерфейсе без туннелей — чтобы понять базовый MTU канала до провайдера, и отдельно через сам туннель (если он есть) — пингуя адрес внутри VPN-подсети, чтобы увидеть эффективный MTU с учётом overhead инкапсуляции.

Дальше, в зависимости от того, где именно узкое место, MTU правится в разных местах:

  • Сетевой интерфейс Linuxsudo ip link set mtu 1420 dev eth0 (не сохранится после перезагрузки, для постоянного применения нужно прописать значение в netplan, NetworkManager или /etc/network/interfaces).
  • WireGuard — строка MTU = 1420 в секции [Interface] конфига wg0.conf, с перезапуском интерфейса (wg-quick down wg0 && wg-quick up wg0); установка WireGuard с нуля разобрана в статье Как установить и настроить WireGuard на VPS.
  • Windowsnetsh interface ipv4 set subinterface "Ethernet" mtu=1420 store=persistent (имя интерфейса подставьте своё, список — netsh interface ipv4 show subinterfaces).
  • macOSsudo ifconfig en0 mtu 1420.
  • Домашние роутеры — отдельное поле MTU в настройках WAN-интерфейса или конкретного VPN-подключения в веб-интерфейсе устройства.

Если правка MTU на одном конкретном устройстве кажется неудобной (много клиентов, разные сети, сложно синхронизировать значение везде), для TCP-трафика есть более системное решение — MSS clamping на сервере, который заставляет TCP-соединения сразу договариваться о безопасном размере сегмента независимо от настроек клиента. Он разобран отдельно, вместе с готовым правилом iptables, в статье про подбор значения MTU для VPN — тот же принцип применим не только к VPN, но и к любому туннелю с TCP-трафиком внутри.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Можно ли просто всегда ставить MTU поменьше, например 1400, и не разбираться?

Можно, и в большинстве случаев это снимет проблему — запас в 100 байт покрывает почти любую реальную инкапсуляцию. Плата — чуть больше служебного трафика на каждый мегабайт передаваемых данных, так как полезной нагрузки в каждом пакете меньше. Для разовой настройки дома или в небольшом проекте это разумный компромисс; для канала с заметной нагрузкой лучше найти точное значение через ping с запретом фрагментации.

Почему ping работает нормально, если проблема именно в размере пакета?

Потому что стандартный ICMP-запрос ping весит около 56–64 байт полезной нагрузки — это в разы меньше любого реалистичного MTU, поэтому он проходит даже там, где сильно урезанный канал уже не пропускает полноразмерные пакеты. Проверка через ping -M do -s <крупный_размер> намеренно посылает пакет большого размера именно для того, чтобы воспроизвести проблему, а не спрятать её.

Это проблема моего компьютера, сервера или сети между ними?

Чаще всего — какого-то промежуточного звена: провайдера, VPN-туннеля, роутера с нестандартной инкапсуляцией. Ни ваша машина, ни сервер сами по себе обычно не виноваты — оба готовы отправлять пакеты стандартного размера, а вот канал между ними где-то по пути этот размер не пропускает и не может (из-за заблокированного ICMP) сообщить об этом отправителю.

Нужно ли одинаковое значение MTU на всех устройствах в сети?

Не обязательно одинаковое, но каждое устройство должно использовать значение не больше самого узкого места на пути его трафика. Если сомневаетесь — безопаснее занизить MTU там, где настраиваете сами (сервер, VPN-туннель), чем полагаться на то, что все промежуточные узлы корректно поддержат PMTUD.

Как отличить проблему MTU от обычной перегрузки канала или потери пакетов?

Главный признак — избирательность и стабильная воспроизводимость: маленькие запросы работают всегда, крупные — не работают всегда, и это не меняется от попытки к попытке. Случайная потеря пакетов из-за перегрузки канала, наоборот, задевает пакеты любого размера и плавает от раза к разу.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →