Spec-Zone.ru › Apache HTTP Server

Разделы конфигурации

Директивы в файлах конфигурации могут применяться ко всему серверу или быть ограничены определёнными каталогами, файлами, хостами или URL. В этом документе описано, как использовать контейнеры разделов конфигурации или файлы .htaccess, чтобы изменить область действия других директив конфигурации.

Типы контейнеров разделов конфигурации

Связанные модули Связанные директивы
  • core
  • mod_version
  • mod_proxy
  • <Directory>
  • <DirectoryMatch>
  • <Files>
  • <FilesMatch>
  • <If>
  • <IfDefine>
  • <IfModule>
  • <IfVersion>
  • <Location>
  • <LocationMatch>
  • <MDomainSet>
  • <Proxy>
  • <ProxyMatch>
  • <VirtualHost>

Существует два основных типа контейнеров. Большинство контейнеров проверяются для каждого запроса. Заключённые в них директивы применяются только к запросам, соответствующим условиям контейнера. Контейнеры <IfDefine>, <IfModule> и <IfVersion>, напротив, проверяются только при запуске и перезапуске сервера. Если при запуске их условия истинны, заключённые в них директивы будут применяться ко всем запросам. Если условия не выполняются, заключённые директивы будут проигнорированы.

Директива <IfDefine> заключает в себе директивы, которые применяются только в том случае, если в командной строке httpd задан соответствующий параметр. Например, при следующей конфигурации все запросы будут перенаправляться на другой сайт, только если сервер запущен с использованием httpd -DClosedForNow:

<IfDefine ClosedForNow>
    Redirect "/" "http://otherserver.example.com/"
</IfDefine>

Директива <IfModule> очень похожа, но заключает в себе директивы, которые применяются только в том случае, если на сервере доступен определённый модуль. Модуль должен быть либо статически скомпилирован в сервере, либо скомпилирован динамически, а его строка LoadModule должна находиться в файле конфигурации раньше. Эту директиву следует использовать только в том случае, если необходимо, чтобы файл конфигурации работал независимо от того, установлены ли определённые модули. Не следует заключать в неё директивы, которые должны работать всегда, поскольку это может скрыть полезные сообщения об ошибках, связанных с отсутствующими модулями.

В следующем примере директива MimeMagicFile будет применена только в том случае, если доступна mod_mime_magic.

<IfModule mod_mime_magic.c>
    MimeMagicFile "conf/magic"
</IfModule>

Директива <IfVersion> очень похожа на <IfDefine> и <IfModule>, но заключает в себе директивы, которые применяются только при работе определённой версии сервера. Этот модуль предназначен для использования в наборах тестов и крупных сетях, которым приходится работать с разными версиями httpd и разными конфигурациями.

<IfVersion >= 2.4>
    # this happens only in versions greater or
    # equal 2.4.0.
</IfVersion>

Директивы <IfDefine>, <IfModule> и <IfVersion> могут задавать отрицательные условия, если перед проверкой поставить «!». Кроме того, эти разделы можно вкладывать друг в друга, чтобы задавать более сложные ограничения.

Файловая система, веб-пространство и булевы выражения

Чаще всего используются контейнеры разделов конфигурации, которые изменяют конфигурацию для определённых мест в файловой системе или веб-пространстве. Прежде всего важно понимать разницу между ними. Файловая система — это представление дисков, доступное операционной системе. Например, при установке по умолчанию Apache httpd находится по адресу /usr/local/apache2 в файловой системе Unix или "c:/Program Files/Apache Group/Apache2" в файловой системе Windows. (Обратите внимание: в файлах конфигурации Apache httpd в качестве разделителя пути всегда следует использовать прямую косую черту, даже в Windows.) Веб-пространство, напротив, — это представление сайта, которое формируется веб-сервером и отображается клиенту. Поэтому путь /dir/ в веб-пространстве соответствует пути /usr/local/apache2/htdocs/dir/ в файловой системе при установке Apache httpd по умолчанию в Unix. Веб-пространство не обязательно напрямую соответствует файловой системе, поскольку веб-страницы могут динамически формироваться из баз данных или других источников.

Контейнеры файловой системы

Директивы <Directory> и <Files>, а также их аналоги с регулярными выражениями, применяют директивы к частям файловой системы. Директивы, заключённые в раздел <Directory>, применяются к указанному каталогу файловой системы и всем его подкаталогам (а также к находящимся в них файлам). Того же эффекта можно добиться с помощью файлов .htaccess. Например, в следующей конфигурации индексирование каталогов будет включено для каталога /var/web/dir1 и всех его подкаталогов.

<Directory "/var/web/dir1">
    Options +Indexes
</Directory>

Директивы, заключённые в раздел <Files>, применяются к любому файлу с указанным именем, независимо от того, в каком каталоге он находится. Например, следующие директивы конфигурации, помещённые в основной раздел файла конфигурации, запретят доступ к любому файлу с именем private.html, где бы он ни находился.

<Files "private.html">
    Require all denied
</Files>

Чтобы обратиться к файлам в определённой части файловой системы, можно объединить разделы <Files> и <Directory>. Например, следующая конфигурация запретит доступ к /var/web/dir1/private.html, /var/web/dir1/subdir2/private.html, /var/web/dir1/subdir3/private.html и любому другому экземпляру private.html, найденному в каталоге /var/web/dir1/.

<Directory "/var/web/dir1">
    <Files "private.html">
        Require all denied
    </Files>
</Directory>

Контейнеры веб-пространства

Директива <Location> и её аналог с регулярным выражением, напротив, изменяют конфигурацию для содержимого веб-пространства. Например, следующая конфигурация запрещает доступ к любому URL-пути, начинающемуся с /private. В частности, она будет применяться к запросам для http://yoursite.example.com/private, http://yoursite.example.com/private123 и http://yoursite.example.com/private/dir/file.html, а также к любым другим запросам, начинающимся со строки /private.

<LocationMatch "^/private">
    Require all denied
</LocationMatch>

Директива <Location> не обязательно связана с файловой системой. Например, в следующем примере показано, как сопоставить определённый URL с внутренним обработчиком Apache HTTP Server, предоставляемым mod_status. Файл с именем server-status не обязательно должен существовать в файловой системе.

<Location "/server-status">
    SetHandler server-status
</Location>

Перекрывающиеся области веб-пространства

Чтобы иметь дело с двумя перекрывающимися URL, необходимо учитывать порядок обработки определённых разделов или директив. Для <Location> порядок будет следующим:

<Location "/foo">
</Location>
<Location "/foo/bar">
</Location>

С другой стороны, разделы <Alias> сопоставляются в обратном порядке:

Alias "/foo/bar" "/srv/www/uncommon/bar"
Alias "/foo"     "/srv/www/common/foo"

То же самое относится и к директивам ProxyPass:

ProxyPass "/special-area" "http://special.example.com" smax=5 max=10
ProxyPass "/" "balancer://mycluster/" stickysession=JSESSIONID|jsessionid nofailover=On

Подстановочные знаки и регулярные выражения

В директивах <Directory>, <Files> и <Location> можно использовать подстановочные знаки в стиле оболочки, как в fnmatch из стандартной библиотеки C. Символ «*» соответствует любой последовательности символов, «?» — любому отдельному символу, а «[seq]» — любому символу из seq. Символ «/» не соответствует ни одному подстановочному знаку; его необходимо указывать явно.

Если требуется более гибкое сопоставление, для каждого контейнера есть аналог с регулярным выражением: <DirectoryMatch>, <FilesMatch> и <LocationMatch>. Они позволяют использовать совместимые с Perl регулярные выражения для выбора совпадений. Однако ознакомьтесь с разделом ниже об объединении конфигурации, чтобы узнать, как использование разделов с регулярными выражениями меняет порядок применения директив.

Раздел с подстановочными знаками, не использующий регулярные выражения и изменяющий конфигурацию для всех пользовательских каталогов, может выглядеть так:

<Directory "/home/*/public_html">
    Options Indexes
</Directory>

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

<FilesMatch "\.(?i:gif|jpe?g|png)$">
    Require all denied
</FilesMatch>

Регулярные выражения, содержащие именованные группы и обратные ссылки, добавляются в окружение под соответствующими именами в верхнем регистре. Это позволяет ссылаться на элементы путей к файлам и URL из выражений и таких модулей, как mod_rewrite.

<DirectoryMatch "^/var/www/combined/(?<SITENAME>[^/]+)">
    Require ldap-group "cn=%{env:MATCH_SITENAME},ou=combined,o=Example"
</DirectoryMatch>

Булевы выражения

Директива <If> изменяет конфигурацию в зависимости от условия, которое можно задать булевым выражением. Например, следующая конфигурация запрещает доступ, если заголовок HTTP Referer не начинается с «http://www.example.com/».

<If "!(%{HTTP_REFERER} -strmatch 'http://www.example.com/*')">
    Require all denied
</If>

Что и когда использовать

Выбрать между контейнерами файловой системы и контейнерами веб-пространства на самом деле довольно просто. При применении директив к объектам, находящимся в файловой системе, всегда используйте <Directory> или <Files>. При применении директив к объектам, не находящимся в файловой системе (например, к веб-странице, сформированной из базы данных), используйте <Location>.

Важно никогда не использовать <Location> для ограничения доступа к объектам в файловой системе. Это связано с тем, что несколько разных адресов веб-пространства (URL) могут соответствовать одному и тому же месту в файловой системе, что позволит обойти ограничения. Например, рассмотрим следующую конфигурацию:

<Location "/dir/">
    Require all denied
</Location>

Она работает, если запрос направлен к http://yoursite.example.com/dir/. Но что, если файловая система не учитывает регистр символов? Тогда ограничение можно легко обойти, запросив http://yoursite.example.com/DIR/. В отличие от неё, директива <Directory> применяется ко всему содержимому, обслуживаемому из этого места, независимо от того, как оно вызывается. (Исключение составляют ссылки в файловой системе. Один и тот же каталог можно поместить в несколько мест файловой системы с помощью символических ссылок. Директива <Directory> будет следовать по символической ссылке, не сбрасывая имя пути. Поэтому для обеспечения максимального уровня безопасности символические ссылки следует отключить с помощью соответствующей директивы Options.)

Возможно, вы думаете, что это вас не касается, поскольку ваша файловая система учитывает регистр символов. Но существует множество других способов сопоставить несколько адресов веб-пространства с одним местом в файловой системе. Поэтому по возможности всегда используйте контейнеры файловой системы. Однако из этого правила есть одно исключение. Размещение ограничений конфигурации в разделе <Location "/"> совершенно безопасно, поскольку этот раздел применяется ко всем запросам независимо от конкретного URL.

Вложенность разделов

Некоторые типы разделов можно вкладывать в другие. С одной стороны, <Files> можно использовать внутри <Directory>. С другой стороны, <If> можно использовать внутри разделов <Directory>, <Location> и <Files> (но не внутри другого <If>). Аналоги именованных разделов с регулярными выражениями ведут себя так же.

Вложенные разделы объединяются после невложенных разделов того же типа.

Виртуальные хосты

Контейнер <VirtualHost> заключает в себе директивы, применяемые к определённым хостам. Это полезно, если на одном компьютере обслуживается несколько хостов с разными конфигурациями. Дополнительные сведения см. в документации по виртуальным хостам.

Прокси

Контейнеры <Proxy> и <ProxyMatch> применяют заключённые в них директивы конфигурации только к сайтам, доступ к которым осуществляется через прокси-сервер mod_proxy и которые соответствуют указанному URL. Например, следующая конфигурация разрешит доступ к сайту www.example.com через прокси-сервер только некоторым клиентам:

<Proxy "http://www.example.com/*">
    Require host yournetwork.example.com
</Proxy>

Какие директивы разрешены?

Чтобы узнать, какие директивы разрешены в тех или иных типах разделов конфигурации, проверьте контекст директивы. Всё, что разрешено в разделах <Directory>, синтаксически разрешено и в разделах <DirectoryMatch>, <Files>, <FilesMatch>, <Location>, <LocationMatch>, <Proxy> и <ProxyMatch>. Однако есть несколько исключений:

  • Директива AllowOverride работает только в разделах <Directory>.
  • Директивы FollowSymLinks и SymLinksIfOwnerMatch Options работают только в разделах <Directory> или файлах .htaccess.
  • Директиву Options нельзя использовать в разделах <Files> и <FilesMatch>.

Как объединяются разделы

Разделы конфигурации применяются в строго определённом порядке. Поскольку это может существенно влиять на интерпретацию директив конфигурации, важно понимать, как это работает.

Порядок объединения:

  1. <Directory> (кроме регулярных выражений) и .htaccess обрабатываются одновременно (если это разрешено, .htaccess имеет приоритет над <Directory>)
  2. <DirectoryMatch> (и <Directory "~">)
  3. <Files> и <FilesMatch> обрабатываются одновременно
  4. <Location> и <LocationMatch> обрабатываются одновременно
  5. разделы <If>, даже если они заключены в любой из предшествующих контекстов.

Несколько важных замечаний:

  • За исключением <Directory>, разделы внутри каждой группы обрабатываются в порядке их появления в файлах конфигурации. Например, запрос для /foo/bar соответствует <Location "/foo/bar"> и <Location "/foo"> (в данном случае это группа 4): будут обработаны оба раздела, но в порядке их появления в файлах конфигурации.
  • <Directory> (группа 1 выше) обрабатывается в порядке от самого короткого компонента каталога к самому длинному. Например, <Directory "/var/web/dir"> будет обработан раньше <Directory "/var/web/dir/subdir">.
  • Если к одному каталогу применяются несколько разделов <Directory>, они обрабатываются в порядке их появления в файле конфигурации.
  • Конфигурации, подключённые с помощью директивы Include, рассматриваются так, как если бы они находились во включающем файле в месте расположения директивы Include.
  • Разделы внутри разделов <VirtualHost> применяются после соответствующих разделов за пределами определения виртуального хоста. Это позволяет виртуальным хостам переопределять конфигурацию основного сервера.
  • Если запрос обслуживается посредством mod_proxy, контейнер <Proxy> занимает в порядке обработки место контейнера <Directory>.
  • При смешивании связанных директив конфигурации внутри и вне <If> следует соблюдать осторожность из-за влияния на порядок объединения. Явное использование <Else> может помочь.
  • Если <If> используется в .htaccess, заключённые в него директивы родительского каталога будут объединены после директив подкаталога, не заключённых в контейнер.

Техническое примечание

На самом деле непосредственно перед этапом преобразования имени (на котором Aliases и DocumentRoots используются для сопоставления URL с именами файлов) выполняется последовательность <Location>/<LocationMatch>. Результаты этой последовательности полностью отбрасываются после завершения преобразования.

Взаимосвязь модулей и разделов конфигурации

После знакомства с порядком объединения разделов конфигурации часто возникает вопрос о том, как и когда обрабатываются директивы отдельных модулей, таких как mod_rewrite. Ответ не так прост и требует небольшого пояснения. Каждый модуль httpd управляет собственной конфигурацией, а каждая его директива в httpd.conf задаёт одну часть конфигурации в определённом контексте. httpd не выполняет команду в момент её чтения.

Во время выполнения ядро httpd перебирает определённые разделы конфигурации в описанном выше порядке, чтобы определить, какие из них применяются к текущему запросу. Когда совпадает первый раздел, он считается текущей конфигурацией для этого запроса. Если совпадает и следующий раздел, каждому модулю, директива которого присутствует хотя бы в одном из этих разделов, предоставляется возможность объединить конфигурацию из двух разделов. В результате получается третья конфигурация, и процесс продолжается до тех пор, пока не будут обработаны все разделы конфигурации.

После этого начинается «реальная» обработка HTTP-запроса: каждый модуль получает возможность выполнить необходимые ему задачи. Чтобы определить, как действовать, модули могут получить из ядра httpd собственную итоговую объединённую конфигурацию.

Пример поможет наглядно представить весь процесс. В следующей конфигурации директива Header модуля mod_headers задаёт определённый HTTP-заголовок. Какое значение httpd установит в заголовке CustomHeaderName для запроса к /example/index.html ?

<Directory "/">
    Header set CustomHeaderName one
    <FilesMatch ".*">
        Header set CustomHeaderName three
    </FilesMatch>
</Directory>

<Directory "/example">
    Header set CustomHeaderName two
</Directory>
  • Совпадает Directory «/», после чего создаётся начальная конфигурация для установки заголовка CustomHeaderName со значением one.
  • Совпадает Directory «/example», и поскольку в коде mod_headers указано переопределение при объединении, создаётся новая конфигурация для установки заголовка CustomHeaderName со значением two.
  • Совпадает FilesMatch «.*», и возникает ещё одна возможность объединения, в результате чего заголовку CustomHeaderName присваивается значение three.
  • В конечном итоге, на следующих этапах обработки HTTP-запроса будет вызван mod_headers, который получит конфигурацию для установки заголовка CustomHeaderName со значением three. Обычно mod_headers использует эту конфигурацию для выполнения своей задачи, а именно установки заголовка foo. Это не означает, что модуль не может выполнять более сложные действия, например отбрасывать ненужные или устаревшие директивы и т. п.

Это справедливо и для .htaccess, поскольку при объединении они имеют тот же приоритет, что и Directory. Важно понимать, что такие разделы конфигурации, как Directory и FilesMatch, нельзя сравнивать с директивами конкретных модулей, такими как Header или RewriteRule, поскольку они работают на разных уровнях.

Несколько полезных примеров

Ниже приведён искусственный пример, иллюстрирующий порядок объединения. Если предположить, что все директивы применяются к запросу, в этом примере они будут применены в порядке A > B > C > D > E.

<Location "/">
    E
</Location>

<Files "f.html">
    D
</Files>

<VirtualHost *>
    <Directory "/a/b">
        B
    </Directory>
</VirtualHost>

<DirectoryMatch "^.*b$">
    C
</DirectoryMatch>

<Directory "/a/b">
    A
</Directory>

Для более конкретного примера рассмотрим следующую конфигурацию. Независимо от ограничений доступа, заданных в разделах <Directory>, раздел <Location> будет обработан последним и разрешит неограниченный доступ к серверу. Иными словами, порядок объединения имеет значение, поэтому будьте внимательны!

<Location "/">
    Require all granted
</Location>

# Whoops!  This <Directory> section will have no effect
<Directory "/">
    <RequireAll>
        Require all granted
        Require not host badguy.example.com
    </RequireAll>
</Directory>

© 2018 The Apache Software Foundation
Licensed under the Apache License, Version 2.0.
https://httpd.apache.org/docs/2.4/en/sections.html

Spec-Zone.ru

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