HTTP Mise en oeuvre
1. Apache HTTPd Server
1.1. Introduction à Apache HTTP Server
Le logiciel libre Apache HTTP Server (Apache) est un serveur HTTP créé et maintenu au sein de la fondation Apache. C’est le serveur HTTP le plus populaire du World Wide Web. Il est distribué selon les termes de la licence Apache.
Historique
Apache est apparu en avril 1995. Au début, il s’agissait d’une collection de correctifs et d’additions au serveur NCSA HTTPd 1.3, qui était dans ledomaine public et le serveur HTTP alors le plus répandu. De cette origine, de nombreuses personnes affirment que le nom Apache vient de a patchy server, soit « un serveur rafistolé ». Par la suite, Apache a été complètement réécrit, de sorte que, dans la version 2, il ne reste pas de trace de NCSA HTTPd.
Au début, Apache était la seule alternative sérieuse et libre au serveur HTTP de Netscape (iPlanet, maintenant Sun ONE). Depuis avril 1996, selon l’étude permanente de Netcraft, Apache est devenu le serveur HTTP le plus répandu sur Internet.
Part de marché d’Apache :
- En mai 1999, il faisait tourner 57 % des serveurs Web, début 2004, il était à environ 69 % de parts de marché, et il ne détient plus que 50,61 % du marché à la fin du mois de janvier 2008 ;
- En février 2008, Apache représente 50,93 % des parts de marché ;
- En novembre 2008, 72,45 % de parts de marché pour Apache ;
- En novembre 2011, 65,00 % de parts de marché pour Apache ;
- En mai 2014, 38,00 % de parts de marché pour Apache et 33,00 % pour Microsoft IIS.
- En janvier 2015 sur l’analyse de 876,812,666 sites, correspondant à 5,061,365 ordinateurs frontaux, les parts de marché sont de 39.74 % pour Apache, et 27,52 % pour IIS. Sur les part de marché des serveurs actifs (en excluant les sites parkings) par contre, 50.72 % pour Apache, 14.82 % pour Nginx et IIS passe en 3e position avec seulement 10.55 %, perdant 1.17 % de parts par rapport au mois précédent.
- En février 2017, Apache est utilisé par 59,76% du total des domaines français enregistrés.
La version 2 d’Apache possède plusieurs avancées majeures par rapport à la version 1, entre autres le support de plusieurs plates-formes (Windows, Linux et UNIX, entre autres), le support de processus légers UNIX, une nouvelle API et le support IPv6.
La fondation Apache (Apache Software Foundation ou ASF) a été créée en 1999 à partir du groupe Apache (Apache Group) à l’origine du serveur en 1995. Depuis, de nombreux autres logiciels utiles au World Wide Web sont développés à côté du serveur HTTP.
Voir aussi Comparison of web server software
Disponibilité
Apache fonctionne principalement sur les systèmes d’exploitation UNIX (Linux, Mac OS X, Solaris, BSD et UNIX) et Windows. La version Windows n’est considérée comme stable que depuis la version 1.2 d’Apache. Apache est utilisé par de nombreux produits, dont WebSphere d’IBM, ainsi que par Oracle Corporation.
Fonctionnalités
Apache est conçu pour prendre en charge de nombreux modules lui donnant des fonctionnalités supplémentaires : interprétation du langage Perl, PHP, Python et Ruby, serveur proxy, Common Gateway Interface, Server Side Includes, réécriture d’URL, négociation de contenu, protocoles de communication additionnels, etc. Néanmoins, il est à noter que l’existence de nombreux modules Apache complexifie la configuration du serveur web. En effet, les bonnes pratiques recommandent de ne charger que les modules utiles : de nombreuses failles de sécurité affectant uniquement les modules d’Apache sont régulièrement découvertes.
Les possibilités de configuration d’Apache sont une fonctionnalité phare. Le principe repose sur une hiérarchie de fichiers de configuration, qui peuvent être gérés indépendamment. Cette caractéristique est notamment utile aux hébergeurs qui peuvent ainsi servir les sites de plusieurs clients à l’aide d’un seul serveur HTTP. Pour les clients, cette fonctionnalité est rendue visible par le fichier .htaccess.
Parmi les outils aidant la maintenance d’Apache, les fichiers de log peuvent s’analyser à l’aide de nombreux scripts et logiciels libres tels que AWStats, Webalizer ou W3Perl. Plusieurs interfaces graphiques facilitent la configuration du serveur.
Sources et crédits
- https://fr.wikipedia.org/wiki/Apache_HTTP_Server
- https://httpd.apache.org/docs/2.4/fr/new_features_2_4.html
1.2. Arborescence et architecture logicielle
- Prise en charge des processus
- Modules et configuration de modules
- Fichiers de configuration :
/etc/httpd/conf/
(CentOS) - Emplacement des fichiers à servir :
/var/www/html/
Le logiciel Apache HTTP peut connaître différents emplacements selon la distribution Linux utilisée. On retrouve ces modèles comme étape de configuration d’une compilation par les sources du logiciel. On trouvera dans les sources du logiciel un fichier config.layout qui illustre différents modèles d’emplacement des résultats d’une compilation :
$ head -n35 config.layout
##
## config.layout -- Pre-defined Installation Path Layouts
##
## Hints:
## - layouts can be loaded with configure's --enable-layout=ID option
## - when no --enable-layout option is given, the default layout is `Apache'
## - a trailing plus character (`+') on paths is replaced with a
## `/<target>' suffix where <target> is currently hardcoded to 'apache2'.
## (This may become a configurable parameter at some point.)
##
# Classical Apache path layout.
<Layout Apache>
prefix: /usr/local/apache2
exec_prefix: ${prefix}
bindir: ${exec_prefix}/bin
sbindir: ${exec_prefix}/bin
libdir: ${exec_prefix}/lib
libexecdir: ${exec_prefix}/modules
mandir: ${prefix}/man
sysconfdir: ${prefix}/conf
datadir: ${prefix}
installbuilddir: ${datadir}/build
errordir: ${datadir}/error
iconsdir: ${datadir}/icons
htdocsdir: ${datadir}/htdocs
manualdir: ${datadir}/manual
cgidir: ${datadir}/cgi-bin
includedir: ${prefix}/include
localstatedir: ${prefix}
runtimedir: ${localstatedir}/logs
logfiledir: ${localstatedir}/logs
proxycachedir: ${localstatedir}/proxy
</Layout>
Source : Installation par les sources d’Apache HTTP Server
1.3. Configuration globale
Sous CentOS 7, les directives de configuration se retrouvent dans le fichier /etc/httpd/conf/httpd.conf
.
Directive ServerRoot
La directive ServerRoot
permet de définir le répertoire dans lequel le serveur est installé. En particulier, il contiendra les sous-répertoires conf
/ et logs/
. Les chemins relatifs indiqués dans les autres directives (comme Include
ou LoadModule
) seront définis par rapport à ce répertoire.
Directive ServerSignature
- Syntaxe:
ServerSignature On|Off|EMail
- Défaut:
ServerSignature Off
La directive ServerSignature
permet de définir une ligne de pied de page fixe pour les documents générés par le serveur (messages d’erreur, listings de répertoires ftp de mod_proxy
, sorties de mod_info
, etc…). Dans le cas d’une chaîne de mandataires, l’utilisateur n’a souvent aucun moyen de déterminer lequel des mandataires chaînés a généré un message d’erreur, et c’est une des raisons pour lesquelles on peut être amené à ajouter un tel pied de page.
La valeur par défaut Off
supprime la ligne de pied de page (et est ainsi compatible avec le comportement des versions 1.2 et antérieures d’Apache). la valeur On
ajoute simplement une ligne contenant le numéro de version du serveur ainsi que le nom du serveur virtuel issu de la directive ServerName, alors que la valeur EMail
ajoute en plus une référence “mailto:” à l’administrateur du document référencé issu la directive ServerAdmin.
Directive ServerTokens
- Syntaxe:
ServerTokens Major|Minor|Min[imal]|Prod[uctOnly]|OS|Full
- Défaut:
ServerTokens Full
Cette directive permet de contrôler le contenu de l’en-tête Server inclus dans la réponse envoyée au client : cet en-tête peut contenir le type de système d’exploitation du serveur, ainsi que des informations à propos des modules compilés avec le serveur.
- ServerTokens Full (ou non spécifié) : Le serveur envoie par exemple :
Server: Apache/2.4.2 (Unix) PHP/4.2.2 MyMod/1.2
- ServerTokens Prod[uctOnly] : Le serveur renvoie (par exemple):
Server: Apache
- ServerTokens Major : Le serveur renvoie (par exemple):
Server: Apache/2
- ServerTokens Minor : Le serveur renvoie (par exemple):
Server: Apache/2.4
- ServerTokens Min[imal] : Le serveur renvoie (par exemple):
Server: Apache/2.4.2
- ServerTokens OS : Le serveur renvoie (par exemple): Server:
Apache/2.4.2 (Unix)
Cette définition s’applique à l’ensemble du serveur et ne peut être activée ou désactivée pour tel ou tel serveur virtuel.
Directive LoadModule
- Syntaxe:
LoadModule module nom-fichier
La directive LoadModule
permet de lier le fichier objet ou la bibliothèque nom-fichier avec le serveur, et d’ajouter la structure de module nommée module à la liste des modules actifs. module
est le nom de la variable externe de type module dans le fichier, et est référencé comme Identificateur de module dans la documentation des modules. Exemple :
LoadModule status_module modules/mod_status.so
charge le module spécifié depuis le sous-répertoire des modules situé à la racine du serveur.
1.4. Serveur virtuel basé sur le nom
Comment le serveur sélectionne-t-il le serveur virtuel basé sur le nom approprié
Il est important de savoir que la première étape de la résolution de serveur virtuel basée sur le nom est une résolution basée sur IP. La résolution de serveur virtuel basée sur le nom ne fait que choisir le serveur virtuel basé sur le nom le plus approprié, en se limitant aux candidats qui conviennent le mieux du point de vue IP. La résolution basée sur IP est sans objet si l’on utilise un caractère générique (*
) pour l’adresse IP dans toutes les directives VirtualHost
.
A l’arrivée d’une requête, le serveur va rechercher l’argument de section <VirtualHost>
présentant la meilleure (la plus exacte) correspondance avec la paire adresse IP/port utilisée dans la requête. Si plusieurs serveurs virtuels possèdent cette même paire adresse IP/port, Apache va ensuite comparer les valeurs des directives ServerName
et ServerAlias
avec le nom de serveur présent dans la requête.
Si vous ne définissez pas de directive ServerName
pour un serveur virtuel à base de nom, le serveur utilisera par défaut le nom de domaine entièrement qualifié (FQDN) déduit du nom d’hôte système. Cette configuration sans nom de serveur explicite peut conduire à des erreurs de choix du serveur virtuel à utiliser et est déconseillée.
Le serveur virtuel à base de nom par défaut pour une paire adresse IP/port
Si aucune directive ServerName
ou ServerAlias
ne correspond dans la liste de serveurs virtuels présentant la meilleure correspondance du point de vue adresse IP/port, c’est le premier serveur virtuel de cette liste qui sera utilisé.
Utilisation de serveurs virtuels par nom
- Modules Apparentés : Core
- Directives Apparentées
DocumentRoot
ServerAlias
ServerName
<VirtualHost>
La première étape consiste à créer une section <VirtualHost>
pour chacun des serveurs à définir. Dans chaque section <VirtualHost>
, vous devez définir au minimum une directive ServerName
pour désigner le serveur concerné et une directive DocumentRoot
pour préciser l’emplacement sur le système de fichiers du contenu de ce serveur.
Le serveur principal disparaît
Par exemple, supposez que vous hébergez le domaine www.example.com et que vous souhaitez ajouter le serveur virtuel other.example.com qui pointe sur la même adresse IP. Il vous suffit d’ajouter la configuration suivante à httpd.conf :
<VirtualHost *:80>
# Le premier serveur virtuel de la liste est aussi le
# serveur par défaut pour *:80
ServerName www.example.com
ServerAlias example.com
DocumentRoot "/www/domain"
</VirtualHost>
<VirtualHost *:80>
ServerName other.example.com
DocumentRoot "/www/otherdomain"
</VirtualHost>
Autrement, vous pouvez spécifiez une adresse IP explicite à la place de *
dans la directive <VirtualHost>
. Par exemple, cette méthode est utile si vous souhaitez faire tourner quelques serveurs virtuels par nom sur une même adresse IP, et d’autres, soit par IP, soit basés sur un autre jeu de serveurs virtuels par nom sur une autre adresse IP.
Plusieurs serveurs sont accessibles par plus d’un nom. Il suffit de placer la directive ServerAlias
dans une section <VirtualHost>
. Par exemple, dans la première section <VirtualHost>
ci-dessus, la directive ServerAlias
indique aux utilisateurs les autres noms permis pour accéder au même site Web :
ServerAlias example.com *.example.com
ainsi, toutes les requêtes portant sur un domaine example.com
seront servies par le serveur virtuel www.example.com
. Les caractères joker *
et ?
peuvent être utilisés pour les correspondances. Bien entendu, vous ne pouvez pas inventer des noms et les placer dans une directive ServerName
ou ServerAlias
. Tout d’abord, votre serveur DNS doit être correctement configuré pour lier ces noms à une adresse IP associée avec votre serveur.
La recherche du serveur virtuel à base de nom qui correspond au plus près à la requête s’effectue parmi les <virtualhost>
selon leur ordre d’apparition dans le fichier de configuration. Le premier serveur virtuel dont le ServerName
ou le ServerAlias
correspond est utilisé, sans priorité particulière en cas de présence de caractères génériques (que ce soit pour le ServerName
ou le ServerAlias
).
La liste complète des noms dans la section VirtualHost
sont traités comme une directive ServerAlias
sans caractères génériques.
Finalement, vous pouvez affiner la configuration des serveurs virtuels en plaçant d’autres directives à l’intérieur des sections <VirtualHost>
. La plupart des directives peut être placée dans ces sections en y changeant seulement la configuration du serveur virtuel associé. Pour déterminer si une directive particulière est permise, consultez le contexte de la directive. Le jeu de directives configurées dans le contexte du serveur principal (en dehors de toutes sections <VirtualHost>
) sera utilisé seulement s’il n’y a pas de configuration contraire par un serveur virtuel.
Directive ServerName
Terminologie :
- Serveur virtuel, hôte virtuel, “vhost” : instance HTTP répondant à un domaine sur un même serveur physqiue
- Nom canonique : nom standard dans l’URL
La directive ServerName
permet de définir les protocole, nom d’hôte et port d’une requête que le serveur utilise pour s’authentifier lui-même.
La directive ServerName
permet (éventuellement en conjonction avec la directive ServerAlias) d’identifier de manière unique un serveur virtuel, lorsqu’elle est utilisée dans un contexte de serveurs virtuels à base de noms.
Cette directive est aussi utilisée lors de la création d’URLs de redirection relatives quand la directive UseCanonicalName
est définie à une valeur autre que la valeur par défaut.
Par exemple, si le nom de la machine hébergeant le serveur web est simple.example.com
, la machine possède l’alias DNS www.example.com
, et si vous voulez que le serveur web s’identifie avec cet alias, vous devez utilisez la définition suivante :
ServerName www.example.com
Si vous définissez des serveurs virtuels à base de nom, une directive ServerName
située à l’intérieur d’une section <VirtualHost>
spécifiera quel nom d’hôte doit apparaître dans l’en-tête de requête Host:
pour pouvoir atteindre ce serveur virtuel.
Directive ServerAlias
La directive ServerAlias
permet de définir les noms alternatifs d’un serveur utilisables pour atteindre des serveurs virtuels à base de nom. La directive ServerAlias
peut contenir des caractères génériques, si nécessaire.
<VirtualHost *:80>
ServerName server.example.com
ServerAlias server server2.example.com server2
ServerAlias *.example.com
UseCanonicalName Off
# ...
</VirtualHost>
La recherche du serveur virtuel à base de nom correspondant au plus près à la requête s’effectue selon l’ordre d’apparition des directives <virtualhost>
dans le fichier de configuration. Le premier serveur virtuel dont le ServerName
ou le ServerAlias
correspond est choisi, sans priorité particulière si le nom contient des caractères génériques (que ce soit pour ServerName
ou ServerAlias
).
Tous les noms spécifiés au sein d’une section VirtualHost sont traités comme un ServerAlias
(sans caractères génériques).
Directive ServerAdmin
La directive ServerAdmin
permet de définir l’adresse de contact que le serveur va inclure dans tout message d’erreur qu’il envoie au client. Si le programme httpd ne reconnait pas l’argument fourni comme une URL, il suppose que c’est une adresse électronique, et lui ajoute le préfixe mailto:
dans les cibles des hyperliens. Il est cependant recommandé d’utiliser exclusivement une adresse électronique, car de nombreux scripts CGI considèrent ceci comme implicite. Si vous utilisez une URL, elle doit pointer vers un autre serveur que vous contrôlez. Dans le cas contraire, les utilisateurs seraient dans l’impossibilité de vous contacter en cas de problème.
Il peut s’avérer utile de définir une adresse dédiée à l’administration du serveur, par exemple :
ServerAdmin www-admin@foo.example.com
car les utilisateurs ne mentionnent pas systématiquement le serveur dont ils parlent !
Directive DocumentRoot
Cette directive permet de définir le répertoire à partir duquel httpd va servir les fichiers. S’il ne correspond pas à un Alias, le chemin de l’URL sera ajouté par le serveur à la racine des documents afin de construire le chemin du document recherché. Exemple :
DocumentRoot "/usr/web"
un accès à http://my.example.com/index.html
se réfère alors à /usr/web/index.html
. Si chemin répertoire n’est pas un chemin absolu, il est considéré comme relatif au chemin défini par la directive ServerRoot
.
Le répertoire défini par la directive DocumentRoot
ne doit pas comporter de slash final.
Directive Error
Si une erreur peut être détectée dans la configuration, souvent un module manquant, cette directive peut être utilisée pour générer un message d’erreur personnalisé, et interrompre la lecture de la configuration.
Par exemple,
# vérification du chargement de mod_include
<IfModule !include_module>
Error "mod_include is required by mod_foo. Load it with LoadModule."
</IfModule>
# vérification de la définition de SSL ou (exclusif) NOSSL
<IfDefine SSL>
<IfDefine NOSSL>
Error "Both SSL and NOSSL are defined. Define only one of them."
</IfDefine>
</IfDefine>
<IfDefine !SSL>
<IfDefine !NOSSL>
Error "Either SSL or NOSSL must be defined."
</IfDefine>
</IfDefine>
Directive ErrorLog
La directive ErrorLog
permet de définir le nom du fichier dans lequel le serveur va journaliser toutes les erreurs qu’il rencontre. Si le chemin fichier n’est pas absolu, il est considéré comme relatif au chemin défini par la directive ServerRoot
.
ErrorLog "/var/log/httpd/error_log"
Si le chemin fichier commence par une barre verticale “(|)”, il est considéré comme une commande à lancer pour traiter la journalisation de l’erreur.
ErrorLog "|/usr/local/bin/httpd_errors"
Voir les notes à propos des journaux redirigés pour plus d’informations.
L’utilisation de syslog à la place d’un nom de fichier active la journalisation via syslogd(8) si le système le supporte. Le dispositif syslog par défaut est local7, mais vous pouvez le modifier à l’aide de la syntaxe syslog:facility
, où “facility” peut être remplacé par un des noms habituellement documentés dans la page de man syslog(1). Le dispositif syslog local7 est global, et si il est modifié dans un serveur virtuel, le dispositif final spécifié affecte l’ensemble du serveur
ErrorLog syslog:user
Des modules supplémentaires peuvent fournir leurs propres fournisseurs ErrorLog
. La syntaxe est similaire à celle de l’exemple syslog ci-dessus.
Directive ErrorLogFormat
La directive ErrorLogFormat
permet de spécifier quelles informations supplémentaires vont être enregistrées dans le journal des erreurs en plus du message habituel.
| Chaîne de format |Description |
| – | – |
| %a
| Adresse IP et port clients
| %E
| Etat d’erreur APR/OS et chaîne
| %F
| Nom du fichier source et numéro de ligne de l’appel du journal
| %{name}i
| En-tête de requête name
| %k
| Nombre de requêtes persistantes pour cette connexion
| %l
| Sévérité du message
| %L
| Identifiant journal de la requête
| %m
| Nom du module qui effectue la journalisation du message
| %M
| Le message effectif
| %P
| Identifiant du processus courant
| %T
| Identifiant du thread courant
| %t
| L’heure courante
| %{u}t
| L’heure courante avec les microsecondes
| %{cu}t
| L’heure courante au format compact ISO 8601, avec les microsecondes
| %v
| Le nom de serveur canonique ServerName du serveur courant.
| %V
| Le nom de serveur du serveur qui sert la requête en accord avec la définition de la directive UseCanonicalName.
| \
(anti-slash espace) | Espace non délimiteur
| %
(pourcentage espace) | Délimiteur de champ (aucune sortie)
Voir https://httpd.apache.org/docs/2.4/fr/mod/core.html#errorlogformat pour la signification des codes.
Exemple simple
ErrorLogFormat "[%t] [%l] [pid %P] %F: %E: [client %a] %M"
Exemple (format par défaut pour les MPMs threadés)
ErrorLogFormat "[%{u}t] [%-m:%l] [pid %P:tid %T] %7F: %E: [client\ %a] %M% ,\ referer\ %{Referer}i"
Cet exemple renverrait un message d’erreur du style :
[Thu May 12 08:28:57.652118 2011] [core:error] [pid 8777:tid 4326490112] [client ::1:58619] File does not exist: /usr/local/apache2/htdocs/favicon.ico
Notez que certains champs sont totalement supprimés s’ils n’ont pas été définis.
Exemple (similaire au format 2.2.x)
ErrorLogFormat "[%t] [%l] %7F: %E: [client\ %a] %M% ,\ referer\ %{Referer}i"
Exemple avancé avec identifiants journal de requête/connexion
ErrorLogFormat "[%{uc}t] [%-m:%-l] [R:%L] [C:%{C}L] %7F: %E: %M" ErrorLogFormat request "[%{uc}t] [R:%L] Request %k on C:%{c}L pid:%P tid:%T" ErrorLogFormat request "[%{uc}t] [R:%L] UA:'%+{User-Agent}i'" ErrorLogFormat request "[%{uc}t] [R:%L] Referer:'%+{Referer}i'" ErrorLogFormat connection "[%{uc}t] [C:%{c}L] local\ %a remote\ %A"
Directive LogLevel
La directive LogLevel
permet d’ajuster la verbosité des messages enregistrés dans les journaux d’erreur (voir la directive ErrorLog
). Les niveaux disponibles sont présentés ci-après, par ordre de criticité décroissante :
| Niveau | Description | Exemple |
|–|–|–|
| emerg
| Urgences - le système est inutilisable. | “Child cannot open lock file. Exiting”
| alert
| Des mesures doivent être prises immédiatement. | “getpwuid: couldn’t determine user name from uid”
| crit
| Conditions critiques. | “socket: Failed to get a socket, exiting child”
| error
| Erreurs. | “Premature end of script headers”
| warn
| Avertissements. | “child process 1234 did not exit, sending another SIGHUP”
| notice
| Evènement important mais normal. | “httpd: caught SIGBUS, attempting to dump core in …”
| info
| Informations. | “Server seems busy, (you may need to increase StartServers, or Min/MaxSpareServers)…”
| debug
| Messages de débogage. | “Opening config file …”
Lorsqu’un niveau particulier est spécifié, les messages de tous les autres niveaux de criticité supérieure seront aussi enregistrés. Par exemple, si LogLevel info
est spécifié, les messages de niveaux notice
et warn
seront aussi émis.
Il est recommandé d’utiliser un niveau crit
ou inférieur.
Par exemple :
LogLevel notice
Spécifier un niveau sans nom de module va attribuer ce niveau à tous les modules. Spécifier un niveau avec nom de module va attribuer ce niveau à ce module seulement.
Il est possible de spécifier un module par le nom de son fichier source ou par son identificateur, avec ou sans le suffixe _module
. Les trois spécifications suivantes sont donc équivalentes :
LogLevel info ssl:warn
LogLevel info mod_ssl.c:warn
LogLevel info ssl_module:warn
Il est aussi possible d’attribuer un niveau de journalisation par répertoire :
LogLevel info
<Directory "/usr/local/apache/htdocs/app">
LogLevel debug
</Directory>
Exemples de configuration VirtualHost
Source : https://httpd.apache.org/docs/2.4/fr/vhosts/examples.html Source : https://httpd.apache.org/docs/2.4/fr/vhosts/mass.html
2. Pratique de Apache HTTPd Server
2.1. Installation de HTTPd Server sur Centos
Après une installation RHEL7 / Centos 7 :
fqdn="server.example.com"
hostnamectl set-hostname ${fqdn}
yum install -y curl firewalld
yum groupinstall -y "Web Server"
echo "127.0.0.1 ${fqdn}" >> /etc/hosts
echo "ServerName ${fqdn}" >> /etc/httpd/conf/httpd.conf
systemctl enable httpd
systemctl start httpd
systemctl enable firewalld
systemctl start firewalld
firewall-cmd --permanent --add-service=http
firewall-cmd --reload
Examen des emplacements du logiciel
La commande rpm -ql
donne la liste des fichiers du paquetage httpd :
rpm -ql httpd
Principalement, on retouve les emplacements (pour Centos/RHEL) :
/etc/httpd/
avec notamment le fichier principal de configurationhttpd.conf
: fichiers de configuration./etc/httpd/conf.d/
: fichiers de configuration supplémentaires (vhosts)./usr/lib64/httpd/
modules et librairies./usr/sbin/
binaires :httpd
,apachectl
, etc./usr/share/doc/httpd-*/
: documentation./var/log/httpd/
: emplacement des logs par défaut./var/www/html/
: emplacement par défaut des pages à servir.
2.2. Configurer un hôte virtuel
Fichier de configuration
cat /usr/share/doc/httpd*/httpd-vhosts.conf
# Virtual Hosts
#
# Required modules: mod_log_config
# If you want to maintain multiple domains/hostnames on your
# machine you can setup VirtualHost containers for them. Most configurations
# use only name-based virtual hosts so the server doesn't need to worry about
# IP addresses. This is indicated by the asterisks in the directives below.
#
# Please see the documentation at
# <URL:http://httpd.apache.org/docs/2.4/vhosts/>
# for further details before you try to setup virtual hosts.
#
# You may use the command line option '-S' to verify your virtual host
# configuration.
#
# VirtualHost example:
# Almost any Apache directive may go into a VirtualHost container.
# The first VirtualHost section is used for all requests that do not
# match a ServerName or ServerAlias in any <VirtualHost> block.
#
<VirtualHost *:@@Port@@>
ServerAdmin webmaster@dummy-host.example.com
DocumentRoot "@@ServerRoot@@/docs/dummy-host.example.com"
ServerName dummy-host.example.com
ServerAlias www.dummy-host.example.com
ErrorLog "/var/log/httpd/dummy-host.example.com-error_log"
CustomLog "/var/log/httpd/dummy-host.example.com-access_log" common
</VirtualHost>
<VirtualHost *:@@Port@@>
ServerAdmin webmaster@dummy-host2.example.com
DocumentRoot "@@ServerRoot@@/docs/dummy-host2.example.com"
ServerName dummy-host2.example.com
ErrorLog "/var/log/httpd/dummy-host2.example.com-error_log"
CustomLog "/var/log/httpd/dummy-host2.example.com-access_log" common
</VirtualHost>
Mise en place d’un hôte virtuel HTTP
Mise en place pour l’hôte virtuel host1.example.com
.
Le principe consiste à adapter la copie de ce fichier d’exemple dans /etc/httpd/conf.d/
sous le nom host1.example.com
.
Pour rendre nos opérations plus souples, notamment si vous voulez choisir un autre nom de domaine, on propose de placer le nom de domaine en variable :
httpdomain="host1.example.com"
Résolution de nom locale
echo "127.0.0.1 ${httpdomain}" >> /etc/hosts
Création du dossier et des pages Web
mkdir -p /var/www/html/${httpdomain}
echo "${httpdomain} test page" > /var/www/html/${httpdomain}/index.html
Restauration de la policy Selinux sur le dossier créé
restorecon -Rv /var/www/html/${httpdomain}
Création du dossier et des fichiers pour les logs
mkdir -p /var/log/httpd
touch /var/log/httpd/${httpdomain}-error_log
touch /var/log/httpd/${httpdomain}-access_log
Configuration du vhost HTTP
cat << EOF > /etc/httpd/conf.d/${httpdomain}.conf
<VirtualHost *:80>
ServerAdmin webmaster@${httpdomain}
DocumentRoot /var/www/html/${httpdomain}
ServerName ${httpdomain}
ErrorLog /var/log/httpd/${httpdomain}-error_log
CustomLog /var/log/httpd/${httpdomain}-access_log common
</VirtualHost>
EOF
Redémarrage du service
apachectl restart
Diganostic
curl ${httpdomain}
httpd -D DUMP_VHOSTS
VirtualHost configuration:
*:80 host1.example.com (/etc/httpd/conf.d/host1.example.com.conf:1)
*:443 192.168.122.39 (/etc/httpd/conf.d/ssl.conf:56)
Script create_vhost_httpd.sh
https://gist.github.com/goffinet/33205a18152fe3a87a5cf2d46e65dc3f
bash -x create_vhost_httpd.sh host1.example.com
#!/bin/bash
#create_vhost_httpd.sh in Centos7
#Variables
host=$1
port="80"
location="/var/www/html"
error_log="/var/log/httpd/${host}-error_log"
access_log="/var/log/httpd/${host}-access_log common"
#Résolution de nom locale
echo "127.0.0.1 ${host}" >> /etc/hosts
#Création du dossier et des pages Web
mkdir -p ${location}/${host}
echo "${host} test page" > ${location}/${host}/index.html
#Restauration de la policy Selinux sur le dossier créé
restorecon -Rv ${location}/${host}
#Création du dossier et des fichiers pour les logs
mkdir -p /var/log/httpd
touch /var/log/httpd/${host}-error_log
touch /var/log/httpd/${host}-access_log
#Configuration du vhost
cat << EOF > /etc/httpd/conf.d/${host}.conf
<VirtualHost *:${port}>
ServerAdmin webmaster@${host}
DocumentRoot ${location}/${host}
ServerName ${host}
ErrorLog ${error_log}
CustomLog ${access_log}
</VirtualHost>
EOF
#Activation et lancement du service
systemctl enable httpd
systemctl start httpd
systemctl restart httpd
#Diganostic
curl ${host}
httpd -D DUMP_VHOSTS
2.3. Configuration d’un vhost en HTTPS
Trois possibilités pour faire fonctionner HTTPS avec des certificats x509 :
- Générer un CSR et le soumettre à un CA (Autorité de Certification) : le plus fonctionnel et sûr, mais moins souple et le plus coûteux sur le plan financier et administratif.
- Générer un certificat auto-signé : coût nul, mais pose un problème de sécurité qui peut devenir indépassable pour certaines applications. Utile pour des environnement de développement ou pour assurer la confidentialité simplement.
- Let’s Encrypt : coût nul, facile à déployer, sûr.
Aussi, il s’agit de s’intéresser à la force des certificats et aux protocoles autorisés.
Différentes méthodes sont disponibles, certaines valides dans tous les cas ou uniquement sous cette distribution RHEL7/Centos7.
Toujours pour une question de souplesse, on propose de placer le nom de domaine en variable :
httpdomain="host1.example.com"
Force des certificats
Cipherli.st Strong Ciphers for Apache, nginx and Lighttpd
“Red Hat Keypair Generation ©” tout-en-un
L’utilitaire crypto-utils
crée les configurations HTTPS pour Apache.
yum install -y crypto-utils
Par exemple, on s’informera sur la commande genkey
:
# genkey --help
Unknown option: help
Usage: genkey [options] servername
--test Test mode, faster seeding, overwrite existing key
--genreq Generate a Certificate Signing Request (CSR)
--makeca Generate a self-signed certificate for a CA
--days Days until expiry of self-signed certificate (default 30)
--renew CSR is for cert renewal, reusing existing key pair, openssl certs only
--cacert Renewal is for a CA certificate, needed for openssl certs only
--nss Use the nss database for keys and certificates
--gdb For package maintainers, to trace into the nss utilities
genkey ${httpdomain}
Génération du certificat public et de la clé auto-signée
openssl req -nodes -x509 -newkey rsa:4096 -days 365 \
-out /etc/pki/tls/certs/${httpdomain}.crt \
-keyout /etc/pki/tls/private/${httpdomain}.key \
-subj "/C=BE/ST=Brussels/L=Brussels/O=IT/CN=${httpdomain}"
Génération d’un CSR en manuel
- Génération d’un clé sécurisée et non sécurisée
- Génération du CSR
Eventuellement, auto-signer la requête CSR avec sa propre clé.
Si plusieurs certificats sont à gérér en interne, il est peut être nécessaire d’implémenter une autorité de certification (CA).
Ansible : Module command
Voici une solution fonctionnelle avec le module command
mais elle est “brut de décoffrage”.
- name: Install nginx and python-openssl
apt:
name:
- nginx
- python-openssl
update_cache: yes
cache_valid_time: 3600
- name: Create self-signed certificate, if configured.
command: >
openssl req -x509 -nodes -subj '/CN=localhost' -days 365
-newkey rsa:4096 -sha256 -keyout {{ key_file }} -out {{ cert_file }}
creates={{ cert_file }}
notify: restart nginx
- name: "fix right on key file"
file:
name: "{{ key_file }}"
mode: 0600
notify: restart nginx
Ansible : Modules openssl_*
Voici une solution avec des variables et des tâches idempotentes grâce aux modules Ansibles openssl_*
:
openssl_privatekey
openssl_csr
openssl_certificate
openssl_dhparam
Variables
vars:
key_file: "/path/{{ ansible_fqdn }}.key.pem"
csr_file: "/path/{{ ansible_fqdn }}.csr.pem"
cert_file: "/path/{{ ansible_fqdn }}.cert.pem"
dh_file: "/path/{{ ansible_fqdn }}.dh.pem"
Tâches
- name: Generate an OpenSSL private key.
openssl_privatekey:
path: "{{ key_file }}"
notify: restart nginx
- name: Generate an OpenSSL CSR.
openssl_csr:
path: "{{ csr_file }}"
privatekey_path: "{{ key_file }}"
common_name: "{{ ansible_fqdn }}"
notify: restart nginx
- name: Generate a Self Signed OpenSSL certificate.
openssl_certificate:
path: "{{ cert_file }}"
privatekey_path: "{{ key_file }}"
csr_path: "{{ csr_file }}"
provider: selfsigned
notify: restart nginx
- name: "fix right on key file"
file:
name: "{{ key_file }}"
mode: 0600
notify: restart nginx
Pour générer un fichier Diffie-Helman (DH) :
- name: "generate a DH key"
openssl_dhparam:
path: "{{ dh_file }}"
size: 2048
Fichier de configuration du vhost HTTPS par défaut
A l’installation du groupe “Web Server” sous Centos7/RHEL7, un fichier /etc/httpd/conf.d/ssl.conf
active par défaut un vhost HTTPS (yum install -y mod_ssl
), celui sert par défaut les pages en HTTPS.
grep -v '^$\|^\s*\#' /etc/httpd/conf.d/ssl.conf
Listen 443 https
SSLPassPhraseDialog exec:/usr/libexec/httpd-ssl-pass-dialog
SSLSessionCache shmcb:/run/httpd/sslcache(512000)
SSLSessionCacheTimeout 300
SSLRandomSeed startup file:/dev/urandom 256
SSLRandomSeed connect builtin
SSLCryptoDevice builtin
<VirtualHost _default_:443>
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
LogLevel warn
SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5:!SEED:!IDEA
SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
<Files ~ "\.(cgi|shtml|phtml|php3?)$">
SSLOptions +StdEnvVars
</Files>
<Directory "/var/www/cgi-bin">
SSLOptions +StdEnvVars
</Directory>
BrowserMatch "MSIE [2-5]" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
CustomLog logs/ssl_request_log \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>
On peut le désactiver en renommant ce fichier autrement qu’en .conf
, ce qui n’est pas nécessaire dans notre exercice.
mv /etc/httpd/conf.d/ssl.conf /etc/httpd/conf.d/ssl.conf.bak
Nouveau vhost HTTPS
Par rapport à une configuration HTTP simple, quelques directives comme SSLCertificateFile
, SSLCertificateKeyFile
ainsi que d’autres paramètres comme le port d’écoute TCP 443 sont à ajouter/adapter. On ajoutera cette entrée dans le fichier de configuration.
cat << EOF >> /etc/httpd/conf.d/host1.example.com.conf
<VirtualHost *:443>
ServerAdmin webmaster@host1.example.com
DocumentRoot /var/www/html/host1.example.com
ServerName host1.example.com
ErrorLog /var/log/httpd/host1.example.com-error_log
CustomLog /var/log/httpd/host1.example.com-access_log common
SSLEngine on
# 128-bit mini anti-beast
#SSLCipherSuite !EDH:!ADH:!DSS:!RC2:RC4-SHA:RC4-MD5:HIGH:MEDIUM:+AES128:+3DES
# 128-bit mini PFS favorisé
#SSLCipherSuite !EDH:!ADH:!DSS:!RC2:HIGH:MEDIUM:+3DES:+RC4
# 128-bit securité maximale
SSLCipherSuite !EDH:!ADH:!DSS:!RC4:HIGH:+3DES
SSLProtocol all -SSLv2 -SSLv3
SSLCertificateFile /etc/pki/tls/certs/host1.example.com.crt
SSLCertificateKeyFile /etc/pki/tls/private/host1.example.com.key
</VirtualHost>
EOF
Vérifier la configuration.
apachectl configtest
Redémarrer le service et adapter le pare-feu.
apachectl restart
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
Vérifications
httpd -D DUMP_VHOSTS
VirtualHost configuration:
*:80 host1.example.com (/etc/httpd/conf.d/host1.example.com.conf:1)
*:443 is a NameVirtualHost
default server host1.example.com (/etc/httpd/conf.d/host1.example.com.conf:9)
port 443 namevhost host1.example.com (/etc/httpd/conf.d/host1.example.com.conf:9)
port 443 namevhost 192.168.122.38 (/etc/httpd/conf.d/ssl.conf:56)
Vérification client/serveur HTTP.
curl http://host1.example.com
host1.example.com test page
Vérification client/serveur HTTPS.
curl -k https://host1.example.com
host1.example.com test page
Vérification du certificat.
openssl s_client -connect host1.example.com:443 -state
...
Script create_vhost_httpds.sh
Source : https://gist.github.com/goffinet/935c79afaffb6860386880e8bbfb7287
bash -x create_vhost_httpds.sh host1.example.com
#!/bin/bash
#create_vhost_httpds.sh in Centos7
#Variables
host=$1
port="443"
location="/var/www/html"
error_log="/var/log/httpd/${host}-error_log"
access_log="/var/log/httpd/${host}-access_log common"
#Résolution de nom locale
echo "127.0.0.1 ${host}" >> /etc/hosts
#Création du dossier et des pages Web
mkdir -p ${location}/${host}
echo "${host} test page" > ${location}/${host}/index.html
#Restauration de la policy Selinux sur le dossier créé
restorecon -Rv ${location}/${host}
#Création du dossier et des fichiers pour les logs
mkdir -p /var/log/httpd
touch ${error_log}
touch ${access_log}
#Configuration du vhost HTTPS
cat << EOF >> /etc/httpd/conf.d/${host}.conf
<VirtualHost *:${port}>
ServerAdmin webmaster@${host}
DocumentRoot ${location}/${host}
ServerName ${host}
ErrorLog ${error_log}
CustomLog ${access_log} common
SSLEngine on
SSLCipherSuite !EDH:!ADH:!DSS:!RC4:HIGH:+3DES
SSLProtocol all -SSLv2 -SSLv3
SSLCertificateFile /etc/pki/tls/certs/${host}.crt
SSLCertificateKeyFile /etc/pki/tls/private/${host}.key
</VirtualHost>
EOF
#Génération du certificat auto-signé
openssl req -nodes -x509 -newkey rsa:4096 \
-out /etc/pki/tls/certs/${host}.crt \
-keyout /etc/pki/tls/private/${host}.key \
-days 365 \
-subj "/C=BE/ST=Brussels/L=Brussels/O=webteam/CN=${host}"
#Activation et lancement du service
systemctl enable httpd
systemctl start httpd
systemctl restart httpd
#Diganostic
curl https://${host}
httpd -D DUMP_VHOSTS
Redirection HTTP vers HTTPS
Voir Let’s Encrypt.
Script vhost-creator
Pour la curiosité.
Source : https://github.com/mattmezza/vhost-creator.
2.4. Let’s Encrypt en Centos 7 pour Apache
Source : https://certbot.eff.org/all-instructions/#centos-rhel-7-apache
Installation du logiciel
yum install epel-release
yum install python2-certbot-apache
Démarrage rapide
certbot --apache
certbot --apache certonly
certbot renew --dry-run
Fonction Let’s Encrypt pour une installation silencieuse
https_installation() {
site_name="www.mondomainepublic.fr"
# Three times if DNS failure
certbot --apache --register-unsafely-without-email --agree-tos -d "${site_name}" -n || \
certbot --apache --register-unsafely-without-email --agree-tos -d "${site_name}" -n || \
certbot --apache --register-unsafely-without-email --agree-tos -d "${site_name}" -n
(crontab -l 2>/dev/null; echo "0 0,12 * * * python -c "import random; import time; time.sleep(random.random() * 3600)" && certbot renew") | crontab -
}
2.5. Activation de HTTP/2
La disponibilité de HTTP2 dans HTTPd Server dépend du modulemod_http2
:
LoadModule http2_module modules/mod_http2.so
On déclarera l’utilisation de HTTP/2 avec la directive Protocols
dans la configuration globale ou dans un conteneur <VirtualHost ...>
.
h2
correspond à HTTP/2 sur TLS (négociation de protocole via ALPN).h2c
correspond à HTTP/2 sur TCP.
L’ordre des protocoles a son importance !
Protocols http/1.1
<VirtualHost ...>
ServerName test.example.org
Protocols h2 http/1.1 h2c
</VirtualHost>
Dans cet exemple, Protocols h2 http/1.1 h2c
désigne dans l’ordre HTTP/2 sur TCP, HTTP/1.1 et enfin HTTP/2 sur TLS.
Source : Guide HTTP/2
Plus détaillé : Setting up HTTP/2 on your web server
3. Nginx
4. Bases de données
4.1. MariaDB SQL Server
- Install and configure MariaDB.
- Backup and restore a database.
- Create a simple database schema.
- Perform simple SQL queries against a database.
Installation et configuration de Mariadb
Installation de MariaDB
yum install -y mariadb mariadb-server
systemctl start mariadb && systemctl enable mariadb
Il s’agit de profiter de l’absence de mot de passe sur le compte root pour créer la base et l’utilisateur de la base de données.
dbuser=user
dbuser_password=testtest
dbroot_password=testtest
database_creation() {
# Create dbuser
mysql -e "CREATE USER ${dbuser}@localhost IDENTIFIED BY '${dbuser_password}';"
# Create database
mysql -e "CREATE DATABASE javatest;"
mysql -e "USE javatest; CREATE table testdata (id int not null auto_increment primary key,foo varchar(25),bar int); INSERT into testdata values(null, 'hello', 12345);"
# Fix dbuser rights on wp_database
mysql -e "GRANT ALL ON javatest.* TO ${dbuser}@localhost;"
# Make our changes take effect
mysql -e "FLUSH PRIVILEGES"
}
Sécurisation de type mysql_secure
mysql_secure() {
# mysql_secure_installation as model
# Make sure that NOBODY can access the server without a password
mysql -e "UPDATE mysql.user SET Password = PASSWORD('${dbroot_password}') WHERE User = 'root'"
# Kill the anonymous users
mysql -e "DROP USER ''@'localhost'"
# Because our hostname varies we'll use some Bash magic here.
mysql -e "DROP USER ''@'$(hostname)'"
# Kill off the demo database
mysql -e "DROP DATABASE test"
# Make our changes take effect
mysql -e "FLUSH PRIVILEGES"
}