linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Уроки
  • How it works
  • Симулятор
  • База знаний
  • Собеседование
Index
Categories
All entries
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
home/linux/kb/Протоколы/quic-http3

kb/protocols ── Протоколы ── advanced

QUIC и HTTP/3 - современный транспорт поверх UDP

QUIC - транспорт поверх UDP. TLS 1.3 встроен (1 RTT, 0-RTT для resume). Multiplexing без head-of-line blocking. Connection migration (Wi-Fi → 4G без drop). HTTP/3 = HTTP-семантика поверх QUIC.

view as markdownaka: quic, http3, h3, quic-protocol

Зачем QUIC

HTTP/2 решил большую часть проблем HTTP/1.1 (мультиплексирование, бинарность, header compression). Но HTTP/2 поверх TCP имеет фундаментальный изъян: head-of-line blocking на уровне транспорта.

Если в TCP-stream'е потерян один пакет, весь поток ждёт ретрансмита. HTTP/2 умеет parallel-streams в приложении, но всё это идёт через один TCP-сокет, и потерянный пакет блокирует все streams сразу.

В мобильных сетях это особенно болезненно: высокий jitter, частые потери. И HTTP/2 на мобиле часто медленнее HTTP/1.1.

QUIC решает это, двигая транспорт в user-space над UDP:

  • Мультиплексирование на уровне самого транспорта
  • TLS 1.3 встроен (нет отдельного handshake'а)
  • Connection ID вместо 4-tuple (соединение переживает смену IP)
  • 0-RTT resume

Чем QUIC отличается от TCP

ПризнакTCP+TLSQUIC
Транспортв kerneluser-space (поверх UDP)
TLSотдельный layer (RFC 5246)встроен (TLS 1.3 message в QUIC frame)
Handshake до encrypted-данных2-3 RTT1 RTT (или 0-RTT для известных)
Stream multiplexingнет (один поток)да, независимые streams
HOL-blockingда (на уровне TCP)нет (между streams)
Connection ID4-tuple (src/dst IP:port)random ID, переживает смену IP
Где крутитсяOS (sendfile-friendly)user-space (CPU нагрузка выше)

Handshake QUIC vs TCP+TLS

TCP+TLS 1.3:

client                 server
  │ ── SYN ────────────►│
  │ ◄── SYN/ACK ────────│        <- 1 RTT TCP
  │ ── ACK + ClientHello ─►│
  │ ◄── ServerHello + Cert │      <- 2 RTT для encrypted
  │ ── Finished + HTTP req ►│
                                  Total: ~2 RTT до данных

QUIC:

client                 server
  │ ── Initial(ClientHello) UDP ──►│
  │ ◄── Initial(ServerHello+Cert) ─│   <- 1 RTT
  │ ── Handshake done + HTTP req ─►│
                                     Total: ~1 RTT

С 0-RTT (resume известного сервера), данные можно слать сразу с первым пакетом. Резко меньше задержка для repeat-visit'ов.

0-RTT, и его опасности

При повторном connect'е клиент использует session-ticket с прошлой сессии и шлёт early data ещё до подтверждения handshake'а.

Замечательно для performance, но:

  • Replay-attack: атакующий может перехватить early-data и переслать. Если запрос меняет state (POST), реплей опасен.
  • Server-side нужно ограничить: only idempotent-методы (GET, HEAD), либо полный replay-protection через nonce.

В nginx:

nginx
ssl_early_data on;
# И блокировать non-idempotent методы:
if ($request_method !~ ^(GET|HEAD)$) {
    return 405;
}

Stream multiplexing

В QUIC есть streams, независимые двунаправленные потоки внутри одного connection'а. Каждый stream имеет свой ID, свои retransmit'ы, свой flow control.

QUIC Connection
     ├── Stream 0 (control)
     ├── Stream 4 (HTTP request 1), потерял пакет, ретрансмитит
     ├── Stream 8 (HTTP request 2), продолжает работать
     └── Stream 12 (HTTP request 3), продолжает работать

В TCP всё это было бы заблокировано на одном пакете. В QUIC только Stream 4.

Connection migration

Connection identifier, random byte-string в QUIC header'е, не привязанный к IP. Клиент сменил Wi-Fi на 4G:

  • source IP меняется
  • source UDP port меняется
  • Connection ID остаётся тот же

Сервер видит новый IP с тем же CID → молча обновляет 4-tuple, соединение продолжается. TCP бы порвался и пришлось бы переустанавливать.

Полезно для:

  • Mobile-приложений (метро/улица)
  • Long-running uploads
  • WebRTC over QUIC

QPACK, header compression без HOL

HTTP/2 использует HPACK, компрессия с общим dictionary. Проблема: оба endpoint'а должны знать состояние dictionary, иначе декодирование сломается. На потерянных пакетах в HTTP/2-over-TCP это работало (TCP гарантирует order). В QUIC не работает (streams независимы).

QPACK, переработка HPACK: dictionary в отдельном stream'е, с координацией updates. Сложнее, но позволяет header-compression без HOL.

HTTP/3, это HTTP-семантика над QUIC

HTTP/3, это «как HTTP/2 запросы и ответы упакованы в QUIC streams». Семантика та же:

  • Methods (GET/POST/...), URL, headers, body
  • Status codes (200/404/...)

Отличия от HTTP/2:

  • QPACK вместо HPACK (header compression)
  • Server Push не поддерживается (snimали с roadmap)
  • Каждый HTTP request в своём QUIC stream

Для приложения разница минимальна, те же curl https://..., тот же fetch() в браузере. Транспорт делает за вас.

ALPN-discovery, как клиент узнаёт что сервер умеет h3

Браузер сначала идёт по HTTPS/TCP, при handshake получает заголовок Alt-Svc:

Alt-Svc: h3=":443"; ma=86400

Это говорит «попробуй h3 на UDP/443 в следующий раз». Браузер кэширует и при следующем запросе сразу использует QUIC.

Альтернатива, HTTPS DNS RR (RFC 9460): сервер декларирует поддержку h3 в DNS:

example.com. 300 IN HTTPS 1 . alpn="h3,h2"

Поддержка в стеке

СофтВерсия с h3Note
nginx1.25+полная поддержка
Caddy2.6+default-on
Apachemod_http3 (експ.)в работе
HAProxy2.6+через quictls
curl7.66+ с --http3требует quiche/msh3 backend
wget22.0+да
Cloudflare/Fastly/Cloud LBда, defaultпрозрачно
Chrome / Firefox / Safariда, по умолчаниюfeature-detection

Включить HTTP/3 в nginx

nginx
server {
    listen 443 ssl;                          # TCP/TLS
    listen 443 quic reuseport;               # UDP/QUIC
    ssl_protocols TLSv1.3;                   # QUIC требует TLS 1.3
    ssl_certificate     /etc/ssl/fullchain.pem;
    ssl_certificate_key /etc/ssl/privkey.pem;
    add_header Alt-Svc 'h3=":443"; ma=86400';
    ssl_early_data on;                       # 0-RTT
    # ... остальное идентично TCP
}

Не забыть открыть UDP/443 в firewall'е!

bash
ufw allow 443/udp
iptables -A INPUT -p udp --dport 443 -j ACCEPT

Производительность

Реальные цифры (зависят от RTT и потерь):

  • Low RTT, low loss (датацентр): QUIC чуть медленнее TCP (CPU overhead user-space)
  • High RTT, low loss (CDN, edge): QUIC выигрывает за счёт меньшего handshake'а
  • High RTT, high loss (мобильная сеть): QUIC выигрывает значительно, нет HOL blocking

Cloudflare замеряли: QUIC в среднем на 5-15% быстрее на page-load для мобильных, до 30% на плохих сетях. Для cable/fiber, статпогрешность.

CPU: QUIC потребляет на 30-50% больше CPU чем TCP, потому что user-space (нет kernel sendfile, нет TSO/GSO до недавнего offload). В 2026 многие NIC и kernel-version'ы получают QUIC offload (UDP-segmentation offload + TLS-offload), разрыв сокращается.

Запрет middlebox-вмешательства

TCP открыт для middlebox-инспекции (заголовки в plaintext, sequence numbers видно). QUIC зашифровано почти полностью: только connection-ID и часть header'а в открытом виде. Middlebox не может:

  • Modify packets (broken)
  • Track state (только видит UDP-flow)
  • DPI на содержимое

С точки зрения op-team:

  • Firewall должен пропускать UDP/443 (часто блокировано «по привычке» enterprise-проксями)
  • NAT-таблицы должны правильно ageing UDP-flow (default 30s мало для QUIC, лучше 5+ min)
  • DPI/IDS теряет visibility, security ratio shifted

Когда что-то пошло не так

  • Браузер не использует h3, нет Alt-Svc header'а или DNS HTTPS RR. Curl: curl --http3 -v https://example.com.
  • quictls не собирается, nginx требует BoringSSL/quictls (форки OpenSSL с QUIC API). Стандартный OpenSSL до 3.5 не поддерживает.
  • UDP/443 не работает, firewall (90% случаев), либо load balancer не пропускает UDP. AWS ALB не поддерживает h3, нужен NLB.
  • 0-RTT replay-атака, смотри предупреждения выше. Никогда не разрешай non-idempotent через 0-RTT.
  • CPU нагрузка на QUIC-сервере высокая, включить kernel UDP-GSO, TLS-offload где доступно.
  • Connection migration не работает, некоторые middlebox'ы дропают пакеты с непривычным CID. Чаще всего работает прозрачно.
  • Старые клиенты не могут подключиться, QUIC v1 ≠ draft-29. nginx 1.25+ только v1, старые curl-builds, draft-29.

Когда выбирать QUIC

  • Mobile-heavy traffic, реальный win
  • High-RTT клиенты (другие континенты), handshake выигрывает
  • Many small requests, мультиплексирование без HOL

Когда не выбирать или подождать:

  • Внутренний RPC в датацентре, TCP+TLS proven, QUIC-overhead не оправдан
  • Long-running streams (file upload, video), TCP неплохо справляется
  • Если стек/firewall/observability не готовы, добавит сложности

§ команды

bash
curl --http3 -v https://cloudflare-quic.com

Принудительно через HTTP/3 - проверка что клиент и сервер договорились

bash
curl -I https://example.com | grep -i alt-svc

Получить Alt-Svc header - анонсирует ли сервер h3 поверх h2/h1

bash
tcpdump -ni any 'udp port 443' -w quic.pcap

Захватить QUIC-трафик для анализа в Wireshark - decrypt только с keys

bash
ufw allow 443/udp

Открыть UDP/443 для QUIC в firewall - частая забывка после конфига nginx

bash
openssl s_client -connect example.com:443 -alpn h3

Проверить ALPN-negotiation для h3 на TCP - не настоящий QUIC, но проверка cert и ALPN

bash
dig +short HTTPS example.com

DNS HTTPS RR - современный способ декларации поддержки h3 в DNS

bash
nginx -t && nginx -s reload

После добавления listen quic - проверить конфиг и перезагрузить без даунтайма

§ см. также

  • http-protocolHTTP/1.1, HTTP/2, HTTP/3HTTP/1.1 - текстовый протокол с keep-alive. HTTP/2 - бинарный с мультиплексированием в одном TCP-соединении. HTTP/3 = HTTP/2-семантика поверх QUIC/UDP без TCP-head-of-line blocking.
  • http2-internalsHTTP/2 internals - binary framing, HPACK, stream multiplexingHTTP/2 - бинарный мультиплексинг поверх одного TCP-соединения. HPACK сжимает headers через индексированный словарь. Streams независимы. Server push deprecated. На loss-friendly link HoL-blocking - проблема, которую решил QUIC.
  • udp-basicsUDP - User Datagram ProtocolUDP - простой протокол доставки датаграмм без установки соединения, без ретрансмитов, без гарантии порядка. Заголовок 8 байт. Применение: DNS, DHCP, QUIC, VoIP, любой случай когда задержка важнее надёжности.
  • tls-handshakeTLS handshakeTLS - слой шифрования поверх TCP. Перед передачей данных стороны делают handshake: обмениваются ключами, проверяют сертификат, выбирают cipher.
  • tls-certificatesTLS-сертификаты - X.509, цепочка доверия, Let's EncryptTLS cert - X.509 объект с public key + identity (CN/SAN) + подписью CA. Цепочка: leaf → intermediate → root (доверенный OS). Let's Encrypt = бесплатный CA через ACME (HTTP-01/DNS-01 challenge). В k8s - cert-manager.
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки