Obtenir un certificat SSL

Prévoir un accès avec chiffrement pour votre site n'est pas obligatoire. C'est malgré tout intéressant si :

Un certificat sera de toute façon nécessaire dès que vous voudrez chiffrer les échanges, pas seulement pour un site web mais aussi pour un serveur mail entre autres.

Letsencrypt

Nous allons proposer en exemple d'obtenir un certificat via letsencrypt (https://letsencrypt.org), une autorité de certification gratuite dont un client est disponible sous OpenBSD nativement : acme-client. Cette démarche est décrite dans la partie concernant httpd car nous en auront besoin pour "communiquer" avec letsencrypt. C'est un service absolument génial tout à fait adapté à l'auto-hébergement. Ces certificats pourront tout aussi bien être utilisés pour un site web qu'un serveur mail ou autre service en ayant besoin.

⚠ Attention : vérifiez que le port 80 est bien ouvert sur votre parefeu (et si vous utilisez un adressage privé, vérifiez vos renvois de ports, beaucoup d'erreurs viennent de là) ! En effet, acme-client doit rendre disponible sur votre serveur des "fichiers secrets" pour obtenir le certificat.

Cet outil va vérifier que vous avez bien accès au domaine pour lequel vous souhaitez un certificat. Il procède ainsi :

Il demande tout d'abord à letsencrypt un fichier unique, une sorte d'empreinte, qui est enregistrée dans "/var/www/acme". Ensuite, letsencrypt tente de récupérer ce fichier en allant sur votre site dans le dossier ".well-known/acme-challenge" pour certifier que c'est bien votre serveur qui a fait la demande. Autrement dit, il demande "http://chezmoi.tld/.well-known/acme-challenge/unfichiersecret". S'il y accède, la demande de certificat est acceptée. Enfin, le fichier est supprimé.

Cependant, votre site web est sans doute enregistré dans "/var/www/htdocs/votresite". Il faut donc rendre disponible le dossier "/var/www/acme" lorsque letsencrypt cherche à récupérer le fichier en question.

Ajoutez une nouvelle instruction "location" dans votre fichier /etc/httpd.conf.

server "chezmoi.tld" {
    listen on * port 80
    location "/.well-known/acme-challenge/*" {
        root "/acme"
        request strip 2
    }
    root "/htdocs/super-site"
}

Quelques explications :

⚠ Attention, il faut mettre cette portion pour chaque sous-domaine indiqué dans la partie alternative names du fichier de configuration d'acme-client détaillé ci-dessous. Il sera donc plus pratique d'utiliser des instructions "include" dans la configuration d'httpd comme indiqué dans la partie des astuces pour httpd ou dans le paragraphe suivant 😉.

Avant d'utiliser acme-client, nous allons le configurer dans le fichier "/etc/acme-client.conf" qu'il faudra créer si besoin. Vous pouvez copier l'exemple situé dans "/etc/examples/acme-client.conf".

Dans ce dernier fichier, nous allons donc mettre ces lignes :

authority letsencrypt {
  api url "https://acme-v02.api.letsencrypt.org/directory"
  account key "/etc/acme/letsencrypt-privkey.pem"
}
authority letsencrypt-staging {
  api url "https://acme-staging-v02.api.letsencrypt.org/directory"
  account key "/etc/acme/letsencrypt-staging-privkey.pem"
}
domain chezmoi.tld {
    alternative names { webmail.chezmoi.tld www.chezmoi.tld }
    domain key "/etc/ssl/private/chezmoi.tld.key"
    domain full chain certificate "/etc/ssl/chezmoi.tld.crt"
    sign with letsencrypt
}

Remplacez les éléments suivants :

Assurez-vous que les dossiers nécessaires sont bien créés (normalement ils le sont déjà):

# mkdir -p -m 700 /etc/ssl/private
# mkdir -p -m 755 /var/www/acme

Vérifiez que votre configuration est correcte, une faute de frappe est vite arrivée :

# acme-client -n

Si tout est bon, alors la commande précédente ne renvoie aucun message 😉.

Vous pourrez ensuite générer vos certificats avec cette commande :

# acme-client -v chezmoi.tld

Conseil : La première fois, il vaut mieux tester qu'il n'y a pas d'erreurs dans votre configuration en utilisant "sign with letsencrypt-staging" dans le fichier "/etc/acme-client.conf". Lorsque tout fonctionne comme prévu, vous forcerez l'obtention d'un certificat avec l'option -F après avoir modifié la configuration d'acme-client.

Pour renouveler les certificats, il suffira d'entrer à nouveau la commande précédente.

Je vous invite à ajouter cette ligne dans le fichier "/etc/weekly.local" pour un renouvellement chaque semaine si nécessaire :

/usr/sbin/acme-client -v chezmoi.tld && /usr/sbin/rcctl reload httpd

L'utilisation de "&&" permet de recharger httpd seulement si les certificats ont été renouvelés. Vous devriez recharger les autres services utilisant ce certificat (relayd et dovecot par exemple).

Maintenant, nous allons utiliser notre certificat en activant l'accès https dans la configuration de httpd :

# extrait de /etc/httpd.conf
server "chezmoi.tld" {
    listen on * port 80
	# partie http
	# [...]
}
server "chezmoi.tld" {
    listen on * tls port 443
    root "/htdocs/monsupersite"
    tls {
        certificate "/etc/ssl/chezmoi.tld.crt"
        key "/etc/ssl/private/chezmoi.tld.key"
    }
    hsts
    # n'oubliez pas d'ajouter la configuration
    # specifique liee à votre site
}

Vous remarquerez que la connexion se fait désormais sur le port 443 (https), qu'il faut ouvrir dans le parefeu et rediriger dans le routeur.

Vous voudrez sans doute rediriger les visiteurs de la version http vers la version https de votre site tout en gardant la possibilité d'utiliser acme-client, on ajoute le bloc suivant :

# extrait de /etc/httpd.conf
server "chezmoi.tld" {
    listen on * port 80
    location "/.well-known/acme-challenge/*" {
        root "/acme"
        request strip 2
    }
    # on redirige vers la version https
    location * { block return 301 "https://$SERVER_NAME$REQUEST_URI" }
}
server "chezmoi.tld" {
    listen on * tls port 443
	#[...]
}

Ce dernier morceau est important 😉

Il permet de rediriger toutes les requêtes ("location *") vers la version https. Si httpd en est arrivé là, c'est que la requête ne correspondait pasaux précédentes, c'est à dire celle pour acme-client.

Remarquez l'utilisation de "location *" qui correspond à toutes les requêtes APRÈS celle concernant acme. En effet, httpd lit chaque cas de figure dans l'ordre et traite le premier venu.

Cette configuration sera à mettre en place pour tous les sites servis. Dans l'exemple, nous avons aussi "www.chezmoi.tld" et "webmail.chezmoi.tld". Puisque cela risque de vite devenir long, on va utiliser une petite astuce (voir paragraphe suivant).

Utilisons "include"

Puisqu'on doit permettre l'obtention des certificats pour chaque site servi, autrement dit ceux définis dans la ligne "alternative names" du fichier "/etc/acme-client.conf", je vous propose de profiter de la capacité d'httpd à inclure des fichiers.

Commençons par créer un dossier nommé "httpd.d" :

# mkdir /etc/httpd.d

Ensuite, on crée le fichier "/etc/httpd.d/acme.conf" qui contient les lignes relatives à acme vues plus haut.

location "/.well-known/acme-challenge/*" {
    root "/acme"
    request strip 2
}

On peut pouser le bouchon un peu plus loin en créant "/etc/httpd.d/tls.conf" pour les lignes appelant le certificat :

tls {
	certificate "/etc/ssl/chezmoi.tld.crt"
	key "/etc/ssl/private/chezmoi.tld.key"
}
hsts

Désormais, le fichier "/etc/httpd.conf" pourra être réduit à ces quelques lignes, le tout pour servir 3 sites : www.chezmoi.tld, chezmoi.tld et webmail.chezmoi.tld (le "www" étant le principal) :

server "www.chezmoi.tld" {
	listen on * tls port 443
	include "/etc/httpd.d/tls.conf"
	root "/htdocs/www.chezmoi.tld"
}
server "www.chezmoi.tld" {
	listen on * port 80
	include "/etc/httpd.d/acme.conf"
	location * { block return 301 "https://$SERVER_NAME$REQUEST_URI" }
}
server "chezmoi.tld" {
	listen on * tls port 443
	include "/etc/httpd.d/tls.conf"
	block return 301 "https://www.$SERVER_NAME$REQUEST_URI"
}
server "chezmoi.tld" {
	listen on * port 80
	include "/etc/httpd.d/acme.conf"
	location * { block return 301 "https://$SERVER_NAME$REQUEST_URI" }
}
server "webmail.chezmoi.tld" {
	listen on * tls port 443
	include "/etc/httpd.d/tls.conf"
	root "/htdocs/webmail.chezmoi.tld"
}
server "webmail.chezmoi.tld" {
	listen on * port 80
	include "/etc/httpd.d/acme.conf"
	location * { block return 301 "https://$SERVER_NAME$REQUEST_URI" }
}

La configuration ci-dessus redirige les visiteurs de chezmoi.tld vers www.chezmoi.tld. Elle ajoute un site webmail.chezmoi.tld. À chaque fois, l'utilisation d'acme est possible.

Vous aurez remarqué que chaque section est répétitive. Je vous laisse imaginer une façon encore plus réduite d'écrire ce fichier en utilisant encore plus d'instructions "include" si cela vous chante. Notez que cela n'a d'intérêt que si vous servez un grand nombre de sites.

Merci à Grégory Marchal pour les suggestions sur cette partie 😄

Facultatif : enregistrements CAA

Vous pouvez ajouter à votre zone DNS des enregistrements de type CAA. Ce n'est pas obligatoire, mais ça permet de démontrer que vous, le propriétaire de ce domaine, avez autorisé letsencrypt à vous donner un certificat. Ça démontre que le certificat n'est pas là de façon fortuite. Cette étape est une preuve de bonne foi supplémentaire. Dans votre zone, il y aura donc :

@ 300 IN   CAA   0 issue "letsencrypt.org"

Générer un certificat SSL auto-signé

Dans cette partie, nul besoin d'httpd. si vous avez besoin d'un certificat sans vouloir configurer httpd, vous êtes au bon endroit 😉.

Nous allons ici auto-signer le certificat comme indiqué dans "man 8 ssl"

Les visiteurs de votre site risquent juste d'avoir un avertissement disant :

Cette connexion n'est pas certifiés, Que faire ?

Ils peuvent alors choisir d'accepter le certificat et la suite se déroule sans problème 😇.

Pour créer un certificat et le signer, il faut lancer la commande suivante. Bien sûr, remplacez le nom du fichier serveur à votre convenance :

# openssl req -x509 -sha512 -nodes -days 365 -newkey rsa:4096 \
  -keyout /etc/ssl/private/serveur.key \
  -out /etc/ssl/serveur.crt

Quelques questions vous seront posées. Vous n'êtes pas obligé de remplir tous les champs, mais essayez d'être le plus précis possible.

Deux fichiers sont créés :

Retenez bien le chemin vers ces fichiers. Il faudra le préciser dans la configuration de votre serveur web (http).

Finalement, il faut protéger la clé associée au certificat. Lancez ces deux dernières commandes afin d'en restreindre les permissions :

# chown root:wheel /etc/ssl/private/serveur.key
# chmod 600 /etc/ssl/private/serveur.key
# chmod -R go-rwx /etc/ssl/private

Tester la sécurité apportée par le chiffrement

Voici quelques services permettant de tester la qualité du chiffrement proposé par votre serveur :

https://www.ssllabs.com/

https://tls.imirhil.fr/

https://observatory.mozilla.org/