Module 7 · 7.4
Français
Caddy, HSTS et security.txt
Module 7: Domaine, serveur web et https · Temps de lecture : 12 minutes
Objectif pédagogique : À l'issue de cette leçon, vous saurez utiliser Caddy comme serveur web simple avec https automatique, activer HSTS et les principaux en-têtes de sécurité (dans Caddy et nginx) sans rendre votre site inaccessible, et publier un fichier security.txt valide.
Notions clés : Caddy, Caddyfile, https automatique, reverse_proxy, file_server, header, HSTS (Strict-Transport-Security), max-age, includeSubDomains, preload, X-Content-Type-Options, frame-ancestors, Referrer-Policy, security.txt, Contact, Expires, /.well-known/
Caddy : du https sans vous en soucier
Dans les leçons 7.2 et 7.3, vous avez mis en place un site en https avec nginx et certbot. Cela représente deux programmes, quelques fichiers et un timer. Caddy fait tout cela à lui seul : c'est un serveur web avec un client ACME intégré. Si un nom figure dans la configuration, pointe vers le serveur et que les ports 80 et 443 sont accessibles, Caddy obtient lui-même un certificat, le renouvelle à temps et redirige http vers https.
Caddy se trouve dans les dépôts de Debian et Ubuntu (dans une version un peu plus ancienne) ; ses auteurs proposent aussi leur propre dépôt apt avec la version la plus récente, avec sa propre clé et Signed-By, comme dans la leçon 4.1. Dans le module 9, Caddy tourne en conteneur devant vos services Docker (leçon 9.4). Ici, vous l'utilisez comme un service ordinaire.
anna@web1:~$ sudo apt install caddy
anna@web1:~$ systemctl status caddyUtilisez soit nginx, soit Caddy sur les ports 80 et 443, pas les deux : un seul programme peut écouter sur un port donné.
Le Caddyfile
La configuration se trouve dans /etc/caddy/Caddyfile. Voici un site statique et une application derrière un reverse proxy :
example.com, www.example.com {
root * /var/www/example.com
file_server
encode zstd gzip
}
app.example.com {
reverse_proxy 127.0.0.1:3000
}C'est tout. Caddy écoute automatiquement en IPv4 et en IPv6, demande des certificats pour les trois noms, redirige http vers https et, avec reverse_proxy, transmet automatiquement les en-têtes X-Forwarded-For et X-Forwarded-Proto (ce que vous faisiez à la main dans nginx, leçon 7.2).
Le test et le rechargement se font comme avec nginx :
anna@web1:~$ caddy validate --config /etc/caddy/Caddyfile
Valid configuration
anna@web1:~$ sudo systemctl reload caddy
anna@web1:~$ sudo journalctl -u caddy -fDans le journal, vous voyez l'obtention des certificats. En cas d'échec, la raison y figure : le plus souvent la même qu'avec certbot (port 80 fermé, nom qui pointe ailleurs, IPv6 défaillant ; leçon 7.3).
HSTS : faire retenir au navigateur que c'est du https
La redirection de http vers https a un point faible : la toute première requête en http passe encore en clair. Une personne sur le même réseau peut l'intercepter et maintenir le visiteur en http. HSTS (HTTP Strict Transport Security, RFC 6797) résout ce problème. Votre site envoie cet en-tête via https :
Strict-Transport-Security: max-age=31536000Le navigateur retient alors pendant un an (31.536.000 secondes) que ce nom n'est accessible qu'en https. Si le visiteur tape plus tard http://, le navigateur le transforme lui-même en https, avant même que quoi que ce soit ne passe sur le réseau. Un en-tête HSTS reçu via http est ignoré par le navigateur ; il ne compte que via https.
Il y a un revers. Si un navigateur a retenu HSTS et rencontre une erreur de certificat (certificat expiré, mauvais nom), le visiteur n'a aucun bouton pour continuer malgré tout. Votre site est alors inaccessible pour ces visiteurs jusqu'à ce que le certificat soit correct. Par conséquent :
- N'activez HSTS que lorsque https fonctionne partout et que le renouvellement est automatique (leçon 7.3).
- Commencez avec un
max-agecourt, par exemple un jour (86400), puis augmentez progressivement jusqu'à un an. - Soyez prudent avec
includeSubDomains: cela s'applique à chaque sous-domaine, y compris un ancien sous-domaine avec un appareil ou un service sans certificat valide. preloaddemande l'inscription dans une liste intégrée aux navigateurs (hstspreload.org). Cette liste exige notamment unmax-aged'au moins un an,includeSubDomainset du https sur tous les sous-domaines. En sortir prend des mois. Ne le faites que si vous êtes certain que tout le domaine restera définitivement en https.
Les autres en-têtes de sécurité
En plus de HSTS, quelques en-têtes apportent beaucoup pour peu d'effort :
| En-tête | Contre quoi | Valeur de départ |
|---|---|---|
X-Content-Type-Options | le navigateur devine le type d'un fichier, si bien qu'une « image » téléversée peut s'exécuter comme script | nosniff |
Content-Security-Policy: frame-ancestors (ou l'ancien X-Frame-Options) | le clickjacking : un autre site charge votre page de façon invisible dans un cadre | frame-ancestors 'self' (ou X-Frame-Options: SAMEORIGIN) |
Referrer-Policy | l'adresse de votre page (avec des termes de recherche ou des numéros de commande) fuit vers d'autres sites | strict-origin-when-cross-origin |
Une politique Content-Security-Policy complète (quels scripts et styles peuvent être chargés) est propre à chaque site et sort du cadre de cette formation ; commencez uniquement avec frame-ancestors.
Dans Caddy, vous les définissez avec la directive header dans le bloc d'un site :
example.com, www.example.com {
root * /var/www/example.com
file_server
header {
Strict-Transport-Security "max-age=31536000"
X-Content-Type-Options "nosniff"
Content-Security-Policy "frame-ancestors 'self'"
Referrer-Policy "strict-origin-when-cross-origin"
-Server
}
}Caddy n'ajoute ni HSTS ni ces en-têtes de lui-même ; vous devez donc vraiment les ajouter. -Server supprime l'en-tête Server. Dans la leçon 9.4, vous ajouterez dans le même type de bloc votre propre en-tête X-Weboke-Cursus pour l'exercice.
Dans nginx, vous placez les mêmes lignes dans le bloc server du port 443 :
add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Content-Security-Policy "frame-ancestors 'self'" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;always garantit qu'ils sont aussi envoyés avec les pages d'erreur. Attention à un piège connu de nginx : si un bloc location contient lui-même une seule directive add_header, les lignes add_header du bloc server ne s'appliquent plus à cette location. Vérifiez donc toujours le résultat :
anna@laptop:~$ curl -sI https://example.com | grep -iE 'strict|nosniff|frame|referrer'
strict-transport-security: max-age=31536000
x-content-type-options: nosniff
content-security-policy: frame-ancestors 'self'
referrer-policy: strict-origin-when-cross-originsecurity.txt : permettre de vous signaler une faille
Imaginons que quelqu'un découvre une faille sur votre serveur, par exemple un répertoire ouvert ou un service obsolète. Comment cette personne sait-elle qui prévenir ? C'est le rôle de security.txt (RFC 9116) : un petit fichier texte à un emplacement fixe, https://<jouwdomein>/.well-known/security.txt.
Contact: mailto:security@example.com
Expires: 2027-10-31T23:00:00Z
Preferred-Languages: nl, en
Canonical: https://example.com/.well-known/security.txtLes règles :
Contactest obligatoire : une adressemailto:,https://outel:à laquelle arrivent les signalements. Utilisez une adresse que quelqu'un lit réellement.Expiresest obligatoire et ne peut apparaître qu'une seule fois : la date après laquelle le fichier est considéré comme obsolète. La RFC recommande une date à moins d'un an. Ainsi, aucun fichier ne reste en ligne avec une adresse oubliée depuis longtemps. Notez dans votre agenda quand le prolonger.Preferred-Languages,CanonicaletPolicy(un lien vers votre politique de signalement) sont facultatifs.- Le fichier doit être servi en https, en texte brut (
text/plain, UTF-8). L'ancien emplacement/security.txtest permis en complément, mais/.well-known/prévaut.
Mise en place pour un site statique :
anna@web1:~$ sudo mkdir -p /var/www/example.com/.well-known
anna@web1:~$ sudoedit /var/www/example.com/.well-known/security.txt
anna@laptop:~$ curl -sI https://example.com/.well-known/security.txt | grep -i content-type
content-type: text/plain; charset=utf-8Si vous utilisez dans nginx la règle par défaut location ~ /\. { deny all; } de la leçon 7.2, placez une exception avant elle : location ^~ /.well-known/ { }. Pour une application derrière un reverse proxy, vous pouvez dans Caddy faire pointer le chemin /.well-known/security.txt vers un fichier avec un bloc handle et file_server.
Une erreur fréquente : un site ou une application qui répond à tout chemin inconnu avec la page d'accueil et le statut 200. security.txt « existe » alors, mais c'est du HTML. Vérifiez donc aussi le contenu.
Sur AlmaLinux et Rocky Linux
Caddy y provient du dépôt de ses auteurs ou d'EPEL/COPR. Comme pour nginx, SELinux doit autoriser un reverse proxy (setsebool -P httpd_can_network_connect 1). Le Caddyfile et les en-têtes sont identiques.
Résumé
- Caddy gère lui-même les certificats, leur renouvellement et la redirection vers https ;
reverse_proxytransmet automatiquement les bons en-têtes. - HSTS fait retenir aux navigateurs que votre site est uniquement en https ; augmentez
max-ageprogressivement, soyez prudent avecincludeSubDomainset très prudent avecpreload. - Ajoutez aussi
X-Content-Type-Options: nosniff,frame-ancestors 'self'et unReferrer-Policy; dans Caddy avecheader, dans nginx avecadd_header ... always, et vérifiez aveccurl -I. - security.txt se trouve à
/.well-known/security.txt, servi en https, en texte brut, avec obligatoirementContactet un seulExpiresà moins d'un an.
Quiz
Exercice
Exercice Z7.4 : HSTS, en-têtes et security.txt. Activez pour votre site HSTS (au moins 180 jours, une fois que https fonctionne bien depuis un certain temps), X-Content-Type-Options: nosniff et frame-ancestors 'self' (ou X-Frame-Options), et publiez un fichier security.txt avec Contact et un Expires à moins d'un an. Saisissez votre nom d'hôte. Le programme récupère https://<hostnaam>/ et vérifie les en-têtes, puis récupère https://<hostnaam>/.well-known/security.txt et vérifie les champs. Il n'enregistre rien d'autre que le résultat et la date Expires.
Pour aller plus loin
- HSTS et en-têtes de sécurité pour votre site web
- Caddy, Automatic HTTPS : https://caddyserver.com/docs/automatic-https
- Caddy, directive header : https://caddyserver.com/docs/caddyfile/directives/header
- RFC 6797, HTTP Strict Transport Security : https://www.rfc-editor.org/rfc/rfc6797.html
- Liste de preload HSTS et ses exigences : https://hstspreload.org/
- RFC 9116, security.txt : https://www.rfc-editor.org/rfc/rfc9116.html
- securitytxt.org (créer et vérifier) : https://securitytxt.org/
