Passer son serveur en HTTPS

De plus en plus de navigateurs avertissent quand on utilise des sites sans protocole de sécurité, reconnaissable au https:// au début de l’adresse internet. Ici est décrit le passage en https pour un site sur un serveur Ubuntu/Apache avec accès root. On utilise un certificat libre de Let’s Encrypt avec le logiciel certbot qui gère l’obtention des certificats, de leurs mises à jour etc. Certbot s’occupe aussi de prendre le certificat, il n’y a donc pas besoin de s’occuper de Let’s Encrypt.

Installer certbot

Vu les modification à apporter sous /etc/, il est nécessaire d’exécuter toutes ces commandes sous root (sudo).

La méthode sûre est d’appeler toutes ces commandes à la suite, souvent elles ne sont pas toutes nécessaires quand on dispose d’un système déjà en fonction.

$> apt-get update
$> apt-get install software-properties-common
$> add-apt-repository universe
$> add-apt-repository ppa:certbot/certbot
$> apt-get update

Lancer certbot et les changements apportés

Avec cette commande, on obtient une version courte des paramètres pour certbot:

$> certbot --help

Avec la commande ci-bas, on passe un site, par exemple andre.carto.net, en mode https. On peut et il est utile d’ajouter tous les alias à la requête, car sinon il faudra plusieurs certificats. Il est donc judicieux de limiter les chaînes à un (sous-)domaine avec ou sans “www” devant par exemple.

$> certbot -d andre.carto.net -d www.andre.carto.net --apache

Attention avec plusieurs alias à certifier en chaîne: Si on efface plus tard un alias de cette chaîne au niveau DNS, le renouvellement du certificat ne peut plus se faire et tous les alias et/ou domaines de la chaîne seront en erreur. Concrètement, cela arrive lors de la fin de durée du certificat et au moment du renouvellement, donc pas au moment de l’effacement au niveau DNS ou sur le serveur. Les messages d’erreurs sont malicieux, cela commence par un email de Let’s Encrypt signifiant que le renouvellement a échoué et c’est le même message quand on fait $> certbot renew. Rien ne dit cependant quel alias de domaine est concerné par le problème. Quand on rétablit un alias au niveau DNS, il faut un certain temps que la réplication se face.

Concernant les noms de domaines internationalisés: dans données de configuration apache sous /etc/apache/sites-available/, il faut à rédiger les noms en code IDN (Internationalized Domain Names, RFC3492) et on doit les appeler tels quels sous certbot, donc par exemple xn--htel-vqa.com pour hôtel.com.

Le dialogue qui suit la commande demande plusieurs détails sans importance sauf le dernier, où il s’agit d’introduire une redirection de http vers https. Vu que l’on veut que les vieux liens soit tous automatiquement traduits par les nouveaux, cela s’impose.

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2

Les changements les plus importants pour le site se trouvent dans la définition des vhosts sous /etc/apache/sites-available/. À la définition andre.carto.net.conf est automatiquement rajouté la redirection suivante. Le code permanent correspond à 301, que l’on trouve dans les anciennes documentations. S’il y a plusieurs alias (sous-domaine), il y aura une ligne additionelle pour chacun.

RewriteCond %{SERVER_NAME} =www.andre.carto.net [OR]
RewriteCond %{SERVER_NAME} =andre.carto.net
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

Cependant ce code n’effectue chez moi pas de redirection quand on appelle la page sous http. Je l’ai donc changé contre celui ci-bas, ainsi une page quelconque appelée en http est immédiatement chargé en https.

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [NE,R=301,L]

Il y a aussi une nouvelle entrée sous andre.carto.net-le-ssl.conf. Il s’agit pour le début de la copie de andre.carto.net.conf. À la place des redirections se trouvent les lignes relatives aux certificats:

Include [LOCAL PATH]/options-ssl-apache.conf
SSLCertificateFile [LOCAL PATH]/fullchain.pem
SSLCertificateKeyFile [LOCAL PATH]/privkey.pem

Sous les références indiqués se trouvent effectivement les clés des certificats.

Certbot rajoute pour les deux sites aussi les liens sous sites-enabled/.

Par contre certbot ne fait pas le redémarrage d’Apache, il faut le faire manuellement à la fin des changements:

$> /etc/init.d/apache2 restart

Pour éviter le dédoublement des fichiers *.conf, il est possible de les garder en un seul comme décrit ici. Un fichier *.conf ressemble alors par exemple à ceci:

<VirtualHost *:80>
  # SHORT DEFINITION
  ServerName andre.carto.net
  ServerAlias  www.andre.carto.net
  ServerAdmin [XXXXXXX@XXX.XXX]
  # REDIRECT
  RewriteEngine On
  RewriteCond %{HTTPS} off
  RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [NE,R=301,L]
</VirtualHost>
<IfModule mod_ssl.c>
  <VirtualHost *:443>
    # FULL DEFINITION
    DocumentRoot [LOCAL PATH]
    ServerName andre.carto.net
    ServerAlias www.andre.carto.net
    ServerAdmin [XXXXXXX@XXX.XXX]
    AddDefaultCharset utf-8
    ErrorLog [LOCAL PATH]
    CustomLog [LOCAL PATH] combined
    # SSL
    Include [LOCAL PATH]/options-ssl-apache.conf
    SSLCertificateFile [LOCAL PATH]/fullchain.pem
    SSLCertificateKeyFile [LOCAL PATH]/privkey.pem
  </VirtualHost>
</IfModule>

Durée par défaut

Le certificat est valable durant 90 jours par défaut.

$> certbot certificates
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
  Certificate Name: andre.carto.net
    Domains: andre.carto.net www.andre.carto.net
    Expiry Date: 2020-01-02 09:36:12+00:00 (VALID: 89 days)
    Certificate Path: [LOCAL PATH]/fullchain.pem
    Private Key Path: [LOCAL PATH]/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

On peut vérifier l’état de la mise à jour ainsi, cette commande affiche divers services périodiques. Comme on vient d’activer le service à 2019-10-05 11:47:49, il n’y a pas encore d’autres occurrences.

$> systemctl list-timers
NEXT                          LEFT        LAST   PASSED   UNIT            ACTIVATES
Sat 2019-10-05 11:47:49 CEST  19h left    n/a    n/a      certbot.timer   certbot.service

Les détails s’obtiennent par la commande ci-bas. il ne faut cependant pas s’inquiéter de la ligne Active: inactive (dead).

$> systemctl status certbot.service
● certbot.service - Certbot
Loaded: loaded ([LOCAL PATH]/certbot.service; static; vendor preset: enabled)
Active: inactive (dead)
Docs: file:///[LOCAL PATH]/python-certbot-doc/html/index.html
https://letsencrypt.readthedocs.io/en/latest/

En effet, certbot ayant mis par défaut la durée à 90 jours,  la mise à jour ne se fera pas 30 jours avant l’échéance du certificat. Il n’est pas facile de trouver une confirmation de ce fait, surtout que sous /etc/letsencrypt/renewal/andre.carto.net.conf se trouve la ligne # renew_before_expiry = 30 days qui est mise sous commentaire. À priori ces 30 jours sont fixés dans le code de base certbot, comme supposé ici.

30 jours avant l’échéance du certificat est lancé le service de mise à jour. Ce sera à raison de deux fois par jour jusqu’à ce soit avec succès.

$> vim [LOCAL PATH]/certbot.timer
[Unit]
Description=Run certbot twice daily
[Timer]
OnCalendar=*-*-* 00,12:00:00
RandomizedDelaySec=43200
Persistent=true
[Install]
WantedBy=timers.target

Réponse défaut avec plusieurs VirtualHosts sous Apache et Ubuntu

Lorsque l’on configure des sous-domaines du type andre.carto.net ou pro.carto.net à côté du site principal, on définit en général ces adresses: deux pour le domaine principal (carto.net et www.carto.net) et deux par sous-domaine (andre.carto.net, www.andre.carto.net, pro.carto.net, www.pro.carto.net). Il s’agit donc de trois sites différents, avec “www” devant ou pas. Quand on appelle cependant un autre sous-domaine non défini (comme projects.carto.net), le DNS renverra généralement au serveur gérant le domaine principal (carto.net) et celui-ci devra produire une réponse

Dans la définition des VirtualHosts sous /etc/apache2/sites-available/ on aura ces trois fichiers:

  • a.carto.net
  • andre.carto.net.conf
  • carto.net.conf
  • pro.carto.net.conf

Dans la logique par défaut sous Apache et Ubuntu il existe lors de l’installation un domaine [LOCAL PATH]/sites-available/000-default.conf renvoyant à /var/www/html/index.html. Ce sera cette réponse qui sera donné à l’appel de projects.carto.net. Observons bien les trois zéros devant et partons du principe que nous ayons effacé ce fichier 000-default.conf. En appelant project.carto.net, ce sera a.carto.net qui sera servi. Tout simplement parce que c’est alphabétiquement le premier de la liste. Cela est indépendant des domaines principaux s’il y en a plusieurs!

La chose se complique quand on passe certains sites en https et d’autres non. Un exemple de VirtualHosts à la base:

  • a.carto.net
  • andre.carto.net.conf *
  • carto.net.conf
  • geoidee.ch.conf
  • pro.carto.net.conf
  • provence-guide.net.conf *

En passant uniquement ceux avec astérisque en https, on aura des fichiers additionnels sous /etc/apache2/sites-available/:

  • a.carto.net
  • andre.carto.net.conf *
  • andre.carto.net-le-ssl.conf
  • carto.net.conf
  • geoidee.ch.conf
  • pro.carto.net.conf
  • provence-guide.net.conf *
  • provence-guide.net-le-ssl.conf

Rappelons-nous que geoidee.ch n’est pas sous https, mais que cette adresse réponde proprement sous http. Que se passe-t-il si on appelle l’adresse https://www.geoidee.ch/? Le navigateur reconnaîtra le domaine geoidee.ch, émettra un avertissement que l’appel sécurisé donne une réponse non-sécurisé. Si on confirme que l’on veut continuer, le serveur devrait répondre avec le domaine alphabétiquement par défaut, car https://www.geoidee.ch/ n’est pas défini. Or ce n’est pas a.carto.net, c’est andre.carto.net-le-ssl.conf. C’est donc toujours alphabétiquement le premier, mais c’est le premier défini en https!

Passer un site WordPress en https

Le principe pour le nom du domaine sur le serveur est le même que pour un site statique normal. Le problème est que WordPress stocke le nom du domaine avec le protocole dans la configuartion principale. Ce qui est plus grave par contre, c’est que tous les liens internes sont aussi stockés dans le texte avec le protocole http. Le problème est identique au changement complet de l’URL.

Après le changement sur le serveur, on s’enregistres sur son site et backend apparaît normalement sous https. On peut aussi éditer, mais on remarquera que dès que l’on appelle une page du frontend, celle-ci repasse en http. Les deux choses à faire donc:

Changer l’adresse du site WordPress

Sous Backend > Settings > General il faut remplacer:

WordPress Address (URL) :  https://andre.carto.net
Site Address (URL):        https://andre.carto.net

Après avoir confirmé ces changements (en bas), les changements entre backend et frontend restent tous en https.

Modifier tous les liens internes sous WordPress

Tous les liens sont enregistrés dans la base de données avec le texte en code HTML, il n’y a pas de table des liens. Les liens internes sont vraiment mis de la forme <a href="https://andre.carto.net/2019/passer-son-serveur-en-https/> alors que sous la forme <a href="/2019/passer-son-serveur-en-https/> cela aurait évité tous les ennuis. Il faut donc recherche et remplacer ces liens dans  les tables de la base de données sur laquelle est basé l’instance WordPress. Cela marche bien avec le plug-in Search & Replace par Inpsyde GmbH, mais il y en a d’autres. Avantage de celui-ci: on peut agir sur toutes les tables et on peut faire un test pour trouver toutes les occurrences.

Une fois installé, on démarre le plugin sous Tools Search & Replace > Search & Replace. L’interface est simple:

Search for:    https://andre.carto.net
Replace with:  https://andre.carto.net

Au-dessous on sélectionne toutes les tables et on peut lancer la recherche test. Cela dure quelques minutes. Il ne faut pas s’étonner du nombre d’occurrences trouvés, pour ce blog cela dépassait 300.000 cas! Le replacement est assez évident et il y a peu de chance d’occasionner un remplacement non réversible. On peu donc désactiver la case Dry Run et lancer le remplacement effectif.

Erreurs avec contenu externe

Pour que les navigateurs acceptent pleinement la sécurité activée, il faut que tous les éléments inclus soient servis sous https. Cela arrive avec des inclusion comme youtube, des cartes Google Maps API, des cartes OSM ou simplement des photos incluses. Cela vaut aussi pour des éléments sur son propre site. Dans ces cas, dans la barre adresse du navigateur n’est pas affiché le cadenas fermé, mais une information du type: “Votre connexion à ce site n’est pas totalement sécurisé”. Les inclusions non-sécurisées peuvent être compliqués et récurrents. Il faut les exclure une après une. La console d’erreur des navigateurs aide un peu.

J’ai eu un cas compliqué avec des cartes Open Street Map (OSM) sur lesquelles je charge mes propres fichiers KLM qui contiennent des icônes graphiques que je sers de mon propre serveur. Ces fichiers KML sont édités dans Google Earth et pour que cela marche, il faut une adresse complète et non relative. J’avais longtemps une erreur, parce que dans mes fichiers KML, générés il y a plusieurs années, se trouvaient ce type de référence initialement sans le “s”. Cependant Google Earth rajoute souvent une longue liste de styles qui contient aussi des icônes non utilisés. Malheureusement, un fichier KML exporté de Google Earth en 2019 contient toujours des liens en http seulement vers ses propres icônes.

<href>https://provence-guide.net/pix/icon/i-ycro.png</href>

Bien sûr, il faut aussi s’occuper d’appeler les tuiles OSM correctement:

https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'

No Comments

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.