Подробное обсуждение сопоставления виртуальных хостов
В этом документе объясняется, что именно делает Apache HTTP Server, определяя, какой виртуальный хост будет обслуживать запрос.
Большинству пользователей следует прочитать раздел Виртуальные хосты на основе имени и на основе IP-адреса, чтобы решить, какой тип использовать, затем узнать больше о виртуальных хостах на основе имени или на основе IP-адреса, а затем посмотреть примеры.
Если вы хотите разобраться во всех подробностях, вернитесь к этой странице.
Файл конфигурации
Существует основной сервер, который состоит из всех определений, находящихся вне разделов <VirtualHost>.
Существуют виртуальные серверы, называемые виртуальными хостами или vhost, которые определяются разделами <VirtualHost>.
Каждая директива VirtualHost включает один или несколько адресов и необязательные номера портов.
В определении виртуального хоста вместо IP-адресов можно использовать имена узлов, но они разрешаются при запуске, и если разрешение какого-либо имени завершается неудачно, соответствующие определения виртуальных хостов игнорируются. Поэтому такой способ не рекомендуется.
В качестве адреса можно указать *; в этом случае запрос будет сопоставлен, если ни у одного другого виртуального хоста нет явного адреса, по которому был получен запрос.
Адрес в директиве VirtualHost может содержать необязательный номер порта. Если порт не указан, он считается портом-шаблоном; его также можно указать явно с помощью *. Порт-шаблон соответствует любому порту.
(Номера портов, указанные в директиве VirtualHost, не влияют на то, какие порты Apache будет прослушивать; они лишь определяют, какой VirtualHost будет выбран для обработки запроса. Используйте директиву Listen, чтобы задать адреса и порты, которые будет прослушивать сервер.)
Весь набор адресов, включая несколько результатов поиска DNS, называется набором адресов виртуального хоста.
Apache автоматически выполняет сопоставление на основе HTTP-заголовка Host, переданного клиентом, если наиболее точное соответствие для комбинации IP-адреса и порта указано в нескольких виртуальных хостах.
Директива ServerName может находиться в любом месте определения сервера. Однако каждое ее вхождение заменяет предыдущее в пределах этого сервера. Если ServerName не указано, сервер пытается определить его по IP-адресу сервера.
Первый виртуальный хост на основе имени в файле конфигурации для заданной пары IP-адрес:порт имеет особое значение: он используется для всех запросов, полученных по этому адресу и порту, которым не соответствует ServerName или ServerAlias другого виртуального хоста для той же пары IP-адрес:порт. Он также используется для всех SSL-соединений, если сервер не поддерживает индикацию имени сервера.
Полный список имен в директиве VirtualHost обрабатывается так же, как ServerAlias без подстановочных символов (но не переопределяется никаким оператором ServerAlias).
Для каждого виртуального хоста задаются различные значения по умолчанию. В частности:
- Если для виртуального хоста не заданы директивы
ServerAdmin,Timeout,KeepAliveTimeout,KeepAlive,MaxKeepAliveRequests,ReceiveBufferSizeилиSendBufferSize, соответствующее значение наследуется от основного сервера. (То есть наследуется итоговое значение этого параметра, заданное для основного сервера.) - «Значения поиска по умолчанию», определяющие стандартные разрешения для каталогов виртуального хоста, объединяются с соответствующими значениями основного сервера. Сюда входят любые сведения о конфигурации на уровне каталогов для любого модуля.
- Конфигурации каждого модуля на уровне сервера из основного сервера объединяются с конфигурацией виртуального хоста.
По сути, основной сервер рассматривается как набор «значений по умолчанию» или «база», на основе которой создается каждый виртуальный хост. При этом расположение определений основного сервера в файле конфигурации практически не имеет значения: к моменту окончательного объединения вся конфигурация основного сервера уже разобрана. Поэтому определение основного сервера, расположенное после определения виртуального хоста, все равно может повлиять на него.
Если к этому моменту у основного сервера нет ServerName, вместо него используется имя узла, на котором запущен httpd. Набором адресов основного сервера мы будем называть IP-адреса, возвращенные поиском DNS для ServerName основного сервера.
Для всех неопределенных полей ServerName виртуальный хост на основе имени использует адрес, указанный первым в директиве VirtualHost, определяющей этот виртуальный хост.
Любому виртуальному хосту, включающему специальный подстановочный символ _default_, назначается тот же ServerName, что и основному серверу.
Сопоставление виртуальных хостов
Сервер определяет, какой виртуальный хост использовать для запроса, следующим образом:
Поиск по IP-адресу
Когда соединение впервые устанавливается по некоторому адресу и порту, сервер ищет все определения VirtualHost с теми же IP-адресом и портом.
Если точных совпадений для адреса и порта нет, рассматриваются совпадения с подстановочным символом (*).
Если совпадений не найдено, запрос обслуживается основным сервером.
Если для IP-адреса имеются определения VirtualHost, на следующем шаге решается, нужно ли обрабатывать запрос с помощью виртуального хоста на основе IP-адреса или имени.
Виртуальный хост на основе IP-адреса
Если комбинацию IP-адреса и порта, признанную наилучшим совпадением, указывает ровно одна директива VirtualHost, дальнейшие действия не выполняются, а запрос обслуживается соответствующим виртуальным хостом.
Виртуальный хост на основе имени
Если комбинацию IP-адреса и порта, признанную наилучшим совпадением, указывают несколько директив VirtualHost, то на следующих шагах под «списком» понимается список соответствующих виртуальных хостов в том порядке, в котором они указаны в файле конфигурации.
Если соединение использует SSL, сервер поддерживает индикацию имени сервера, а рукопожатие SSL-клиента содержит расширение TLS с запрошенным именем узла, это имя далее используется так же, как заголовок Host: при соединении без SSL. В противном случае для SSL-соединений используется первый виртуальный хост на основе имени, адрес которого совпал. Это важно, поскольку виртуальный хост определяет, какой сертификат сервер будет использовать для соединения.
Если запрос содержит поле заголовка Host:, в списке ищется первый виртуальный хост с соответствующим ServerName или ServerAlias, и запрос обслуживается этим виртуальным хостом. Поле заголовка Host: может содержать номер порта, но Apache всегда игнорирует его и сопоставляет запрос с фактическим портом, на который клиент его отправил.
Первый виртуальный хост в файле конфигурации с указанным IP-адресом имеет наивысший приоритет и перехватывает любой запрос с неизвестным именем сервера, а также запрос без поля заголовка Host: (например, запрос HTTP/1.0).
Постоянные соединения
Описанный выше поиск по IP-адресу выполняется только один раз для конкретного сеанса TCP/IP, тогда как поиск по имени выполняется при каждом запросе в рамках постоянного соединения KeepAlive. Иными словами, в одном постоянном соединении клиент может запрашивать страницы с разных виртуальных хостов на основе имени.
Абсолютный URI
Если URI запроса является абсолютным, его имя узла и порт соответствуют основному серверу или одному из настроенных виртуальных хостов и совпадают с адресом и портом, на которые клиент отправил запрос, то префикс со схемой, именем узла и портом удаляется, а оставшийся относительный URI обслуживается соответствующим основным сервером или виртуальным хостом. Если совпадения нет, URI остается без изменений, а запрос считается прокси-запросом.
Замечания
- Виртуальный хостинг на основе имени применяется после того, как сервер выбрал наиболее подходящий виртуальный хост на основе IP-адреса.
- Если вам не важно, к какому IP-адресу подключился клиент, используйте «*» в качестве адреса каждого виртуального хоста; в этом случае виртуальный хостинг на основе имени будет применяться ко всем настроенным виртуальным хостам.
-
Проверки
ServerNameиServerAliasникогда не выполняются для виртуального хоста на основе IP-адреса. - Значение имеет только порядок виртуальных хостов на основе имени для конкретного набора адресов. Первый виртуальный хост на основе имени в файле конфигурации имеет наивысший приоритет для соответствующего набора адресов.
- Порт в поле заголовка
Host:никогда не используется при сопоставлении. Apache всегда использует фактический порт, на который клиент отправил запрос. - Если у двух виртуальных хостов есть общий адрес, такие общие адреса неявно работают как виртуальные хосты на основе имени. Это новое поведение, появившееся в версии 2.3.11.
- Основной сервер используется для обслуживания запроса только в том случае, если IP-адрес и номер порта, к которым подключился клиент, не соответствуют ни одному виртуальному хосту (включая виртуальный хост
*). Иными словами, основной сервер перехватывает запрос только для неуказанной комбинации адреса и порта (если только для этого порта нет соответствующего виртуального хоста_default_). - Никогда не указывайте имена DNS в директивах
VirtualHost, поскольку это заставит сервер полагаться на DNS при запуске. Кроме того, это создает угрозу безопасности, если вы не контролируете DNS для всех указанных доменов. Дополнительная информация об этом и двух следующих темах доступна здесь. -
Для каждого виртуального хоста всегда следует задавать
ServerName. В противном случае для каждого виртуального хоста потребуется поиск DNS.
Советы
В дополнение к советам на странице Проблемы DNS приведем еще несколько рекомендаций:
- Размещайте все определения основного сервера перед любыми определениями
VirtualHost. (Это упрощает чтение конфигурации: из-за объединения после разбора конфигурации неочевидно, что определения, расположенные вперемешку с виртуальными хостами, могут влиять на все виртуальные хосты.)
© 2018 The Apache Software Foundation
Licensed under the Apache License, Version 2.0.
https://httpd.apache.org/docs/2.4/en/vhosts/details.html