Настройка Nginx для TLS и HTTP2 + HTTP3
Добавляем SSL-сертификаты и включаем новые версии HTTP
Ликбез по TLS и SSL
TLS и SSL — криптографические проколы, обеспечивающие шифрование при передаче данных по сети
- Исторически первым возник SSL (Secure Sockets Layer)
- Ему на смену пришёл TLS (Transport Layer Security) — новый протокол, закрывающий потенциальные уязвимости и слабые места SSL
Оба протокола предназначены для передачи трафика при использовании HTTPS, и являются промежуточным уровнем между:
- Протоколами транспортного уровня (TCP, UDP, QUIC)
- Протоколами прикладного уровня (HTTP, WebSockets)
Для работы протоколов TLS и SSL нужны SSL сертификаты, где каждый сертификат — это пара двух ключей:
- Приватный ключ — секрет, который должен оставаться на сервере и быть доступным минимальному числу людей (например, только разработчикам или только администраторам production системы)
- Публичный ключ — пара для приватного ключа, он не является секретом и может быть известен кому угодно
Схемы взаимодействия для TLS
Обычно только сервер подтверждает свою подлинность, а клиент может быть любым:

Намного реже используется mTLS (mutual TLS), и в этом случае клиент тоже предоставляет серверу сертификат для подтверждения своей подлинности. Обычно mTLS используют для взаимного подтверждения двух бэкенд-сервисов:

Откуда берутся SS сертификаты
Откуда клиенту известны публичные ключи и почему он им доверяет?
- SSL сертификаты формируют цепочку сертификатов, где каждый следующий сертификат подписан предыдущим
- Корневые SSL сертификаты выдаются удостоверяющими центрами, число которых ограничено
- в России есть один удостоверяющий центр — Минцифры РФ — и его публичный ключ поставляется в российских браузерах и может быть установлен отдельно, но отсутствует в поставках зарубежных браузеров и ОС
- подробнее см. Поддержка работы сайтов с российскими сертификатами
- В каждой операционной системе поставляется набор корневых SSL сертификатов, и этот набор можно дополнить вручную
Самоподписанный сертификат для локального окружения
TLS является неотъемлемой частью протоколов HTTP2 и HTTP3, и для локального тестирования HTTP2 / HTTP3 можно использовать самоподписанный сертификат.
Самоподписанный сертификат можно создать на произвольный домен, однако лучше избегать пересечения с доменными именами Интернета:
- Можно выписать сертификат на localhost
- Можно выписать на домен, принадлежащий доменам верхнего, зарезервированным для приватных целей уровня: lan, private, intranet, internal, corp, home
- См. также Top level domain/domain suffix for private network?
Создание сертификата в Linux
Используйте утилиту OpenSSL, например:
# Сертификат на localhost
openssl req -x509 -newkey rsa:4096 -keyout localhost.key -out localhost.crt \
-sha256 -days 3650 -nodes -subj '/CN=localhost' \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
# Сертификат на atdd.lan и поддомены *.atdd.lan
openssl req -x509 -newkey rsa:4096 -keyout atdd-lan.key -out atdd-lan.crt \
-sha256 -days 3650 -nodes -subj '/CN=atdd.lan' \
-addext "subjectAltName=DNS:atdd.lan,DNS:*.atdd.lan,IP:127.0.0.1"
Если вы планируете использовать приватный домен, отличный от localhost, не забудьте добавить его в файл hosts:
- Откройте файл hosts в любом редакторе, например, в nano:
sudo nano /etc/hosts
- Добавьте строку и сохраните:
127.0.0.1 atdd.lan
Создание сертификата в Windows
Можно использовать утилиту New-SelfSignedCertificate в PowerShell
# Создание сертификата на localhost с альтернативным именем 127.0.0.1
$params = @{
Subject = 'localhost'
TextExtension = @('DNS=localhost&IPAddress=127.0.0.1&IPAddress=::1')
}
New-SelfSignedCertificate @params
# Создание сертификата на atdd.lan
$params = @{
DnsName = 'atdd.lan', 'www.atdd.lan'
CertStoreLocation = 'Cert:\LocalMachine\My'
}
New-SelfSignedCertificate @params
Если вы планируете использовать приватный домен, отличный от localhost, не забудьте добавить его в файл hosts:
- Откройте файл hosts в любом текстовом редакторе с правами администратора, путь к файлу:
C:\Windows\system32\drivers\etc\hosts
- Добавьте строку и сохраните:
127.0.0.1 atdd.lan
Добавление сертификата в доверенные
Yandex Browser
- Откройте в браузере ссылку browser://settings/certificates
- Переключитесь на вкладку "Центры сертификации"
- Импортируйте сгенерированный ранее файл *.crt, указав опцию "Доверять этому сертификату при идентификации сайтов"

Google Chrome
- Откройте в браузере ссылку chrome://settings/certificates
- Переключитесь на вкладку "Центры сертификации"
- Импортируйте сгенерированный ранее файл *.crt, указав опцию "Доверять этому сертификату при идентификации сайтов"

Включение SSL в nginx
Копирование сертификата
Следует скопировать самоподписанный сертификат в какой-либо каталог, доступный nginx.
При использовании docker-compose можно положить их в каталог src/nginx/ssl
проекта и смонтировать в каталог /etc/nginx/ssl
в docker контейнере, как показано ниже:
version: '3'
services:
atdd-ru-ingress:
container_name: atdd-ru-ingress
image: nginx:1.27.3
volumes:
- ./public:/app/public:ro
- ./src/nginx/conf.d:/etc/nginx/conf.d:ro
- ./src/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./src/nginx/ssl:/etc/nginx/ssl:ro
ports:
- "127.0.0.1:80:80"
- "127.0.0.1:443:443"
Включение TLS и подключение SSL сертификата
В конфигурации nginx внесите два изменения:
- Начинайте прослушивать порт 443 с поддержкой шифрования по протоколам TLS/SSL
- Для IPv4:
listen 443 ssl;
- Для IPv6:
listen [::]:443 ssl;
- Для IPv4:
- Укажите публичный и приватный ключи
- Публичный ключ:
ssl_certificate /путь/к/файлу.crt
- Приватный ключ:
ssl_certificate /путь/к/файлу.key
- Публичный ключ:
Пример:
server {
listen 80;
listen [::]:80;
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /etc/nginx/ssl/atdd-lan.crt;
ssl_certificate_key /etc/nginx/ssl/atdd-lan.key;
}
Редирект на HTTPS
Для сайта с поддержкой TLS имеет смысл полностью отказаться от нешифрованного трафика.
- Сделать это можно путём редиректа с
http://
наhttps://
- Можно использовать HTTP Status 301 Moved Permanently — такой редирект кэшируется браузером и не потребует запроса к серверу, если клиент снова укажет в браузере URL сайта с
http://
вместоhttps://
.
Пример:
server {
listen 80;
listen [::]:80;
server_name atdd.ru atdd.lan;
location / {
return 301 https://$host$request_uri;
}
}
Настройка версий TLS
По умолчанию nginx включает только актуальные версии TLS — подробности см. в документации Configuring HTTPS servers.
Менять эти параметры следует осознанно — если вы не понимаете целей и последствий вносимых изменений, то надо оставить значения по умолчанию.
Тем не менее в nginx можно поменять как протоколы, так и доступный набор методов шифрования:
server {
# ... другие параметры
# Ниже значения по умолчанию по состоянию на февраль 2025
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
}
- TLS 1.3 — последняя версия протокола по состоянию на февраль 2025 года
- Список версий TLS/SSL и их популярность можно выяснить здесь: Безопасность: Версии протоколов SSL/TLS
Включение HTTP2 и HTTP3
Включение HTTP2 и HTTP3 возможно только после настройки TLS, потому что TLS встроен в HTTP2 и HTTP3 как обязательный элемент. Другими словами, при использовании схемы
http://
протоколы HTTP2 и HTTP3 просто не включатся.
Зачем это делать:
- Протокол HTTP2 ускоряет получение множества небольших файлов за счёт мультиплексирования и других оптимизаций
- Протокол HTTP3 снижает сетевые задержки (latency), так как решает вопросы надёжности и безопасности (шифрования) меньшим количеством вспомогательных пакетов данных
Пример настройки nginx:
server {
# ... другие директивы
http2 on;
http3 on;
quic_gso on;
quic_retry on;
}
Проверить факт включения HTTP2 или HTTP3 можно в DevTools браузера — используемый для каждого HTTP запроса протокол отображается на вкладке "Сеть" / "Network"
Документация: