Désormais, le certificat SSL pour passer en HTTP est un pré-requis pour pouvoir être indexé par Google. La configuration d’Apache ( et de Nginx aussi d’ailleurs ) est par défaut trop minimale pour avoir de bons résultats en matière de sécurité. Bien que certbot soit désormais simple et accessible, le certificat obtenu est faible. L’ensemble des 2 provoque l’obtention d’un certificat de grade B d’où l’intérêt de ce tutoriel. J’ai aussi ajouté la configuration simple de mods pour monitorer les tentatives d’exploitation contre votre site.

Environnement

Voici les détails de la machine utilisée :

J’ai un ancien VPS donc j’ai le compte root directement donné. Si vous prenez un VPS maintenant, vous aurez le compte debian par défaut, et dans ce cas, sudo su est votre ami. En tous les cas, pensez à changer le mot de passe par défaut, qui est faible.

Pré-requis

On va modifier / s’assurer de 2,3 trucs sur le VPS.

Sources list

Dans les anciennes versions de VPS, vous devez éditer le fichier: /etc/apt/sources.list

Mais pour les récentes (>2023), c’est ce fichier ci: /etc/apt/sources.list.d/debian.sources

Contenu à mettre:

deb https://deb.debian.org/debian/ stable main
deb https://deb.debian.org/debian/ stable-updates main
deb https://security.debian.org/debian-security stable-security main

Pour la suite, faites apt update puis apt upgrade.

Hostnames

  1. nano /etc/hosts :
127.0.0.1       localhost
127.0.1.1       vps123456.ovh.net       vps123456

Note 1: vps123456 est à remplacer par le votre.

Note 2: Comme vous le voyez, je ne référence pas les valeurs pour l’IPv6 ici.

  1. Faire pointer votre nom de domaine vers le serveur. Pour la suite de ce tutoriel, j’utiliserai le nom de domaine ( = ndd ) : risible.fr

Apache & PHP

On va d’abord installer Apache2 et PHP. Pour le moment, nous sommes en stable sur PHP 8.2 ( pensez à modifier, si besoin, dans la suite du tutoriel la version à chaque fois qu’elle est présente ). Les packages proposés ne sont pas le minimum strict mais le minimum optimal, ce que je vous recommende :

apt install apache2 php-fpm libapache2-mod-php php-curl php-memcache php-mbstring php-zip certbot python3-certbot-apache libapache2-mod-evasive libapache2-mod-security2 libmodsecurity3 modsecurity-crs

C’est parti pour les modifications à apporter sur les composantes Apache et PHP.

Initialisation

  1. source /etc/apache2/envvars
  2. sed -i 's;MaxKeepAliveRequests 100;MaxKeepAliveRequests 500;g' /etc/apache2/apache2.conf
  3. sed -i 's;KeepAliveTimeout 5;KeepAliveTimeout 3;g' /etc/apache2/apache2.conf
  4. sed -i 's;ServerSignature On;ServerSignature Off;g' /etc/apache2/conf-available/security.conf
  5. sed -i 's;ServerTokens OS;ServerTokens Prod;g' /etc/apache2/conf-available/security.conf

Confs

  1. a2dismod php8.2 mpm_prefork
  2. cd /etc/apache2/conf-available
  3. nano mod-evasive-custom.conf:
<IfModule mod_evasive20.c>
        DOSHashTableSize 3097
        DOSPageCount 2
        DOSSiteCount 50
        DOSPageInterval 1
        DOSSiteInterval 1
        DOSBlockingPeriod 60
        DOSEmailNotify <admin@risible.fr>
</IfModule>
  1. mv /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
  2. nano http2-custom.conf:
<IfModule http2_module>
        Protocols h2 h2c http/1.1
        H2Direct on
</IfModule>
  1. nano mpm-event-custom.conf:
<IfModule mpm_event_module>
        StartServers 3
        MinSpareThreads          25
        MaxSpareThreads          75
        ThreadLimit                      64
        ThreadsPerChild          25
        MaxRequestWorkers    30
        MaxConnectionsPerChild    1000
</IfModule>
  1. a2enconf php8.2-fpm http2-custom mod-evasive-custom mpm-event-custom
  2. systemctl enable php8.2-fpm

Mods

  1. a2enmod proxy_fcgi setenvif rewrite ssl mpm_event headers deflate security2 http2
  2. a2dismod evasive

Enable

service apache2 restart && service php8.2-fpm restart

SSL

On va passer à la partie pure SSL.

On va commencer par l’étape la plus longue du tutoriel, la génération de la clé pour le DHE. Ce n’est pas obligatoire mais je vous conseille vivement de faire ainsi car la clé ainsi générée aura une bien meilleure solidité ( 4096 ). Je vous recommende cet article pour le pourquoi du comment. Et donc : openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096

Une fois générée, nous pouvons passer à la suite. Nous allons modifier le fichier de configuration par défaut qui gère tous les paramètres SSL sous Apache :

  1. echo '' > /etc/letsencrypt/options-ssl-apache.conf

  2. On va maintenant modifier le fichier de configuration SSL via la commande nano /etc/letsencrypt/options-ssl-apache.conf.

Toutefois 2 cas se posent:

Soit vous voulez garder la compatibilié, en conservant un ancien algorithme faible, des appareils entre Safari 6 et Safari 8 inclus (iOS 6.0.1, iOS 7.1, iOS 8.4, OS X 10.9 et OS X 10.10) et dans ce cas la configuration est:

# This file contains important security parameters. If you modify this file
# manually, Certbot will be unable to automatically provide future security
# updates. Instead, Certbot will print and log an error message with a path to
# the up-to-date file that you will need to refer to when manually updating
# this file.

SSLEngine on

# Intermediate configuration, tweak to your needs
SSLProtocol             -all +TLSv1.2 +TLSv1.3
SSLCipherSuite		ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:!DSS

SSLOpenSSLConfCmd Curves X25519:secp521r1:secp384r1:prime256v1
SSLOpenSSLConfCmd DHParameters "/etc/ssl/certs/dhparam.pem"

SSLHonorCipherOrder     on
SSLCompression          off

SSLOptions +StrictRequire

# Add vhost name to log entries:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" vhost_combined
LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common

#CustomLog /var/log/apache2/access.log vhost_combined
#LogLevel warn
#ErrorLog /var/log/apache2/error.log

# Always ensure Cookies have "Secure" set (JAH 2012/1)
#Header edit Set-Cookie (?i)^(.*)(;\s*secure)??((\s*;)?(.*)) "$1; Secure$3$4"

ou alors, vous voulez la sécurité maximale et ne pas tenir compte d’anciens systèmes, et dans ce cas, la configuration est:

# This file contains important security parameters. If you modify this file
# manually, Certbot will be unable to automatically provide future security
# updates. Instead, Certbot will print and log an error message with a path to
# the up-to-date file that you will need to refer to when manually updating
# this file.

SSLEngine on

# Intermediate configuration, tweak to your needs
SSLProtocol             -all +TLSv1.2 +TLSv1.3
SSLCipherSuite      ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:!DSS

SSLOpenSSLConfCmd Curves X25519:secp521r1:secp384r1:prime256v1
SSLOpenSSLConfCmd DHParameters "/etc/ssl/certs/dhparam.pem"

SSLHonorCipherOrder     on
SSLCompression          off

SSLOptions +StrictRequire

# Add vhost name to log entries:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" vhost_combined
LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common

#CustomLog /var/log/apache2/access.log vhost_combined
#LogLevel warn
#ErrorLog /var/log/apache2/error.log

# Always ensure Cookies have "Secure" set (JAH 2012/1)
#Header edit Set-Cookie (?i)^(.*)(;\s*secure)??((\s*;)?(.*)) "$1; Secure$3$4"

La configuration ci-dessus est la mienne. J’ai pris la configuration par défaut, enlevé les chiffrements faibles, forcer l’utilisation uniquement de TLS 1.2 et TLS 1.3, ajouter notre clé DHE et ajouter les meilleurs algos de “elliptic curves”.

Configuration du nom de domaine

Pour cette partie là, on va prendre 2 postulats :

  • domaine = risible.fr
  • répertoire des fichiers du site = /home/risible.fr

Note: N’oubliez pas de remplacer le domaine et le répertoire par les vôtres.

  1. cd /etc/apache2/sites-available/

  2. a2dissite *

  3. service apache2 reload

  4. rm *

  5. nano risible.fr.conf :

<VirtualHost risible.fr:80>
        ServerAdmin admin@risible.fr
        
        ServerName risible.fr
        ServerAlias www.risible.fr
        
        DocumentRoot /home/risible.fr
        <Directory /home/risible.fr>
                Options -Indexes +FollowSymLinks +MultiViews
                AllowOverride all
                <IfVersion < 2.3>
                        Order allow,deny
                        allow from all
                </IfVersion>
                <IfVersion >= 2.4>
                        Require all granted
                </IfVersion>
        </Directory>
        
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
        
        RewriteEngine on
        RewriteCond %{SERVER_NAME} =www.risible.fr [OR]
        RewriteCond %{SERVER_NAME} =risible.fr
        RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

SSLUseStapling on
SSLStaplingCache "shmcb:logs/stapling-cache(150000)"
SSLStaplingResponseMaxAge 900

<VirtualHost risible.fr:443>
        Protocols h2 h2c http/1.1
        
        H2Push on
        H2PushPriority * after
        H2PushPriority text/css before
        H2PushPriority image/jpg after 32
        H2PushPriority image/jpeg after 32
        H2PushPriority image/png after 32
        H2PushPriority application/javascript interleaved

        Header always set Strict-Transport-Security: "max-age=63072000; includeSubDomains; preload"
        Header always set Referrer-Policy "no-referrer, strict-origin-when-cross-origin"
        Header always set X-Frame-Options SAMEORIGIN
        Header always set X-Content-Type-Options nosniff
        Header always set X-XSS-Protection "1; mode=block"

        ServerAdmin admin@risible.fr
        
        ServerName risible.fr
        ServerAlias www.risible.fr

        DocumentRoot /home/risible.fr
        <Directory /home/risible.fr>
                Options -Indexes +FollowSymLinks +MultiViews
                AllowOverride all
                <IfVersion < 2.3>
                        Order allow,deny
                        allow from all
                </IfVersion>
                <IfVersion >= 2.4>
                        Require all granted
                </IfVersion>
        </Directory>
        
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
        
        #SSLEngine on
        #SSLCertificateFile /etc/letsencrypt/live/risible.fr/fullchain.pem
        #SSLCertificateKeyFile /etc/letsencrypt/live/risible.fr/privkey.pem
        #Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>

Vous noterez que les lignes 60 à 63 sont commentées.

  1. a2ensite risible.fr.conf

  2. service apache2 reload. A partir de cette étape, votre site devrait être accessible en HTTP. Si ce n’est pas le cas, inutile de passer à la suite c’est que vous avez fait une erreur / un oubli avant et il est impératif de corriger le problème.

  3. certbot --apache --rsa-key-size 4096 :

Note : Vous devriez avoir un message en rouge. Il est normal puisqu’on a modifié le fichier pour augmenter la sécurité justement.

  1. nano risible.fr.conf

Vous devez aller aux lignes commentées de tout à l’heure, vous devriez voir que certbot a ajouté des lignes. Celles-ci sont à supprimer et ensuite il faut décommenter les lignes. Ce qui en images donne :

devient

  1. service apache2 reload

Activer le DNS CAA

Le but étant de créer une ligne CAA dans la zone DNS: risible.fr CAA 128 "letsencrypt.org". Voilà ce que cela donne en ajout quand vous êtes chez OVH:

Voilà

Pour vérifier la solidité de notre travail :

  1. https://www.ssllabs.com/ssltest/analyze.html?d=risible.fr&latest

  1. https://http2.pro/check?url=https%3A//risible.fr/