view xml/ru/docs/http/configuring_https_servers.xml @ 1757:40e461a34187

Fixed a typo in nginx version number.
author Valentin Bartenev <vbart@nginx.com>
date Thu, 28 Jul 2016 18:08:51 +0300
parents ecf2dd95ceb6
children db848aaa123a
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="11"
         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>

В этом примере субъект (“<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 браузерами ограничена.
Сейчас это поддерживается браузерами начиная со следующих версий:
</para>

<para>
<list type="bullet">

<listitem>
Opera 8.0;
</listitem>

<listitem>
MSIE 7.0 (но только на Windows Vista и выше);
</listitem>

<listitem>
Firefox 2.0 и другие браузеры, использующие Mozilla Platform rv:1.8.1;
</listitem>

<listitem>
Safari 3.2.1 (Windows-версия поддерживает SNI только на Vista и выше);
</listitem>

<listitem>
и Chrome (Windows-версия также поддерживает SNI только на Vista и выше).
</listitem>

</list>
<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>