« Webserver/Apache » : différence entre les versions
Aucun résumé des modifications |
|||
| (12 versions intermédiaires par le même utilisateur non affichées) | |||
| Ligne 1 : | Ligne 1 : | ||
= Apache = | |||
==Présentation d'Apache== | ==Présentation d'Apache== | ||
| Ligne 250 : | Ligne 251 : | ||
Cet article doit vous avoir permis de rendre apache opérationnel sur votre machine.<br/> | Cet article doit vous avoir permis de rendre apache opérationnel sur votre machine.<br/> | ||
Il vous reste maintenant beaucoup de lecture pour découvrir un aperçu de ses fonctionnalités. | Il vous reste maintenant beaucoup de lecture pour découvrir un aperçu de ses fonctionnalités. | ||
{{author|Remi Collet}} | {{author|Remi Collet}} | ||
= Configurer le module mod_ssl = | |||
Il faut générer un certificat signé par une autorité de certification. | |||
On créé l'arborescence nécessaire à la génération des clés et certificats | |||
<syntaxhighlight lang="bash"> | |||
mkdir /etc/pki/httpd/ | |||
cd /etc/pki/httpd/ | |||
mkdir {certs,private,confs} | |||
touch index.txt | |||
echo 01 > serial | |||
</syntaxhighlight> | |||
Création du fichier de configuration de nos futurs certificats : <path>/etc/pki/httpd/ssl.cnf</path> | |||
<pre> | |||
HOME = . | |||
RANDFILE = .rand | |||
[ca] | |||
default_ca = ca_default | |||
[ca_default] | |||
dir = . | |||
certs = $dir/certs | |||
crl_dir = $dir/crl | |||
database = $dir/index.txt | |||
new_certs_dir = $dir/newcerts | |||
certificate = $dir/%s_ca_cert.pem | |||
private_key = $dir/private/%s_ca_key.pem | |||
serial = $dir/serial | |||
crl = $dir/crl.pem | |||
x509_extensions = usr_cert | |||
name_opt = ca_default | |||
cert_opt = ca_default | |||
default_days = 3650 | |||
default_crl_days = 30 | |||
default_md = md5 | |||
preserve = no | |||
policy = policy_match | |||
[policy_match] | |||
countryName = match | |||
stateOrProvinceName = match | |||
organizationName = match | |||
organizationalUnitName = optional | |||
commonName = supplied | |||
emailAddress = optional | |||
[req] | |||
default_bits = 1024 | |||
default_keyfile = privkey.pem | |||
distinguished_name = req_distinguished_name | |||
attributes = req_attributes | |||
x509_extensions = v3_ca # The extentions to add to the self signed cert | |||
string_mask = MASK:0x2002 | |||
req_extensions = v3_req | |||
[req_distinguished_name] | |||
countryName = Country Name (2 letter code) | |||
countryName_default = FR | |||
countryName_min = 2 | |||
countryName_max = 2 | |||
stateOrProvinceName = State or Province Name (full name) | |||
stateOrProvinceName_default = Paca | |||
localityName = Locality Name (eg, city) | |||
localityName_default = Cavaillon | |||
0.organizationName = Organization Name (eg, company) | |||
0.organizationName_default = B2PWeb | |||
organizationalUnitName = Organizational Unit Name (eg, section) | |||
commonName = Common Name (eg, your name or your server\'s hostname) | |||
commonName_max = 64 | |||
emailAddress = Email Address | |||
emailAddress_max = 64 | |||
[req_attributes] | |||
challengePassword = A challenge password | |||
challengePassword_min = 4 | |||
challengePassword_max = 20 | |||
unstructuredName = An optional company name | |||
[usr_cert] | |||
basicConstraints = CA:FALSE | |||
nsComment = "OpenSSL Generated Certificate" | |||
subjectKeyIdentifier = hash | |||
authorityKeyIdentifier = keyid,issuer:always | |||
[v3_ca] | |||
subjectKeyIdentifier = hash | |||
authorityKeyIdentifier = keyid:always,issuer:always | |||
basicConstraints = CA:true | |||
[v3_req] | |||
subjectAltName = "DNS:www-secure.b2pweb.com,DNS:statgeo.b2pweb.com" | |||
</pre> | |||
{{Admon/important|Utilisation de wildcard pour le CommonName|On peut utiliser un wildcard (joker) du type *.b2pweb.com pour que le certificat s'applique à un ensemble de sous-domaines. Mais c'est plus propre d'ajouter un ou plusieurs subjectAltName au certificat. De cette manière, la liste est finie et ne peut s'appliquer qu'aux virtual hosts connus.}} | |||
D'abord on génère une clé non chiffrée sur disque (pour éviter d'avoir à saisir un mot de passe à chaque redémarrage d'Apache) : | |||
<syntaxhighlight lang="bash"> | |||
openssl genrsa -out private/server.key 2048 | |||
</syntaxhighlight> | |||
On crée un certificat signé avec cette clé ( validité 1 an ): | |||
<syntaxhighlight lang="bash"> | |||
openssl req -config ssl.cnf -new -x509 -days 365 -key private/server.key -out server.crt -extensions v3_ca -extensions v3_req | |||
</syntaxhighlight> | |||
Répondre à l'ensemble des questions posées. Le nom de la machine ( {{command|hostname --fqdn}} doit être donné en réponse à Common Name. | |||
Ensuite, dans Apache, modifier le fichier de définition du VirtualHost qui va bien : | |||
<syntaxhighlight lang="apache"> | |||
NameVirtualHost *:443 | |||
<VirtualHost *:443> | |||
SSLEngine on | |||
SSLCertificateFile /etc/pki/httpd/server.crt | |||
SSLCertificateKeyFile /etc/pki/httpd/private/server.key | |||
SSLVerifyClient none | |||
[etc., etc.] | |||
</VirtualHost> | |||
</syntaxhighlight> | |||
{{Admon/tip|Renouvellement du certificat|La méthode décrite ici permet de renouveler très facilement le certificat. En effet la configuration du certificat est toujours présente dans le fichier <path>/etc/pki/httpd/ssl.cnf</path><br />On sauvegarde l'existant, on ne sais jamais: | |||
<pre> | |||
mv /etc/pki/httpd/private/server.key /etc/pki/httpd/private/server.key.bak | |||
mv /etc/pki/httpd/server.crt /etc/pki/httpd/server.crt.bak | |||
</pre> | |||
Puis de générer une nouvelle clé et un nouveau certificat | |||
<pre> | |||
openssl genrsa -out private/server.key 2048 | |||
openssl req -config ssl.cnf -new -x509 -days 365 -key private/server.key -out server.crt \ | |||
-extensions v3_ca -extensions v3_req | |||
</pre>}} | |||
=== F.A.Q. === | |||
How to solve particular security constraints for an SSL-aware webserver is not always obvious because of the coherences between SSL, HTTP and Apache's way of processing requests. This chapter gives instructions on how to solve such typical situations. Treat is as a first step to find out the final solution, but always try to understand the stuff before you use it. Nothing is worse than using a security solution without knowing it's restrictions and coherences. | |||
==== Cipher Suites and Enforced Strong Security ==== | |||
{{Admon/faq|How can I create a real SSLv2-only server? [L]|The following creates an SSL server which speaks only the SSLv2 protocol and its ciphers.<br> | |||
Fichier httpd.conf | |||
<syntaxhighlight lang="apache"> | |||
SSLProtocol -all +SSLv2 | |||
SSLCipherSuite SSLv2:+HIGH:+MEDIUM:+LOW:+EXP | |||
</syntaxhighlight>}} | |||
{{Admon/faq|How can I create an SSL server which accepts strong encryption only? [L]|The following enables only the seven strongest ciphers: | |||
Fichier httpd.conf | |||
<syntaxhighlight lang="apache"> | |||
SSLProtocol all | |||
SSLCipherSuite HIGH:MEDIUM | |||
</syntaxhighlight>}} | |||
{{Admon/faq|How can I create an SSL server which accepts strong encryption only, but allows export browsers to upgrade to stronger encryption? [L]|This facility is called Server Gated Cryptography (SGC) and details you can find in the README.GlobalID document in the mod_ssl distribution. In short: The server has a Global ID server certificate, signed by a special CA certificate from Verisign which enables strong encryption in export browsers. This works as following: The browser connects with an export cipher, the server sends it's Global ID certificate, the browser verifies it and subsequently upgrades the cipher suite before any HTTP communication takes place. The question now is: How can we allow this upgrade, but enforce strong encryption. Or in other words: Browser either have to initially connect with strong encryption or have to upgrade to strong encryption, but are not allowed to keep the export ciphers. The following does the trick: | |||
Fichier httpd.conf | |||
<syntaxhighlight lang="apache"> | |||
# allow all ciphers for the inital handshake, | |||
# so export browsers can upgrade via SGC facility | |||
SSLCipherSuite ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL | |||
<Directory /usr/local/apache/htdocs> | |||
# but finally deny all browsers which haven't upgraded | |||
SSLRequire %{SSL_CIPHER_USEKEYSIZE} >= 128 | |||
</Directory> | |||
</syntaxhighlight>}} | |||
{{Admon/faq|How can I create an SSL server which accepts all types of ciphers in general, but requires a strong ciphers for access to a particular URL? [L]|Obviously you cannot just use a server-wide SSLCipherSuite which restricts the ciphers to the strong variants. But mod_ssl allows you to reconfigure the cipher suite in per-directory context and automatically forces a renegotiation of the SSL parameters to meet the new configuration. So, the solution is: | |||
Fichier httpd.conf | |||
<syntaxhighlight lang="apache"> | |||
# be liberal in general | |||
SSLCipherSuite ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL | |||
<Location /strong/area> | |||
# but https://hostname/strong/area/ and below requires strong ciphers | |||
SSLCipherSuite HIGH:MEDIUM | |||
</Location> | |||
</syntaxhighlight>}} | |||
==== Client Authentication and Access Control ==== | |||
{{Admon/faq|How can I authenticate clients based on certificates when I know all my clients? [L]|When you know your user community (i.e. a closed user group situation), as it's the case for instance in an Intranet, you can use plain certificate authentication. All you have to do is to create client certificates signed by your own CA certificate ca.crt and then verifiy the clients against this certificate.<br> | |||
Fichier httpd.conf | |||
<syntaxhighlight lang="apache"> | |||
# require a client certificate which has to be directly | |||
# signed by our CA certificate in ca.crt | |||
SSLVerifyClient require | |||
SSLVerifyDepth 1 | |||
SSLCACertificateFile conf/ssl.crt/ca.crt | |||
</syntaxhighlight>}} | |||
{{Admon/faq|How can I authenticate my clients for a particular URL based on certificates but still allow arbitrary clients to access the remaining parts of the server? [L]|For this we again use the per-directory reconfiguration feature of mod_ssl:<br> | |||
Fichier httpd.conf | |||
<syntaxhighlight lang="apache"> | |||
SSLVerifyClient none | |||
SSLCACertificateFile conf/ssl.crt/ca.crt | |||
<Location /secure/area> | |||
SSLVerifyClient require | |||
SSLVerifyDepth 1 | |||
</Location> | |||
</syntaxhighlight>}} | |||
{{Admon/faq|How can I authenticate only particular clients for a some URLs based on certificates but still allow arbitrary clients to access the remaining parts of the server? [L]|The key is to check for various ingredients of the client certficate. Usually this means to check the whole or part of the Distinguished Name (DN) of the Subject. For this two methods exists: The mod_auth based variant and the SSLRequire variant. The first method is good when the clients are of totally different type, i.e. when their DNs have no common fields (usually the organisation, etc.). In this case you've to establish a password database containing all clients. The second method is better when your clients are all part of a common hierarchy which is encoded into the DN. Then you can match them more easily. | |||
'''The first method'''<br> | |||
Fichier httpd.conf<syntaxhighlight lang="apache"> | |||
SSLVerifyClient none | |||
<Directory /usr/local/apache/htdocs/secure/area> | |||
SSLVerifyClient require | |||
SSLVerifyDepth 5 | |||
SSLCACertificateFile conf/ssl.crt/ca.crt | |||
SSLCACertificatePath conf/ssl.crt | |||
SSLOptions +FakeBasicAuth | |||
SSLRequireSSL | |||
AuthName "Snake Oil Authentication" | |||
AuthType Basic | |||
AuthUserFile /usr/local/apache/conf/httpd.passwd | |||
require valid-user | |||
</Directory> | |||
</syntaxhighlight> | |||
Fichier httpd.htaccess | |||
<syntaxhighlight lang="apache"> | |||
/C=DE/L=Munich/O=Snake Oil, Ltd./OU=Staff/CN=Foo:xxj31ZMTZzkVA | |||
/C=US/L=S.F./O=Snake Oil, Ltd./OU=CA/CN=Bar:xxj31ZMTZzkVA | |||
/C=US/L=L.A./O=Snake Oil, Ltd./OU=Dev/CN=Quux:xxj31ZMTZzkVA | |||
</syntaxhighlight> | |||
'''The second method'''<br> | |||
Fichier httpd.conf | |||
<syntaxhighlight lang="apache"> | |||
SSLVerifyClient none | |||
<Directory "/var/www/html/area"> | |||
SSLVerifyClient require | |||
SSLVerifyDepth 5 | |||
SSLCACertificateFile conf/ssl.crt/ca.crt | |||
SSLCACertificatePath conf/ssl.crt | |||
SSLOptions +FakeBasicAuth | |||
SSLRequireSSL | |||
SSLRequire %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." and \ | |||
%{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"} | |||
</Directory> | |||
</syntaxhighlight>}} | |||
{{Admon/faq|How can I require HTTPS with strong ciphers and either basic authentication or client certificates for access to a subarea on the Intranet website for clients coming from the Internet but still allow plain HTTP access for clients on the Intranet? [L]|Let us assume the Intranet can be distinguished through the IP network 192.160.1.0/24 and the subarea on the Intranet website has the URL /subarea. Then configure the following outside your HTTPS virtual host (so it applies to both HTTPS and HTTP):<br> | |||
Fichier httpd.conf | |||
<syntaxhighlight lang="apache"> | |||
SSLCACertificateFile conf/ssl.crt/company-ca.crt | |||
<Directory /usr/local/apache/htdocs> | |||
# Outside the subarea only Intranet access is granted | |||
Order deny,allow | |||
Deny from all | |||
Allow from 192.168.1.0/24 | |||
</Directory> | |||
<Directory /var/www/html/subarea> | |||
# Inside the subarea any Intranet access is allowed | |||
# but from the Internet only HTTPS + Strong-Cipher + Password | |||
# or the alternative HTTPS + Strong-Cipher + Client-Certificate | |||
# If HTTPS is used, make sure a strong cipher is used. | |||
# Additionally allow client certs as alternative to basic auth. | |||
SSLVerifyClient optional | |||
SSLVerifyDepth 1 | |||
SSLOptions +FakeBasicAuth +StrictRequire | |||
SSLRequire %{SSL_CIPHER_USEKEYSIZE} >= 128 | |||
# Force clients from the Internet to use HTTPS | |||
RewriteEngine on | |||
RewriteCond %{REMOTE_ADDR} !^192\.168\.1\.[0-9]+$ | |||
RewriteCond %{HTTPS} !=on | |||
RewriteRule .* - [F] | |||
# Allow Network Access and/or Basic Auth | |||
Satisfy any | |||
# Network Access Control | |||
Order deny,allow | |||
Deny from all | |||
Allow 192.168.1.0/24 | |||
# HTTP Basic Authentication | |||
AuthType basic | |||
AuthName "Protected Intranet Area" | |||
AuthUserFile conf/protected.passwd | |||
Require valid-user | |||
</Directory> | |||
</syntaxhighlight>}} | |||
= Journalisation conditionnelle = | |||
La récupération par un client d'une page web complète peut générer beaucoup de log: téléchargement des images, etc... On peut conditionner la journalisation. | |||
La journalisation peut être conditionnelle et les variables d'environnement système contiennent une variable basée sur la requète. La directive ''CustomLog'' accepte une condition basée sur celle-ci. | |||
* On créer une varible d'environnement conditionnée par la cible de la requète | |||
* On applique notre filtrage sur les logs. | |||
Ici on spécifie que l'on veut logguer uniquement les .html et .shtml dans le log: | |||
<syntaxhighlight lang="apache"> | |||
SetEnvIf Request_URI "(\.html|\.shtml)$" html | |||
CustomLog logs/access.log common env=html | |||
</syntaxhighlight> | |||
Ici on spécifie que l'on veut tous logguer sauf les images dans le log (condition inverse): | |||
<syntaxhighlight lang="apache"> | |||
SetEnvIf Request_URI "(\.gif|\.png|\.jpg)$" image | |||
CustomLog logs/access.log common env=!image | |||
</syntaxhighlight> | |||
Ici on dispatche les logs avec un filtre basé sur le premier répertoire de la requète: | |||
<syntaxhighlight lang="apache"> | |||
SetEnvIf Request_URI "^/foo/" foo | |||
SetEnvIf Request_URI "^/bar/" bar | |||
CustomLog /logs/access_foo_log common env=foo | |||
CustomLog /logs/access_bar_log common env=bar | |||
</syntaxhighlight> | |||
= Forcer l'utilisation d'https au lieu de http = | |||
Il suffit de rajouter, soit à la fin du fichier <path>/etc/httpd/conf/httpd.conf</path> pour tous les sites du serveur, soit dans la définition du vhost, ou encore dans un fichier htaccess les lignes suivantes | |||
<syntaxhighlight lang="apache"> | |||
RewriteEngine On | |||
RewriteCond %{HTTPS} off | |||
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} | |||
</syntaxhighlight> | |||
= Autres pages sur Apache = | |||
[[Webserver/Apache/Authentification|Méthodes d'authentification avec Apache]] | |||
[[Catégorie:Administrer un serveur dédié|Apache]] | [[Catégorie:Administrer un serveur dédié|Apache]] | ||
Dernière version du 30 septembre 2013 à 10:54
Apache
Présentation d'Apache
Apache est un fournisseur de services Http. C'est un logiciel libre disponible pour la plupart des systèmes d'exploitation. Il équipe actuellement plus de 60% des serveurs internet mondiaux.
Liens :
- http://www.planetapache.org/ : Site de la "Apache Software Foundation"
- http://httpd.apache.org/ : Site officiel
- http://www.apachefrance.com/ : Le site francophone sur Apache
- http://www.planetapache.org/ : Planet Apache
Installation d'Apache
Installation
Il fait partie des logiciels fournis avec la distribution Fedora: <package>httpd</package>
Versions fournies :
- Versions actuelles :
- Fedora Rawhide : 2.4.2
- Fedora 17 : 2.2.22
- Fedora 16 : 2.2.22
- Anciennes versions (non maintenues) de Fedora (pour mémoire) :
- Fedora 15 : 2.2.22
- Fedora 14 : 2.2.17
- Fedora 13 : 2.2.17
- Fedora 12 : 2.2.15
- Fedora 11 : 2.2.15
- Fedora 10 : 2.2.14
- Fedora 9 : 2.2.10
- Fedora 8 : 2.2.9
- Fedora 7 : 2.2.8
- Fedora Core 6 : 2.2.6
- Fedora Core 5 : 2.2.2
- Fedora Core 4 : 2.0.54
- Fedora Core 3 : 2.0.53
- Fedora Core 2 : 2.0.51
- Fedora Core 1 : 2.0.50
Attention : il n'est pas nécessaire de vouloir la dernière sous-version (troisième chiffre), en effet il s'agit généralement uniquement de correctifs de sécurité qui sont intégrés dans les RPM de la distribution (exemple la version 2.2.2-1.2 de FC5 contient les correctifs de la version 2.2.3).
Nous allons l'installer avec sa documentation, très complète et source de renseignements précieux
$ su -c 'yum install httpd-manual'
Activation
Ensuite il est nécessaire de démarrer le service :
$ su -lc 'service httpd start'
Si vous souhaitez que son lancement soit automatique lors du démarrage de la machine :
$ su -lc 'chkconfig httpd on'
Pour vérifier son fonctionnement, essayez les adresses suivantes dans votre navigateur :
- http://localhost/ : Test Page for the Apache HTTP Server on Fedora Core
- http://localhost/manual/ : Apache HTTP Server Version 2.2 Documentation
Fichiers et dossiers à connaitre
- /etc/httpd : dossier contenant l'ensemble des fichiers de configuration
- /etc/httpd/conf/httpd.conf : fichier principal de configuration. Nous verrons qu'il est possible - et fortement recommandé - de ne jamais modifier ce fichier
- /etc/httpd/conf.d : dossier contenant les fichiers secondaires de configuration, fournis par les extensions et les logiciels utilisant Apache. C'est ici que nous allons travailler
- /var/log/httpd : dossier contenant les journaux
- /var/log/httpd/access_log : journal retraçant toutes les pages traitées par le serveur
- /var/log/httpd/error_log : journal des erreurs
- /var/www : dossier contenant les données du site par défaut
- /var/www/cgi-bin : dossier (vide) contenant les scripts
- /var/www/error : dossier contenant les pages affichées en cas d'erreur
- /var/www/html : dossier (vide) contenant les pages du site par défaut
- /var/www/icons : dossier contenant quelques icônes
- /var/www/manual : dossier contenant la documentation
Exploitation d'Apache
Lors de l'installation d'une extension, il est nécessaire de relancer le service :
$ su -lc 'service httpd start'
Lors d'une modification de la configuration, il est nécessaire de demander à Apache de rechercher sa configuration. Pour cela il est toujours préférable de procéder en 2 temps.
Contrôle de la nouvelle configuration
$ su -lc 'service httpd configtest' Syntax OK
Cette opération permet de vérifier la syntaxe sans arrêter le service. C'est très pratique, notamment pour un serveur en production.
Ensuite, si tout est OK
$ su -lc 'service httpd reload'
L'outil logrotate est automatiquement configuré lors de l'installation pour faire tourner les journaux chaque semaine en conservant 4 générations. Il n'y a donc pas de risque de saturer le disque.
Si vous souhaitez modifier ces réglages, ça se passe dans le fichier /etc/logrotate.d/httpd.
L'outil logwatch est automatiquement configuré pour transmettre quotidiennement un rapport par courrier sur les anomalies (courantes et connues) rencontrées dans les journaux, et donc dans ceux d'Apache, voic un exemple de compte-rendu :
--------------------- httpd Begin ------------------------ A total of 6 unidentified 'other' records logged GET /test4 HTTP/1.1 with response code(s) 4 404 responses GET /thunderbird.jsc HTTP/1.0 with response code(s) 1002 200 responses GET /phpgwapi/js/tinymce/jscripts/tiny_mce/themes/advanced/images/%7B$lang_bold_img%7D HTTP/1.1 with response code(s) 8 404 responses GET /bei/test4 HTTP/1.1 with response code(s) 2 404 responses GET /phpgwapi/js/tinymce/jscripts/tiny_mce/themes/advanced/images/%7B$lang_italic_img%7D HTTP/1.1 with response code(s) 8 404 responses GET /phpgwapi/js/tinymce/jscripts/tiny_mce/themes/advanced/images/%7B$lang_underline_img%7D HTTP/1.1 with response code(s) 8 404 responses ---------------------- httpd End -------------------------
Configuration d'Apache
La configuration par défaut du service, livrée avec l'application, se trouve dans le fichier /etc/httpd/conf/httpd.conf.
La lecture de la documentation officielle et de nombreux sites consacrés à ce sujet vous permettra de découvrir les différentes directives de configurations.
Documentation officielle : Directive Index
Voici un exemple de fichier de configuration minimum, adapté à une machine de développement et de test.
Les commentaires doivent vous permettre de comprendre chaque partie.
Fichier /etc/httpd/conf.d/messites.conf
# activation des hôtes virtuels
NameVirtualHost *:80
# Hôte virtuel par défaut
<VirtualHost *:80>
# Activation des sites de quelques utilisateurs : http://localhost/~nomutilisateur
UserDir enabled nomutilisateur unautre undernier
UserDir public_html
<Directory /home/*/public_html>
AllowOverride all
Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
</Directory>
# Activation de l'adresse : http://localhost/server-status
<Location /server-status>
SetHandler server-status
Order deny,allow
Deny from all
Allow from 127.0.0.1
Allow from ::1
</Location>
# Activation de l'adresse : http://localhost/server-info
<Location /server-info>
SetHandler server-info
Order deny,allow
Deny from all
Allow from 127.0.0.1
Allow from ::1
</Location>
</VirtualHost>
La définition d'un hôte virtuel permet de redéfinir les valeurs par défaut du fichier principal.
L'ajout d'hôte supplémentaire est très simple et permet de varier les options de configuration.
- ajout du nom du site dans le DNS ou, pour test, dans le fichier /etc/hosts
127.0.0.1 nommachine site1 site2 site3 localhost.localdomain localhost
- définition de l'hôte dans notre fichier de configuration (messites.conf)
<VirtualHost *:80>
# home du site : URL = http://site1/
ServerName site1
# Dossier contenant les pages
DocumentRoot /var/www/site1
<Directory /var/www/site1>
Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
AllowOverride FileInfo AuthConfig Limit
</Directory>
# jeu de caractères (UTF-8 par défaut)
AddDefaultCharset ISO-8859-1
</VirtualHost>
Extensions
L'une des principales forces d'Apache est de disposer d'une grande quantité d'extensions pouvant être installées en fonction des besoins. La plupart sont disponible dans la distribution.
Petite liste non exhaustive :
- mod_authz_ldap : gestion des authentifications LDAP
- mod_perl : un interpréteur Perl embarqué
- mod_python : un interpréteur Python embarqué
- mod_security : une extension de sécurité
- mod_ssl : extension SSL/TLS (pour les sites https)
- php : un interpréteur PHP embarqué. Voir la page Installation et configuration de PHP
- etc...
Liste exhaustive :
yum list mod_\*
SELinux et apache
Le dossier /var/www et ses sous dossiers doivent posséder un contexte SELinux particulier (si SELinux est activé, bien entendu).
La manifestation la plus évidente d'un problème de contexte SELinux pour les fichiers d'un site web se traduit dans le fichier log d'apache (/var/log/httpd/error_log) par un message du type :
[Thu Sep 06 09:04:54 2007] [error] [client 127.0.0.1] (13)Permission denied: access to /index.php denied
Accompagné dans le fichier /var/log/messages d'une entrée du type :
SELinux is preventing access to files with the default label, default_t. For complete SELinux messages. run sealert -l b5c3f837-f138-4853-97f9-8fd8dbd27531
Ces messages signifient que le contexte SELinux n'est pas correct pour le serveur web, et donc que SELinux en a bloqué l'accès. Dans ce cas précis, la commande sealert vous expliquera qu'il faut restaurer le contexte par défaut avec la commande :
restorecon -R -v /var/www/html
Cette astuce n'est évidemment pas universelle, mais c'est un problème fréquemment rencontré lorsque l'on commence à travailler sous apache. Pour de plus amples informations, je vous conseille de lire attentivement la page de manuel des commandes restorecon et sealert.
Gardez à l'esprit qu'il reste toujours possible qu'une erreur proviennent d'un problème de droits UNIX, et pas forcément de SELinux, dans ce cas vous aurez une entrée access denied dans le fichier de log d'apache, mais rien dans /var/log/messages
Conclusion
Cet article doit vous avoir permis de rendre apache opérationnel sur votre machine.
Il vous reste maintenant beaucoup de lecture pour découvrir un aperçu de ses fonctionnalités.
Configurer le module mod_ssl
Il faut générer un certificat signé par une autorité de certification.
On créé l'arborescence nécessaire à la génération des clés et certificats
mkdir /etc/pki/httpd/
cd /etc/pki/httpd/
mkdir {certs,private,confs}
touch index.txt
echo 01 > serial
Création du fichier de configuration de nos futurs certificats : <path>/etc/pki/httpd/ssl.cnf</path>
HOME = . RANDFILE = .rand [ca] default_ca = ca_default [ca_default] dir = . certs = $dir/certs crl_dir = $dir/crl database = $dir/index.txt new_certs_dir = $dir/newcerts certificate = $dir/%s_ca_cert.pem private_key = $dir/private/%s_ca_key.pem serial = $dir/serial crl = $dir/crl.pem x509_extensions = usr_cert name_opt = ca_default cert_opt = ca_default default_days = 3650 default_crl_days = 30 default_md = md5 preserve = no policy = policy_match [policy_match] countryName = match stateOrProvinceName = match organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = optional [req] default_bits = 1024 default_keyfile = privkey.pem distinguished_name = req_distinguished_name attributes = req_attributes x509_extensions = v3_ca # The extentions to add to the self signed cert string_mask = MASK:0x2002 req_extensions = v3_req [req_distinguished_name] countryName = Country Name (2 letter code) countryName_default = FR countryName_min = 2 countryName_max = 2 stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = Paca localityName = Locality Name (eg, city) localityName_default = Cavaillon 0.organizationName = Organization Name (eg, company) 0.organizationName_default = B2PWeb organizationalUnitName = Organizational Unit Name (eg, section) commonName = Common Name (eg, your name or your server\'s hostname) commonName_max = 64 emailAddress = Email Address emailAddress_max = 64 [req_attributes] challengePassword = A challenge password challengePassword_min = 4 challengePassword_max = 20 unstructuredName = An optional company name [usr_cert] basicConstraints = CA:FALSE nsComment = "OpenSSL Generated Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer:always [v3_ca] subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer:always basicConstraints = CA:true [v3_req] subjectAltName = "DNS:www-secure.b2pweb.com,DNS:statgeo.b2pweb.com"
D'abord on génère une clé non chiffrée sur disque (pour éviter d'avoir à saisir un mot de passe à chaque redémarrage d'Apache) :
openssl genrsa -out private/server.key 2048
On crée un certificat signé avec cette clé ( validité 1 an ):
openssl req -config ssl.cnf -new -x509 -days 365 -key private/server.key -out server.crt -extensions v3_ca -extensions v3_req
Répondre à l'ensemble des questions posées. Le nom de la machine ( hostname --fqdn doit être donné en réponse à Common Name.
Ensuite, dans Apache, modifier le fichier de définition du VirtualHost qui va bien :
NameVirtualHost *:443
<VirtualHost *:443>
SSLEngine on
SSLCertificateFile /etc/pki/httpd/server.crt
SSLCertificateKeyFile /etc/pki/httpd/private/server.key
SSLVerifyClient none
[etc., etc.]
</VirtualHost>
F.A.Q.
How to solve particular security constraints for an SSL-aware webserver is not always obvious because of the coherences between SSL, HTTP and Apache's way of processing requests. This chapter gives instructions on how to solve such typical situations. Treat is as a first step to find out the final solution, but always try to understand the stuff before you use it. Nothing is worse than using a security solution without knowing it's restrictions and coherences.
Cipher Suites and Enforced Strong Security
Fichier httpd.conf
SSLProtocol -all +SSLv2
SSLCipherSuite SSLv2:+HIGH:+MEDIUM:+LOW:+EXP
Fichier httpd.conf
SSLProtocol all
SSLCipherSuite HIGH:MEDIUM
Fichier httpd.conf
# allow all ciphers for the inital handshake,
# so export browsers can upgrade via SGC facility
SSLCipherSuite ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
<Directory /usr/local/apache/htdocs>
# but finally deny all browsers which haven't upgraded
SSLRequire %{SSL_CIPHER_USEKEYSIZE} >= 128
</Directory>
Fichier httpd.conf
# be liberal in general
SSLCipherSuite ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
<Location /strong/area>
# but https://hostname/strong/area/ and below requires strong ciphers
SSLCipherSuite HIGH:MEDIUM
</Location>
Client Authentication and Access Control
Fichier httpd.conf
# require a client certificate which has to be directly
# signed by our CA certificate in ca.crt
SSLVerifyClient require
SSLVerifyDepth 1
SSLCACertificateFile conf/ssl.crt/ca.crt
Fichier httpd.conf
SSLVerifyClient none
SSLCACertificateFile conf/ssl.crt/ca.crt
<Location /secure/area>
SSLVerifyClient require
SSLVerifyDepth 1
</Location>
The first method
SSLVerifyClient none
<Directory /usr/local/apache/htdocs/secure/area>
SSLVerifyClient require
SSLVerifyDepth 5
SSLCACertificateFile conf/ssl.crt/ca.crt
SSLCACertificatePath conf/ssl.crt
SSLOptions +FakeBasicAuth
SSLRequireSSL
AuthName "Snake Oil Authentication"
AuthType Basic
AuthUserFile /usr/local/apache/conf/httpd.passwd
require valid-user
</Directory>
Fichier httpd.htaccess
/C=DE/L=Munich/O=Snake Oil, Ltd./OU=Staff/CN=Foo:xxj31ZMTZzkVA
/C=US/L=S.F./O=Snake Oil, Ltd./OU=CA/CN=Bar:xxj31ZMTZzkVA
/C=US/L=L.A./O=Snake Oil, Ltd./OU=Dev/CN=Quux:xxj31ZMTZzkVA
The second method
Fichier httpd.conf
SSLVerifyClient none
<Directory "/var/www/html/area">
SSLVerifyClient require
SSLVerifyDepth 5
SSLCACertificateFile conf/ssl.crt/ca.crt
SSLCACertificatePath conf/ssl.crt
SSLOptions +FakeBasicAuth
SSLRequireSSL
SSLRequire %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." and \
%{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"}
</Directory>
Fichier httpd.conf
SSLCACertificateFile conf/ssl.crt/company-ca.crt
<Directory /usr/local/apache/htdocs>
# Outside the subarea only Intranet access is granted
Order deny,allow
Deny from all
Allow from 192.168.1.0/24
</Directory>
<Directory /var/www/html/subarea>
# Inside the subarea any Intranet access is allowed
# but from the Internet only HTTPS + Strong-Cipher + Password
# or the alternative HTTPS + Strong-Cipher + Client-Certificate
# If HTTPS is used, make sure a strong cipher is used.
# Additionally allow client certs as alternative to basic auth.
SSLVerifyClient optional
SSLVerifyDepth 1
SSLOptions +FakeBasicAuth +StrictRequire
SSLRequire %{SSL_CIPHER_USEKEYSIZE} >= 128
# Force clients from the Internet to use HTTPS
RewriteEngine on
RewriteCond %{REMOTE_ADDR} !^192\.168\.1\.[0-9]+$
RewriteCond %{HTTPS} !=on
RewriteRule .* - [F]
# Allow Network Access and/or Basic Auth
Satisfy any
# Network Access Control
Order deny,allow
Deny from all
Allow 192.168.1.0/24
# HTTP Basic Authentication
AuthType basic
AuthName "Protected Intranet Area"
AuthUserFile conf/protected.passwd
Require valid-user
</Directory>
Journalisation conditionnelle
La récupération par un client d'une page web complète peut générer beaucoup de log: téléchargement des images, etc... On peut conditionner la journalisation.
La journalisation peut être conditionnelle et les variables d'environnement système contiennent une variable basée sur la requète. La directive CustomLog accepte une condition basée sur celle-ci.
- On créer une varible d'environnement conditionnée par la cible de la requète
- On applique notre filtrage sur les logs.
Ici on spécifie que l'on veut logguer uniquement les .html et .shtml dans le log:
SetEnvIf Request_URI "(\.html|\.shtml)$" html
CustomLog logs/access.log common env=html
Ici on spécifie que l'on veut tous logguer sauf les images dans le log (condition inverse):
SetEnvIf Request_URI "(\.gif|\.png|\.jpg)$" image
CustomLog logs/access.log common env=!image
Ici on dispatche les logs avec un filtre basé sur le premier répertoire de la requète:
SetEnvIf Request_URI "^/foo/" foo
SetEnvIf Request_URI "^/bar/" bar
CustomLog /logs/access_foo_log common env=foo
CustomLog /logs/access_bar_log common env=bar
Forcer l'utilisation d'https au lieu de http
Il suffit de rajouter, soit à la fin du fichier <path>/etc/httpd/conf/httpd.conf</path> pour tous les sites du serveur, soit dans la définition du vhost, ou encore dans un fichier htaccess les lignes suivantes
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}