Avoir un certificat SSL A+ en HTTP/2 avec support du HSTS et TLS 1.3 sous Apache

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.

Environnement

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

  • VPS: OVH Starter
  • OS: Debian 10 kernel Linux
  • Utilisateur: root

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. Débutons :

1) nano /etc/apt/sources.list :

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

Pour la suite, faites apt update puis apt upgrade.

2) nano /etc/hosts :

127.0.0.1       localhost

127.0.1.1       vps123456       vps123456
127.0.1.1       vps123456.ovh.net       vps123456

Note: vps123456 est à remplacer par le votre.

3) 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 7.3 ( 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 python-certbot-apache

C'est parti pour les modifications à apporter sur les composantes Apache et PHP :

1) nano /etc/apache2/conf-available/http2.conf :

<IfModule http2_module>
    Protocols h2 h2c http/1.1
    H2Direct on
</IfModule>

2) sed -i 's;ServerSignature On;ServerSignature Off;g' /etc/apache2/conf-available/security.conf

3) a2dismod php7.3 mpm_prefork

4) a2enmod proxy_fcgi setenvif rewrite ssl mpm_event http2 headers

5) a2enconf php7.3-fpm

6) service apache2 restart && service php7.3-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 solidité énorme ( 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) nano /etc/letsencrypt/options-ssl-apache.conf :

# 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"

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>
</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=15768000; 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>

    #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.

6) a2ensite risible.fr.conf

7) 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.

8) certbot --apache :

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

9) 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

10) service apache2 reload

Voilà

Pour vérifier la solidité de notre travail :

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

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

Oletros