Configurer les hôtes virtuels (Apache)

Avant de modifier quoi que ce soit, il faut dans un premier temps faire une sauvagarde du ou des fichier(s) puis activer la nouvelle configuration:

cd /etc/apache2/sites-available
cp 000-default.conf mon_site.conf
a2dissite 000-default.conf
a2ensite mon_site.conf

Et n'oublions pas de vérifier que la syntaxe dans le fichier de configuration est correcte :

apache2ctl -t

Plusieurs domaines par IP

<VirtualHost *:80>
        ServerName toto.org
        DocumentRoot /var/www/html/docs/
</VirtualHost>

<VirtualHost *:80>
        ServerName titi.org
        DocumentRoot /var/www/html
</VirtualHost>

Il existe une autre solution avec les virtualhosts dynamique

Ces directives se placent en dehors de la balise </VirtualHost>
UseCanonicalName Off
VirtualDocumentRoot "/var/www/html/%0"

Ainsi http://toto.org/index.html revient à se rendre dans le dossier /var/www/html/toto.com/index.html

Modifier le fichier par défaut

Au lieu que le serveur lise la page index.html lorsqu'un vsiteur lis cette url : http://mon-site-web.com/ Le serveur enverra au client la page portail.html

<VirtualHost *:80>
  <Directory "/var/www/html">
    DirectoryIndex portail.html
  </Directory>
</VirtualHost>

Ne pas lister un répertoire

<VirtualHost *:80>
<Directory "/var/www/html">
        Options -Indexes
        # Activer le listage :
        # Options Indexes
</Directory>
</VirtualHost>

Accés d'un dossier utilisateur système

Admettons que l'utilisateur toto veut partager ces documents. Il devra dans un premier temps créer un dossier spécifique à cette accès :

mkdir /home/toto/www
echo "acces web" > /home/toto/www/fichier.txt

On a besion d'activer le module mod_userdir :

# a2enmod userdir 

Puis ajouter ces lignes dans un contexte :

<IfModule mod_userdir.c>
    <Directory /home/*/www>
        # Autres directives ...
    </Directory>
</IfModule>

Ainsi, on peut télécharger son fichier depuis l'url http://mon-site-web.com/~toto/fichier.txt

Inclure une ressource externe

<VirtualHost *:80>
  <FilesMatch "\.(jpg|jpeg|png|gif)$">
        DocumentRoot /var/www/html/images/
        # Dans un cas plus concret on pourrait utiliser un reverse proxy.
  </FilesMatch>
</VirtualHost>

Si apache est derrière un reverse proxy

    <IfModule mod_setenvif.c>
        SetEnvIf X-Forwarded-Proto "^https$" HTTPS
    </IfModule>

Redirection d'un domaine

On veut faire une redirection de exemple.com vers www.exemple.com. Dans ce cas, il faut modifier le virtualhost concerné :

  • Soit par une re-écriture d'url :
nano /etc/apache2/site-enabled/exemple.com.conf
exemple.com.conf
<VirtualHost *:80>
        ServerName exemple.com
        RewriteEngine on
        RewriteRule ^/(.*)$ http://www.exemple.com%{REQUEST_URI}
</VirtualHost>
 
<VirtualHost *:80>
        ServerName www.exemple.com
        DocumentRoot /var/www/html/
</VirtualHost>

Puis on active le module permettant de réaliser ceci :

a2enmod rewrite
  • Soit en renvoyant en plus le code 301 :
Redirect 301 / http://exemple.com

Réécriture d’URL

Par exemple http://mon-site.com/test/ devienne http://mon-site.com/docs/index.html :

<VirtualHost *:80>
        ServerName mon-site.com
        DocumentRoot /var/www/html/

        RewriteEngine On
        RewriteRule /test/ /docs/index.html [R=301,L]

        ErrorLog ${APACHE_LOG_DIR}/toto.error.log
        CustomLog ${APACHE_LOG_DIR}/toto.access.log combined
</VirtualHost>

Pour que ça fonctionne, il y a besoin du module suivant :

a2enmod rewrite

Réécriture conditionnelle

On veut que le visiteur 192.167.1.31 accède à une page du site différente par rapport aux autres internautes :

RewriteEngine On
RewriteCond %{REMOTE_ADDR} ^192\.168\.1\.31
RewriteRule /(.*) /premium/$1 [R=301,L]

RewriteRule /(.*) /publique/$1 [R=301,L]

Redirection de ports

On souhaite forcer l'utilisation du port 443 pour sécuriser les communications :

exemple.conf
 <VirtualHost *:80>
     ServerName exemple.com
     Redirect permanent / https://exemple.com
 </VirtualHost>
 
 <IfModule mod_ssl.c>
 <VirtualHost *:443>
     ServerName exemple.com     
     SSLEngine on
 
     # ... d'autres directives
 </VirtualHost>
 </IfModule>

Filtrer les accès

<VirtualHost *:80>

   # Par IP :
    <Directory "/accueil/strategie">
        <RequireAny>
            Require ip 192.168.1.30
            Require not 192.168.1.129
            # Accès en local
            Require local
        </RequireAny>
    </Directory>

   # Par utilisateur (besoin du module userdir):
   <FilesMatch "\.(jpg|jpeg|png|gif)$">        
        UserDir disabled toto
   </FilesMatch>
   
   # Désactive les accès pour tout
   <File .htpasswd>
        Require all denied
   </File>

</VirtualHost>

Créer un Alias

Pour une courte période on peut simplifier l'accès à une ressource situé sur un serveur web en raccourcissant son URL :

Alias /court /var/www/html/chemin/vers/le/chemin/long

<VirtualHost>
#...
</VirtualHost>

La deuxième partie désigné par la directive correspond à l'url que l'on souhaite raccourcir.

Exécuter des scripts

  • Ancienne méthode avec CGI

Les directives ScriptAlias et ScriptAliasMatch permettent de désigner les répertoires pouvant contenir des fichiers exécutables. Ainsi le code suivant permet de récupérer la sortie standard d'un script pour l'afficher dans une page web.

<VirtualHost _default_:80>

    ScriptAlias /script/ /home/perso/scripts/
    <Directory /var/www/html/cgi/>
                Options ExecCGI
                AddHandler cgi-script .pl .rb
    </Directory>
</virtualhost>
  • Nouvelle méthode avec Fast-CGI

Elle a l'avantage de conserver en mémoire le dernier scripts exécuté. Ceci permet de réduire le temps de réponse et pour cela il nous faut le module fcgid :

apt-get install libapache2-mod-fcgid

Avec cette exemple de configuration :

<VirtualHost _default_:80>
<IfModule fcgid_module>

        <Directory /var/www/html/cgi/>
                Options ExecCGI
                AddHandler fcgid-script .fcgi .pl .rb
        </Directory>

</IfModule>
</VirtualHost>

Informations sur le service

On active le module :

a2enmod info

Puis on modifie notre hôte virtuel :

<VirtualHost *:80>
  <Location "/server-info">
    SetHandler server-info
  </Location>
</VirtualHost>

Personnaliser les logs

LogFormat "%P %U" custom
CustomLog ${APACHE_LOG_DIR}/toto.access.log custom

Dans LogFormat ont choisi les variables que l'on souhaite utiliser. Par défaut common est la variable utilisé. Celle-ci contient le format suivant :

LogFormat "%h %l %u %t \"%r\" %>s %b" common

Filtrage conditionnel

Imaginons que l'on souhaite journaliser les activités de 192.168.1.30:

<VirtualHost *:80>
   SetEnvIf Remote_Addr "192.168.1.30$" filtre
   CustomLog ${APACHE_LOG_DIR}/filtre.access.log custom env=filtre
   CustomLog ${APACHE_LOG_DIR}/access.log custom env=!filtre
</VirtualHost>

Personnaliser un en tête

<VirtualHost *:80>
        Header set X-Talking-To-Me "Are you talking to ?"
</VirtualHost>

Voici le résultat attendu :

$ curl -I http://127.0.0.1
HTTP/1.1 200 OK
Date: Thu, 12 Jan 2017 13:36:05 GMT
Server: Apache/2.4.10 (Debian)
Last-Modified: Wed, 11 Jan 2017 16:18:53 GMT
ETag: "7-545d3f4f6b300"
Accept-Ranges: bytes
Content-Length: 7
X-Talking-To-Me: Are you talking to ?                   # Header personnalisé
Content-Type: text/html

Eviter la surcharge .htaccess

<VirtualHost *:80>
   <Directory "/var/www/">
      AllowOverride None
      #...
   </Directory>
</VirtualHost>

Limiter les méthodes HTTP

Admettons qu'une ressource doit être uniquement accessible en lecture et pas moyen d'envoyer une image. On insérer ces directives :

<VirtualHost *:80>
   <Location /secure>
      <LimitExcept GET HEAD>
        Allow from all
      </LimitExcept>
   </Location>
</VirtualHost>

Authentification avec LDAP

<VirtualHost *:80>
  <directory /var/www/html>
    AuthName "acces restreint"
    AuthType Basic
    AuthBasicProvider ldap
    AuthLDAPURL ldap://localhost/dc=asrall,dc=fr
    Require valid-user
  </directory>
</VirtualHost>

Jouer avec les logs

  • Lister ceux qui envoit le plus de requêtes http :
awk '{print $2}' /var/log/apache2/access.log |sort |uniq -c |grep -P '^\s+\d\d\d\d '