HTTP/2 и HTTP/3 (QUIC) в 2026

Рейтинг: 52.9% · 8 голосов
Самый подробный курс по Nginx - от первого конфига до production API-gateway. Архитектура и event loop, контексты и location, виртуальные хосты, статика, reverse proxy и upstream-балансировка, кэширование, HTTPS и TLS (post-quantum), HTTP/2 и HTTP/3 QUIC, безопасность и rate limiting, realip, JSON-логи и сквозная трассировка, метрики, тюнинг и траблшутинг. Плюс OpenResty (Lua, фазы, JWT, динамика) и Angie (нативные Prometheus, ACME, dynamic upstream). На основе эталонного gateway и лучших практик. Для новичков и SRE/DevOps. Актуально на 2026 (nginx 1.30/1.31, Angie, ingress-nginx EOL -> Gateway API).
Ответить
Аватара пользователя
Igor_NgINX
Сообщения: 44
Зарегистрирован: 11 май 2026, 05:31

HTTP/2 и HTTP/3 (QUIC) в 2026

Сообщение Igor_NgINX »

Оглавление курса (44)
  1. Что такое Nginx и почему он захватил веб
  2. Установка Nginx, Angie и OpenResty: пакеты, версии, Docker
  3. Первый конфиг с нуля: минимальный сервер за 5 минут
  4. Архитектура процессов: master, worker и event loop
  5. Анатомия конфигурации: контексты, наследование и модульность
  6. Виртуальные хосты: server и server_name
  7. Директива location: матчинг и приоритеты по шагам
  8. Раздача статики: root, alias, try_files, sendfile
  9. Переменные, map и блок if
  10. rewrite, return и канонизация URL
  11. Работа с заголовками: add_header и proxy_set_header
  12. Модель доверия прокси-заголовков: realip и защита от спуфинга
  13. Сжатие: gzip, brotli и zstd
  14. Reverse proxy: proxy_pass и проброс запроса
  15. upstream и балансировка нагрузки
  16. Таймауты, повторы и устойчивость прокси
  17. FastCGI и PHP: nginx + PHP-FPM (и uwsgi/scgi)
  18. WebSocket, gRPC и стриминг через Nginx
  19. Кэширование ответов: proxy_cache и микрокэш
  20. HTTPS и TLS: сертификаты, протоколы, шифры (2026)
  21. Let's Encrypt и ACME: certbot, acme.sh, нативный ACME Angie
  22. HTTP/2 и HTTP/3 (QUIC) в 2026 (вы здесь)
  23. Безопасность: заголовки, скрытие версии, ограничения
  24. Rate limiting и защита от перегрузки
  25. Контроль доступа: allow/deny, auth_basic, auth_request и mTLS
  26. Логирование: access_log, форматы и структурированный JSON
  27. Сквозная трассировка запросов и OpenTelemetry
  28. Метрики и мониторинг Nginx
  29. Производительность и тюнинг под нагрузку
  30. Траблшутинг: 502, 504, 403, 404 и debug-лог
  31. OpenResty: Nginx как платформа на LuaJIT
  32. Фазы обработки запроса и Lua-хуки
  33. Lua API: ngx.*, shared dict, cosocket и lua-resty-core
  34. Практика OpenResty: авторизация, JWT, кэш, Redis
  35. Angie: современный форк Nginx 2026
  36. Динамическая конфигурация и service discovery
  37. Nginx как API-gateway и Kubernetes Gateway API
  38. Динамические модули, njs и WAF
  39. Stream-модуль: проксирование TCP и UDP
  40. Деплой, перезагрузка и конфиг как код
  41. Сценарий: статика, SPA и кэширование за CDN
  42. Сценарий: микросервисный gateway по образцу ngx-trace-gateway
  43. Капстоун: собираем production-gateway с нуля
  44. Чек-лист безопасности, CVE 2026 и аудит конфигурации
Боль, которую мы лечим: один сайт, три протокола, ноль тормозов

Открой DevTools на любом серьезном сайте в 2026 и посмотри на колонку Protocol. Ты увидишь зоопарк: часть запросов идет по h2, часть по h3, а если клиент совсем старый или сеть кривая - по http/1.1. Это не баг, это норма. Один и тот же шлюз обязан одновременно говорить на трех протоколах, потому что ты не управляешь клиентами. У кого то корпоративный прокси режет UDP, у кого то браузер 2019 года, у кого то мобильник скачет между Wi-Fi и LTE по дороге на работу.

Старая боль HTTP/1.1 - это head-of-line blocking на уровне соединения. Браузер открывал по 6 TCP-соединений на домен, городил domain sharding, склеивал CSS в один файл - все ради того, чтобы обойти ограничение "одно соединение - один запрос за раз". HTTP/2 убрал это мультиплексированием. HTTP/3 пошел дальше и убрал head-of-line blocking уже на уровне транспорта, переехав с TCP на UDP. В этом уроке разберем механику обоих, актуальный синтаксис 2026 года (он реально менялся, и старые гайды врут), и как заставить h1, h2 и h3 мирно жить на одном порту 443.

Сразу уточню по версиям, чтобы ты не настраивал по мертвым статьям. На момент урока stable - это nginx 1.30.0 (вышла 14 апреля 2026), mainline - ветка 1.31. HTTP/3 в nginx стабилен с 1.25.0 в mainline и приехал в stable 1.30, лежит в официальных пакетах и docker-образах. Никакого "экспериментально, не для прода" - это устаревшая формулировка из 2022 года.

Изображение

nginx http2: мультиплексирование и почему http2 on - это директива, а не параметр

HTTP/2 - это бинарный протокол поверх того же TLS поверх TCP. Ключевая идея - один TCP-коннект, внутри которого живут много независимых потоков (streams). Каждый запрос и ответ режется на фреймы (HEADERS, DATA, SETTINGS), фреймы помечены номером стрима и едут вперемешку в одном соединении. Сервер собирает их обратно. Это и есть мультиплексирование: десять картинок грузятся параллельно по одному коннекту, а не по шести.

Плюс HPACK - сжатие заголовков. В HTTP/1.1 каждый запрос тащил полный набор заголовков текстом (Cookie, User-Agent, Accept на сотни байт каждый раз). HPACK держит динамическую таблицу уже виденных заголовков и шлет вместо повтора короткий индекс. На страницах с десятками запросов это экономит реально много.

Теперь про синтаксис, на котором спотыкаются все. До nginx 1.25.1 HTTP/2 включали параметром в listen:

Код: Выделить всё

# УСТАРЕЛО, так больше не пишут
listen 443 ssl http2;
Этот способ объявлен устаревшим. С версии 1.25.1 HTTP/2 включается ОТДЕЛЬНОЙ директивой http2:

Код: Выделить всё

server {
    listen 443 ssl;
    http2 on;

    server_name cyberlake.ru;
    ssl_certificate     /etc/ssl/cyberlake/fullchain.pem;
    ssl_certificate_key /etc/ssl/cyberlake/privkey.pem;
}
Почему так сделали - не косметика. Параметр в listen привязывал HTTP/2 к конкретному сокету, и в виртуальном хостинге это приводило к каше: если несколько server-блоков слушали один и тот же listen, поведение HTTP/2 размазывалось по ним непредсказуемо. Директива http2 on живет в контексте server (и может в http, чтобы включить глобально), четко привязана к виртуальному серверу и не зависит от того, сколько у тебя listen. Это и есть правильная nginx http2 настройка в 2026.

Проверка, что HTTP/2 реально поднялся:

Код: Выделить всё

curl -sI --http2 https://cyberlake.ru/ -o /dev/null -w '%{http_version}\n'
# ожидаем: 2
Server push мертв: вместо него 103 Early Hints

Если ты читал старые статьи про HTTP/2, там обязательно был server push: сервер сам пихал клиенту CSS и JS, не дожидаясь запроса. Звучало красиво, на практике провалилось. Директивы http2_push, http2_push_preload и http2_max_concurrent_pushes УДАЛЕНЫ из nginx. Браузеры тоже выпилили поддержку: Chrome убрал push еще в 106-й версии. Не ищи эти директивы и не вставляй - конфиг просто не пройдет nginx -t.

Проблема push была фундаментальной: сервер не знает, что уже лежит в кэше браузера. Он пушил файлы, которые клиент и так имел, и сжигал полосу впустую (over-pushing). Замена 2026 года - это 103 Early Hints, поддержка которых появилась в nginx (директива early_hints, в ветке 1.29 и в stable 1.30).

Механика принципиально другая и честная. Сервер думает над основным ответом (ходит в базу, рендерит), и пока думает - шлет промежуточный ответ со статусом 103 и заголовком Link с rel=preload или rel=preconnect. Это не данные, это ПОДСКАЗКА. Браузер сам решает, тянуть ему ресурс или он уже в кэше. Никакого over-push.

Код: Выделить всё

location / {
    early_hints on;
    proxy_pass http://app_backend;
    # бэкенд может вернуть промежуточный 103 с заголовком:
    # HTTP/1.1 103 Early Hints
    # Link: </css/app.css>; rel=preload; as=style
    # Link: </js/app.js>; rel=preload; as=script
}
Директива early_hints on; разрешает nginx пробрасывать клиенту 103-й ответ от апстрима. Браузер начинает грузить CSS, пока бэкенд еще считает HTML. Выигрыш во времени до первого рендера - это та самая пауза server think time, которая раньше просто пропадала.

nginx http3 и quic: транспорт поверх UDP, 0-RTT и устойчивость к смене сети

HTTP/3 - это HTTP поверх QUIC, а QUIC - это транспорт поверх UDP. Зачем уходить от TCP, который работал десятилетиями. Из за главной проблемы HTTP/2: head-of-line blocking на уровне TCP. Да, h2 мультиплексирует стримы, но все они едут в одном TCP-потоке. Потерялся один пакет - TCP останавливает ВСЕ стримы, пока не дождется ретрансмита, потому что TCP гарантирует строгий порядок байт. На плохой мобильной сети один потерянный пакет тормозит всю страницу.

QUIC решает это радикально. Стримы в QUIC независимы на уровне транспорта: потеря пакета в стриме картинки не блокирует стрим с HTML. UDP не требует порядка, а порядок и надежность QUIC реализует сам, поштучно для каждого стрима. Бонусом QUIC встроил TLS 1.3 прямо в рукопожатие - шифрование не опционально, оно часть протокола.

Две killer-фичи QUIC для реальной эксплуатации:
  • Connection migration. У QUIC-соединения есть Connection ID, не привязанный к паре IP:порт. Телефон ушел из Wi-Fi в LTE - IP сменился, но соединение живет по тому же Connection ID, без нового рукопожатия. С TCP это всегда был разрыв и пересоединение.
  • 0-RTT через ssl_early_data. При повторном подключении к уже знакомому серверу клиент может отправить первый запрос ВМЕСТЕ с рукопожатием, не ожидая полного round-trip. Латентность первого байта падает. Но осторожно - 0-RTT данные подвержены replay-атакам, поэтому пускай по 0-RTT только идемпотентные запросы (GET), не платежи.
Теперь конфиг. Тут важно понять: HTTP/3 НЕ заменяет HTTP/2, они сосуществуют. Браузер сначала коннектится по TLS/TCP (h2), сервер отвечает заголовком Alt-Svc "а еще я умею h3 на этом порту", и браузер при следующем заходе пробует UDP/QUIC. Поэтому нужны оба listen.

Код: Выделить всё

server {
    # h1 и h2 поверх TCP
    listen 443 ssl;
    # h3 поверх QUIC/UDP, reuseport обязателен для нескольких воркеров
    listen 443 quic reuseport;

    http2 on;
    http3 on;

    server_name cyberlake.ru;

    ssl_certificate     /etc/ssl/cyberlake/fullchain.pem;
    ssl_certificate_key /etc/ssl/cyberlake/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;   # QUIC требует TLS 1.3

    # разрешаем 0-RTT (по желанию, с оговоркой про replay)
    ssl_early_data on;

    location / {
        # говорим браузеру: этот же origin доступен по h3 на 443/UDP
        add_header Alt-Svc 'h3=":443"; ma=86400' always;
        proxy_pass http://app_backend;
    }
}
Разберем по строкам. listen 443 quic reuseport открывает UDP-сокет для QUIC; параметр reuseport включает SO_REUSEPORT, чтобы каждый воркер получил свой сокет и ядро равномерно раскидало QUIC-пакеты - без него многопоточность QUIC работает криво, ставь его ровно один раз на адрес. listen 443 ssl - привычный TCP-сокет для h1/h2. http3 on включает обработку HTTP/3 на quic-листенере (модуль ngx_http_v3_module). Alt-Svc с ma=86400 говорит браузеру помнить про h3 сутки. Без Alt-Svc браузер никогда не узнает, что у тебя есть HTTP/3, и так и останется на h2 - это грабля номер один.

И не забудь про firewall: HTTP/3 - это UDP/443, а его по привычке закрывают. Если порт 443/UDP не открыт, h3 молча не заработает, а h2 будет жить - ты даже не сразу заметишь.

ECH (Encrypted Client Hello) приехал в nginx 1.30. Он шифрует ClientHello, в частности SNI - имя хоста, к которому ты идешь. Раньше SNI летел открытым текстом, и провайдер видел, на какой именно сайт ты заходишь, даже при HTTPS. ECH прячет и это. Включается через OpenSSL-интеграцию и требует, чтобы публичный ECH-конфиг был опубликован в DNS (HTTPS RR). Это передовой край приватности 2026 года, но требует свежего OpenSSL и согласованного DNS - вслепую не включай.

Безопасность: держи nginx обновленным. CVE-2026-40460 - это спуфинг адреса при connection migration в HTTP/3 (атакующий может выдать себя за мигрировавшего клиента). Лечится обновлением, поэтому stable 1.30.x с патчами - не прихоть, а гигиена. Отдельно помни про CVE-2026-42945 в rewrite-модуле - не связан напрямую с h3, но это еще один довод держать сборку свежей.

Практика: проверяем, что h2 и h3 реально отвечают

Конфиг написать мало - надо доказать, что протоколы работают. Для HTTP/3 нужен curl, собранный с поддержкой HTTP/3 (флаг --http3 или --http3-only).

Код: Выделить всё

# проверяем версию протокола h3
curl -sI --http3 https://cyberlake.ru/ -o /dev/null -w 'proto=%{http_version}\n'
# ожидаем: proto=3

# смотрим, шлет ли сервер Alt-Svc (через обычный h2-запрос)
curl -sI --http2 https://cyberlake.ru/ | grep -i alt-svc
# alt-svc: h3=":443"; ma=86400

# если curl без h3 - поднимем тестовый контейнер
docker run --rm ymuski/curl-http3 curl -sI --http3 https://cyberlake.ru/
Если curl --http3 падает с "HTTP/3 not supported" - проблема в твоем curl, а не в сервере. Проверь Alt-Svc через h2: если заголовок есть, сервер настроен верно, дело в клиенте. В браузере открой DevTools, вкладка Network, добавь колонку Protocol через правый клик по шапке - увидишь h2 и h3 живьем. Учти, первый заход всегда h2 (браузер еще не видел Alt-Svc), h3 появится со второго.

Типичные грабли
  • Пишешь listen 443 ssl http2; и удивляешься предупреждению. Это устаревший синтаксис - переноси на отдельную директиву http2 on;.
  • Забыл reuseport на quic-листенере. С одним воркером проедет, но в проде с worker_processes auto QUIC будет терять соединения - ядро не знает, какому воркеру отдать пакет.
  • Нет add_header Alt-Svc - браузеры в принципе не перейдут на HTTP/3. h3 настроен, но никто им не пользуется.
  • Закрыт UDP/443 на фаерволе или у облачного провайдера в security group. h3 молча мертв, h2 работает - диагностируется только curl --http3.
  • Ищешь http2_push - его нет, удален. Нужен функционал предзагрузки - это early_hints on и 103 Early Hints.
  • Включил ssl_early_data on и пускаешь по 0-RTT POST с платежом. 0-RTT уязвим к replay - только идемпотентные методы.
  • reuseport указан в нескольких server-блоках на один адрес. Он должен быть ровно ОДИН раз на listen-адрес, иначе конфликт сокета.
Мини-лаба: подними h2 и h3 на одном порту

Повтори руками, по шагам:
  • Шаг 1. Проверь версию: nginx -v - должно быть 1.30.x или новее. Старее - HTTP/3 в stable может не быть.
  • Шаг 2. Возьми server-блок из практики выше, подставь свой сертификат (для теста сгодится самоподписанный).
  • Шаг 3. Открой UDP/443: sudo ufw allow 443/udp (плюс уже открытый 443/tcp).
  • Шаг 4. Проверь конфиг: nginx -t. Должно быть syntax is ok. Если ругается на http3 - модуль ngx_http_v3_module не собран, бери официальный пакет или docker-образ nginx.
  • Шаг 5. Перезагрузи: nginx -s reload.
  • Шаг 6. curl -sI --http2 https://localhost/ -k и убедись, что в ответе есть alt-svc.
  • Шаг 7. curl -sI --http3 https://localhost/ -k -w '%{http_version}\n' - ожидай 3. Нет h3 в curl - запусти docker-образ с curl+http3 из практики.
  • Шаг 8. Убери reuseport, поставь worker_processes 4;, перезагрузи и открой страницу несколько раз - словишь нестабильность h3. Верни reuseport - все чинится. Так ты прочувствуешь, зачем он нужен.
Контрольные вопросы
  • Почему в 2026 правильно писать http2 on; отдельной директивой, а не listen ... http2, и какую проблему виртуального хостинга это решает.
  • Что заменило удаленный server push и в чем принципиальное преимущество 103 Early Hints перед push с точки зрения кэша браузера.
  • Зачем на одном порту 443 одновременно нужны listen 443 ssl и listen 443 quic, и какую роль играет заголовок Alt-Svc.
  • За что отвечает параметр reuseport на quic-листенере и что сломается без него при нескольких воркерах.
Итог

HTTP/2 дал мультиплексирование и HPACK поверх TCP, но застрял на head-of-line blocking транспорта. HTTP/3 поверх QUIC/UDP это лечит, плюс дарит connection migration и 0-RTT. В 2026 синтаксис четкий: http2 on; и http3 on; - отдельные директивы, два listen на 443 (ssl для TCP, quic reuseport для UDP), add_header Alt-Svc для апгрейда. Server push мертв, его место заняли 103 Early Hints. HTTP/3 - это production, а не эксперимент. Держи nginx обновленным (CVE-2026-40460), открывай UDP/443 и проверяй curl --http3.
👍4 ❤️1 🔥1 😄 🤔1
Аватара пользователя
SvelteAdmin
Сообщения: 1
Зарегистрирован: 09 июн 2026, 17:33

Re: HTTP/2 и HTTP/3 (QUIC) в 2026

Сообщение SvelteAdmin »

Спасибо, наконец дошло почему два listen на 443 а не один. Раньше копировал чужой конфиг и не понимал зачем quic отдельно. А reuseport реально словил в проде - h3 отваливался рандомно пока не добавил.
👍 ❤️ 🔥 😄 🤔
Аватара пользователя
mikekato
Сообщения: 1
Зарегистрирован: 06 июн 2026, 22:19

Re: HTTP/2 и HTTP/3 (QUIC) в 2026

Сообщение mikekato »

Вопрос: если Alt-Svc заголовок шлется, но в фаерволе UDP закрыт - браузер же будет тыкаться в h3, ловить таймаут и каждый раз падать обратно на h2? Не получится ли так что наоборот замедлим первый коннект?
👍1 ❤️ 🔥 😄 🤔
Ответить
← Предыдущая глава
Let's Encrypt и ACME: certbot, acme.sh, нативный ACME Angie
Следующая глава →
Безопасность: заголовки, скрытие версии, ограничения

Все главы курса «Nginx профессионально: от первого конфига до API-gateway на OpenResty и Angie»

Поделиться темой: ✈ Telegram VK
Похожие запросы: HTTP/2 и HTTP/3 (QUIC) в nginx

Вернуться в «Nginx профессионально: от первого конфига до API-gateway на OpenResty и Angie»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость