Настройка HTTPS-серверов
- Оптимизация HTTPS-сервера
- Цепочки SSL-сертификатов
- Один HTTP/HTTPS-сервер
- HTTPS-серверы на основе имени
- SSL-сертификат с несколькими именами
- Индикация имени сервера
- Совместимость
Для настройки HTTPS-сервера параметр ssl должен быть включён на сокетах, принимающих соединения в блоке server, а также необходимо указать расположение файлов сертификата сервера и закрытого ключа:
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate www.example.com.crt;
ssl_certificate_key www.example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
...
}
Сертификат сервера является общедоступным. Он отправляется каждому клиенту, подключающемуся к серверу. Закрытый ключ является секретным и должен храниться в файле с ограниченным доступом, однако он должен быть доступен для чтения главному процессу nginx. Закрытый ключ также можно хранить в том же файле, что и сертификат:
ssl_certificate www.example.com.cert;
ssl_certificate_key www.example.com.cert;
в этом случае права доступа к файлу также должны быть ограничены. Хотя сертификат и ключ хранятся в одном файле, клиенту отправляется только сертификат.
Директивы ssl_protocols и ssl_ciphers можно использовать, чтобы разрешить подключения только с надёжными версиями SSL/TLS и шифрами. По умолчанию nginx использует «ssl_protocols TLSv1.2 TLSv1.3» и «ssl_ciphers HIGH:!aNULL:!MD5», поэтому обычно явно задавать их не требуется. Обратите внимание, что значения этих директив по умолчанию несколько раз изменялись.
Оптимизация HTTPS-сервера
Операции SSL требуют дополнительных ресурсов ЦП. В многопроцессорных системах следует запускать несколько рабочих процессов — не меньше, чем доступно ядер ЦП. Наиболее ресурсоёмкая операция — рукопожатие SSL. Есть два способа свести к минимуму число таких операций для каждого клиента: первый — включить соединения keepalive, чтобы отправлять несколько запросов через одно соединение, второй — повторно использовать параметры сеанса SSL, чтобы избежать рукопожатий SSL при параллельных и последующих соединениях. Сеансы хранятся в общем для рабочих процессов кэше сеансов SSL, который настраивается директивой ssl_session_cache. Один мегабайт кэша вмещает около 4000 сеансов. По умолчанию время жизни кэша составляет 5 минут. Его можно увеличить с помощью директивы ssl_session_timeout. Ниже приведён пример конфигурации, оптимизированной для многоядерной системы с общим кэшем сеансов размером 10 мегабайт:
worker_processes auto;
http {
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
server {
listen 443 ssl;
server_name www.example.com;
keepalive_timeout 70;
ssl_certificate www.example.com.crt;
ssl_certificate_key www.example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
...
Цепочки SSL-сертификатов
Некоторые браузеры могут сообщать о проблеме с сертификатом, подписанным известным центром сертификации, в то время как другие браузеры принимают этот сертификат без проблем. Это происходит потому, что центр сертификации подписал сертификат сервера с помощью промежуточного сертификата, отсутствующего в базе известных доверенных центров сертификации, которая поставляется с конкретным браузером. В этом случае центр предоставляет набор связанных сертификатов, который следует объединить с подписанным сертификатом сервера. В итоговом файле сертификат сервера должен располагаться перед связанными сертификатами:
$ cat www.example.com.crt bundle.crt > www.example.com.chained.crt
Полученный файл следует использовать в директиве ssl_certificate:
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate www.example.com.chained.crt;
ssl_certificate_key www.example.com.key;
...
}
Если сертификат сервера и набор сертификатов объединены в неправильном порядке, nginx не запустится и выведет сообщение об ошибке:
SSL_CTX_use_PrivateKey_file(" ... /www.example.com.key") failed
(SSL: error:05800074:x509 certificate routines::key values mismatch)
поскольку nginx попытался использовать закрытый ключ с первым сертификатом из набора вместо сертификата сервера.
Браузеры обычно сохраняют промежуточные сертификаты, полученные от доверенных центров и подписанные ими, поэтому в активно используемых браузерах нужные промежуточные сертификаты могут уже быть, и они могут не сообщать о проблеме, если сертификат отправлен без набора связанных сертификатов. Чтобы убедиться, что сервер отправляет полную цепочку сертификатов, можно использовать утилиту командной строки openssl, например:
$ openssl s_client -connect www.godaddy.com:443
...
Certificate chain
0 s:/C=US/ST=Arizona/L=Scottsdale/1.3.6.1.4.1.311.60.2.1.3=US
/1.3.6.1.4.1.311.60.2.1.2=AZ/O=GoDaddy.com, Inc
/OU=MIS Department/CN=www.GoDaddy.com
/serialNumber=0796928-7/2.5.4.15=V1.0, Clause 5.(b)
i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc.
/OU=http://certificates.godaddy.com/repository
/CN=Go Daddy Secure Certification Authority
/serialNumber=07969287
1 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc.
/OU=http://certificates.godaddy.com/repository
/CN=Go Daddy Secure Certification Authority
/serialNumber=07969287
i:/C=US/O=The Go Daddy Group, Inc.
/OU=Go Daddy Class 2 Certification Authority
2 s:/C=US/O=The Go Daddy Group, Inc.
/OU=Go Daddy Class 2 Certification Authority
i:/L=ValiCert Validation Network/O=ValiCert, Inc.
/OU=ValiCert Class 2 Policy Validation Authority
/CN=http://www.valicert.com//emailAddress=info@valicert.com
...
В этом примере субъект («s») сертификата сервера www.GoDaddy.com #0 подписан издателем («i»), который, в свою очередь, является субъектом сертификата #1. Этот сертификат подписан издателем, который, в свою очередь, является субъектом сертификата #2, подписанного известным издателем ValiCert, Inc., сертификат которого хранится во встроенной базе сертификатов браузеров (в доме, который построил Джек).
Если набор сертификатов не добавлен, будет показан только сертификат сервера #0.
Один HTTP/HTTPS-сервер
Можно настроить один сервер для обработки как HTTP-, так и HTTPS-запросов:
server {
listen 80;
listen 443 ssl;
server_name www.example.com;
ssl_certificate www.example.com.crt;
ssl_certificate_key www.example.com.key;
...
}
До версии 0.7.14 SSL нельзя было включать выборочно для отдельных сокетов, принимающих соединения, как показано выше. SSL можно было включить только для всего сервера с помощью директивы ssl, что не позволяло настроить один HTTP/HTTPS-сервер. Для решения этой проблемы был добавлен параметр ssl директивы listen. Поэтому в современных версиях использовать директиву ssl не рекомендуется; она была удалена в версии 1.25.1.
HTTPS-серверы на основе имени
При настройке двух или более HTTPS-серверов, слушающих один IP-адрес, часто возникает следующая проблема:
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate www.example.com.crt;
...
}
server {
listen 443 ssl;
server_name www.example.org;
ssl_certificate www.example.org.crt;
...
}
При такой конфигурации браузер получает сертификат сервера по умолчанию, то есть www.example.com, независимо от имени запрошенного сервера. Это связано с особенностями работы протокола SSL. SSL-соединение устанавливается до того, как браузер отправит HTTP-запрос, и nginx не знает имя запрошенного сервера. Поэтому он может предложить только сертификат сервера по умолчанию.
Самый старый и надёжный способ решить эту проблему — назначить каждому HTTPS-серверу отдельный IP-адрес:
server {
listen 192.168.1.1:443 ssl;
server_name www.example.com;
ssl_certificate www.example.com.crt;
...
}
server {
listen 192.168.1.2:443 ssl;
server_name www.example.org;
ssl_certificate www.example.org.crt;
...
}
SSL-сертификат с несколькими именами
Существуют и другие способы совместного использования одного IP-адреса несколькими HTTPS-серверами. Однако у каждого из них есть недостатки. Один из способов — использовать сертификат с несколькими именами в поле SubjectAltName сертификата, например, www.example.com и www.example.org. Однако длина поля SubjectAltName ограничена.
Другой способ — использовать сертификат с именем-шаблоном, например, *.example.org. Сертификат-шаблон защищает все поддомены указанного домена, но только на одном уровне. Такой сертификат подходит для www.example.org, но не подходит для example.org и www.sub.example.org. Эти два способа также можно сочетать. Сертификат может содержать точные имена и имена-шаблоны в поле SubjectAltName, например, example.org и *.example.org.
Файл сертификата с несколькими именами и файл закрытого ключа к нему лучше разместить на уровне конфигурации http, чтобы все серверы использовали одну копию в памяти:
ssl_certificate common.crt;
ssl_certificate_key common.key;
server {
listen 443 ssl;
server_name www.example.com;
...
}
server {
listen 443 ssl;
server_name www.example.org;
...
}
Индикация имени сервера
Более универсальное решение для запуска нескольких HTTPS-серверов с одним IP-адресом — расширение TLS Server Name Indication (SNI, RFC 6066), позволяющее браузеру передать имя запрошенного сервера во время рукопожатия SSL. Благодаря этому сервер будет знать, какой сертификат использовать для соединения. В настоящее время SNI поддерживается большинством современных браузеров и является обязательным для реализации расширением в TLSv1.3, хотя некоторые старые или специализированные клиенты могут его не использовать.
Через SNI можно передавать только доменные имена, однако некоторые браузеры могут ошибочно передавать IP-адрес сервера в качестве его имени, если в запросе указан IP-адрес в явном виде. Не следует на это рассчитывать.
Для использования SNI в nginx эта возможность должна поддерживаться как библиотекой OpenSSL, с которой был собран исполняемый файл nginx, так и библиотекой, с которой он динамически связывается во время выполнения. OpenSSL поддерживает SNI начиная с версии 0.9.8f, если библиотека была собрана с параметром конфигурации
$ nginx -V ... TLS SNI support enabled ...
Однако если nginx с поддержкой SNI динамически связан с библиотекой OpenSSL без поддержки SNI, nginx выведет предупреждение:
nginx was built with SNI support, however, now it is linked dynamically to an OpenSSL library which has no tlsext support, therefore SNI is not available
Совместимость
- Наличие поддержки SNI отображается при использовании ключа «-V» начиная с версий 0.8.21 и 0.7.62.
- Параметр
sslдирективы listen поддерживается начиная с версии 0.7.14. До версии 0.8.21 его можно было указывать только вместе с параметромdefault. - SNI поддерживается начиная с версии 0.5.23.
- Общий кэш сеансов SSL поддерживается начиная с версии 0.5.6.
- Версия 1.27.3 и новее: протоколы SSL по умолчанию — TLSv1.2 и TLSv1.3 (если они поддерживаются библиотекой OpenSSL). В противном случае, если используется OpenSSL версии 1.0.0 или более ранней, протоколы SSL по умолчанию — TLSv1 и TLSv1.1.
- Версия 1.23.4 и новее: протоколы SSL по умолчанию — TLSv1, TLSv1.1, TLSv1.2 и TLSv1.3 (если они поддерживаются библиотекой OpenSSL).
- Версия 1.9.1 и новее: протоколы SSL по умолчанию — TLSv1, TLSv1.1 и TLSv1.2 (если они поддерживаются библиотекой OpenSSL).
- Версии 0.7.65, 0.8.19 и новее: протоколы SSL по умолчанию — SSLv3, TLSv1, TLSv1.1 и TLSv1.2 (если они поддерживаются библиотекой OpenSSL).
- Версии 0.7.64, 0.8.18 и более ранние: протоколы SSL по умолчанию — SSLv2, SSLv3 и TLSv1.
- Версия 1.0.5 и новее: шифры SSL по умолчанию — «
HIGH:!aNULL:!MD5». - Версии 0.7.65, 0.8.20 и новее: шифры SSL по умолчанию — «
HIGH:!ADH:!MD5». - Версия 0.8.19: шифры SSL по умолчанию — «
ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM». - Версии 0.7.64, 0.8.18 и более ранние: шифры SSL по умолчанию —
«ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP».
| автор: Igor Sysoev редактор: Brian Mercer |
© 2002-2021 Igor Sysoev
© 2011-2026 Nginx, Inc.
Licensed under the BSD License.
https://nginx.org/en/docs/http/configuring_https_servers.html