Ко всем статьям

QUIC-миграция: чему мы научились за полгода в проде

Инженерная команда· Опубликовано 28.01.2026· 9 мин

Сюрпризы с MTU, неожиданно высокий CPU на серверной стороне и как перестали бояться handshake'а 0-RTT.

Зачем вообще мигрировали

Наш initial набор транспортов был TLS + WebSocket. Этого хватает, пока сеть «дружелюбная». Но как только начинается тротлинг long-lived TCP connection'ов, у обоих транспортов начинаются одинаковые проблемы — латентность растёт, RTT прыгает.

QUIC даёт три вещи, которые нам важны:

  1. 0-RTT handshake — переподключение после разрыва занимает миллисекунды, а не секунды.
  2. Multipath-ready (Apple/Google уже делают реальные мульти-путь эксперименты).
  3. Меньше feature-print в DPI — он все ещё развивающийся, сигнатуры не так отточены.

Первая неожиданность — MTU

В первый же день мы увидели, что на мобильных сетях (особенно LTE) QUIC иногда фрагментируется. DPI некоторых операторов дропает фрагменты UDP — handshake обрывается. Решили принудительным PMTUd + запасным frame-size 1200 bytes.

Вторая — CPU

QUIC требует в разы больше AEAD операций чем TLS (каждый packet отдельно шифруется). На серверах мы увидели +40% CPU по сравнению с TLS-connections. Спасло:

  • Batched packet processing (libquic позволяет).
  • Хардовая поддержка AES-NI на всех наших x86-нодах.
  • Для мобильных клиентов на старых ARM — fallback на TLS.

Третья — 0-RTT paranoia

Поначалу мы боялись включать 0-RTT: реплей атаки, session ticket leak. Оказалось, для VPN-use-case это не страшно — мы уже аутентифицируем пользователя через отдельный handshake после connection'а, и даже реплей 0-RTT пакета не даст атакующему ничего полезного. Включили — получили −180ms на перекoннект.

Итог

QUIC стал транспортом по умолчанию для мобильных. TLS остаётся fallback'ом для десктопа в жёстких сетях, где UDP режется на корню.

Поделиться

X / TwitterTelegram