11/08/2014

DNSsec, DANE ou la mort des CA

CDNS-ethernetlockVous avez vu un peu toutes les déclarations sur l’espionnage de masse toussa toussa ? Les scandales sur les autorités de certifications (aussi appelé “tiers de confiance” haha), les soucis de vie privée et tout le toutim ?

Bon et si on faisait quelque chose pour protéger sa vie privée sans pour autant filer des thunes à des soit disant tiers de confiance… On va utiliser le DNS pour renforcer nos connexions TLS et plus si affinité.

Donc dans l’ordre on va faire du DNSSec sinon le reste ne sert pas à grand chose, ensuite on va commencer par sécuriser notre petit SSH, ensuite notre serveur Web puis notre joli SMTP et ça sera un bon début !

DNSSec, t’es un peu chiant mais tu es indispensable

Bon là c’est l’étape préliminaire. Elle est pas indispensable techniquement, mais si l’on met des certificats et autres hash pour valider l’utilisation d’autres services dans le DNS, il faut sécuriser le DNS afin que les infos ne soient pas usurpables.

Donc là on va bosser sur Bind9, tout d’abord on active dnssec. Pour ça on modifie
/etc/bind/named.conf.options

dnssec-enable yes;
dnssec-validation yes;
dnssec-lookaside auto;
Bon maintenant on va s’attaquer à la partie crypto. Je rentrerai pas dans tous les détails (loin de là) c’est une mise en pratique cependant je suis obligé de vous expliquer un peu le bordel des clés : il y a déjà deux types, les KSK (key signing key) et les ZSK (zone signing key). Une ZSK est une “petite” clé qui signe la zone. On la change régulièrement (pas plus de quelques semaines de durée de vie). Cependant pour garantir tout de même une sécurité pas trop dégueue, on signe cette clé via la KSK qui elle est plus grande et renouvelée beaucoup moins souvent (une fois par an environ, lorsqu’on renouvelle le nom de domaine par exemple). Vu que l’on change régulièrement la ZSK et que la propagation DNS est ce qu’elle est, il y a donc une période où l’on signe la zone avec l’ancienne ZSK et également avec la nouvelle ZSK, puis on supprimme l’ancienne. Il y a donc un roulement à faire (qui peut-être automatisé). La période de vie de la clé est indiquée à l’intérieur de celle-ci.

Action !

Donc il va nous falloir une KSK et une ZSK. Vu qu’on aura un joli bordel de clés, utilisons un dossier à part : /etc/bind/keys . On génère la KSK puis la ZSK :

dnssec-keygen -K /etc/bind/keys/ -f KSK lord.re
dnssec-keygen -K /etc/bind/keys/ lord.re

Et maintenant on signe la zone :

dnssec-signzone -S -o lord.re -K /etc/bind/keys/ /etc/bind/zones/lord.re

On a maintenant notre fichier de zone classique et le fichier de zone signé /etc/bind/zones/lord.re.signed. On indique à bind de servir la zone signé dans le fichier de conf, on reload et c’est bon ! Vous remarquerez que dnssec-signzone se débrouille tout seul pour trouver les bonnes clés.

C’est fini ! Ah en fait non. DNSSec c’est toute une chaîne. Votre partie à vous est sécurisée, la partie parente est sécurisée (enfin ça dépend du TLD), mais il n’y a pas le lien entre votre domaine et le TLD. Il faut fournir un enregistrement de type DS (cela fait partie des glue records) à votre registrar pour lier les maillons de la chaîne. Pour créer cet enregistrement :

dnssec-dsfromkey -1 -K /etc/bind/keys/ -f /etc/bind/zones/lord.re.signed lord.re

À savoir que certains TLD sont plus longs que d’autres pour prendre en compte ce DS.

Bon bha … ça marche ?

$ dig +dnssec lord.re

; <<>> DiG 9.9.5 <<>> +dnssec lord.re
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 39131
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1460
;; QUESTION SECTION:
;lord.re.           IN  A

;; ANSWER SECTION:
lord.re.        600 IN  A   90.0.0.105
lord.re.        600 IN  RRSIG   A 5 2 600 20140908115752 20140809115752 11250 lord.re. hshNikmVmI8YcRtOvTHzmwQIHbEVZTu7TVUY/vT5y6RC/IgwFs4dVvTO WXL42d7pOBzbabqwjU00SAd0Um3TXY7Zo3tT2NzUnBTSzWnLDoT2dj7Z i3UnqPqnu2MQA+0mxDgKojDiJbIuYz5kXvM1FQSb2ooSbLMoL2SnTMNt Yz8=
lord.re.        600 IN  RRSIG   A 5 2 600 20140908115752 20140809115752 47592 lord.re. J1wQ3NZlboTIZTKRXA3IRjI/pWuxGxbAAVw9MWo3g/dbM6jM/HYth6/5 MFYPk/r4Xj8+NcMNWi4uaAw7I0/F8T3qA2Eb4dl8F3quSa4jBFm1rx50 ls5Z/fdzKSiIq8LqKEgKJlK7G6OJjbN+edJbRsgSlUNhQgmMnr/vjV0N 2SA=
lord.re.        600 IN  RRSIG   A 5 2 600 20140908115752 20140809115752 55107 lord.re. F7TnXt/mEfZTBa9Ni9ukqRMSBuntO8jFkytCiaVVKFTC34NprV28G/K0 /KDX9om8f+BHxaJlrZB/kzbVI/GEnlz2am1kSNFEsIHigOxW+xCh8HL5 TkAcKqxHvGEeM4+bxFQjY0NN6sU0/RcGtHPyg0cnDzVLeCnN1TqnaAFA ORI=

;; Query time: 43 msec
;; SERVER: 10.0.0.1#53(10.0.0.1)
;; WHEN: Sun Aug 10 15:02:36 CEST 2014
;; MSG SIZE  rcvd: 553

Regardez la présence du flag ad dans la réponse. Attention si vous consultez en direct le Bind autoritaire, vous n’aurez pas le flag ad, utilisez un autre serveur DNS pour cette requête.

NB: oui je vous mens, en vrai ça ne marche pas, il n’y a pas le champ ad sur mon domaine, cependant online.net ne permet pas d’envoyer le DS record.

SSH, mon amour, je vais te protéger !

Voilà le truc : lorsqu’on a un serveur généralement on installe un serveur SSH dessus. SSH c’est super sécurisé sauf qu’il y a un point faible dans le protocole qui est le TOFU. TOFU c’est Trust On First Use. Lorsqu’on se connecte à un serveur SSH, le client va récupérer l’empreinte unique du serveur SSH. Cette empreinte ne change jamais (en dehors des réinstallation bien entendu). S’il s’agit de la première connexion à ce serveur, le client va stocker cette empreinte de son côté. Toutes les autres fois où le client va se connecter, il va récupérer l’empreinte serveur et la comparer à l’empreinte stockée lors de la première connexion. Si celle-ci est identique, pas de soucis, sinon un joli message d’avertissement vous préviendra d’une éventuelle attaque de type Man in the middle. On voit donc que le moment sensible est donc la récupération de l’empreinte lors de la première connexion.

L’astuce consiste donc tout simplement à publier cette empreinte dans le serveur DNS. Pour ça il existe le champ SSHFP (ssh fingerprint, thanks Captain Obvious). Pour générer ce champs, on peut tout simplement demander à ssh de le faire avec la commande

ssh-keygen -r mon.serveur.ssh

et paf vous n’avez plus qu’à insérer dans votre zone DNS. Bien entendu il faut aussi règler votre client SSH pour regarder ce champs (ce qui n’est pas le cas par défaut sur Gentoo). Donc il faut éditer le fichier /etc/ssh/ssh_config et y rajouter

VerifyHostKeyDns yes

Une fois cela fait vous verrez une ligne supplémentaire lors de la première connexion :

The authenticity of host ‘lord.re (90.0.0.105)’ can’t be established.
ECDSA key fingerprint is 6f:9e:ca:ce:e6:3d:85:72:3b:0d:0e:77:94:a5:53:b4.
Matching host key fingerprint found in DNS.
Are you sure you want to continue connecting (yes/no)?

Par contre rien ne vous assure que la résolution est validée par DNSSec. Veillez à ce que votre résolveur le fasse !

Toi aussi Nginx tu pourras arrêter de faire râler les navigateurs avec ton certif auto-signé (ou presque)

Remarquez bien le “ou presque” parceque c’est que de la théorie. En fait on va utiliser un autre type de champs DNS qui sera valable pour toutes les connexions de type TLS (rien de spécifique à un serveur web).

Bon on a un serveur web avec son certificat auto-signé qui fait râler (à juste titre) les navigateurs. Ce qu’on va faire c’est qu’on va foutre ce certificat dans notre DNS et donc notre zone DNS sera à considérer comme notre tiers de confiance. Le soucis c’est qu’actuellement la partie cliente ne suit pas et donc ne vérifie pas l’existence de ce fameux champs et râle quand même lors de l’utilisation d’un certificat auto-signé. Mais bon, on peut rêver d’un futur radieux où toutes les connexions TLS vérifieront ce champs et donc arrêteront de couiner.

Donc, enlevons nos gants et foutons les doigts dans la mélasse. On va utiliser le champ de type TLSA. Donc il va falloir hasher notre certificat puis dans le champ : indiquer l’utilisation de ce champs, le type d’info qu’on y met, le type de hash, le hash en question, le numéro de port, le protocole de transport et le nom de domaine bien entendu.

Pour un serveur web ça donne : ça nous donne

_443._tcp.lord.re. IN TLSA 3 0 1 8281d07d690fdf2c21df532ffc110d09fc4728e72df2fc776be793859b1d9ea8

Cette ligne est valable pour le TCP 443 pour lord.re. avec un certificat auto-signé (le 3), qui est un certificat complet (le 0) qu’on a hashé par sha256 (le 1). Pour générer le hash :

openssl x509 -in moncertificat.crt -outform DER | openssl sha256

Comme dit précédemment vous pouvez répétez l’opération pour n’importe quel service utilisant TLS (irc, smtp, …) mais rien ne garanti que le client fasse la vérification de ce champs DNS.

Toutefois DANE c’est l’avenir, autant l’adopter au plus vite.

Pas de jaloux Postfix, toi aussi tu y passes.

Avec le serveur mail on peut surcharger le DNS en deux endroits : faire du DANE comme pour tout le TLS mais aussi faire du SPF et du DKIM, ce qui a pour but de réduire la possibilité de spam et de spoof. Donc pour le DANE comme précédemment, un champs TLSA de la forme

_25._tcp.lord.re IN TLSA 3 0 1 blablablabla

Bon ça c’est bon maintenant on gère facilement, rien de spécifique. On peut demander au serveur mail de faire la vérification DANE également (la méthode varie en fonction de votre serveur mail).

Puis on va se créer un SPF qui veux dire Sender Policy Framework. C’est un champs qui permet d’annoncer les seuls serveurs autorisés à envoyer des mails pour un domaine. Typiquement dans mon cas, le seul serveur de mail autorisé à envoyer des mails provenant de *@lord.re est zoid.lordtoniok.com. Donc je créé une entrée DNS de la forme :

lord.re. 3600 IN SFP "v=spf1 +a:zoid.lordtoniok.com -all"

Et voilà ! Rien de plus dans ce cas. C’est une petite protection sympatoche qui ne mange pas de pain.

Maintenant je survole DKIM car là c’est plus compliqué. DKIM consiste à faire signer les mails sortants de son serveur en fonction du domaine d’expédition. Lorsqu’un serveur reçoit un mail provenant de notre nom de domaine, il est possible pour le destinataire de vérifier que le message a bien été émis par le serveur émetteur. C’est donc une bonne technique anti-phishing et anti-spoof. La mise en place est plus compliqué car il y a la signature à faire côté smtp, cependant on trouve de nombreux tutos.

Des ptits outils pour se simplifier la vie

Il existe pleins d’outils pour aider :

Conclusion

Vous voilà dans l’internet du futur, où les CA sont mortes et enterrées car rendues inutiles par DANE et en plus c’est encore plus sécurisé qu’avant.

  1. | #1

    Salut Lord,

    Tout d’abord, merci pour le tutoriel, il est bien pratique.

    Juste quelques ajouts : Il faut aussi transmettre à son “registar” la clef publique, pour faire la liaison entre nous, et le reste du monde.
    Dans ton tutoriel, tu parles de la commande dnssec-dsfromkey, mais ça ne semble pas être la bonne solution.
    Par exemple, pour OVH, il faut renseigner les infos concernant la partie publique de la KSK, en lisant son contenu (source http://guides.ovh.com/dnssec#link11)
    Et tout de même, doit-on mettre ces enregistrements de type DS renvoyés par la commande dnssec-dsfromkey dans nos entrées ?

    Encore merci, et bonne continuation.

  1. | #1