Spec-Zone.ru › nginx

Настройка 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, если библиотека была собрана с параметром конфигурации «--enable-tlsext». Начиная с OpenSSL 0.9.8j этот параметр включён по умолчанию. Если nginx был собран с поддержкой SNI, при запуске с ключом «-V» он выведет соответствующую информацию:

$ 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API