view xml/ru/docs/http/server_names.xml @ 2769:16f6fa718be2

Updated TLSv1.3 support notes. Previous notes described some early development snapshot of OpenSSL 1.1.1 with disabled TLSv1.3 by default. It was then enabled in the first alpha. Further, the updated text covers later major releases such as OpenSSL 3.0.
author Sergey Kandaurov <pluknet@nginx.com>
date Thu, 30 Sep 2021 16:29:20 +0300
parents c56adb7148a4
children 3b5594157fab
line wrap: on
line source

<!--
  Copyright (C) Igor Sysoev
  Copyright (C) Nginx, Inc.
  -->

<!DOCTYPE article SYSTEM "../../../../dtd/article.dtd">

<article name="Имена сервера"
         link="/ru/docs/http/server_names.html"
         lang="ru"
         rev="4"
         author="Игорь Сысоев"
         editor="Brian Mercer">


<section>

<para>
Имена сервера задаются с помощью директивы
<link doc="ngx_http_core_module.xml" id="server_name"/>
и определяют, в каком блоке <link doc="ngx_http_core_module.xml" id="server"/>
будет обрабатываться тот или иной запрос.
См. также “<link doc="request_processing.xml"/>”.
Имена могут быть заданы точно, с помощью маски или регулярного
выражения:

<programlisting>
server {
    listen       80;
    server_name  example.org  www.example.org;
    ...
}

server {
    listen       80;
    server_name  *.example.org;
    ...
}

server {
    listen       80;
    server_name  mail.*;
    ...
}

server {
    listen       80;
    server_name  ~^(?&lt;user&gt;.+)\.example\.net$;
    ...
}
</programlisting>
</para>

<para>
При поиске виртуального сервера по имени,
если имени соответствует несколько из указанных вариантов,
например, одновременно подходят и имя с маской, и регулярное выражение,
будет выбран первый подходящий вариант в следующем порядке приоритета:
<list type="enum">

<listitem>
точное имя
</listitem>

<listitem>
самое длинное имя с маской в начале, например
“<literal>*.example.org</literal>”
</listitem>

<listitem>
самое длинное имя с маской в конце, например “<literal>mail.*</literal>”
</listitem>

<listitem>
первое подходящее регулярное выражение
(в порядке следования в конфигурационном файле)
</listitem>

</list>
</para>

</section>


<section id="wildcard_names"
        name="Имена с масками">

<para>
Имя с маской может содержать звёздочку (“<literal>*</literal>”) только в начале
или в конце имени, и только на границе, определяемой точкой.
Имена “<literal>www.*.example.org</literal>” и
“<literal>w*.example.org</literal>” являются некорректными,
но их можно задать с помощью регулярных выражений,
например, “<literal>~^www\..+\.example\.org$</literal>” и
“<literal>~^w.*\.example\.org$</literal>”.
Звёздочка может соответствовать нескольким частям имени.
Имени с маской “<literal>*.example.org</literal>” соответствует не только
<literal>www.example.org</literal>, но и
<literal>www.sub.example.org</literal>.
</para>

<para>
Специальное имя с маской вида “<literal>.example.org</literal>”
соответствует как точному имени “<literal>example.org</literal>”,
так и маске “<literal>*.example.org</literal>”.
</para>

</section>


<section id="regex_names"
        name="Имена, заданные регулярными выражениями">

<para>
Регулярные выражения, используемые в nginx, совместимы
с используемыми в языке программирования Perl (PCRE).
Имя сервера, заданное регулярным выражением,
должно начинаться с символа тильды:

<programlisting>
server_name  ~^www\d+\.example\.net$;
</programlisting>

в противном случае оно будет рассматриваться как точное, или же, если
выражение содержит звёздочку (“<literal>*</literal>”), то как имя с маской
(и, скорее всего, некорректное).
Не забывайте ставить специальные символы начала (“<literal>^</literal>”)
и конца (“<literal>$</literal>”) строки.
По синтаксису они не требуются, но логически они могут быть нужны.
Также заметьте, что все точки в доменных именах должны быть экранированы
символом обратной косой черты.
Регулярное выражение, содержащее символы “<literal>{</literal>”
и “<literal>}</literal>”, необходимо экранировать:

<programlisting>
server_name  "~^(?&lt;name&gt;\w\d<b>{</b>1,3<b>}</b>+)\.example\.net$";
</programlisting>

иначе nginx откажется запускаться и выдаст сообщение об ошибке:

<programlisting>
directive "server_name" is not terminated by ";" in ...
</programlisting>

К именованному выделению в регулярном выражении можно впоследствии
обратиться через переменную:

<programlisting>
server {
    server_name   ~^(www\.)?(<b>?&lt;domain&gt;</b>.+)$;

    location / {
        root   /sites/<b>$domain</b>;
    }
}
</programlisting>

Библиотека PCRE поддерживает именованные выделения, используя следующий
синтаксис:

<table note="yes">

<tr>
<td><literal>?&lt;<value>name</value>&gt;</literal></td>
<td>Совместимый с Perl 5.10 синтаксис, поддерживается начиная с PCRE-7.0</td>
</tr>

<tr>
<td><literal>?'<value>name</value>'</literal></td>
<td>Совместимый с Perl 5.10 синтаксис, поддерживается начиная с PCRE-7.0</td>
</tr>

<tr>
<td><literal>?P&lt;<value>name</value>&gt;</literal></td>
<td>Python-совместимый синтаксис, поддерживается начиная с PCRE-4.0</td>
</tr>

</table>

Если nginx отказывается запускаться и выдаёт сообщение об ошибке:

<programlisting>
pcre_compile() failed: unrecognized character after (?&lt; in ...
</programlisting>

то это значит, что используется старая версия библиотеки PCRE и следует
вместо этого попробовать синтаксис
“<literal>?P&lt;<value>name</value>&gt;</literal>”.
Также можно использовать нумерованные выделения:

<programlisting>
server {
    server_name   ~^(www\.)?(.+)$;

    location / {
        root   /sites/<b>$2</b>;
    }
}
</programlisting>

Однако такое использование должно ограничиваться простыми случаями как в
примере выше, поскольку нумерованные выделения легко могут быть перезаписаны.
</para>


</section>


<section id="miscellaneous_names"
        name="Прочие имена">

<para>
Некоторые имена имеют специальное значение.
</para>

<para>
Если необходимо обрабатывать запросы без поля <header>Host</header> в заголовке
в блоке <link doc="ngx_http_core_module.xml" id="server"/>, который не
является сервером по умолчанию, следует указать пустое имя:

<programlisting>
server {
    listen       80;
    server_name  example.org  www.example.org  "";
    ...
}
</programlisting>
</para>

<para>
Если директива
<link doc="ngx_http_core_module.xml" id="server_name"/>
не задана в блоке <link doc="ngx_http_core_module.xml" id="server"/>,
то nginx будет использовать пустое имя в качестве имени сервера.
<note>
Версии nginx вплоть до 0.8.48 в этом случае использовали имя хоста (hostname)
машины в качестве имени сервера.
</note>
</para>

<para>
Если имя сервера задано как “<literal>$hostname</literal>” (0.9.4), то
используется имя хоста (hostname) машины.
</para>

<para>
Если в запросе вместо имени сервера указан IP-адрес,
то поле <header>Host</header> заголовка запроса будет содержать
IP-адрес, и запрос можно обработать, используя IP-адрес как имя сервера:

<programlisting>
server {
    listen       80;
    server_name  example.org
                 www.example.org
                 ""
                 <b>192.168.1.1</b>
                 ;
    ...
}
</programlisting>
</para>

<para>
В примерах конфигурации серверов, обрабатывающих все запросы, встречается
странное имя “<literal>_</literal>”:

<programlisting>
server {
    listen       80  default_server;
    server_name  _;
    return       444;
}
</programlisting>

Оно не является каким-то особенным, это просто одно из множества
некорректных доменных имён, которые никогда не пересекутся ни с одним из
реальных имён.
С тем же успехом можно использовать имена типа “<literal>--</literal>”
и “<literal>!@#</literal>”.
</para>

<para>
Версии nginx вплоть до 0.6.25 поддерживали специальное имя
“<literal>*</literal>”, которое многими неверно воспринималось как
имя сервера для обработки всех запросов.
Оно никогда так не работало, и не работало как имя с маской.
Это имя действовало так же, как сейчас действует директива
<link doc="ngx_http_core_module.xml" id="server_name_in_redirect"/>.
Специальное имя “<literal>*</literal>” объявлено устаревшим, а вместо него
следует использовать директиву
<link doc="ngx_http_core_module.xml" id="server_name_in_redirect"/>.
Заметьте, что с помощью директивы
<link doc="ngx_http_core_module.xml" id="server_name"/>
нельзя задать ни имя сервера для обработки всех запросов,
ни сервер по умолчанию.
Это является свойством директивы
<link doc="ngx_http_core_module.xml" id="listen"/>,
а не
<link doc="ngx_http_core_module.xml" id="server_name"/>.
См. также “<link doc="request_processing.xml"/>”.
Можно настроить серверы, слушающие на портах *:80 и *:8080,
и указать, что один из них будет сервером по умолчанию для порта *:8080,
а другой — для порта *:80:
<programlisting>
server {
    listen       80;
    listen       8080  default_server;
    server_name  example.net;
    ...
}

server {
    listen       80  default_server;
    listen       8080;
    server_name  example.org;
    ...
}
</programlisting>
</para>


</section>


<section id="idn"
        name="Интернационализованные имена">
<para>
Для указания интернационализированных доменных имён
(<link url="https://en.wikipedia.org/wiki/Internationalized_domain_name">IDNs</link>)
в директиве <link doc="ngx_http_core_module.xml" id="server_name"/>
следует указывать Punycode-представление имени:
<programlisting>
server {
    listen       80;
    server_name  xn--e1afmkfd.xn--80akhbyknj4f;  # пример.испытание
    ...
}
</programlisting>
</para>

</section>


<section id="virtual_server_selection"
        name="Выбор виртуального сервера">

<para>
Сначала соединение создаётся в контесте сервера по умолчанию.
Затем имя сервера может быть определено
на следующих стадиях обработки запроса,
каждая из которых участвует в выборе конфигурации:

<list type="bullet">

<listitem>
<para>
предварительно во время операции SSL handshake согласно
<link doc="configuring_https_servers.xml" id="sni">SNI</link>
</para>
</listitem>

<listitem>
<para>
после обработки строки запроса
</para>
</listitem>

<listitem>
<para>
после обработки поля <literal>Host</literal> заголовка запроса
</para>
</listitem>

<listitem>
<para>
если после обработки строки запроса или
поля <literal>Host</literal> заголовка запроса имя сервера не было выбрано,
то nginx будет использовать пустое имя в качестве имени сервера.
</para>
</listitem>

</list>

На каждой из этих стадий могут применяться различные конфигурации сервера.
Таким образом, некоторые директивы следует указывать с осторожностью:
<list type="bullet">

<listitem>
в случае использования
директивы <link doc="ngx_http_ssl_module.xml" id="ssl_protocols"/>
список протоколов задаётся библиотекой OpenSSL
перед применением конфигурации сервера согласно имени,
запрашиваемого через SNI.
Таким образом, протоколы должны быть заданы только для сервера по умолчанию;
</listitem>

<listitem>
директивы
<link doc="ngx_http_core_module.xml" id="client_header_buffer_size"/>
и
<link doc="ngx_http_core_module.xml" id="merge_slashes"/>
задействуются перед чтением строки запроса,
таким образом они используют конфигурацию сервера по умолчанию или
конфигурацию сервера, выбранного через SNI;
</listitem>

<listitem>
в случае использования директив
<link doc="ngx_http_core_module.xml" id="ignore_invalid_headers"/>,
<link doc="ngx_http_core_module.xml" id="large_client_header_buffers"/>
и
<link doc="ngx_http_core_module.xml" id="underscores_in_headers"/>,
которые участвуют в обработке полей заголовка запроса,
выбор сервера дополнительно зависит от того,
была ли обновлена конфигурация сервера
согласно строке запроса или полю заголовка <literal>Host</literal>;
</listitem>

<listitem>
ошибочный ответ будет обработан с помощью
директивы <link doc="ngx_http_core_module.xml" id="error_page"/>
в том сервере, который в настоящий момент выполняет запрос.
</listitem>

</list>
</para>

</section>


<section id="optimization"
        name="Оптимизация">

<para>
Точные имена, имена с масками, начинающиеся со звёздочки,
и имена с масками, заканчивающиеся на звёздочку, хранятся
в трёх хэш-таблицах, привязанных к слушающим портам.
Размеры хэш-таблиц оптимизируются на фазе конфигурации таким образом,
что имя может быть найдено с минимальным числом непопаданий в кэш процессора.
Подробнее настройка хэш-таблиц обсуждается в отдельном
<link doc="../hash.xml">документе</link>.
</para>

<para>
В первую очередь имя ищется в хэш-таблице точных имён.
Если имя не было найдено, то имя ищется в хэш-таблице имён с масками,
начинающихся со звёздочки.
Если и там поиск не дал результата, то имя ищется в хэш-таблице имён с масками,
оканчивающихся на звёздочку.
</para>

<para>
Поиск в хэш-таблице имён с масками медленнее, чем поиск в хэш-таблице точных
имён, поскольку имена сравниваются по доменным частям.
Заметьте, что специальное имя с маской вида “<literal>.example.org</literal>”
хранится в хэш-таблице имён с масками, а не в хэш-таблице точных имён.
</para>

<para>
Регулярные выражения проверяются последовательно,
а значит являются самым медленным и плохо масштабируемым методом.
</para>

<para>
По вышеизложенным причинам предпочтительнее использовать точные имена,
где это только возможно.
Например, если к серверу наиболее часто обращаются по именам
<literal>example.org</literal> и <literal>www.example.org</literal>,
то эффективнее будет указать их явно:

<programlisting>
server {
    listen       80;
    server_name  example.org  www.example.org  *.example.org;
    ...
}
</programlisting>

нежели чем использовать упрощённую форму:

<programlisting>
server {
    listen       80;
    server_name  .example.org;
    ...
}
</programlisting>
</para>

<para>
Если задано большое число имён серверов, либо заданы необычно
длинные имена, возможно потребуется скорректировать значения директив
<link doc="ngx_http_core_module.xml" id="server_names_hash_max_size"/>
и <link doc="ngx_http_core_module.xml" id="server_names_hash_bucket_size"/>
на уровне <i>http</i>.
Значение по умолчанию директивы
<link doc="ngx_http_core_module.xml" id="server_names_hash_bucket_size"/>
может быть равно 32, 64, либо другой величине,
в зависимости от размера строки кэша процессора.
Если значение по умолчанию равно 32 и имя сервера задано как
“<literal>too.long.server.name.example.org</literal>”,
то nginx откажется запускаться и выдаст сообщение об ошибке:

<programlisting>
could not build the server_names_hash,
you should increase server_names_hash_bucket_size: 32
</programlisting>

В этом случае следует увеличить значение директивы до следующей степени двойки:

<programlisting>
http {
    server_names_hash_bucket_size  64;
    ...
</programlisting>

Если задано большое число имён серверов, то будет выдано другое
сообщение об ошибке:

<programlisting>
could not build the server_names_hash,
you should increase either server_names_hash_max_size: 512
or server_names_hash_bucket_size: 32
</programlisting>

В таком случае сначала следует попробовать установить
<link doc="ngx_http_core_module.xml" id="server_names_hash_max_size"/>
в величину, близкую к числу имён серверов,
и только если это не поможет
или время запуска nginx станет неприемлемо большим, следует попытаться увеличить
<link doc="ngx_http_core_module.xml" id="server_names_hash_bucket_size"/>.
</para>

<para>
Если сервер является единственным сервером для слушающего порта,
то nginx не будет проверять имена сервера вообще (а также не будет
строить хэш-таблицы для слушающего порта).
За одним исключением: если имя сервера задано регулярным выражением
с выделениями, то nginx’у придётся выполнить это выражение,
чтобы получить значения выделений.
</para>

</section>


<section id="compatibility"
        name="Совместимость">

<para>
<list type="bullet">

<listitem>
Специальное имя сервера “<literal>$hostname</literal>” поддерживается начиная с
версии 0.9.4.
</listitem>

<listitem>
Имя сервера по умолчанию является пустой строкой “” начиная с версии 0.8.48.
</listitem>

<listitem>
Именованные выделения в именах серверов, заданных с помощью регулярных
выражений, поддерживаются начиная с версии 0.8.25.
</listitem>

<listitem>
Выделения в именах серверов, заданных с помощью регулярных выражений,
поддерживаются начиная с версии 0.7.40.
</listitem>

<listitem>
Пустое имя сервера “” поддерживается начиная с версии 0.7.12.
</listitem>

<listitem>
В качестве первого имени сервера можно задать маску или регулярное выражение
начиная с версии 0.6.25.
</listitem>

<listitem>
Регулярные выражения в имени сервера поддерживаются начиная с версии 0.6.7.
</listitem>

<listitem>
Имена с маской вида <literal>example.*</literal> поддерживаются начиная
с версии 0.6.0.
</listitem>

<listitem>
Специальная форма имени вида <literal>.example.org</literal> поддерживается
начиная с версии 0.3.18.
</listitem>

<listitem>
Имена с маской вида <literal>*.example.org</literal> поддерживаются начиная
с версии 0.1.13.
</listitem>

</list>
</para>

</section>

</article>