Вложенные туннели VPN: почему внутренний застревает на больших пакетах
Каждый туннель тратит часть бюджета пакетов пути, прежде чем начнётся следующий. Сложите заголовки, и внутренняя сессия срывается на больших пакетах.
DNS разрешается, сессия SSH держится, а затем большая загрузка замирает, хотя ping до того же хоста всё ещё отвечает. Это разделение указывает на размер пакета, а не на сломанный туннель. Вложенные туннели доходят до этого при размерах, которых ни один туннель по отдельности не достиг бы. Внутренняя сессия в порядке; ей просто передают пакеты, которые больше не помещаются.
Куда на самом деле уходит MTU пути
Каждая инкапсуляция тратит байты, прежде чем следующий уровень получит свою очередь. Путь Ethernet предлагает внешнему пакету 1500 байт, а внешний туннель забирает свою долю, прежде чем что-либо внутри него можно будет адресовать. Одно угаданное значение накладных расходов будет неверным ровно на ту величину, которая важна.
Перечислите уровни по порядку: путь доступа, внешний транспорт, внешний туннель, внутренний транспорт, внутренний туннель, приложение. Считайте каждый заголовок один раз, а UDP держите отдельно от собственного заголовка и метки туннеля.
Два уровня WireGuard, посчитанные один раз
Возьмите путь доступа IPv4 с одним туннелем WireGuard внутри другого. Внешний уровень стоит 20 байт IPv4, 8 UDP и 32 для заголовка данных WireGuard плюс его метки аутентификации. Внутри него внутреннему туннелю нужны собственный 20-байтовый заголовок IPv4 и 8-байтовый заголовок UDP перед его вторыми 32 байтами накладных расходов WireGuard. Остаток вмещает заголовок IPv4, заголовок TCP и данные. Внешний путь IPv6 стоит 40 вместо 20 и оставляет 1320.
| Layer | Bytes |
|---|---|
| Path MTU | 1500 |
| Outer IPv4 header | 20 |
| Outer UDP header | 8 |
| Outer WireGuard header and tag | 32 |
| Inner transport IPv4 header | 20 |
| Inner UDP header | 8 |
| Inner WireGuard header and tag | 32 |
| Innermost IPv4 header | 20 |
| TCP header | 20 |
| Payload that fits | 1340 |
Арифметика сходится на 1340 байтах. Один уровень по тем же правилам оставляет 1400 для полезной нагрузки TCP, то есть 1500 минус 20, 8, 32, 20 и 20, а разница в 60 байт — это ровно та внутренняя инкапсуляция, которую добавляет второй туннель.
Примените 1400 к вложенному пути, и внутреннему туннелю не хватит 60 байт, незаметно, пока пакет не станет достаточно большим, чтобы они понадобились. Дополнение и собственная опция фрагментации протокола снова сдвигают цифры, поэтому доверяйте таблице.
MTU, MSS и фрагментация действуют в разных местах
MTU интерфейса ограничивает то, что интерфейс отправит, а сжатие MSS в TCP меняет то, что TCP-партнёр готов отправить. Сжатие исправляет сессии TCP и ничего не делает для большой дейтаграммы UDP, поэтому исправление выглядит успешным для одного приложения и тихо промахивается мимо следующего. Собственная опция фрагментации протокола — третий рычаг со своими отказами. MTU интерфейса — обычный первый шаг и самый грубый.
Мостовые и маршрутизируемые туннели несут разные кадры, поэтому цифры из другого развёртывания редко переносятся. Обнаружение MTU пути, описанное в RFC 8201, помогает только пока ICMP-сообщения, от которых оно зависит, пропускаются.
Найти уровень, которому не хватает
Проверьте каждый туннель отдельно, прежде чем вкладывать их, если требования допускают сравнение. Зонд фиксированного размера решает это: ping -M do -s 1472 -c 3 10.8.0.1 отправляет полный пакет IPv4 на 1500 байт внутри этого уровня. Добавьте второй уровень и повторите тот же зонд, чтобы любой сбой относился к известному изменению.
Когда передача застревает, меняйте один документированный параметр за раз и записывайте размер, на котором она срывается. Проверьте и обратный путь, потому что вложенная рекурсия маршрутов может достаточно точно имитировать проблему размера пакета, чтобы стоить целого дня. Отфильтрованный ответ ICMP может скрыть настоящий предел, поэтому зонд важнее рассуждений.
Запишите бюджет там, где его найдёт следующий человек
Таблица с одной строкой на уровень переживает правило большого пальца. Держите её рядом со схемой туннеля, чтобы никто не пересчитывал арифметику под давлением.
Больше туннелей — больше зависимостей, поэтому план отката заслуживает места рядом с бюджетом. Если цифры всё ещё не сходятся, измерьте путь вместо очередного угадывания. Цель — число, которое вы можете защитить, а не запомнить.