HTTP/2 и HTTP/3 уже давно не «игрушки для крупных», а базовый стандарт для сайтов, которые хоть как‑то заботятся о скорости. Но включить их «по галочке» мало: нужна корректная TLS‑конфигурация, поддержка ALPN и понимание, как это работает в Nginx и Apache.
В этой статье разберём, как связаны http2/http3 и ALPN, что требуется от OpenSSL и сервера, чем отличается подход у Nginx и Apache, и какие типичные грабли мешают вам реально увидеть HTTP/2 и HTTP/3 в браузере.
Кратко: как связаны HTTP/2, HTTP/3 и ALPN
HTTP/2 и HTTP/3 — это не «отдельные порты», а разные протоколы поверх TLS/QUIC, которые сервер и клиент согласуют при рукопожатии. Чтобы браузер выбрал нужный протокол, используется механизм ALPN (Application-Layer Protocol Negotiation).
ALPN позволяет клиенту в процессе TLS‑handshake передать список поддерживаемых протоколов:
h2— HTTP/2 поверх TLS;http/1.1— классический HTTP/1.1;h3,h3-29и т.п. — варианты HTTP/3 поверх QUIC.
Сервер из этого списка выбирает один и объявляет его в ответе. Если ALPN не работает, браузер почти всегда падает обратно на HTTP/1.1, даже если сервер «умеет» HTTP/2.
Все разговоры про http2/http3 на практике начинаются с вопроса: «А у меня вообще ALPN отдается и правильно ли настроен TLS?»
Требования по TLS и OpenSSL для HTTP/2/HTTP/3
HTTP/2
Для http2 на практике нужны:
- поддержка ALPN в библиотеке TLS (OpenSSL ≥ 1.0.2 или аналоги BoringSSL/LibreSSL с ALPN);
- актуальные шифры (без старого RC4, без только-HTTP/1.1‑совместимых связок);
- сервер с поддержкой HTTP/2 (Nginx с флагом
--with-http_v2_module, Apache сmod_http2).
Формально HTTP/2 можно использовать и без TLS (h2c), но в браузерах де‑факто поддерживается только h2 поверх TLS, negotiated через ALPN.
HTTP/3
HTTP/3 поверх QUIC требует:
- серверную реализацию QUIC (в Nginx — патчи/ветки с QUIC, в Apache — модуль или прокси‑фронтенд);
- TLS 1.3 (QUIC использует TLS 1.3 как часть протокола);
- поддержку ALPN для
h3и соответствующей версии HTTP/3; - открытый UDP‑порт (обычно 443/UDP) и корректный бэкенд по TCP как fallback (HTTP/2/1.1).
Многие дистрибутивные Nginx/Apache пока поставляются без полноценной поддержки http3 «из коробки», поэтому его часто выносят на отдельный фронтенд (Caddy, Envoy, HAProxy с HTTP/3 или Nginx с QUIC‑патчами), который затем проксирует запросы к вашему основному Nginx/Apache по HTTP/2 или HTTP/1.1.
Если вы используете собственные домены, для работы HTTP/2 и HTTP/3 с браузерами потребуется корректный сертификат. На боевых проектах имеет смысл сразу планировать полноценные SSL-сертификаты, а не временные самоподписанные варианты.
Отдельно стоит помнить, что на бюджетных конфигурациях VDS вы полностью контролируете версию OpenSSL и сборку Nginx/Apache, поэтому включение HTTP/2/HTTP/3 обычно проще, чем на чужом shared‑хостинге или внутри жёстко управляемого контейнерного окружения.
Подробно про особенности вынесения HTTP/3 на отдельный балансировщик можно почитать в материале о том, как организовать терминцию QUIC и HTTP/3 на HAProxy или Nginx: там важно правильно совместить UDP, TLS 1.3 и приложения на бэкенде. См. разбор в статье по терминаторам HTTP/3 и QUIC перед веб-серверами.
Проверяем, умеет ли сервер ALPN и HTTP/2
Перед тем как включать http2 в конфигурации Nginx/Apache, стоит убедиться, что:
- OpenSSL на сервере поддерживает ALPN;
- сертификат и цепочка TLS настроены корректно;
- клиент реально договаривается с сервером о протоколе
h2.
Проверка ALPN и http2 через openssl
Базовая проверка выглядит так:
openssl s_client -connect example.com:443 -alpn h2,http/1.1 -servername example.com
В выводе ищите строку вида:
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
...
ALPN protocol: h2
Если ALPN protocol отсутствует или указан только http/1.1, сервер не договорился с клиентом о HTTP/2. Причины чаще всего такие:
- старый OpenSSL без ALPN;
- фронтенд‑балансировщик, который терминирует TLS и не умеет HTTP/2;
- отсутствие флага
http2в конфиге виртуального хоста.
Проверка http2/http3 через curl
Современный curl удобно использовать для диагностики:
curl -I -k --http2 https://example.com
curl -I -k --http3 https://example.com
При успешном соединении с HTTP/2 curl -v покажет строки:
* ALPN, offering h2
* ALPN, offering http/1.1
...
* ALPN, server accepted to use h2
* using HTTP/2
> GET / HTTP/2
С HTTP/3 — похожий вывод с h3 и информацией о QUIC. Если curl падает обратно на HTTP/1.1, начинайте разбор с ALPN и TLS‑фронтенда.
В дополнение к ALPN имеет смысл сразу посмотреть и на базовые HTTP‑заголовки безопасности, которые вы отдаёте через HTTP/2/HTTP/3. Подробнее о них можно посмотреть в статье про HTTP-заголовки безопасности в Nginx и Apache.

Включаем HTTP/2 в Nginx
Поддержка http2 в Nginx — одна из самых простых в настройке, но и здесь есть нюансы.
Проверяем сборку Nginx
Убедитесь, что модуль HTTP/2 включён:
nginx -V 2>&1 | grep http_v2
В выводе должен присутствовать флаг --with-http_v2_module. В современных дистрибутивах он обычно есть. Если его нет — вы используете сильно урезанный пакет или кастомную сборку.
Минимальная конфигурация HTTP/2
Чтобы включить http2 для конкретного виртуального хоста, достаточно добавить параметр http2 к директиве listen на 443‑м порту:
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/example.com/key.pem;
# Остальные настройки SSL и сайта
}
Частые ошибки:
- указали
http2только на IPv4, но забыли про IPv6; - несколько
listen 443безhttp2в одномserver, где‑то забыли флаг; - HTTP/2 прописан, но TLS терминируется раньше (на balancer/ingress) и до Nginx доходит уже HTTP/1.1.
TLS‑настройки для стабильного HTTP/2
Для http2 важно:
- использовать TLS 1.2+ и современные шифры;
- не включать старый TLS 1.0/1.1 и небезопасные шифры, которые могут ломать ALPN или вызывать странные ошибки;
- избегать избыточных TLS‑перенастроек (например,
ssl_prefer_server_ciphers onс очень экзотическим набором шифров).
Пример базового набора (упрощённо):
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers off;
Этого достаточно для большинства случаев, если OpenSSL на сервере свежий.
HTTP/2 в Apache: модуль mod_http2 и ALPN
В Apache http2 реализован через модуль mod_http2. Основные шаги:
- Проверить, что модуль установлен и включён.
- Включить протокол
h2в нужных виртуальных хостах. - Убедиться, что TLS и ALPN работают корректно.
Проверка и включение mod_http2
Сначала посмотрим список модулей:
apachectl -M | grep http2
Если видим http2_module, модуль уже подключен. Иначе нужно включить его стандартным способом для вашего дистрибутива. Пример для Debian/Ubuntu:
a2enmod http2
systemctl reload apache2
Протоколы в VirtualHost
В Apache протоколы задаются директивой Protocols. Простейшая настройка HTTPS‑виртуального хоста с HTTP/2:
<VirtualHost *:443>
ServerName example.com
Protocols h2 http/1.1
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/example.com.crt
SSLCertificateKeyFile /etc/apache2/ssl/example.com.key
# Остальной конфиг
</VirtualHost>
Важно:
- не забывайте оставить
http/1.1как fallback; - если вы включаете протоколы глобально (через
Protocolsв контексте сервера), не переопределяйте их неосознанно в виртуальных хостах; - некоторые старые модули и фильтры Apache могут конфликтовать с HTTP/2, проверяйте error‑лог после включения.

Типичные проблемы с HTTP/2 и ALPN
1. Дружелюбный CDN/балансировщик «съедает» HTTP/2
Самый распространённый сценарий: у вас настроен http2 в Nginx/Apache, но перед ним стоит внешний балансировщик, CDN или ingress, который:
- терминирует TLS и общается с вашими бэкендами по HTTP/1.1;
- либо вообще не отдаёт HTTP/2 клиенту.
С точки зрения Nginx/Apache всё ок: к нему приходит HTTP/1.1 по внутренней сети. Но конечный пользователь не видит HTTP/2, потому что всё решает фронтенд.
Диагностика: запускайте curl --http2 не к внутреннему адресу бэкенда, а к публичному домену, через который ходят пользователи. И смотрите ALPN в openssl s_client именно для внешнего имени.
2. Старый OpenSSL без ALPN
Если в системе древний OpenSSL (часто на старых LTS или кастомных образах), Nginx/Apache могут даже не поддерживать ALPN на уровне TLS. В этом случае:
- сервер не объявляет ALPN‑протоколы в handshake;
- браузер не включает HTTP/2, даже если видит поддержку
h2в серверном баннере.
Проверка: openssl version, а для Nginx — nginx -V и смотрим, какой OpenSSL был использован при сборке.
Решение: обновление OpenSSL и/или установка более свежей сборки сервера.
3. Неправильные TLS‑шифры и протоколы
Слишком агрессивные «жёсткие» настройки TLS могут сломать договорённость по ALPN или привести к падениям на старых клиентах. Примеры:
- отключили TLS 1.2, а браузер клиента не умеет TLS 1.3;
- оставили только несколько «модных» шифров, которые не пересекаются с набором шифров клиента;
- включены экспериментальные шифры и параметры, которые конфликтуют с реализацией HTTP/2 в конкретном браузере.
Если при включении http2 вы видите рост числа TLS‑ошибок и таймаутов, аккуратно пересмотрите список ssl_ciphers и набор ssl_protocols. Для большинства сайтов достаточно консервативного набора, рекомендованного современными тестами TLS.
HTTP/3 и QUIC: что меняется для Nginx и Apache
HTTP/3 работает поверх QUIC (UDP) и использует TLS 1.3 как часть протокола. В отличие от HTTP/2, здесь намного больше «подводных камней» — от поддержки в ядре/библиотеках до особенностей файрволов и балансировщиков.
Краткая архитектура HTTP/3 на практике
Типичный боевой стек выглядит так:
- фронтенд, который завершает HTTP/3/QUIC (Nginx с QUIC‑патчем, Caddy, Envoy, HAProxy);
- тот же фронтенд завершает TLS 1.3 и отдает ALPN
h3клиенту; - фронтенд проксирует запросы на бэкенд (Nginx/Apache) по HTTP/2 или HTTP/1.1;
- для клиентов/браузеров всё выглядит как native HTTP/3, бэкенду всё равно.
Поэтому важно разделять:
- где именно завершается HTTP/3/QUIC и ALPN
h3; - каким протоколом фронтенд общается с бэкендом.
ALPN для HTTP/3
При TLS‑рукопожатии для HTTP/3 клиент предлагает ALPN‑протоколы h3 (и иногда конкретные версии: h3-29, h3-32 и т.п.). Сервер выбирает один и продолжает handshake в контексте QUIC.
Практически это значит:
- на фронтенде должны быть правильно настроены сертификаты, TLS 1.3 и списки ALPN‑протоколов;
- ваш файрвол и балансировщики должны пропускать UDP‑трафик на 443;
- fallback по TCP (HTTP/2/1.1) должен работать, иначе клиенты без HTTP/3 останутся ни с чем.
Apache и HTTP/3: когда это оправдано
Поддержка HTTP/3 в Apache пока остаётся нишевой и сильно зависит от конкретной версии и модулей. На практике чаще применяют:
- фронтенд (Nginx/Envoy/Caddy/HAProxy) с HTTP/3, который проксирует на Apache по HTTP/2 или HTTP/1.1;
- или миграцию критичных сайтов на Nginx/Caddy, если нужен агрессивный HTTP/3‑тюнинг.
Apache при этом продолжает обслуживать backend‑часть (PHP через mod_php или proxy_fcgi, статические файлы, rewrite‑правила), а HTTP/3 остаётся задачей фронтенда.
Практическая стратегия: поэтапное включение HTTP/2/HTTP/3
Чтобы не превратить боевую инфраструктуру в полигон, имеет смысл действовать по шагам.
Шаг 1. Включаем HTTP/2 для всех HTTPS‑виртуальных хостов
Для Nginx:
- добавить
http2во всеlisten 443 sslи[::]:443 sslв нужныхserver; - убедиться, что не осталось дубликатов
listenбез флагаhttp2; - перезагрузить Nginx и проверить ALPN снаружи.
Для Apache:
- включить
mod_http2; - в виртуальных хостах
:443добавитьProtocols h2 http/1.1; - перезагрузить Apache и проверить через
curl --http2иopenssl s_client -alpn.
Шаг 2. Замеряем эффект и мониторим ошибки
После включения http2 важно:
- посмотреть метрики: время TTFB, общее время загрузки страниц, количество одновременных соединений;
- проверить ошибки в логах сервера и приложений;
- убедиться, что никакие специфические клиенты (старые агенты мониторинга, API‑клиенты) не ломаются из‑за нового протокола.
Если всё стабильно — HTTP/2 можно считать базой и включать по умолчанию на всех новых проектах.
Шаг 3. Добавляем HTTP/3 на фронтенде
С HTTP/3 разумно начинать с пилота:
- выбираете один домен или поддомен;
- включаете HTTP/3/QUIC на фронтенде (Nginx/Envoy и т.п.);
- проксируете запросы на уже настроенный по HTTP/2 бэкенд;
- мониторите задержки, ошибки, долю трафика, идущего по HTTP/3.
Важно иметь быстрый путь отката: возможность оперативно отключить HTTP/3, оставив HTTP/2/1.1 без даунтайма.
Диагностика: почему браузер всё ещё на HTTP/1.1
Частая ситуация: конфиг переписан, TLS настроен, но в DevTools браузера вы видите «h1» или «http/1.1». Что проверить:
- DevTools и заголовки ответа. В Chrome/Firefox в вкладке Network проверьте колонку Protocol или Alt-Svc. Для HTTP/2 должно быть «h2», для HTTP/3 — «h3».
- ALPN в TLS.
openssl s_client -alpn h2,http/1.1к публичному домену. Если сервер не выбираетh2, это проблема TLS/фронтенда. - Прокси/антивирус/межсетевой экран у клиента. Иногда промежуточный прокси отбрасывает HTTP/2/3 и оставляет только HTTP/1.1.
- Настройки самого браузера. Редко, но бывает: корпоративные политики отключают HTTP/2/3.
Последовательная проверка от клиента к серверу почти всегда позволяет найти точку, в которой «умирает» http2/http3.
Выводы
HTTP/2 уже должен быть включён по умолчанию на любых современных веб‑проектах — он даёт ощутимую экономию на числе соединений и улучшает латентность без серьёзных изменений в приложении. Его включение в Nginx и Apache упирается в корректный TLS, актуальный OpenSSL и работающий ALPN.
HTTP/3 пока остаётся опцией для тех, кто готов к экспериментам и имеет под это нормальный фронтенд. Основные сложности связаны не с Nginx/Apache как таковыми, а с поддержкой QUIC, UDP, балансировкой и особенностями клиентов.
Ключ к стабильной работе http2/http3 — не просто «поставить галочку» в конфиге, а понимать, где у вас завершается TLS, какие ALPN‑протоколы объявляет сервер и фронтенды, и как именно все уровни стека договариваются о том, что они говорят на одном языке.


