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. 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 :
- VPS: OVH VPS
- OS: Debian Stable
- Droits requis:
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.
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
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.
- 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
source /etc/apache2/envvars
sed -i 's;MaxKeepAliveRequests 100;MaxKeepAliveRequests 500;g' /etc/apache2/apache2.conf
sed -i 's;KeepAliveTimeout 5;KeepAliveTimeout 3;g' /etc/apache2/apache2.conf
sed -i 's;ServerSignature On;ServerSignature Off;g' /etc/apache2/conf-available/security.conf
sed -i 's;ServerTokens OS;ServerTokens Prod;g' /etc/apache2/conf-available/security.conf
Confs
a2dismod php8.2 mpm_prefork
cd /etc/apache2/conf-available
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>
mv /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
nano http2-custom.conf
:
<IfModule http2_module>
Protocols h2 h2c http/1.1
H2Direct on
</IfModule>
nano mpm-event-custom.conf
:
<IfModule mpm_event_module>
StartServers 3
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
MaxRequestWorkers 30
MaxConnectionsPerChild 1000
</IfModule>
a2enconf php8.2-fpm http2-custom mod-evasive-custom mpm-event-custom
systemctl enable php8.2-fpm
Mods
a2enmod proxy_fcgi setenvif rewrite ssl mpm_event headers deflate security2 http2
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 :
-
echo '' > /etc/letsencrypt/options-ssl-apache.conf
-
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.
-
cd /etc/apache2/sites-available/
-
a2dissite *
-
service apache2 reload
-
rm *
-
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.
-
a2ensite risible.fr.conf
-
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. -
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.
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
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 :
https://www.ssllabs.com/ssltest/analyze.html?d=risible.fr&latest
https://http2.pro/check?url=https%3A//risible.fr/