Мифы о MTU в VPN: почему ваши пакеты уменьшаются и куда девается место
Инкапсуляция и PPPoE съедают место в пакете, но пониженный MTU — не диагноз. Разделите внутренние и внешние размеры, прежде чем менять число.
Кто-то говорит вам, что VPN "теряет пакеты из-за MTU", вы ставите туннель на 1400, и передача снова работает. Такой результат кажется диагнозом. Обычно это арифметическое совпадение: вы выбрали число, достаточно малое, чтобы уместиться под пределом, который так и не определили, и снова столкнётесь с тем же пределом в следующей сети с другим бюджетом.
Большую часть этого создают два мифа. Первый — что MTU интерфейса туннеля это MTU пути. Второй — что инкапсуляция стоит "одного заголовка", а PPPoE не стоит ничего, что имело бы смысл считать. Оба неверны так, что выбранное число кажется произвольным, хотя на самом деле оно определено.
Миф первый: MTU туннеля это MTU пути
Значение, которое вы задаёте на интерфейсе туннеля, — это локальное обещание о самом большом внутреннем пакете, который реализация передаст вниз. Реальная ёмкость пути — свойство каждого звена между вами и дальним концом, и она может меняться, когда меняется маршрут, когда мобильное соединение передаётся другой сети или когда трафик идёт через другой пиринг. Заданные 1500 говорят, что построит ваш хост, а не что понесёт сеть.
Обнаружение MTU пути существует, чтобы согласовать эти две вещи, и зависит от обратной связи. В IPv4 маршрутизатор, который не может переслать пакет полного размера, должен отправить сообщение ICMP "fragmentation needed", и отправитель снижает свою оценку. В IPv6 эквивалент — сообщение Packet Too Big, и маршрутизаторы вообще не фрагментируют в транзите. Когда эта обратная связь фильтруется, отправитель продолжает создавать пакеты, которые путь не может нести, и ничто не говорит ему почему.
Миф второй: инкапсуляция стоит одного заголовка
Посчитайте внешние слои честно. Внешний заголовок IP — 20 байт в IPv4 или 40 в IPv6. Инкапсуляция UDP для прохода через NAT добавляет 8. Протокол туннеля добавляет свой заголовок, вектор инициализации или nonce, заполнение до границы блока или выравнивания шифра, концевой сегмент и значение проверки целостности. В зависимости от протокола и шифра сумма спокойно составляет десятки байт ещё до начала внутреннего пакета.
Затем снова вычтите заголовки самого внутреннего пакета. Сегмент TCP внутри туннеля несёт свой 20-байтовый заголовок IP и 20-байтовый заголовок TCP, а MSS в TCP выводится из MTU, а не из номинальной полезной нагрузки туннеля. Поэтому ping с меньшей нагрузкой может пройти, пока передача файла стоит: инструменты проверяют разные вещи, и только один из них задействует сегмент TCP полного размера.
ip link show tun0
ping -M do -s 1472 192.0.2.10
ping -M do -s 1400 192.0.2.10
Первая команда показывает заданный MTU туннеля. Две проверки отправляют нагрузку 1472 байта, что с 28 байтами заголовков IPv4 и ICMP составляет пакет 1500 байт, а затем меньшую. Если большая проверка полностью терпит неудачу, а малая проходит, у вас неполадка, зависящая от размера, а не общая проблема маршрутизации.
Миф третий: PPPoE всё ещё даёт вам чистые 1500
Обычное звено доступа PPPoE не несёт пакет IP размером 1500 байт. Заголовок PPPoE вместе с полем протокола PPP занимают 8 байт внутри кадра Ethernet, что оставляет 1492 для пакета IP. Это традиционный предел, описанный в RFC 2516. Если вы гоняете VPN через такое звено, накладные расходы туннеля берутся из этих 1492, а не из 1500.
RFC 4638 определяет способ согласовать большую полезную нагрузку PPP, когда её поддерживают и концентратор доступа, и оборудование клиента, поэтому одна фраза "это соединение использует PPPoE" не доказывает конкретное число. Локальная настройка не может заставить промежуточное устройство принять пакет, для которого оно никогда не настраивалось, поэтому полезный вопрос — что звено действительно согласовало, а не что говорит ярлык.
Почему сбой выглядит избирательным
То, что мелкие запросы проходят, а крупные передачи встают, — классическая примета чёрной дыры MTU пути. Рукопожатие, запрос DNS и вызов API помещаются; массовая передача порождает сегменты полного размера, которые умирают на одном звене, а сообщение ICMP, которое должно было сообщить о проблеме, так и не приходит. Соединение выглядит исправным, а загрузка висит, и люди начинают смотреть на сервер вместо пути.
Вторая, связанная ошибка — путать три числа: MTU интерфейса, MSS в TCP и собственную настройку фрагментации или заполнения протокола. Сжатие MSS на маршрутизаторе переписывает объявленный MSS, чтобы отправитель строил меньшие сегменты; оно не меняет MTU туннеля и не помогает трафику UDP. Дать всем трём одно и то же число, потому что они выглядят связанными, — это способ, которым добросовестное изменение ломает работающую конфигурацию.
Что менять и в каком порядке
Начните с доказательств. Подтвердите проверками выше, что неполадка зависит от размера, и затем найдите наименьший размер, который проходит, и наибольший, который не проходит. Проверьте реальный MTU звена доступа, прежде чем винить туннель; звено PPPoE ограничивает бюджет ещё до того, как VPN его коснётся. Запишите исходные значения, чтобы изменение можно было откатить.
Затем примените наименьшую правку, которую документирует клиент. Многие клиенты предлагают MTU туннеля и опцию исправления MSS, и опция MSS часто является лучшим рычагом для TCP, потому что достигает отправителя, не уменьшая каждый пакет. Повторите проверку того же назначения и той же передачи и запишите числа, на которых остановились. Значение туннеля, работающее в одной сети доступа, не является универсальной константой, и у следующей площадки будет свой бюджет.