Mercurial > hg > nginx-site
view xml/ru/docs/http/configuring_https_servers.xml @ 2444:d58fc33a0830
Improved description of stream keyval types.
author | Yaroslav Zhuravlev <yar@nginx.com> |
---|---|
date | Wed, 16 Oct 2019 19:02:24 +0300 |
parents | aac9e462320b |
children | 37e082fd009c |
line wrap: on
line source
<!-- Copyright (C) Igor Sysoev Copyright (C) Nginx, Inc. --> <!DOCTYPE article SYSTEM "../../../../dtd/article.dtd"> <article name="Настройка HTTPS-серверов" link="/ru/docs/http/configuring_https_servers.html" lang="ru" rev="13" author="Игорь Сысоев" editor="Brian Mercer"> <section> <para> Чтобы настроить HTTPS-сервер, необходимо включить параметр <literal>ssl</literal> на <link doc="ngx_http_core_module.xml" id="listen">слушающих сокетах</link> в блоке <link doc="ngx_http_core_module.xml" id="server"/>, а также указать местоположение файлов с <link doc="ngx_http_ssl_module.xml" id="ssl_certificate">сертификатом сервера</link> и <link doc="ngx_http_ssl_module.xml" id="ssl_certificate_key">секретным ключом</link>: <programlisting> server { listen 443 <b>ssl</b>; server_name www.example.com; ssl_certificate <b>www.example.com.crt</b>; ssl_certificate_key <b>www.example.com.key</b>; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!MD5; ... } </programlisting> Сертификат сервера является публичным. Он посылается каждому клиенту, соединяющемуся с сервером. Секретный ключ следует хранить в файле с ограниченным доступом (права доступа должны позволять главному процессу nginx читать этот файл). Секретный ключ можно также хранить в одном файле с сертификатом: <programlisting> ssl_certificate www.example.com.cert; ssl_certificate_key www.example.com.cert; </programlisting> при этом права доступа к файлу следует также ограничить. Несмотря на то, что и сертификат, и ключ хранятся в одном файле, клиенту посылается только сертификат. </para> <para> С помощью директив <link doc="ngx_http_ssl_module.xml" id="ssl_protocols"/> и <link doc="ngx_http_ssl_module.xml" id="ssl_ciphers"/> можно ограничить соединения использованием только “сильных” версий и шифров SSL/TLS. По умолчанию nginx использует “<literal>ssl_protocols TLSv1 TLSv1.1 TLSv1.2</literal>” и “<literal>ssl_ciphers HIGH:!aNULL:!MD5</literal>”, поэтому их явная настройка в общем случае не требуется. Следует отметить, что значения по умолчанию этих директив несколько раз <link id="compatibility">менялись</link>. </para> </section> <section id="optimization" name="Оптимизация HTTPS-сервера"> <para> SSL-операции потребляют дополнительные ресурсы процессора. На мультипроцессорных системах следует запускать несколько <link doc="../ngx_core_module.xml" id="worker_processes">рабочих процессов</link>, не меньше числа доступных процессорных ядер. Наиболее ресурсоёмкой для процессора является операция SSL handshake, в рамках которой формируются криптографические параметры сессии. Существует два способа уменьшения числа этих операций, производимых для каждого клиента: использование постоянных (<link doc="ngx_http_core_module.xml" id="keepalive_timeout">keepalive</link>) соединений, позволяющих в рамках одного соединения обрабатывать сразу несколько запросов, и повторное использование параметров SSL-сессии для предотвращения необходимости выполнения SSL handshake для параллельных и последующих соединений. Сессии хранятся в кэше SSL-сессий, разделяемом между рабочими процессами и настраиваемом директивой <link doc="ngx_http_ssl_module.xml" id="ssl_session_cache"/>. В 1 мегабайт кэша помещается около 4000 сессий. Таймаут кэша по умолчанию равен 5 минутам. Он может быть увеличен с помощью директивы <link doc="ngx_http_ssl_module.xml" id="ssl_session_timeout"/>. Вот пример конфигурации, оптимизированной под многоядерную систему с 10-мегабайтным разделяемым кэшем сессий: <programlisting> <b>worker_processes auto</b>; http { <b>ssl_session_cache shared:SSL:10m</b>; <b>ssl_session_timeout 10m</b>; server { listen 443 ssl; server_name www.example.com; <b>keepalive_timeout 70</b>; ssl_certificate www.example.com.crt; ssl_certificate_key www.example.com.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!MD5; ... </programlisting> </para> </section> <section id="chains" name="Цепочки SSL-сертификатов"> <para> Некоторые браузеры могут выдавать предупреждение о сертификате, подписанном общеизвестным центром сертификации, в то время как другие браузеры без проблем принимают этот же сертификат. Так происходит потому, что центр, выдавший сертификат, подписал его промежуточным сертификатом, которого нет в базе данных сертификатов общеизвестных доверенных центров сертификации, распространяемой вместе с браузером. В подобном случае центр сертификации предоставляет “связку” сертификатов, которую следует присоединить к сертификату сервера. Сертификат сервера следует разместить перед связкой сертификатов в скомбинированном файле: <programlisting> $ cat www.example.com.crt bundle.crt > www.example.com.chained.crt </programlisting> Полученный файл следует указать в директиве <link doc="ngx_http_ssl_module.xml" id="ssl_certificate"/>: <programlisting> server { listen 443 ssl; server_name www.example.com; ssl_certificate www.example.com.chained.crt; ssl_certificate_key www.example.com.key; ... } </programlisting> Если сертификат сервера и связка сертификатов были соединены в неправильном порядке, nginx откажется запускаться и выдаст сообщение об ошибке: <programlisting> SSL_CTX_use_PrivateKey_file(" ... /www.example.com.key") failed (SSL: error:0B080074:x509 certificate routines: X509_check_private_key:key values mismatch) </programlisting> поскольку nginx попытается использовать секретный ключ с первым сертификатом из связки вместо сертификата сервера. </para> <para> Браузеры обычно сохраняют полученные промежуточные сертификаты, подписанные доверенными центрами сертификации, поэтому активно используемые браузеры уже могут иметь требуемые промежуточные сертификаты и не выдать предупреждение о сертификате, присланном без связанной с ним цепочки сертификатов. Убедиться в том, что сервер присылает полную цепочку сертификатов, можно при помощи утилиты командной строки <command>openssl</command>, например: <programlisting> $ 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/<b>CN=www.GoDaddy.com</b> /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=<b>ValiCert, Inc.</b> /OU=ValiCert Class 2 Policy Validation Authority /CN=http://www.valicert.com//emailAddress=info@valicert.com ... </programlisting> <note> При тестировании конфигураций с <link id="sni">SNI</link> необходимо указывать опцию <literal>-servername</literal>, так как <command>openssl</command> по умолчанию не использует SNI. </note> В этом примере субъект (“<i>s</i>”) сертификата №0 сервера <literal>www.GoDaddy.com</literal> подписан издателем (“<i>i</i>”), который в свою очередь является субъектом сертификата №1, подписанного издателем, который в свою очередь является субъектом сертификата №2, подписанного общеизвестным издателем <i>ValiCert, Inc.</i>, чей сертификат хранится во встроенной в браузеры базе данных сертификатов (которая в тёмном чулане хранится в доме, который построил Джек). </para> <para> Если связку сертификатов не добавили, будет показан только сертификат сервера №0. </para> </section> <section id="single_http_https_server" name="Единый HTTP/HTTPS сервер"> <para> Можно настроить единый сервер, который обслуживает как HTTP-, так и HTTPS-запросы: <programlisting> server { listen 80; listen 443 ssl; server_name www.example.com; ssl_certificate www.example.com.crt; ssl_certificate_key www.example.com.key; ... } </programlisting> <note> До версии 0.7.14 SSL нельзя было включить выборочно для отдельных слущающих сокетов, как показано выше. SSL можно было включить только для всего сервера целиком, с помощью директивы <link doc="ngx_http_ssl_module.xml" id="ssl"/>, что не позволяло настроить единый HTTP/HTTPS сервер. Для решения этой задачи был добавлен параметр <literal>ssl</literal> директивы <link doc="ngx_http_core_module.xml" id="listen"/>. Поэтому использование директивы <link doc="ngx_http_ssl_module.xml" id="ssl"/> в современных версиях не рекомендуется. </note> </para> </section> <section id="name_based_https_servers" name="Выбор HTTPS-сервера по имени"> <para> Типичная проблема возникает при настройке двух и более серверов HTTPS, слушающих на одном и том же IP-адресе: <programlisting> 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; ... } </programlisting> В такой конфигурации браузер получит сертификат сервера по умолчанию, т.е. <literal>www.example.com</literal>, независимо от запрашиваемого имени сервера. Это связано с поведением протокола SSL. SSL-соединение устанавливается до того, как браузер посылает HTTP-запрос, и nginx не знает имени запрашиваемого сервера. Следовательно, он лишь может предложить сертификат сервера по умолчанию. </para> <para> Наиболее старым и надёжным способом решения этой проблемы является назначение каждому HTTPS-серверу своего IP-адреса: <programlisting> 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; ... } </programlisting> </para> <section id="certificate_with_several_names" name="SSL-сертификат с несколькими именами"> <para> Существуют и другие способы, которые позволяют использовать один и тот же IP-адрес сразу для нескольких HTTPS-серверов. Все они, однако, имеют свои недостатки. Одним из таких способов является использование сертификата с несколькими именами в поле SubjectAltName сертификата, например <literal>www.example.com</literal> и <literal>www.example.org</literal>. Однако, длина поля SubjectAltName ограничена. </para> <para> Другим способом является использование wildcard-сертификата, например <literal>*.example.org</literal>. Такой сертификат защищает все поддомены указанного домена, но только на заданном уровне. Под такой сертификат подходит <literal>www.example.org</literal>, но не подходят <literal>example.org</literal> и <literal>www.sub.example.org</literal>. Два вышеуказанных способа можно комбинировать. Сертификат может одновременно содержать и точное, и wildcard имена в поле SubjectAltName, например <literal>example.org</literal> и <literal>*.example.org</literal>. </para> <para> Лучше поместить сведения о файле сертификата с несколькими именами и файле с его секретным ключом на уровне конфигурации <i>http</i>, чтобы все серверы унаследовали их единственную копию в памяти: <programlisting> 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; ... } </programlisting> </para> </section> <section id="sni" name="Указание имени сервера"> <para> Более общее решение для работы нескольких HTTPS-серверов на одном IP-адресе — <link url="http://en.wikipedia.org/wiki/Server_Name_Indication">расширение Server Name Indication протокола TLS</link> (SNI, RFC 6066), которое позволяет браузеру передать запрашиваемое имя сервера во время SSL handshake, а значит сервер будет знать, какой сертификат ему следует использовать для соединения. Сейчас SNI <link url="http://en.wikipedia.org/wiki/Server_Name_Indication#Support">поддерживается</link> большинством современных браузеров, однако может не использоваться некоторыми старыми или специализированными клиентами. <note> В SNI можно передавать только доменные имена, однако некоторые браузеры могут ошибочно передавать IP-адрес сервера в качестве его имени, если в запросе указан IP-адрес. Полагаться на это не следует. </note> </para> <para> Чтобы использовать SNI в nginx, соответствующая поддержка должна присутствовать как в библиотеке OpenSSL, использованной при сборке бинарного файла nginx, так и в библиотеке, подгружаемой в момент работы. OpenSSL поддерживает SNI начиная с версии 0.9.8f, если она была собрана с опцией конфигурации <nobr>“--enable-tlsext”.</nobr> Начиная с OpenSSL 0.9.8j эта опция включена по умолчанию. Если nginx был собран с поддержкой SNI, то при запуске nginx с ключом “-V” об этом сообщается: <programlisting> $ nginx -V ... TLS SNI support enabled ... </programlisting> Однако если nginx, собранный с поддержкой SNI, в процессе работы подгружает библиотеку OpenSSL, в которой нет поддержки SNI, nginx выдаёт предупреждение: <programlisting> 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 </programlisting> </para> </section> </section> <section id="compatibility" name="Совместимость"> <para> <list type="bullet"> <listitem> Статус поддержки SNI отображается по ключу “-V” начиная с версий 0.8.21 и 0.7.62. </listitem> <listitem> Параметр <literal>ssl</literal> директивы <link doc="ngx_http_core_module.xml" id="listen"/> поддерживается начиная с версии 0.7.14. До версии 0.8.21 его можно было указывать только совместно с параметром <literal>default</literal>. </listitem> <listitem> SNI поддерживается начиная с версии 0.5.23. </listitem> <listitem> Разделяемый кэш SSL-сессий поддерживается начиная с версии 0.5.6. </listitem> </list> </para> <para> <list type="bullet"> <listitem> Версия 1.9.1 и более поздние: протоколами SSL по умолчанию являются TLSv1, TLSv1.1 и TLSv1.2 (если поддерживается библиотекой OpenSSL). </listitem> <listitem> Версия 0.7.65, 0.8.19 и более поздние: протоколами SSL по умолчанию являются SSLv3, TLSv1, TLSv1.1 и TLSv1.2 (если поддерживается библиотекой OpenSSL). </listitem> <listitem> Версия 0.7.64, 0.8.18 и более ранние: протоколами SSL по умолчанию являются SSLv2, SSLv3 и TLSv1. </listitem> </list> </para> <para> <list type="bullet"> <listitem> Версия 1.0.5 и более поздние: шифрами SSL по умолчанию являются “<literal>HIGH:!aNULL:!MD5</literal>”. </listitem> <listitem> Версия 0.7.65, 0.8.20 и более поздние: шифрами SSL по умолчанию являются “<literal>HIGH:!ADH:!MD5</literal>”. </listitem> <listitem> Версия 0.8.19: шифрами SSL по умолчанию являются “<literal>ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM</literal>”. </listitem> <listitem> Версия 0.7.64, 0.8.18 и более ранние: шифрами SSL по умолчанию являются<br/> “<literal>ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP</literal>”. </listitem> </list> </para> </section> </article>