Types de conteneurs de sections de
configuration
core
mod_version
mod_proxy
Directory
DirectoryMatch
Files
FilesMatch
If
IfDefine
IfModule
IfVersion
Location
LocationMatch
MDomainSet
Proxy
ProxyMatch
VirtualHost
Il existe deux grands types de conteneurs. La plupart des conteneurs sont
évalués pour chaque requête. Les directives qu'ils contiennent s'appliquent
seulement aux requêtes qui sont concernées par le conteneur. En revanche,
les conteneurs
IfDefine, IfModule, et
IfVersion sont
évalués seulement au démarrage et au redémarrage du serveur.
Si leurs conditions sont vérifiées au démarrage, les directives qu'ils contiennent
s'appliqueront à toutes les requêtes. Si leurs conditions ne sont pas vérifiées, les
directives qu'ils contiennent seront ignorées.
Le conteneur IfDefine
contient des directives qui ne seront appliquées que si un paramètre approprié a
été défini dans la ligne de commande de httpd ou via une
directive Define. Par exemple, avec la
configuration suivante, toutes les requêtes seront redirigées vers un autre site
si le serveur est démarré en utilisant la ligne de commande : httpd
-DClosedForNow
:
<IfDefine ClosedForNow>
Redirect "/" "http://otherserver.example.com/"
</IfDefine>
Le conteneur IfModule
est similaire; les directives qu'il contient ne s'appliqueront que si
un module particulier est disponible au niveau du serveur.
Le module doit être soit compilé statiquement dans le serveur, soit
dynamiquement et dans ce cas, la ligne LoadModule correspondante doit apparaître
plus haut dans le fichier de configuration. Ce conteneur ne doit être
utilisé que dans le cas où votre fichier de configuration doit fonctionner
indépendamment de la présence ou de l'absence de certains modules.
Il ne doit pas contenir de directives que vous souhaitez voir s'appliquer
systématiquement, car vous pouvez perdre ainsi de précieux messages d'erreur
à propos de modules manquants.
Dans l'exemple suivant, la directive MimeMagicFile ne s'appliquera que si le
module mod_mime_magic est disponible.
<IfModule mod_mime_magic.c>
MimeMagicFile "conf/magic"
</IfModule>
Le conteneur
IfVersion
est similaire aux conteneurs IfDefine et IfModule; les directives qu'il contient ne
s'appliqueront que si une version particulière du serveur s'exécute. Ce
conteneur a été conçu pour une utilisation dans les suites de tests
et les grands réseaux qui doivent prendre en compte différentes versions
et configurations de httpd.
<IfVersion >= 2.4>
# les directives situées ici ne s'appliquent que si la version
# est supérieure ou égale à 2.4.0.
</IfVersion>
IfDefine,
IfModule, et
IfVersion
peuvent inverser leur test conditionnel en le faisant précéder d'un "!".
De plus, ces sections peuvent être imbriquées afin de définir des restrictions
plus complexes.
Système de fichiers,
arborescence du site web et expressions booléennes
Les conteneurs de sections de configuration les plus couramment utilisés
sont ceux qui modifient la configuration de points particuliers du système de
fichiers ou de l'arborescence du site web. Tout d'abord, il est important de
comprendre la différence entre les deux. Le système de fichiers est une vue
de vos disques tels qu'ils sont perçus par votre système d'exploitation.
Par exemple, avec une installation par défaut,
Apache httpd est situé dans /usr/local/apache2
pour le système de
fichiers UNIX, ou "c:/Program Files/Apache Group/Apache2"
pour
le système de fichiers Windows. (Notez que des slashes directs doivent
toujours être utilisés comme séparateur de chemin
dans les fichiers de configuration d'Apache httpd, même sous
Windows.) Quant à
l'arborescence du site web, il s'agit d'une vue de votre site
tel que présenté par le
serveur web et perçue par le client. Ainsi le chemin /dir/
dans
l'arborescence du site web correspond au chemin
/usr/local/apache2/htdocs/dir/
dans le système de fichiers pour
une installation d'Apache httpd par défaut sous UNIX.
En outre, l'arborescence du site web n'a pas besoin de correspondre en permanence au
système de fichiers, car les pages web peuvent être générées dynamiquement
à partir de bases de données ou d'autres emplacements.
Conteneurs de système de fichiers
Les conteneurs Directory
et Files,
ainsi que leurs équivalents acceptant les
expressions rationnelles,
appliquent des directives à certaines parties du système de fichiers.
Les directives contenues dans une section Directory s'appliquent au répertoire
précisé, ainsi qu'à tous ses sous-répertoires et aux fichiers que ces
derniers contiennent.
Le même effet peut être obtenu en utilisant les fichiers .htaccess. Par exemple, avec la
configuration suivante, l'indexation sera activée pour le répertoire
/var/web/dir1
et tous ses sous-répertoires.
<Directory "/var/web/dir1">
Options +Indexes
</Directory>
Les directives contenues dans une section Files s'appliquent à tout fichier
avec le nom spécifié, quel que soit le répertoire dans lequel il se trouve.
Ainsi par exemple, les directives de configuration suivantes, si elles sont
placées dans la section principale du fichier de configuration, vont interdire
l'accès à tout fichier nommé private.html
quel que soit
l'endroit où il se trouve.
<Files "private.html">
Require all denied
</Files>
Pour faire référence à des fichiers qui se trouvent en des points
particuliers du système de fichiers, les sections
Files et
Directory
peuvent être combinées. Par exemple, la configuration suivante va interdire
l'accès à /var/web/dir1/private.html
,
/var/web/dir1/subdir2/private.html
,
/var/web/dir1/subdir3/private.html
, ainsi que toute instance de
private.html
qui se trouve dans l'arborescence
/var/web/dir1/
.
<Directory "/var/web/dir1">
<Files "private.html">
Require all denied
</Files>
</Directory>
Conteneurs de l'arborescence du site web
le conteneur Location
et son équivalent acceptant les
expressions rationnelles, modifient quant à eux la
configuration de parties de l'arborescence du site web. Par exemple, la
configuration suivante interdit l'accès à toute URL dont la partie chemin
commence par /private.
En particulier, l'interdiction s'appliquera aux requêtes pour :
http://yoursite.example.com/private
,
http://yoursite.example.com/private123
, et
http://yoursite.example.com/private/dir/file.html
ainsi qu'à
toute requête commençant par la chaîne de caractères /private
.
<LocationMatch "^/private">
Require all denied
</LocationMatch>
Le conteneur Location
n'a pas besoin de faire référence à un élément du système de fichiers.
Par exemple, l'exemple suivant montre comment faire référence à une URL
particulière vers un gestionnaire interne du serveur HTTP Apache fourni par le module
mod_status.
Il n'est pas nécessaire de trouver un fichier nommé server-status
dans le système de fichiers.
<Location "/server-status">
SetHandler server-status
</Location>
Espace web imbriqué
Pour contrôler deux URLs imbriquées, on doit tenir compte de l'ordre
dans lequel certaines sections ou directives sont évaluées. Pour
Location, on doit
avoir :
<Location "/foo">
</Location>
<Location "/foo/bar">
</Location>
Les directives Alias, quant à elles, sont évaluées vice-versa :
Alias "/foo/bar" "/srv/www/uncommon/bar"
Alias "/foo" "/srv/www/common/foo"
Ceci est aussi vrai pour les directives ProxyPass :
ProxyPass "/special-area" "http://special.example.com" smax=5 max=10
ProxyPass "/" "balancer://mycluster/" stickysession=JSESSIONID|jsessionid nofailover=On
Caractères de remplacement
et expressions rationnelles
Les conteneurs
Directory,
Files, et
Location
peuvent utiliser des caractères de remplacement de style shell comme dans
la fonction fnmatch
de la bibliothèque C standard.
Le caractère "*"
correspond à toute séquence de caractères, "?" à un caractère seul,
et "[seq]" à tout caractère contenu dans seq.
Le caractère "/"
ne peut pas faire l'objet d'un remplacement;
il doit être spécifié explicitement.
Si une définition des critères de correspondance
encore plus souple est nécessaire, chaque conteneur
possède son équivalent acceptant les expressions rationnelles : DirectoryMatch, FilesMatch, et LocationMatch acceptent les
expressions rationnelles compatibles Perl
pour définir les critères de correspondance. Mais voyez plus loin la section
à propos de la combinaison des sections de configuration
pour comprendre comment l'utilisation de
conteneurs avec des expressions rationnelles va modifier la manière
dont les directives sont appliquées.
Un conteneur qui modifie la configuration de tous les
répertoires utilisateurs à l'aide de caractères de remplacement
mais sans utiliser
les expressions rationnelles pourrait ressembler à ceci :
<Directory "/home/*/public_html">
Options Indexes
</Directory>
Avec les conteneurs utilisant les expressions rationnelles,
on peut interdire l'accès à de nombreux types de fichiers d'images
simultanément :
+<FilesMatch "\.(?i:gif|jpe?g|png)$">
Require all denied
</FilesMatch>
Les expressions rationnelles contenant des groupes nommés et
des références arrières sont ajoutées à l'environnement avec
leur nom en majuscules. Ceci permet de référencer des éléments de
chemins de fichiers et d'URLs depuis une expression et au sein de modules comme
mod_rewrite.
<DirectoryMatch "^/var/www/combined/(?<SITENAME>[^/]+)">
Require ldap-group "cn=%{env:MATCH_SITENAME},ou=combined,o=Example"
</DirectoryMatch>
Expressions booléennes
La directive If
permet de modifier la configuration en fonction d'une condition qui peut
être définie sous la forme d'une expression booléenne. Dans l'exemple
suivant, l'accès est interdit si l'en-tête HTTP Referer ne commence pas
par "http://www.example.com/".
<If "!(%{HTTP_REFERER} -strmatch 'http://www.example.com/*')">
Require all denied
</If>
Que faut-il utiliser et quand ?
Choisir entre des conteneurs de système de fichiers et des conteneurs
d'arborescence du site web est vraiment très simple.
Pour appliquer des directives à des objets qui résident dans le système de
fichiers, utilisez toujours un conteneur Directory ou Files. Pour appliquer des directives à des objets
qui ne résident pas dans le système de fichiers (comme une page web générée
par une base de données), utilisez un conteneur Location.
Il ne faut jamais utiliser un conteneur Location pour restreindre l'accès à des
objets du système de fichiers, car plusieurs localisations de
l'arborescence du site web (URLs) peuvent correspondre à la même localisation
du système de fichier, ce qui peut permettre de contourner vos restrictions.
Par exemple, imaginez la configuration suivante :
<Location "/dir/">
Require all denied
</Location>
Elle fonctionne correctement si la requête appelle
http://yoursite.example.com/dir/
. Mais que va-t-il se passer si
votre système de fichiers est insensible à la casse ?
Votre restriction va pouvoir être tout simplement contournée en envoyant une
requête sur
http://yoursite.example.com/DIR/
. Le conteneur Directory, quant à lui, s'appliquera
à tout contenu servi à partir de cette localisation,
sans tenir compte de la manière dont il est appelé.
(Les liens du système de fichiers constituent une exception.
Le même répertoire peut être placé dans plusieurs parties du système de
fichiers en utilisant des liens symboliques. Le conteneur
Directory va suivre le
lien symbolique sans modifier le nom du chemin. Par conséquent, pour plus de
sécurité, les liens symboliques doivent être désactivés à l'aide de la
directive
Options appropriée.)
Si vous pensez que vous n'êtes pas concerné par ce problème
parceque vous utilisez un système de fichiers sensible à la casse,
gardez à l'esprit qu'il y a de nombreuses autres manières pour faire
correspondre plusieurs localisations de l'arborescence du site web à la même
localisation du système de fichiers. C'est pourquoi vous devez autant que
possible toujours utiliser les conteneurs de système de fichiers.
Il y a cependant une exception à cette règle. Placer des restrictions de
configuration dans un conteneur <Location
"/">
est tout à fait sans rique car ce conteneur va s'appliquer à
toutes les requêtes sans tenir compte de l'URL spécifique.
Imbrication des sections
Certains types de sections peuvent être imbriqués : d'une part, on peut
utiliser les sections Files
à l'intérieur des sections Directory, d'autre part, on peut utiliser les
directives If à l'intérieur
des sections Directory,
Location et Files (mais pas à l'intérieur d'une
autre section If). Les
valeurs des expressions rationnelles correspondant aux sections nommées se
comportent de manière identique.
Les sections imbriquées sont fusionnées après les sections
non-imbriquées de même type.
Comment les sections sont combinées entre elles
Les sections de configuration sont appliquées dans un ordre très particulier.
Il est important de savoir comment cet ordre est défini car il peut avoir
des effets importants sur la manière dont les directives de configuration
sont interprétées.
L'ordre dans lequel les sections sont appliquées est :
- Les sections Directory (à l'exception des
expressions rationnelles)
et les fichiers
.htaccess
sont appliquées simultanément (avec
la possibilité pour .htaccess
, s'il y est autorisé, de
prévaloir sur
Directory)
- Les sections
DirectoryMatch
(et
<Directory "~">
)
- Les sections Files et FilesMatch sont appliquées
simultanément
- Les sections
Location
et LocationMatch sont appliquées
simultanément
- Les directives If
Quelques remarques importantes :
- Mises à part les sections Directory, dans chaque groupe, les sections sont
traitées selon
l'ordre dans lequel elles apparaissent dans les fichiers de configuration.
Par exemple, une requête pour /foo/bar correspondra à
<Location "/foo/bar">
et <Location
"/foo">
(dans ce cas le groupe 4) : les deux sections seront
évaluées mais selon l'ordre dans lequel elles apparaissent dans le fichier
de configuration..
- Les sections Directory (groupe 1 ci-dessus)
sont traitées dans l'ordre du répertoire le plus court vers le plus long.
Par exemple,
<Directory "/var/web/dir">
sera
traitée avant <Directory
"/var/web/dir/subdir">
.
- Si plusieurs sections Directory s'appliquent au même
répertoire, elles sont traitées selon l'ordre dans lequel elles
apparaissent dans le fichier de configuration.
- Les sections de configuration incluses via la directive Include sont traitées comme si elles se
trouvaient réellement dans le fichier qui les inclut à la position de la
directive
Include.
- Les sections situées à l'intérieur de sections VirtualHost
sont appliquées après les sections correspondantes situées en
dehors de la définition de l'hôte virtuel, ce qui permet à l'hôte virtuel
de prévaloir sur la configuration du serveur principal.
- Quand la requête est servie par le module mod_proxy,
le conteneur Proxy
prend la place du conteneur Directory dans l'ordre de traitement.
Note technique
Une séquence <Location>
/<LocationMatch>
est réellement traitée juste avant la phase de traduction du nom
(où Aliases
et DocumentRoots
sont utilisés pour faire correspondre les URLs aux noms de fichiers).
Les effets de cette séquence disparaissent totalement lorsque
la traduction est terminée.
Interactions entre
modules et sections de configuration
Une question se pose souvent après avoir lu comment les sections de
configuration sont fusionnées : comment et quand les directives de modules
particuliers comme mod_rewrite sont-elles interprétées ? La
réponse n'est pas triviale et nécessite un approfondissement. Chaque module
httpd gère sa propre configuration, et chacune de ses directives dans
httpd.conf définit un élément de configuration dans un contexte particulier.
httpd n'exécute pas une commande au moment où elle est lue.
A l'exécution, le noyau de httpd parcourt les sections de configuration
dans l'ordre décrit ci-dessus afin de déterminer lesquelles s'appliquent à
la requête courante. Lorsqu'une première section s'applique, elle est
considérée comme la configuration courante pour cette requête. Si une
section suivante s'applique aussi, chaque module qui possède des directives
dans chacune de ces sections a la possibilité de fusionner sa configuration
entre ces deux sections. Il en résulte une troisième configuration et le
processus de fusion se poursuit jusqu'à ce que toutes les sections de
configuration aient été évaluées.
Après l'étape précédente, le traitement proprement dit de la requête HTTP
peut commencer : chaque module peut effectuer toute tâche qui lui incombe,
et pour déterminer de quelle manière dont il doit agir, il peut s'appuyer
sur le noyau de httpd pour retrouver sa configuration globale issue de la
fusion précédente.
Un exemple permet de mieux visualiser l'ensemble du processus. La
configuration suivante utilise la directive Header du module
mod_headers pour définir un en-tête HTTP spécifique. Quelle
valeur httpd va-t-il affecter à l'en-tête CustomHeaderName
pour
une requête vers /example/index.html
?
<Directory "/">
Header set CustomHeaderName one
<FilesMatch ".*">
Header set CustomHeaderName three
</FilesMatch>
</Directory>
<Directory "/example">
Header set CustomHeaderName two
</Directory>
- Directory "/" s'applique, et une configuration
initiale est créée qui définit l'en-tête
CustomHeaderName
avec la valeur one
.
- Directory "/example" s'applique, et comme
mod_headers spécifie dans son code que
la valeur d'un en-tête doit être écrasée si ce dernier est défini à
nouveau, une nouvelle configuration est créée qui définit l'en-tête
CustomHeaderName
avec la valeur two
.
- FilesMatch ".*" s'applique, une nouvelle
opportunité de fusion surgit, et l'en-tête
CustomHeaderName
est défini à la valeur three
.
- Finalement, au cours des étapes suivantes du traitement de la
requête HTTP, mod_headers sera sollicité, et il se
basera sur la configuration qui a défini l'en-tête
CustomHeaderName
à la valeur three
.
mod_headers utilise normalement cette configuration pour
accomplir sa tâche, à savoir définir des en-têtes HTTP. Cela ne veut
cependant pas dire qu'un module ne peut pas effectuer des actions plus
complexes comme désactiver des directives car elle ne sont pas
nécessaires ou obsolètes, etc...
Ceci est aussi vrai pour les fichiers .htaccess car ils possèdent la même
priorité que les sections Directory dans l'ordre de
fusion. Il faut bien comprendre que les sections de configuration comme
Directory et FilesMatch ne
sont pas comparables avec les directives spécifiques de modules comme
Header ou RewriteRule car elles agissent à des
niveaux différents.
Quelques exemples utiles
Voici un exemple imaginaire qui montre l'ordre de combinaison des sections.
En supposant qu'elles s'appliquent toutes à la requête, les directives de
cet exemple seront appliquées dans l'ordre suivant : A > B > C > D >
E.
<Location "/">
E
</Location>
<Files "f.html">
D
</Files>
<VirtualHost *>
<Directory "/a/">
B
</Directory>
</VirtualHost>
<DirectoryMatch "^.*b$">
C
</DirectoryMatch>
<Directory "/a/b">
A
</Directory>
Pour un exemple plus concret, considérez ce qui suit. Sans tenir compte
de toute restriction d'accès placée dans les sections Directory, la section Location sera
évaluée en dernier et permettra un accès au serveur sans aucune restriction.
En d'autres termes, l'ordre de la combinaison des sections est important,
soyez donc prudent !
<Location "/">
Require all granted
</Location>
# Arrghs! Cette section <Directory> n'aura aucun effet
<Directory "/">
<RequireAll>
Require all granted
Require not host badguy.example.com
</RequireAll>
</Directory>