← К библиотеке
Каскады Теория

Транспорт каскада: MTU, sockopt, почему рвётся

Самая мучительная поломка каскада — когда он вроде работает, но криво: Google открывается, а Cloudflare нет; сайт грузится, а файл не качается. Это не рандом, это физика транспорта — MTU, вложенные обёртки, привязка исходящего IP. Разберу, почему каждый из этих симптомов возникает и по какому признаку его опознать. Без конфигов, чистая механика.

Почему каскад ломается «наполовину»

Прямая нода либо работает, либо нет. Каскад умеет ломаться частично, и именно это сбивает с толку. Причина в том, что каждый хоп — это ещё одна обёртка вокруг пакета, а обёртки не бесплатны: они съедают место, накапливают задержку и умножают шанс, что где-то по пути что-то не влезет или зависнет. Три классических симптома — MTU-схлопывание, вложенный vision и капризный sendThrough — дают разную картину, и по картине можно поставить диагноз, не гадая.

MTU: почему одни сайты идут, а другие нет

MTU — это максимальный размер пакета, который влезает в канал без фрагментации. Каждая обёртка каскада (Reality, транспорт, ещё один хоп) добавляет свои байты заголовков, и полезное место в пакете сжимается. Даже на двух хопах пакет ужимается ощутимо.

Теперь ключевое наблюдение, которое и есть диагноз. Разные сайты ведут себя по-разному не случайно, а по размеру своего TLS-рукопожатия:

  • Google, YouTube, Telegram — короткие цепочки сертификатов, мелкий хендшейк. Он влезает в ужатый пакет и идёт.
  • Cloudflare, Instagram, GitHub — длинные цепочки сертификатов, крупный хендшейк. Он не влезает — и соединение рвётся ещё на рукопожатии.

Если у клиента «Google работает, Cloudflare нет», и раскол идёт по сайтам, а не рандомно — это почти наверняка MTU. Не транспорт, не блокировка, не ключи. Просто крупные пакеты не пролезают через ужатый каскадом канал.

Есть и вторая, более коварная разновидность — PMTU «чёрная дыра». Это когда мелкие пакеты проходят, а крупные молча дропаются где-то на маршруте (провайдер не шлёт положенное «пакет великоват»). Тогда сайт открывается (мелкие запросы прошли), а закачка виснет (крупные пакеты в никуда). Симптом «открывается, но не качается» — это оно.

Лечится MTU одним классом приёмов — уменьшить максимальный сегмент так, чтобы пакет с запасом влезал в самый узкий участок пути. На уровне транспорта это sockopt с ограничением сегмента (обычно в район 1280–1360 байт), на уровне ядра — MSS-кламп на нодах. Суть одна: заранее ужимаешь пакет сам, чтобы он не упёрся в потолок канала посреди дороги. После этого «непослушные» сайты с крупным хендшейком оживают.

Вложенный vision: почему тройной каскад капризен

Второй источник разрывов — специфика самого XTLS Vision, флоу, который Reality-нода часто применяет автоматически. Vision оптимизирует передачу, «сплайся» потоки, и это отлично работает на одном слое. Но если завернуть vision внутрь vision внутрь vision — три хопа подряд, каждый со своим vision, — обёртки начинают конфликтовать.

Механика поломки: рукопожатие и мелкие ответы проходят, а любая крупная закачка встаёт через пару сотен байт — это дедлок сплайсинга, когда два слоя vision не могут договориться, кто кого читает. Внешне неотличимо от MTU-проблемы («открывается, не качается»), но лечится иначе.

Отсюда практическое правило многохоповых каскадов: vision держи только на одном хопе, остальные переводи на другой транспорт (gRPC), где vision не навязывается и не вкладывается сам в себя. Два слоя vision (вход + выход в двух-хопе) — ещё терпимо и проверено работает. Три — уже нет, HTTPS с крупным хендшейком не пролезает. Если строишь тройной каскад и он «сайт открывает, файл не качает» после того, как MTU уже поправлен, — почти наверняка виноват вложенный vision, а не размер пакета.

sendThrough: стабильность против белизны

Третий симптом тоньше и относится к схемам, где исходящий трафик привязывают к конкретному IP (тот самый приём «белый вход наружу не ходит» из тройного каскада). Привязка egress ко второму адресу через sendThrough — красивая идея, но у неё есть цена.

Наблюдение из практики: маршрут со второго IP до заграничной ноды бывает нестабилен сам по себе, даже когда обычный TCP-connect с него проходит. В результате — флаки: половина соединений встаёт, половина идёт, без явной закономерности. TCP вроде коннектится, а трафик течёт рывками.

Тут возникает честная развилка, и её надо понимать заранее:

  • Приоритет — белизна выходного IP. Держишь sendThrough на втором адресе, миришься с возможной флакой маршрута.
  • Приоритет — стабильность. Снимаешь привязку, egress идёт с входного IP — соединение становится ровным (наблюдалось 16 из 16 против ~50% с привязкой). Плата: вход всё-таки коннектится наружу.

Важно, что даже без sendThrough исходящее с входа обёрнуто в Reality и снаружи выглядит как обычный TLS — то есть жертвуешь ты не маскировкой, а конкретно тем свойством «белый IP абсолютно немой». Иногда стабильность важнее, и это нормальный инженерный компромисс, а не поражение.

Как ставить диагноз

Собери всё вместе — и получится дерево решений, которое экономит часы:

  • Раскол по сайтам (Google да, Cloudflare нет), «открывается — не качается» → сначала MTU (ужать сегмент).
  • MTU поправлен, а закачка всё равно встаёт через пару сотен байт на многохопе → вложенный vision (оставить vision на одном хопе, остальные на gRPC).
  • Флаки без привязки к сайтам, ~50% соединений встаёт в схеме с привязкой egress → sendThrough (взвесить белизну против стабильности).

Общий принцип: разрыв в каскаде почти никогда не случаен. Случайность в сети выглядит как случайность; а «эти сайты да, те нет» или «встаёт ровно на закачке» — это подписи конкретных физических причин. Научился читать подписи — перестал гадать.

Как эти приёмы выглядят в конфигах (sockopt, MSS-кламп, grpc на relay-хопах, sendThrough) — в практике «Тройной каскад: вход → релей → выход» и «Каскад из двух нод + WARP на выходе».

Следующий гайд Гео-разделение трафика: зачем маршрутизация → Не понравилась статья или что-то непонятно? Напишите мне — помогу или поправлю. @notrealvpn →
Материал носит образовательный характер и посвящён инженерии сетевой инфраструктуры. Вы отвечаете за соблюдение законов своей юрисдикции.