Gestion de LetsEncrypt sous FreeBSD avec nginx et une jail

LetsEncypt est une autorité de certification utilisant une API basée sur des appels HTTP et un client côté serveur qui va générer des tokens lus par les serveurs LetsEncrypt. Nous allons ici voir une architecture LetsEncrypt typique dans laquelle nous allons utiliser le client acme-client d'OpenBSD disponible dans les ports et les packages FreeBSD.

Installation

Dans un premier temps installez le client sur votre machine hôte (et pas votre jail web):

pkg install acme-client

Configuration de nginx

Nous allons maintenant configurer nginx afin de pouvoir interagir avec l'API letsencrypt. Créez tout d'abord le répertoire suivant dans votre jail avec l'utilisateur et le groupe nobody

mkdir /usr/local/www/.well-known && chown nobody:nobody /usr/local/www/.well-known

Ensuite configurez vos virtual hosts afin de faire pointer les appels vers /.well-known dans ce répertoire:

server {
        listen 80;
        server_name www.unix-experience.fr;
        location /.well-known {
            alias /usr/local/www/.well-known;
        }
        location / {
            return 301 https://www.unix-experience.fr$request_uri;
        }
        add_header X-Frame-Options "DENY";
        add_header Strict-Transport-Security "max-age=86400; preload";
}

Note: nous ajoutons ici le support du protocole HSTS avec un TTL d'1 journée spécifiant aux navigateurs que le site supporte SSL et qu'il faudrait passer dessus. Vous pouvez sans souci faire pointer plusieurs de vos virtual hosts dans ce même répertoire.

Configuration du client LetsEncrypt

Retournez maintenant sur votre hôte et créez le fichier /usr/local/etc/acme/domains.txt puis ajoutez y un domaine par ligne:

www.unix-experience.fr
ftp.unix-experience.fr

Créez ensuite le script ci-dessous (basé sur le script présent dans le même répertoire sous forme d'exemple) dans /usr/local/etc/acme/acme-client.sh

#!/bin/sh -e
WEBJAIL="web"
BASEDIR="/usr/local/etc/acme"
SSLDIR="/usr/local/etc/ssl/acme"
DOMAINSFILE="${BASEDIR}/domains.txt"
CHALLENGEDIR="/jails/${WEBJAIL}/usr/local/www/.well-known/acme-challenge"

[ ! -d "${SSLDIR}/private" ] && mkdir -pm700 "${SSLDIR}/private"

cat "${DOMAINSFILE}" | while read domain line ; do
   CERTSDIR="${SSLDIR}/${domain}"
   [ ! -d "${CERTSDIR}" ] && mkdir -pm755 "${CERTSDIR}"
   set +e # RC=2 when time to expire > 30 days
   acme-client -b -C "${CHALLENGEDIR}" \
               -k "${SSLDIR}/private/${domain}.pem" \
               -c "${CERTSDIR}" \
               -n -N -v \
               ${domain} ${line}
   RC=$?
   set -e
   [ $RC -ne 0 -a $RC -ne 2 ] && exit $RC
done

Ce script lit les domaines présents dans le fichier domains.txt puis il va s'occuper de créer vos clefs privées et de les faire signer par LetsEncrypt, en se basant sur le répertoire .well-known présent dans votre jail. Une fois ce script exécuté, si tout s'est passé correctement vous trouverez votre clef privée dans le répertoire /usr/local/etc/ssl/acme/private/example.org et votre clef publique et les chaînes de certificats dans le répertoire /usr/local/etc/ssl/acme/example.org. Ces répertoires sont situés sur votre hôte et non dans votre jail web. Pour déployer les scripts un script d'exemple est présent dans le répertoire /usr/local/etc/**acme, mais nous allons légèrement le modifier. Créez le fichier /usr/local/etc/acme/deploy.sh**:

#!/bin/sh

set -e

BASEDIR="/usr/local/etc/acme"
DOMAINSFILE="${BASEDIR}/domains.txt"
LEDIR="/usr/local/etc/ssl/acme"
JAILSDIR="/jails"
TARGETS="web"
cat "${DOMAINSFILE}" | while read domain line ; do
    for jail in ${TARGETS}; do
        targetdir="${JAILSDIR}/${jail}/etc/ssl"
        # Check if the certificate has changed
        [[ -z "`diff -rq ${LEDIR}/${domain}/fullchain.pem ${targetdir}/certs/${domain}.pem`" ]] && continue
        cp -L "${LEDIR}/private/${domain}.pem"   "${targetdir}/private/${domain}.pem"
        cp -L "${LEDIR}/${domain}/fullchain.pem" "${targetdir}/certs/${domain}.pem"
        chmod 400 "${targetdir}/private/${domain}.pem"
        chmod 644 "${targetdir}/certs/${domain}.pem"
        # Restart/-load relevant services
        [[ "${jail}" = "web" ]] && jexec ${jail} service nginx restart
    done
done

Ce script va copier tous les certificats associés à vos dernières négociations LetsEncrypt et va les déployer dans votre jail web puis redémarrer nginx.

Renouvellement automatique

Pour finir il ne reste plus qu'à configurer le cron ajouté par le paquet acme-client afin de configurer la tâche hebdomadaire. Pour se faire, éditez le fichier /usr/local/etc/periodic.conf et ajoutez les entrées suivantes:

# letsencrypt
weekly_acme_client_enable="YES"
weekly_acme_client_user="nobody"
weekly_acme_client_deployscript="/usr/local/etc/acme/deploy.sh"

Cela va vous permettre d'activer le cron, et de lancer le déploiement automatiquement toutes les semaines.

Conclusion

Vous pouvez désormais faire des demandes de certificats LetsEncrypt facilement et les renouveler automatiquement via un cron fourni par acme-client.

Apache: obtenir l’IP source depuis un en-tête conditionel dans les logs

Dans le cadre d'un environnement web haute disponibilité il y a généralement des répartiteurs de charge HTTP comme HAproxy ou des reverse proxies comme Apache ou Nginx en frontal qui vont s'occuper de répartir la charge et/ou filtrer une partie des requêtes pour ménager les serveurs d'application de backend.

Le principal problème rencontré dans ce type d'architecture est que, généralement, le service web de frontend va masquer l'IP source du client, réduisant la tracabilité de celui-ci sur les backends. Nous allons ici partir du principe que le service web de frontend retransmet l'IP au backend via un en-tête HTTP nommé X-Real-IP.

L'astuce que nous allons voir ici permet d'afficher l'adresse IP du client via l'en-tête X-Real-IP si celui-ci existe, auquel cas l'adresse IP source.

Dans un premier temps nous allons définir 2 LogFormat, _completerealip et complete, chacun ayant un paramétrage sur le champ 1 différent:

LogFormat "%{X-Real-IP}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" \"%{Host}i\" %D" complete_realip
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" \"%{Host}i\" %D" complete

Dans un second temps, nous allons nous servir du module _modsetenvif afin de vérifier l'existence de l'en-tête:

SetEnvIf X-Real-IP ^.+$ real_ip_exists

Enfin on définit une condition sur l'environnement afin de basculer le log d'un mode à l'autre suivant la requête entrante:

CustomLog /var/log/apache/myapp_access.log complete_realip env=real_ip_exists
CustomLog /var/log/apache/myapp_access.log complete env=!real_ip_exists

Conclusion

Votre serveur Apache va désormais basculer l'IP présentée dans ses logs dynamiquement en fonction de la présence ou non de l'en-tête X-Real-IP.

Note: Si vous utilisez un haproxy en frontend, la configuration à ajouter à vos backend haproxy est la suivante:

http-request set-header X-Real-IP %[src]

Apache: authentification par certificats

L'authentification par certificats permet de remplacer le traditionnel couple login/password dans un environnement doté de PKI.

Le certificat doit être reconnu par le serveur web, que ce soit par le biais du fait que le CA authentifie côté serveur et qu'on peut également filtrer les utilisateurs par données présentes dans le certificat.

Entre autres, cela permet également d'utiliser des supports externes au clavier pour reconnaître les utilisateurs, comme des lecteurs de carte à puce.

Nous allons voir ici comment activer l'authentification par certificat sous Apache.

Configuration

Ouvrez le fichier de votre virtualhost favori et activez tout d'abord le support HTTPS en ajoutant une clef publique, privée et optionnellement une chaîne de certificats:

SSLEngine on
SSLCertificateFile "/etc/ssl/www.unix-experience.fr.crt"
SSLCertificateKeyFile "/etc/ssl/www.unix-experience.fr.key"
SSLCertificateChainFile "/etc/ssl/myCA.pem"

Maintenant que le chiffrement des communications est assuré, vous pouvez sécuriser l'accès au Virtualhost en rajoutant les lignes suivantes:

SSLVerifyDepth 3
SSLVerifyClient require
SSLCACertificateFile "/etc/ssl/myCA.pem"
SSLOptions +StdEnvVars

Détaillons les différentes options:

  • SSLVerifyDepth: permet de définir quelle est la profondeur de la vérification sur le certificat SSL. Il faut mettre au minimum 2 suivant comment est construit votre certificat client
  • SSLVerifyClient: permet de forcer l'authentification par certificat si vous optez pour require. Autrement spécifiez optionnal
  • SSLCaCertificateFile: Il s'agit du CA qui correspond aux certificats clients
  • SSLOptions + StdEnvVars: permet de passer les options du certificat client aux moteurs sous jacents (PHP par exemple).

Maintenant que votre serveur est capable d'authentifier les certificats provenant du CA myCA.pem, il vous faut générer des certificats utilisant un CN (Common Name) correspondant à l'adresse mail de vos utilisateurs et une application qui soit pleinement compatible en face (un SSO comme Shibboleth par exemple).

Conclusion

Vous savez désormais comment configurer Apache pour authentifier des clients par certificats. Il ne reste plus qu'à mettre en place une PKI.

Shibboleth (IdP): installation et retour d’expérience

Shibboleth est un système de fédération d'identités. Il permet d'authentifier des utilisateurs faisant partie d'établissements/entreprises différentes sur des applications mutualisées.

Peu présent et utile dans le secteur privé, Shibboleth est une référence en terme d'authentification dans le secteur public, au sein du ministère de l'enseignement supérieur et de la recherche. Renater, fournisseur d'accès à Internet réservé aux établissement d'enseignement supérieur et de recherche, est l'un des organismes qui l'utilise le plus.

Shibboleth est composé de plusieurs briques, notamment le Service Provider (SP, fournisseur de services) et dans notre cas le fournisseur d'identité (Identity Provider, IdP)

Installation

Pré-requis

Avant de pouvoir installer et utiliser shibboleth, il vous faudra installer JDK 6 et Tomcat 7.

Si vous utilisez Debian tapez simplement:

apt-get install openjdk-6-jdk tomcat7

Si vous utilisez FreeBSD, compilez le port www/tomcat

cd /usr/ports/www/tomcat7
make install clean

ou installez le package depuis votre repo pkgng préféré

pkg install tomcat

Installation de Shibboleth

Téléchargement de l'archive

On télécharge tout d'abord le dernier Shibboleth puis on l'extrait

wget http://shibboleth.net/downloads/identity-provider/latest/shibboleth-identityprovider-2.4.0-bin.tar.gz
tar xvzf shibboleth-identityprovider-2.4.0-bin.tar.gz

Configuration de la variable JAVA_HOME

Pour pouvoir installer Shibboleth nous allons avoir besoin de spécifier la variable d'environnement JAVA_HOME.

Pour Debian, tapez la commande suivante:

export JAVA_HOME="/usr/lib/jvm/java-6-openjdk-amd64/jre"

Pour FreeBSD:

  • si vous utilisez csh:
setenv JAVA_HOME "/usr/local/openjdk6/jre/"
  • si vous utilisez sh, bash ou encore zsh:
export JAVA_HOME="/usr/local/openjdk6/jre/"

Lancement de l'installeur

Pour finir nous lançons l'installation:

cd shibboleth-identityprovider-2.4.0
./install.sh

Lors de l'installation le chemin d'installation, le nom du serveur (adresse DNS du CAS/SSO) et un mot de passe vous seront demandés:

Where should the Shibboleth Identity Provider software be installed? [/opt/shibboleth-idp]
What is the fully qualified hostname of the Shibboleth Identity Provider server? [idp.example.org]
A keystore is about to be generated for you. Please enter a password that will be used to protect it.

Une fois l'installation terminée, on copie le fichier WAR de l'application java dans le répertoire d'applications tomcat.

Pour Debian:

cp /opt/shibboleth-idp/war/idp.war /usr/share/tomcat7/webapps/

Pour FreeBSD:

cp /opt/shibboleth-idp/war/idp.war /usr/local/apache-tomcat-7.0/webapps/

Il faut ensuite changer les droits des répertoires de logs et de méta-données.

Pour Debian:

chown -R tomcat7 /opt/shibboleth-idp/logs
chown -R tomcat7 /opt/shibboleth-idp/metadata

Pour FreeBSD:

chown -R www /opt/shibboleth-idp/logs
chown -R www /opt/shibboleth-idp/metadata

Pour finir, on va ajouter quelques librairies JAVA à tomcat afin que Shibboleth fonctionne correctement. Vous trouverez ces fichiers dans le répertoire où vous avez extrait l'installeur de Shibboleth.

Pour Debian:

cp endorsed/*.jar /usr/share/tomcat7/endorsed/

Pour FreeBSD:

cp endorsed/*.jar /usr/local/apache-tomcat-7.0/endorsed/

Lancement du service

On peut désormais lancer Tomcat.

Sous Debian:

service tomcat7 start

Sous FreeBSD:

service tomcat start

Pour vérifier que tout fonctionne, connectez vous à l'adresse http://idp.example.org:8080/idp/profile/Status. Si la page affiche ok c'est que l'application est correctement déployée.

Enfin, vérifiez que le portail SSO de Shibboleth fonctionne en allant à l'URL http://idp.example.org:8080/idp/Authn/UserPassword

Designer le SSO

Le premier axe d'amélioration est la personnalisation du design du SSO. Pour cela c'est très simple, il suffit d'aller dans le répertoire webapps/idp/ de votre tomcat et de personnaliser les fichiers login.jsp et login.css, correspondant à la page de login. Vous n'avez pas besoin de redémarrer tomcat à chaque modification, à contrario des fichiers de configuration de Shibboleth.

Conclusion

Nous avons ici fait la partie la plus simple, à savoir l'installation de Shibboleth. Le plus compliqué reste la configuration de l'IdP lui-même. Vous trouverez dans les sources ci-dessous la documentation Renater, extrêmement complète permettant de comprendre les différents éléments à configurer pour Shibboleth (partez de la partie 4)

J'ai également essayé d'installer Shibboleth avec Jetty 8 (Shibboleth ne supporte que Jetty >= 7) mais je n'ai pas réussi, ni sur Debian, ni sur FreeBSD. Jetty nécessite d'intégrer des fichiers de configuration supplémentaires et des librairies Tomcat pour faire fonctionner Shibboleth, il reste donc plus pertinent d'utiliser Tomcat 7.

Par ailleurs, j'ai fortement apprécié le déploiement sur cette version de Tomcat 7. J'utilise peu Tomcat et ma précédente expérience avec Tomcat 6 n'avait pas été convaincante.

Même si vous n'utilisez pas la fédération d'identité, Shibboleth peut très bien être utilisé en tant que serveur CAS/SSO (dans mon cas il est branché sur 2 OpenLDAP). Si vous suivez la documentation Renater vous devriez sans problème arriver à faire fonctionner cette partie et pouvoir commencer à l'intégrer sur vos services web.

Sources

https://wiki.shibboleth.net/confluence/display/SHIB2/IdPInstall https://www.switch.ch/aai/docs/shibboleth/SWITCH/latest/idp/deployment/#shibboleth-idp-configuration https://services.renater.fr/federation/docs/installation/idp_decembre2012

Mettre en place un cluster Apache avec FreeBSD et DragonFlyBSD

Nous allons étudier dans cet article un type d'architecture redondée pour vos serveurs Web Apache. Dans ce type d'architecture, les bases de données sont dissociées du modèle, et ne seront pas étudiées ici. De même nous ne configurerons ni Apache ni le Wordpress de test qui seront installés, d'autres articles seront référencés.

Cluster de données

Dans un premier temps nous allons installer le cluster de données. Nous nous basons sur DragonFlyBSD pour son très bon système de fichiers (HAMMER), qui offre d'excellentes performances avec NFS (limité à la version 3).

Installation de DragonFlyBSD

Les serveurs qui serviront de cluster de données NFS seront installés de manière classique. Il faut 2 raids sur la machine, un raid système (raid 1) et un raid pour les données (raid 5 ou raid 10 par exemple). Lors de l'installation ne configurez que le raid système (da0)

Pour l'installation de DragonFlyBSD, utilisez cet article.

Configuration des volumes de données

DragonFlyBSD étant installé, on va maintenant procéder à la création des volumes de données Hammer. Dans un premier temps on créée un volume Hammer sur notre raid 5 et on le monte

newfs_hammer -L webdatas /dev/da1
mkdir /nfs
mount -t hammer /dev/da1 /nfs

Maintenant on va configurer les PFS (volumes virtuels qui serviront à la réplication Hammer) et les monter. Nous avons besoin de 3 volumes qui correspondront aux répertoires /usr/local, /usr/ports/distfiles et /var/db/pkg sur les serveurs web. Exécutez cet ensemble de commande sur le serveur NFS maître.

mkdir /nfs/pfs/
mkdir /nfs/fsbd_fs/
hammer pfs-master /nfs/pfs/fbsd_fs
mount_null /nfs/pfs/fbsd_fs /nfs/fbsd_fs
mkdir /nfs/fbsd_fs
hammer pfs-master /nfs/pfs/fbsd_distfiles
mount_null /nfs/pfs/fbsd_distfiles /nfs/fbsd_distfiles
mkdir /nfs/fbsd_pkg
hammer pfs-master /nfs/pfs/fbsd_pkg
mount_null /nfs/pfs/fbsd_pkg /nfs/fbsd_pkg

Notez bien les shared-uuid lors de la création de chaque PFS, vous allez en avoir besoin tout de suite. Sur le slave, configurez les PFS, en remplacant xxx,yyy et zzz par les shared-uuid équivalent au maître.

mkdir /nfs/pfs/
mkdir /nfs/fsbd_fs/
hammer pfs-slave /nfs/pfs/fbsd_fs shared-uuid=xxx
mkdir /nfs/fbsd_fs
hammer pfs-slave /nfs/pfs/fbsd_distfiles shared-uuid=yyy
mkdir /nfs/fbsd_pkg
hammer pfs-slave /nfs/pfs/fbsd_pkg shared-uuid=zzz

Vous noterez que les pfs-slave ne sont pas montés. Effectivement, on ne peut pas les monter, la réplication se fait à froid.

Pour finir on rajoute les lignes qui vont bien dans le fichier /etc/fstab

# Cluster
/dev/da1        /nfs            hammer    rw    0    0
/nfs/pfs/fbsd_fs        /nfs/fbsd_fs        null    rw    0    0
/nfs/pfs/fbsd_distfiles    /nfs/fbsd_distfiles    null    rw    0    0
/nfs/pfs/fbsd_pkg    /nfs/fbsd_pkg    null    rw    0    0

Note: attention, il faut absolument monter tous les disques physiques avant de monter les PFS

Configuration de NFS

Configurons le serveur NFS. Ouvrez le fichier /etc/exports. Remplacez l'adresse réseau par celle de vos serveurs web. Il est également possible de spécifier des hôtes.

/nfs/fbsd_fs -maproot=root -network=192.168.1.0 -mask 255.255.255.0
/nfs/fbsd_distfiles -maproot=root -network=192.168.1.0 -mask 255.255.255.0
/nfs/fbsd_pkg -maproot=root -network=192.168.1.0 -mask 255.255.255.0

On va activer les services, ouvrez le fichier /etc/rc.conf et ajoutez les lignes suivantes.

nfs_server_enable="YES"
mountd_enable="YES"
mountd_flags="-r"
rpcbind_enable="YES"
nfsd_flags="-n 16"

Les arguments passés à nfsd permettent de multiplier le nombre de processus en parallèle.

Vous pouvez maintenant démarrer les services

/etc/rc.d/rpcbind start
/etc/rc.d/mountd start
/etc/rc.d/nfsd start

On va maintenant configurer la réplication. Il est possible de configurer la méthode en pull ou en push. Nous préfèrerons ici une réplication en push, le maître pousse vers l'esclave. Exécutez l'ensemble de commandes suivantes:

hammer mirror-stream /nfs/pfs/fbsd_fs root@192.168.1.1:/nfs/pfs/fbsd_fs &
hammer mirror-stream /nfs/pfs/fbsd_distfiles root@192.168.1.1:/nfs/pfs/fbsd_distfiles &
hammer mirror-stream /nfs/pfs/fbsd_pkg root@192.168.1.1:/nfs/pfs/fbsd_pkg &

Afin de gagner en flexibilité, vous pouvez les ajouter au fichier /etc/rc.local afin qu'elles soient exécutées à chaque démarrage.

Votre serveur NFS est prêt.

Serveurs Web

Installation de FreeBSD

Je vous invite à lire cet article concernant l'installation de FreeBSD. Extrayez ensuite l'arbre des ports.

portsnap fetch extract

Montage des volumes NFS

On va maintenant monter les volumes NFS nécessaires à notre cluster. Tout d'abord activons les services NFS nécessaires. Ouvrez le fichier /etc/rc.conf

nfs_client_enable="YES"
rpcbind_enable="YES"

On active ensuite les services

service nfsclient start
service rpcbind start

Sur chacun des serveurs web tapez la commande suivante afin de monter les volumes

mount_nfs -o tcp,nolockd,rw 192.168.1.1:/nfs/fbsd_web /usr/local/
mount_nfs -o tcp,nolockd,rw 192.168.1.1/nfs/fbsd_pkg /var/db/pkg/
mount_nfs -o tcp,nolockd,rw 192.168.1.1:/nfs/fbsd_distfiles /usr/ports/distfiles/

Enfin on rend ce montage permanent en ajoutant les entrées associées au fichier /etc/fstab

# NFS mount
10.117.100.65:/nfs/fbsd_web            /usr/local        nfs    rw,tcp,nolockd    0    0
10.117.100.65:/nfs/fbsd_distfiles    /usr/ports/distfiles    nfs    rw,tcp,nolockd    0    0
10.117.100.65:/nfs/fbsd_pkg    /var/db/pkg    nfs    rw,tcp,nolockd    0    0

Vous remarquerez qu'on utilise l'option TCP. Celle-ci permet de garder une connexion persistante au serveur NFS, et offre une amélioration de performances non négligeable par rapport à UDP. En UDP, beaucoup plus de requêtes RPC sont transmises, ce qui augmente la charge réseau et CPU.

Vous remarquez qu'on désactive lockd. Ceci est dû au fait que nous hébergeons uniquement des données "statiques". Dans le cas d'une base de données il faut impérativement activer le service lockd et statd.

Installation des ports

Maintenant que nos serveurs web sont prêts, passons à l'installation des ports. Ici nous installerons rapidement le serveur web et PHP, je vous convie à lire cet article pour configurer Apache et PHP correctement sous FreeBSD.

Voici quelques commandes afin d'installer rapidement les paquets.

cd /usr/ports/www/apache22
make install clean
cd /usr/ports/lang/php5
make install clean
cd /usr/ports/www/wordpress
make install clean

Je vous conseille de garder les options par défaut pour chacun des softs, hormis si vous avez des besoins spécifiques. Les compilations devraient prendre environ une journée travaillée sur un CPU à 1 seul coeur, n'hésitez pas à faire autre chose en attendant.

A chaque fois qu'un port est configuré/installé vous devriez voir les fichiers mis à jour sur le second serveur web, ainsi que sur le serveur NFS et augmenter la taille du volume sur le serveur NFS réplica.

Ajoutez la ligne suivante afin d'activer le démarrage d'Apache

apache22_enable="YES"

Configuration du démarrage des services

Si vous redémarrez vous vous rendrez compte que, malgré la ligne précédente le service Apache ne se lance pas au démarrage. Ceci est dû au montage NFS lors du démarrage. En effet à ce moment les binaires Apache ne sont pas dans le PATH. Nous allons donc ruser en allumant Apache "à la main".

Ouvrez le fichier /etc/rc.local et ajoutez la ligne suivante sur chacun des serveurs web

service apache22 start

Vous pouvez redémarrer pour tester. Votre cluster web est désormais prêt.

Vous pouvez mettre autant de machines FreeBSD que désiré sur ces volumes NFS. Il vous suffira simplement d'installer FreeBSD, monter les volumes et faire cette dernière manipulation.

Cette fonction de distribution de la partie utilisateur ne marche que sur FreeBSD qui met l'ensemble de ses softs dans /usr/local lors de l'utilisation des ports, et permet ainsi d'obtenir une scalabilité du nombre de machines dépendant uniquement du serveur NFS.

Sur un serveur NFS herbergé sur un Dell R510 vous devriez pouvoir mettre sans problème une trentaine de serveurs Web FreeBSD en parallèle, si ce n'est plus. Il suffira simplement d'augmenter le nombre de processus nfsd (nfsd_flags, 3 par machine)

Activer la maintenance sur un Vhost

Introduction

Maintenir ses services est essentiel. Si vous n'êtes pas dans une configuration de load balancing ou de haute disponibilité, il convient parfois de mettre des services en maintenance. Il faut savoir que le protocole HTTP intègre un code de retour qui définit un service temporairement indisponible ou en maintenance (Code HTTP 503).

Prérequis

Il est essentiel d'avoir le mod_rewrite activé.

Configuration

Ouvrez le fichier de configuration de votre VirtualHost et ajoutez simplement les lignes suivantes:

RewriteEngine on
RewriteCond %{REQUEST_URI} !^/down.html [NC]
RewriteRule .* /down.html [R=503,L]

Avec ces lignes actives votre serveur est définit en maintenance. Vous pouvez créer une page web down.html afin de personnaliser l'alerte.

Il est bien entendu possible d'utiliser ces lignes pour générer d'autres codes d'erreur.

Reverse Proxy

Introduction

Depuis la version 2.2 d'Apache, une fonctionnalité très intéressante est apparue. Il s'agit du module de reverse proxy. Celui-ci permet de définir un serveur Apache comme forwardant des requêtes HTTP vers un autre serveur, par exemple local. Ceci permet notamment de cacher vos sites derrière un ou plusieurs serveurs web frontaux, répondant à une problématique de sécurité. Nous allons ici voir comment se configure le reverse proxy.

Cette manière de fonctionner permet ainsi de pouvoir changer de serveur à chaud par exemple dans le cas d'une maintenance ou d'un upgrade de site (avec deux machines différentes). Ceci permet également dans le cas d'une attaque web de protéger le transit de données en protégeant le contenu derrière plusieurs passerelles et pare-feu (seul le serveur web peut aller sur le site proxifié).

Prérequis

Vous devez au préalable activer/installer le module _modproxy, _mod_proxyhttp, _mod_proxyftp (si vous forwardez du trafic FTP), _mod_proxyconnect (pour le trafic HTTPS), _mod_proxyajp (serveurs tomcat), _mod_proxybalancer (load balacing de serveurs), _modheaders (pour modifier les en-têtes forwardés), _moddeflate (compression), _mod_proxyhtml (réécriture).

A vous de voir quoi activer. Nous nous contenterons de HTTP et HTTPS dans l'immédiat.

Configuration simple

La configuration d'un reverse proxy se fait dans la configuration d'un VirtualHost. Vous pouvez définir qu'un répertoire se situe sur un autre serveur, ou bien encore toute la base de votre site. Voici le template de base d'un VirtualHost en reverse proxy

<Virtualhost *:80>
      ServerName publicserver.domain.tld
      ServerAlias publicserver.domain.tld
      ProxyRequests off
      ProxyPass / http://localserver.local/
      ProxyPassReverse / http://localserver.local/
</Virtualhost>

Attention: n'oubliez pas le / à la fin de l'URL vers laquelle vous redirigez, sinon il est probable que vous soyez vulnérable à une faille de type proxy bypass.

Lorsqu'un client va se connecter sur l'adresse publicserver.domain.tld, il sera envoyé sur l'Apache frontal qui ira chercher les données demandées sur le serveur connu localserver.local. Le serveur localserver.local peut être une adresse DNS locale non connue du net ou une adresse IP non routable sur le net (conseillé dans une optique de sécurité).

Configuration générique

Voici une petite configuration très intéressante qui permet de rediriger l'ensemble des requêtes vers something.domain.tld vers something.local. Il faut au préalable activer le mod_rewrite d'Apache. Ceci permet de cacher facilement tous vos sites vers un ensemble de serveurs locaux (site1.domain.tld vers site1.local, site2.domain.tld vers site2.local).

<VirtualHost *:80>
  ServerName server.domain.tld
  ServerAlias *.domain.tld
  Rewriteengine On
  ProxyRequests off
  RewriteCond %{HTTP_HOST} (.*).domain.tld
  RewriteRule (.*) $1 [E=WHERETO:%1.local]
  ProxyPassReverse / <a>http://%{ENV:WHERETO}/</a>
  RewriteRule ^/(.*) <a>http://%{ENV:WHERETO}/$1</a> [P]
</VirtualHost>

Nous vous déconseillons d'utiliser cette configuration bien qu'elle permette d'administrer facilement un ensemble de serveurs proxifiés locaux.

Authentification .htaccess

Introduction

Généralement certaines parties de votre site sont sensibles, comme la partie administration. Afin de pouvoir sécuriser de façon plus stricte l'accès au fichiers de ces répertoires, il peut être judicieux de cacher derrière une autre sécurité celui-ci. Le fichier .htaccess permet de mettre des ACL d'accès sur un répertoire ou un fichier.

Prérequis

Vous devez avoir installé le service Apache2

Configuration d'Apache

Les .htaccess sont redoutablement efficaces pour permettre d'interdire l'accès à un répertoire.

Avant de commencer ce topic, vérifier que les lignes suivants du fichier /etc/apache2/apache2.conf sont bien dé-commentées, sinon créez les :

<Files ~ "^.ht">
    Order allow,deny
    Deny from all
    Satisfy all
</Files>

Ces lignes permettent de rendre invisible à quiconque les fichiers .htaccess.

Pour information, vous pouvez éviter de créer des .htaccess en utilisant les directives des VirtualHosts et en entrant les mêmes paramètres.

Configuration du .htaccess

Insérez les lignes suivantes afin de garantir la fonctionnalité du .htaccess :

AuthName "Accès Interdit"
AuthType Basic
AuthUserFile "/var/www/prive/.htpasswd"
Require valid-user

Ensuite il faudra créer le fichier de mots de passe. Dans les dernières version d'Apache ce fichier texte chiffre les mots de passe.

Pour créer le fichier .htpasswd :

.htpasswd -c .htpasswd toto
password: ****
repeat password: ****

Retirez l'option -c une fois que le fichier existe afin de rajouter des utilisateurs.

Votre répertoire est protégé.

ATTENTION : les mots de passe ont beau être chiffrés sur le serveur, ils transitent en clair sur votre réseau, sauf si vous utilisez du SSL !

mod_authnz_ldap

Introduction

Apache permet de s'authentifier via des fichiers .htaccess. Il peut s'avérer utile, notamment dans le cas d'un intranet, d'incorporer une couche d'authentification simple pour filtrer les utilisateurs ayant accès à une application Web. Nous allons voir comment mettre en oeuvre l'authentification LDAP sur un serveur Apache.

Configuration

Tout d'abord il faut activer le module déjà présent avec apache2.

a2enmod authnz_ldap
service apache2 force-reload

La configuration est réalisée au niveau du VirtualHost Apache, au niveau de la section Directory. Pour procéder, ajoutez les lignes suivantes à la configuration du répertoire concerné :

<Directory /private>
# <your VHost configuration>
AuthType basic
AuthName "Acces Restreint"
AuthBasicProvider ldap
AuthLDAPURL ldap://ldap.domain.tld/ou=people,dc=domain,dc=tld?uid
AuthLDAPRemoteUserIsDN off
require ldap-filter &(uid=*)
</Directory>

Cette configuration va permettre à tous les utilisateurs de la branche people du serveur domain.tld de s'authentifier en LDAP.

Pour terminer on recharge le service apache.

service apache2 reload

mod_evasive

Introduction

Apache est un serveur Web. Dans le cas de grosses entreprise il convient de définir une politique de répartition des charges (Load Balancing) afin de pouvoir supporter le nombre de clients et limiter les attaques de grande ampleur sur le service.

Nous allons étudier le paquet mod-evasive (anciennement appelé mod-dosevasive) qui permettra de limiter la charge de votre serveur et permettre ainsi de parer aux attaques de type Denial Of Service

Installation

Afin d'installer mod-evasive tapez la commande :

# Debian
apt-get install libapache-mod-evasive
# Redhat
yum install mod-evasive

Pour pouvoir configurer le module il est nécessaire d'ajouter le fichier de configuration /etc/apache2/conf.d/evasive.

touch /etc/apache2/conf.d/evasive
# ou
echo "" > /etc/apache2/conf.d/evasive

et ensuite éditez le fichier afin d'ajouter le contenu suivant permettant d'utiliser le module :

<ifmodule mod_evasive20.c>
</ifmodule>

Configuration

Pour configurer mod-evasive, il suffit d'ajouter les directives entre les balises ifmodule du fichier /etc/apache2/conf.d/evasive.

Voyons maintenant les diverses options du module.

  • DOSSiteCount: définit le nombre de requêtes autorisées dans un intervalle donné. (Attention n'oubliez pas que si vous utilisez une technologie AJAX il faudra augmenter en conséquence du nombre d'appels)
  • DOSSiteInterval: définit l'intervalle de temps pour DOSSiteCount, en secondes
  • DOSPageCount: définit le nombre de requêtes autorisées sur une même page dans un intervalle donné
  • DOSPageInterval: définit l'intervalle de temps pour DOSPageCount
  • DOSBlockingPeriod: définit l'intervalle de temps pendant lesquelles les IP blacklistées ne pourrons plus ce connecter au site et recevront une erreur 403
  • DOSWhiteList: définit une IP ou plage autorisée, il est judicieux d'autoriser 127.0.0.1.
  • DOSSystemCommand: lance la commande spécifiée lorsque l'IP est ajoutée en Blacklist de mod-evasive
  • DOSEmailNotify: spécifie l'adresse mail à qui envoyer l'alerte de mod-evasive lorsque quelqu'un est bloqué

Exemple de configuration

Voici maintenant quelques exemples de configuration suivant le trafic que vous devrez emmagasiner.

Pour moins de 100 connexions simultanées :

DOSPageCount 100
DOSPageInterval 1
DOSSiteInterval 1
DOSSiteCount 120
DOSBlockingPeriod 30

Pour 100 à 500 connexions simultanées ou si le moyen principal est via une passerelle natée (donc une seule IP) :

DOSPageCount 500
DOSPageInterval 1
DOSSiteCount 1000
DOSBlockingPeriod 20

Pour de plus de 1000 connexions simultanées :

DOSPageCount 2000
DOSPageInterval 1
DOSSiteCount 5000
DOSBlockingPeriod 20

Vous savez désormais gérer le trafic efficacement sur votre Apache. N'oubliez pas d'augmenter la valeur de la directive MaxKeepAliveRequests dans le fichier /etc/apache2/apache2.conf afin de pouvoir supporter le trafic.

Introduction à Apache2

Introduction

Apache est libre et gratuit. Néanmoins la liberté n'accorde pas le privilège de sécurité.

Apache souffre de lacunes au niveau sécurités élémentaires, et la variété des modules que l'on peut installer dessus ne permet pas d'obtenir la parfaite garantie de la fiabilité du système. Je vais vous exposer diverses techniques de sécurité permettant à votre Apache de devenir moins sensibles aux attaques Web.

VirtualHosts et séparation des sites

Apache étant une source très courante d'attaques, nous allons tout d'abord utiliser une méthode très simple mais néanmoins permettant de complexifier votre installation dans le cas ou un hacker aurait potentiellement compris l'architecture de votre machine.

Si vous hébergez plusieurs sites avec des domaines différents, vous connaissez sûrement la notion de VirtualHost.

Cela consiste à créer plusieurs fichiers de configuration afin de séparer la configuration de chacun de vos sites.

Afin que vos sites soient réellement séparés, je vous suggère de mettre leur racine dans des rérpetoires différents et de ne mettre aucune racine commune à plusieurs sites.

Admettons que vous ayez 5 sites (A,B,C,D,E) à héberger, la fonction la plus simple serait de répartir de cette façon :

/var/www/
- ./A
- ./B
- ./C
- ./D
- ./E

Il est déjà bien plus propre de se dire que /var/www correspond au site mère de la machine (ici A).

Séparez les virtualhosts et placez les dans le dossier /var/vhosts que vous aurez préalablement créé. Cette configuration étant moins utilisée elle permettra de gagner en sécurité.

Vous voilà déjà avec un rempart supplémentaire.

Vous pouvez gagner en sécurité en changeant le chemin /var/vhosts et en répartissant dans plusieurs dossiers de /var.

Confidentialité du serveur

Apache est très bavard, surtout lors d'erreurs 404, 403 et autres. Pour le faire taire, le fichier /etc/apache2/conf.d/security sera d'une grande aide.

Première modification, le ServerTokens. Celui-ci permettra de cacher lors des requêtes HTTP le gentil message d'accueil : Debian Jessie (Apache v 2.2.24). Configuration recommandée :

ServerTokens Prod

Seconde modification, ServerSignature. Placer l'option à Off permettra de cacher lors d'erreurs Apache (403,404, etc...) les données que j'ai citées ci-dessus.

ServerSignature Off