Ce blog n'a d'autre prétention que de me permettre de mettre à la disposition de tous des petits textes que j'écris. On y parle surtout d'informatique mais d'autres sujets apparaissent parfois.
Première rédaction de cet article le 28 Juillet 2010
Un des services les plus importants que rendent les SGBD est d'isoler les transactions les unes des autres, c'est-à-dire de faire en sorte que, pendant qu'une transaction joue avec les données, les autres pourront continuer à travailler tranquillement, avec des données stables. Mais certains débutants en SGBD ignorent qu'il existe plusieurs niveaux d'isolation dans SQL et que tous ne garantissent pas une isolation parfaite, loin de là.
Prenons l'exemple de PostgreSQL, qui documente très bien ces différents niveaux d'isolation. On va créer une table pour essayer :
essais=> CREATE TABLE Foo (id SERIAL, name TEXT, number INTEGER);
Maintenant, si on se connecte et qu'on lance une transaction, par
défaut, celle-ci aura le niveau d'isolation read
committed. Cela vaut dire qu'on verra les
COMMIT des autres (ce que la littérature SQL
appelle un phantom read) :
essais=> BEGIN;
BEGIN
essais=> SELECT * FROM foo;
id | name | number
----+------+--------
(0 rows)
[Ici, une autre transaction fait un
"INSERT INTO Foo (name, number) VALUES ('durand', 15);"]
essais=> SELECT * FROM foo;
id | name | number
----+--------+--------
1 | durand | 15
(1 rows)
On n'a donc pas été complètement isolé des autres transactions. Si on veut le faire, il faut indiquer explicitement, après le début de la transaction mais avant la première requête, un niveau plus isolant :
essais=> BEGIN;
BEGIN
essais=> SET TRANSACTION isolation level serializable;
SET
essais=> SELECT * FROM foo;
id | name | number
----+--------+--------
1 | durand | 15
(1 rows)
[Cette fois, même si une autre transaction fait, par exemple, "INSERT
INTO Foo (name, number) VALUES ('dupont', 1)", nous ne le verrons pas
tant que notre propre transaction est en cours.]
essais=> SELECT * FROM foo;
id | name | number
----+--------+--------
1 | durand | 15
(1 rows)
[Lorsque notre transaction se termine, on voit les changements faits
entre temps.]
essais=> COMMIT;
COMMIT
essais=> SELECT * FROM foo;
id | name | number
----+--------+--------
1 | durand | 15
2 | dupont | 1
(2 rows)
Pourquoi tout le monde n'utilise pas ce niveau maximal
d'isolation ? Pourquoi n'est-il pas la valeur par défaut ? Parce
qu'isoler a un coût, oblige le SGBD à plus de
travail et à utiliser davantage de
verrous. Pire, cela peut conduire à des cas où
on a une erreur dans l'une des transactions. Prenons le cas où,
pendant qu'on lit gentiment la table, une autre transaction la
modifie avec UPDATE Foo SET number=6 WHERE
id=2;. Par défaut, on verra ce changement dans notre propre
transaction. Mais si on cherche la bagarre et qu'on demande à être
complètement isolé :
essais=> BEGIN; BEGIN essais=> SET transaction ISOLATION LEVEL serializable; SET essais=> SELECT * FROM foo; ... 1 | durand | 15 ... [Ici, une autre transaction modifie cette ligne. On ne voit pas le changement, comme prévu.] essais=> SELECT * FROM foo; ... 1 | durand | 15 ... [Mais si on demande à changer cette ligne ?] essais=> DELETE FROM foo WHERE id=1; ERROR: could not serialize access due to concurrent update
Cette fois, on a eu un conflit. PostgreSQL ne pouvait pas faire les deux opérations demandées. L'une d'elles se termine donc en erreur.
Si l'autre transaction ne faisait pas de
COMMIT immédiatement, PostgreSQL est dans
l'incertitude, il ne sait pas encore laquelle faire échouer car il ne
sait pas s'il n'y aura pas plutôt un ROLLBACK :
essais=> BEGIN; BEGIN essais=> SET transaction ISOLATION LEVEL serializable; SET essais=> SELECT * FROM foo WHERE id=6; id | name | number ----+--------+-------- 6 | armand | 8 (1 row) [Ici, une autre transaction modifie cette ligne. On ne voit pas le changement, comme prévu. Mais :] essais=> DELETE FROM foo WHERE id=6; [Ici, la transaction est bloquée. DELETE ne rendra pas la main avant que l'autre transaction n'aie décidée d'un COMMIT ou d'un ROLLBACK. On voit que cela peut être gênant pour certaines applications.]
Si l'autre transaction fait un COMMIT, on est
ramené au cas précédent : le DELETE se termine en erreur. Si
l'autre transaction fait un ROLLBACK (renonce à
son opération de mise à jour), alors le
DELETE peut se terminer normalement.
Attention pour le comportement par défaut si on utilise une
bibliothèque d'accès à PostgreSQL. Celle-ci peut mettre
automatiquement dans un niveau d'isolation différent. Pour
Python, la norme d'interface avec
les SGBD n'en parle pas. Avec psycopg, ce n'est pas le cas,
le niveau par défaut est le read
committed. Ce petit programme
Python permet de tester. Il ouvre une transaction et affiche
régulièrement la valeur d'une des lignes. Par défaut, il montre les
changements que fait une autre transaction pendant ce temps.
PostgreSQL, pour réaliser cette isolation, utilise un mécanisme
nommé MVCC. Son principal slogan est que « les
écritures ne bloquent jamais les lectures et les lectures ne bloquent
jamais les écritures ». (Dans l'exemple plus haut où
DELETE était bloqué, c'est parce que l'autre
opération était également une écriture, un
UPDATE.)
Les essais ci-dessus étaient faits avec PostgreSQL. Mais cela serait à peu près pareil avec tous les SGBD sérieux. Par exemple, pour Oracle, on peut lire « On Transaction Isolation Levels » ou « How Serializable Transactions Interact ». Pour les autres modèles de SGBD, voir la bonne liste de Wikipédia.
Ceux et celles qui veulent lire davantage peuvent regarder un bon cours en français ou bien une bonne discussion sur Stack Overflow, qui explique bien pourquoi un haut niveau d'isolation n'est pas forcément souhaitable (il diminue le parallélisme).
Première rédaction de cet article le 27 Juillet 2010
La récente signature de la racine du DNS, complétée le 15 juillet, a ravivé l'intérêt pour la validation des signatures DNSSEC, le service qui vérifie que la signature d'un nom de domaine est correcte, et qui met le bit AD (Authentic Data à 1 dans la réponse DNS. Installer un tel résolveur validant n'est pas trop difficile (voir par exemple mes articles « Unbound, un autre résolveur DNS » ou « Valider la racine du DNS »). Mais il est encore plus simple d'utiliser un résolveur existant et publiquement accessible.
En voici une liste partielle, ne comportant que des résolveurs que
j'ai testé. Lisez bien la documentation de chacun notamment pour voir
les clés de confiance (trust anchor) qu'il
utilise. Le seul public semble être l'ODVR
de l'OARC, accessible en IPv4 et IPv6.
Autrement, il n'existe que des résolveurs réservés aux clients d'un
FAI comme celui de Comcast ou bien
spécifiques à un domaine comme celui
de DENIC pour .de
(dans ce dernier cas, on peut toujours configurer son résolveur, par
exemple avec la directive forward de
BIND ou Unbound, pour
utiliser ces serveurs DNSSEC au lieu des serveurs normaux).
Il existe de bonnes raisons à ce manque de serveurs publics, exposés dans le RFC 5358. Pour éviter les problèmes décrits dans le RFC, le service de l'OARC est limité en débit.
Première rédaction de cet article le 25 Juillet 2010
Juste un court article pour attirer l'attention sur les articles faisant partie du recueil « Towards the Future Internet - Emerging Trends from European Research ». Le recueil contient de nombreux articles intéressants sur des aspects en général non-techniques de l'Internet et de son développement. Les textes sont tous disponibles en ligne.
Parmi ces articles, je signale « Modeling the economics of Loc/ID Split for the Future Internet ». Il se penche sur le difficile problème de trouver un sens économique aux propositions de séparation de l'identificateur et du localisateur sur l'Internet. C'est surtout une analyse de coûts, avec plus de maths que de bon sens mais c'est un début.
Première rédaction de cet article le 24 Juillet 2010
Je me souviens bien de cette panne parce qu'un client m'avait
appelé en disant que « L'Internet est
cassé ». Vu l'importance de
.com, ce n'était pas
faux. Mais, autrement, il en reste peu de souvenirs en ligne.
Donc, le 17 juillet 1997, InterNIC publie une zone .COM entièrement
vide. Le
générateur de zones avait planté (disque plein ou problème similaire). Un
ingénieur de Network Solutions (VeriSign n'avait pas
encore racheté l'activité registre de Network Solutions) avait bien vu l'avertissement du
logiciel mais avait choisi de l'ignorer. (Comme lors de la panne de .SE.) Pendant plusieurs
heures, tous les serveurs de noms répondaient « Ce domaine n'existe
pas » (code de réponse DNS NXDOMAIN).
Voici quelques archives disponibles en ligne. À noter que, à
l'époque, les mêmes serveurs servaient la racine et .COM, d'où
l'allusion fréquente aux root nameservers.
Première rédaction de cet article le 21 Juillet 2010
L'exposition « Dans l'ombre des dinosaures » (attention, site Web de daube imposant une technologie privatrice) au Muséum d'Histoire Naturelle de Paris (jusqu'au 14 février 2011) est excellente. Mais j'ai particulièrement apprécié les trois vidéos présentant l'évolution de manière ludique et décalée.
La vulgarisation scientifique n'est jamais une tâche facile : il faut être exact et rigoureux (d'autant plus rigoureux que le public n'est pas expert et n'a pas les moyens de détecter les problèmes) tout en étant clair et même attirant puisque le public a d'autres sources de distraction possibles. Les trois vidéos réalisées par les Chevreaux suprématistes remplissent parfaitement le cahier des charges : l'une, où l'acteur-conférencier parodie un camelot, porte sur l'évolution des siréniens, les deux autres, où l'acteur-conférencier se moque des présentations corporate des années 1980, avec leurs rétro-projecteurs, parlent de l'évolution d'un primate et de celle des rongeurs.
Contrairement à un film vu sur l'Internet, ici, les squelettes des animaux dont on parle sont immédiatement à côté (« Regardez ! Derrière vous ! », dit la vidéo) et le film peut donc aussi encourager à regarder la « vraie » information.
Première rédaction de cet article le 19 Juillet 2010
Comme tout le monde le sait, la racine du DNS a été complètement signée (c'est-à-dire avec publication de la clé) le 15 juillet dernier. Comment valider des noms de domaine avec DNSSEC désormais ?
D'abord, un pré-requis : la racine étant signée en utilisant
l'algorithme SHA-256 (comme le sera
.fr le 14 septembre
prochain), il faudra des logiciels assez récents. Le RFC 5702 qui normalisait l'usage de SHA-256 ne date que
d'octobre 2009. Pour BIND, il faut une version
>= 9.6.2 pour valider la racine. Pour Unbound, une version >= 1.4 (publiée le
26 novembre 2009). Avant cela, Unbound 1.3 pouvait utiliser SHA-256
mais, c'était une option de compilation --enable
(qui n'était pas activée par défaut).
Ensuite, il faut mettre la clé publique de la racine comme clé de
confiance (trust anchor) dans la configuration du
résolveur validant. On pourrait la récupérer dans le
DNS lui-même (dig DNSKEY
.) mais ce serait stupide, puisque non
sécuriré. DNSSEC ne résoudra aucun problème de
sécurité si on gère les clés aussi imprudemment. Il faut donc un canal
sécurisé et authentifié pour amorcer la validation DNSSEC. La clé de la racine est distribuée officiellement par
l'IANA en https://data.iana.org/root-anchors/root-anchors.xml. On peut
authentifier avec uniquement X.509 puisque
c'est du HTTPS. Mais le fichier est aussi signé
avec PGP et on peut donc le valider ainsi. Il
est signé avec la clé 0x0F6C91D2, qui est elle-même signée par
plusieurs personnes connues avec lesquelles vous aurez peut-être un
chemin de confiance. La clé 0x0F6C91D2 se trouve sur les serveurs de
clé et aussi en https://data.iana.org/root-anchors/icann.pgp. Un exemple de
validation est :
wget -nc -O root-anchors.xml https://data.iana.org/root-anchors/root-anchors.xml wget -nc -O root-anchors.asc https://data.iana.org/root-anchors/root-anchors.asc gpg --verify root-anchors.asc root-anchors.xml
Le fichier de la clé de confiance est au format XML et contient un enregistrement DS. Pour le convertir au format qu'attendent nos résolveurs, il y a plusieurs solutions. Pour Unbound, qui accepte les enregistrements DS comme clés de confiance, j'ai fait un petit script en XSLT qui fait cette conversion. Par exemple :
% xsltproc anchors2ds.xsl root-anchors.xml . IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5
Le processus peut s'automatiser à l'aide de mon Makefile.
Pour BIND, qui n'accepte pas les enregistrements DS mais seulement
les DNSKEY, c'est un peu plus compliqué. La
solution que j'utilise est à base de cut, de
sed et de awk et n'est
peut-être pas très robuste mais elle marche. Le principe est de
récupérer la clé dans le DNS, de manière non sécurisée, puis de
fabriquer le DS avec l'outil BIND
dnssec-dsfromkey, puis de comparer avec la DS
obtenue de l'IANA. C'est également automatisé dans le Makefile.
Donc, pour Unbound, il faut taper make
root-anchors.txt puis mettre le contenu de
root-anchors.txt dans
unbound.conf par exemple :
trust-anchor: ". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5"
Pour BIND, on tape make root-anchors.dnskey
puis on met le contenu de ce fichier dans
named.conf. Doit-on le mettre dans
trusted-keys (clés statiques) ou bien dans
managed-keys (clés mises à jour automatiquement
suivant le RFC 5011) ? À l'heure actuelle, il ne
semble pas que les gestionnaires de la racine aient formellement
annoncé qu'ils utiliseraient le RFC 5011 donc je
préfère le trusted-keys :
trusted-keys {
. 257 3 8 "
AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF FVQUTf6v58fLjwBd0YI0Ezr
AcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5
/Efucp2gaD X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz W5hOA2hzCTMj
JPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmR
LKBP1dfwhYB4N7knNnulq QxA+Uk1ihz0= ";
Il existe d'autres solutions pour BIND : le script ta-tool, le script root2anchorkeys, on peut aussi par exemple
utiliser les scripts qui avaient
été conçus pour ITAR. Le format des
fichiers XML n'est pas le même donc ces scripts ne fonctionnent pas
directement avec root-anchors.xml, il faut les
convertir, à la main, ou bien via un script que vous allez devoir
écrire. Une autre solution est de tout faire manuellement comme
indiqué en « Using
the root DNSSEC key in BIND 9 resolvers » ou dans « How to set up DNSSEC validation with BIND-9.7 ».
Sauf si vous faites confiance au RFC 5011, pensez surtout à recommencer les étapes ci-dessus lors de la sortie de la prochaine clé de la racine, dans quelques années. Cette sortie sera sans doute annoncée très largement.
Merci à Alain Thivillon pour son aide.
Première rédaction de cet article le 17 Juillet 2010
On le sait, Twitter a annoncé l'arrêt du mécanisme d'authentification simple à partir du 16 août 2010. Le mécanisme à utiliser désormais est OAuth (RFC 5849). Voici un exemple de passage à OAuth pour un petit programmeur Python.
L'ancien mécanisme d'authentification était le Basic
Authentication décrit dans le RFC 2617. Son gros avantage est la simplicité pour le
programmeur : il suffit de concaténer un identificateur et le
mot de passe, de les encoder en
Base64 et de les mettre dans l'en-tête
HTTP Authorization: et
c'est tout. D'une manière générale, la simplicité de
l'API a d'ailleurs beaucoup fait pour le succès
de Twitter.
Mais ce mécanisme très simple est aussi très dangereux. En effet, tout repose sur la connaissance du mot de passe. Celui-ci doit être connu des applications, voire des applications tierces, et il ne reste donc pas secret longtemps. D'où le passage à OAuth, qui permet une meilleure sécurité, au prix d'une plus grande complexité (et qu'il n'est pas entièrement possible de cacher dans la bibliothèque logicielle).
Heureusement, il y a quand même des bibliothèques qui aident et des articles qui expliquent. Question bibliothèque, comme je programme en Python, j'ai abandonné python-twitter, qui ne semble toujours pas (au 17 juillet, dans sa version 0.6) avoir de gestion de OAuth. Je suis passé à l'excellent Tweepy qui dipose d'une très bonne documentation. Question article, j'ai simplement suivi les instructions dans « Twitter from the command line in Python using OAuth ». Voici les étapes parcourues pour le petit script qui me sert à informer des mises à jour de mon blog. Je ne fais que paraphraser en français l'excellent article ci-dessus, qui inclus en outre d'utiles copies d'écran.
1) Enregistrer l'application. Attention au nom choisi, car il sera
affiché par Twitter (j'ai choisi Blog
Bortzmeyer). Cela se fait en http://twitter.com/oauth_clients.
Choisir Client (et pas browser) pour un logiciel en
ligne de commande. Choisir Read & Write pour
une application qui permettra de faire des mises à jour. Choisir
Twitter pour l'authentification.
2) Lancer l'application à usage unique, qui permettra d'obtenir les éléments d'authentification. Voici celle que j'ai utilisé :
#!/usr/bin/env python
# First connection to Twitter, to get the credentials
import tweepy
CONSUMER_KEY = 'OBTENUE EN ÉTAPE 1'
CONSUMER_SECRET = 'OBTENU EN ÉTAPE 1'
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth_url = auth.get_authorization_url()
print 'Please authorize: ' + auth_url
verifier = raw_input('PIN: ').strip()
auth.get_access_token(verifier)
print "ACCESS_KEY = '%s'" % auth.access_token.key
print "ACCESS_SECRET = '%s'" % auth.access_token.secret
Une fois qu'elle est lancée, elle affiche l'URL qu'il faut visiter avec son navigateur Web favori. On doit alors s'authentifier auprès de Twitter par le mécanisme habituel, autoriser l'application et, en échange, Twitter vous envoie un nombre, le PIN, qu'on peut alors saisir dans son terminal :
% python one-off-connection.py Please authorize: http://twitter.com/oauth/authorize?oauth_token=YukdWz2zW8nf8HnLUtt67rftNiXcjbUvojrWN5dKRs PIN: 185867 ACCESS_KEY = 'MA CLÉ' ACCESS_SECRET = 'MON SECRET'
3) Il ne reste plus qu'à utiliser ces éléments d'authentification dans son programme. Voici un exemple :
#!/usr/bin/python
import tweepy
message = "TEST"
twitteroauthfile = "/home/bortzmeyer/.twitter/oauth"
if not os.path.exists(twitteroauthfile):
print >>sys.stderr, ("Cannot find %s" % twitteroauthfile)
sys.exit(1)
twitteroauth = open(twitteroauthfile)
twitter_consumer_key = twitteroauth.readline()[:-1]
twitter_consumer_secret = twitteroauth.readline()[:-1]
twitter_access_key = twitteroauth.readline()[:-1]
twitter_access_secret = twitteroauth.readline()[:-1]
auth = tweepy.OAuthHandler(twitter_consumer_key, twitter_consumer_secret)
auth.set_access_token(twitter_access_key, twitter_access_secret)
api = tweepy.API(auth)
status = api.update_status(message)
# No method to display a status in Tweepy, it seems
print status
Une autre solution, après la fin de l'authentification de base dans quelques semaines, serait d'utiliser un relais, comme celui que propose Supertweet, ce qui limiterait les modifications à faire aux applications.
Date de publication du RFC : Juillet 2010
Auteur(s) du RFC : D. Taler (Microsoft), L. Zhang (UCLA), G. Lebovitz (Juniper)
Pour information
Première rédaction de cet article le 17 Juillet 2010
Les mécanismes de traduction d'adresse (NAT) ont toujours suscité des polémiques, en raison de leur remise en cause des principes d'architecture de l'Internet. Avec IPv4, ces mécanismes sont nécessaires en raison de la pénurie d'adresses qui fait que, par exemple, un particulier n'a aucune chance d'obtenir plus qu'une adresse IPv4, même s'il a chez lui plusieurs équipements IP. Mais en IPv6 ? La pénurie disparait. Est-ce que le NAT doit donc disparaitre avec elle ? Dans ce RFC, l'IAB étudie la question et donne une réponse, certes hostile au NAT, mais très étayée et pointant du doigt quelques problèmes qui peuvent pousser certains à déployer du NAT IPv6 malgré tout.
La question initiale est pratique (section 1 du RFC) : l'IETF doit-elle normaliser des mécanismes de NAT pour IPv6 ? Elle ne l'avait pas fait pour IPv4, considérant, à juste titre, que c'était un bricolage ayant trop d'effets néfastes et, résultat, le NAT a quand même été largement déployé, de manière non standardisée. Le groupe de travail behave de l'IETF a été créé bien plus tard pour essayer de documenter ce bricolage et ses conséquences, et pour trouver des solutions partielles à certains de ses inconvénients.
Évidemment, pas mal de participants à l'IETF craignent que la même chose se produise avec IPv6. Selon un scénario possible, l'IETF, attachée aux principes de l'adresse IP unique, de la neutralité du réseau, et de la transparence de bout en bout (RFC 4924), refuserait fermement de normaliser des solutions de NAT IPv6 et celles-ci seraient déployées quand même, menant à une prolifération de routeurs NAT différents et gardant l'actuel cauchemar que vivent les applications, notamment pair-à-pair. Mais la situation est-elle la même qu'avec IPv4 ?
Les opposants à cette vision font remarquer que la motivation initiale du déploiement du NAT pour IPv4 était uniquement la pénurie d'adresses. (Je me souviens bien de mon émerveillement quand le premier routeur NAT utilisable, un PC Linux avec ce qui s'appelait à l'époque IP masquerading, est apparu vers 1995. Soudainement, le particulier pouvait avoir plusieurs machines IP chez lui.) Cette pénurie disparaissant avec IPv6, la motivation du NAT disparait aussi. Compte-tenu des défauts du NAT, où un équipement intermédiaire interfère avec la relation entre deux machines, il ne faudrait surtout pas déployer des NAT IPv6 et donc pas les normaliser.
Ce n'est pas et de loin la première fois que la question se pose. Ainsi, le RFC 4864 avait déjà discuté des avantages et inconvénients des NAT. Où en est-on aujourd'hui ?
Pour évaluer la possibilité que des systèmes de NAT soient déployés pour IPv6, même en l'absence de pénurie d'adresses, la section 2 du RFC étudie successivement les motivations possibles pour le NAT ou, en d'autres termes, les bénéfices perçus par certains utilisateurs.
Premier avantage perçu (section 2.1), dispenser de renumérotation. Avec un routeur NAT devant son réseau, celui-ci peut avoir des adresses IP stables, indépendantes des adresses vues de l'extérieur. Si celles-ci changent (par exemple parce qu'on a changé de fournisseur d'accès), il suffit de reconfigurer le routeur et tous les autres problèmes de renumérotation (RFC 5887) sont évités. Notre RFC 5902 note que cet argument saute si on dispose d'adresses PI mais que celles-ci posent d'autres problèmes, les mécanismes de routage actuels de l'Internet ne pouvant peut-être pas gérer un trop grand nombre de préfixes PI.
Autre motivation parfois citée pour déployer du NAT, le désir d'être multi-homé (section 2.2). Aujourd'hui, la seule solution qui isole le routage mondial du multi-homing est le NAT. Autrement, il faut utiliser des adresses PI qui sont routées globalement. Les techniques basées sur la séparation de l'identificateur et du localisateur ne sont pas encore prêtes. Donc, bien que la solution à base de NAT ne fournisse pas tous les services qu'on attend du multi-homing (par exemple, elle ne protège pas les sessions déjà établies d'une défaillance d'un des fournisseurs), elle reste tentante.
Pour un FAI, le NAT a un autre avantage : il
permet d'homogèneiser la configuration des réseaux locaux des
clients. Avec le NAT, tous les clients ont
192.168.0.0/24, tous les routeurs
CPE ont l'adresse
192.168.0.1, etc. Cela peut simplifier le
support utilisateur (section 2.3). En IPv6, un
mécanisme équivalent serait d'utiliser les adresses locales au lien
(section 2.5.6 du RFC 4291) mais il y a trop peu
d'expérience pratique aujourd'hui pour juger de la validité de cette
approche.
Lorsqu'on demande à un administrateur réseaux pourquoi il utilise du NAT alors qu'il dispose de suffisamment d'adresses, il répond souvent « la sécurité ». Cet argument est souvent vague et peu étayé. En creusant un peu, on peut trouver deux propriétés du NAT qui ont un rapport avec la sécurité. La première est le fait de dissimuler partiellement le réseau, sa structure et les machines qui s'y connectent (section 2.4). L'idée est que, sans faire reposer toute la sécurité du réseau sur cette dissimulation, on peut toutefois se dire qu'il n'y a aucune raison que le monde entier puisse analyser facilement le réseau, ce qui faciliterait la préparation d'une éventuelle attaque. Ainsi, le NAT permet de rendre plus difficile le recensement des machines (section 2.4.1). Cachées derrière le routeur NAT, les machines ne sont plus accessible à un comptage, par exemple. Dans ce domaine, la plupart des administrateurs réseau surestiment beaucoup les protections fournies par le NAT. Un article comme « A technique for counting NATted hosts » montre bien que le NAT n'empêche nullement le recensement des machines. Des mécanismes de NAT plus complexes pourraient permettre de limiter certaines des attaques que décrit Bellovin (pas celles par fingerprinting, par exemple) mais ils seront aussi plus difficiles à traverser pour des services comme SIP ou SCTP. La règle traditionnelle s'applique ici : les progrès de la sécurité se font presque toujours au détriment de la facilité d'usage. Notre RFC détaille les contre-mesures possibles mais il n'en existe aucune de miraculeuse. La machine derrière le NAT ne doit donc pas se sentir en complète sécurité.
À défaut de cacher les machines, peut-on cacher la topologie du réseau (section 2.4.2) ? Là encore, l'étude indique un résultat mitigé. On peut dans une certaine mesure rendre l'analyse du réseau interne plus difficile mais on ne peut pas la rendre impossible et ces améliorations de la dissimulation seront presque toujours au détriment des usages du réseau. Bref, comme le résume la section 2.4.3, le NAT fournit davantage une sécurité perçue qu'une sécurité réelle. Et les vrais gains de sécurité seront obtenus en empêchant les techniques de traversée de NAT comme STUN, ce qui diminuera l'utilité du réseau.
La deuxième propriété du NAT qui peut sembler augmenter la sécurité est l'impossibilité de faire une connexion depuis l'extérieur vers une machine NATtée (section 2.5). En fait, cette propriété n'a rien de spécifique au NAT : tout pare-feu à états en fait autant et il n'y a pas besoin du NAT pour avoir ce résultat.
Une fois examinées les bonnes (et moins bonnes) raisons de faire du NAT, même en IPv6, la section 3 de notre RFC prend de la hauteur et essaie de voir quelles sont les conséquences architecturales du NAT. Il n'y a pas de doute que le NAT a des avantages : si les gens le déploient, c'est bien qu'ils y trouvent des bénéfices. La vraie question est donc plutôt « Quel est le coût à payer, notamment pour les autres ? ». Le RFC ne mentionne pas cet exemple mais, aujourd'hui, le déploiement massif des NAT est payé essentiellement par les développeurs d'application (qui doivent consacrer beaucoup d'efforts et une grande partie de leur code réseau à contourner les NAT, à l'aide de solutions comme TURN - RFC 5766) et par les utilisateurs (dont certaines applications marchent ou ne marchent pas selon le spécificités du système NAT rencontré). L'administrateur réseaux qui déploie le NAT pour se faciliter la vie transmet donc les coûts à d'autres. Les RFC 2993 et RFC 4924 discutent plus en détail ce point.
Donc, avant de décider de normaliser un service de NAT, il ne faut pas seulement considérer les avantages perçus par ceux qui les déploient (la section 2 couvrait ces avantages) mais aussi les conséquences globales. Le principe (qui est au cœur de l'architecture de l'Internet) est que deux machines qui veulent se parler (le pare-feu peut donc légitimement filtrer le trafic qu'on ne veut pas) doivent pouvoir le faire sans se soucier du NAT, c'est-à-dire sans avoir à déployer des solutions complexes comme ICE - RFC 5245. Le programmeur, au lieu de consacrer l'essentiel de son code à contourner les NAT, devrait pouvoir tenir pour acquise une connectivité de bout en bout. Des techniques comme la référence (j'indique l'adresse IP à laquelle la suite du trafic doit être envoyé) sont triviales avec l'architecture normale de l'Internet et cauchemardesques avec les NAT.
Bref, l'objectif est que le système NAT, s'il existe, n'aie un effet que purement local et pas, comme actuellement, des conséquences pour tous les utilisateurs. Est-ce possible ?
La section 4 regroupe les solutions qui permettent d'atteindre les avantages cités plus haut (notamment le multihoming et la non-nécessité de renuméroter) en trois classes :
Maintenant, place à la conclusion. La section 4.1 résume les pensées de l'IAB : le NAT est une mauvaise idée, car il est très difficilement compatible avec la transparence du réseau (RFC 4924), celle-ci étant la clé du succès de l'Internet. Mais certains problèmes (comme le Multihoming) ne sont pas encore traités par l'IETF. Il ne suffit donc pas de dire que le NAT est négatif, il faut encore travailler à fournir des solutions pour les problèmes qu'il semble traiter. Dans tous les cas, toute évaluation d'une nouvelle norme (que ce soit du NAT ou pas) devrait se faire en priorité sur le critère de la transparence du réseau aux applications.
Première rédaction de cet article le 15 Juillet 2010
À la réunion de Maastricht de l'IETF, le 28 juillet, un sujet brûlant sera discuté, le DNS aliasing ou la synchronisation de domaines.
Quel est le problème à résoudre ? Eh bien justement, une bonne partie de la difficulté est qu'on ne sait pas trop. Pour la convocation de la réunion du 28, Andrew Sullivan a fait un résumé de la situation. Avant de voir l'état actuel de la discussion, prenons un peu de hauteur sur cette question.
Le DNS fonctionne en comparant des
noms de domaine. Si on
interroge un serveur DNS faisant autorité en lui demandant des
informations sur www.france.fr, il va chercher si
ce nom est dans sa base et répondre si c'est le cas. La norme du DNS
(RFC 1034, section 3.1) précise que cette
recherche se fait de manière insensible à la casse donc on aurait pu demander
Www.France.FR et avoir le même résultat. À part
l'insensibilité à la casse, le serveur n'essaie pas de faire des
recherches approximatives, de trouver un nom « ressemblant ». Il
fonctionne de manière littérale.
Mais, parfois, les humains trouvent que c'est trop littéral et
voudraient que deux noms « identiques » (pour eux) soient reconnus
comme tels par le DNS. Par exemple, un français qui tape
www.saint-ennemond.fr s'attend peut-être à ce que
www.st-ennemond.fr (une abréviation courante)
lui donne le même résultat (le site Web de la commune). Bien sûr, les
informaticiens riront de sa naïveté mais sa demande que les deux noms
soient « aliasés » ou « synchrones » est tout à
fait raisonnable. De même un australien trouvera peut-être que
theatre.com (orthographe anglaise) et
theater.com (orthographe états-unienne) devraient
être « le même domaine ». Bien sûr, les IDN
fournissent encore d'autres possibilités d'« égalité » entre noms. Si
Unicode ne fournit que des équivalences
simples, via ses algorithmes
de canonicalisation, cela laisse bien des cas où un humain
voudrait des équivalences que ne fournit pas Unicode. Un exemple
typique est la différence entre les TLD
.台灣 et
.台湾 (Taïwan,
en sinogrammes traditionnels et
simplifiés).
On le voit, déterminer que deux noms sont « équivalents » n'est pas faisable par un algorithme. Alors, simplifions le problème. Supposons que des humains aient déterminé par un processus quelconque que deux noms sont équivalents et que les domaines qu'ils représentent devraient être « synchronisés ». Existe t-il un moyen technique de le faire ? Et, si non,l'IETF doit-elle en développer un ?
D'abord, et c'est une grande partie de la difficulté, il faut
déterminer ce que veut dire « synchronisés ». Une définition forte
serait « Si A.example et
B.example sont synchronisés, l'utilisateur doit
voir exactement la même chose s'il utilise un nom ou l'autre ». Avec
une telle définition, il n'y a pas de solution DNS au problème
puisque, par exemple, si l'utilisateur se sert d'un
navigateur Web, le résultat dépendra aussi de
la configuration du serveur HTTP (directives
ServerName et ServerAlias
sur Apache). (Merci à John Levine pour ses
bonnes explications sur ce point. On les trouve aussi dans les commentaires
d'EURID au plan ICANN, dont je parle plus loin.)
Avec une définition plus limitée, « Si A.example et
B.example sont synchronisés,
nimportequoi.A.example et
nimportequoi.B.example doivent avoir les mêmes
enregistrements DNS », on s'approche d'un problème soluble. Comment
atteindre ce résultat dans le DNS aujourd'hui ?
La première solution est la plus simple : ne pas compter sur le DNS mais simplement résoudre le problème au niveau de l'avitaillement : si on délègue les deux domaines à la même organisation, celle-ci peut s'assurer que les deux domaines restent « synchronisés ». C'est d'ailleurs ce qui est fait pour les deux TLD IDN de Taïwan cités plus haut, tous les deux délégués à TWNIC. La principale limite de cette méthode est qu'elle ne garantit pas la synchronisation : tout dépend en effet de la politique du titulaire des deux domaines.
La seconde idée est d'utiliser les enregistrements CNAME par exemple dans un
fichier de zone de .example :
B.example. IN CNAME A.example.
mais cela ne gère que le domaine A.example, pas
ses sous-domaines. Et avec les plus récents DNAME du RFC 2672 ? Essayons :
B.example. IN DNAME A.example.
Cette fois, c'est le problème inverse, seuls les sous-domaines sont « aliasés ». Le problème a été bien illustré par Ondřej Surý dans son excellent exposé de synthèse à la réunion CENTR/OARC de Prague le 2 mai 2010 : il n'existe pas de solution idéale, sauf à combiner CNAME et DNAME, ou bien à créer un nouveau type qui combine leurs deux rôles, tel le BNAME proposé J. Yao ou encore un système de réplication comme le SHADOW proposé par Paul Vixie.
Bon, mais, finalement, puisque tout cela est bien compliqué, fallait-il vraiment faire quelque chose ? Mais il faut savoir qu'il y a un contexte politique. Le 22 mars, l'ICANN avait annoncé son plan pour les TLD synchronisés et, bien que ce plan n'imposait pas forcément une solution technique, il a suscité beaucoup de discussions à l'IETF. (Les commentaires de ce plan sont en ligne, notez celui de l'IETF.) L'ICANN a annoncé des positions contradictoires (en faveur d'une solution technique ou bien contre cette idée).
Sur la partie politique, voir aussi la FAQ de l'ICANN. Sur la partie technique, les Internet-Drafts à lire sont :
Date de publication du RFC : Juillet 2010
Auteur(s) du RFC : A.Melnikov (Isode), T. Martin
(BeThereBeSquare)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF sieve
Première rédaction de cet article le 14 Juillet 2010
Le langage de filtrage du courrier Sieve permet d'écrire des scripts décrivant les actions à effectuer automatiquement en fonction du contenu d'un message électronique. Ces scripts peuvent évidemment être édités avec vi directement sur le serveur mais, très souvent, les utilisateurs de Sieve n'ont pas la possibilité de se connecter directement audit serveur. Ce RFC normalise donc un protocole, ManageSieve, qui permet de mettre à jour des scripts Sieve sur le serveur.
Comme résumé en sections 1.2 et 1.3, ManageSieve est un protocole texte, orienté ligne, analogue à de nombreux autres protocoles IETF comme IMAP. Le client ManageSieve se connecte au serveur, s'authentifie, envoie des commandes et le serveur répond par des codes (section 1.4) indiquant le succès ou l'échec de la commande.
Voici un exemple de session où les lignes préfixées par
C: sont envoyées par le client et celles
préfixées par S: sont les réponses du serveur :
S: "IMPLEMENTATION" "Example ManageSieved v001"
S: "SIEVE" "fileinto vacation"
S: "SASL" "PLAIN"
S: "STARTTLS"
S: "VERSION" "1.0"
S: "LANGUAGE" "fr"
S: OK
C: Authenticate "PLAIN" "QJIrweAPyo6Q1T9xy"
S: OK
C: Putscript "mysievescript" {110+}
C: require ["fileinto"];
C:
C: if envelope :contains "to" "tmartin+sent" {
C: fileinto "INBOX.sent";
C: }
S: OK
L'utilisateur s'est authentifié, puis a déposé un script Sieve
nommé mysievescript.
Une notion importante du protocole ManageSieve est celle de
script actif (section 1.5). ManageSieve permet de déposer
plusieurs scripts sur le serveur, chacun identifié par un nom (les
noms sont décrits en section 1.7, ils peuvent être pratiquement n'importe quelle
chaîne Unicode) mais un
seul est script actif (est réellement exécuté lors de la délivrance du
courrier). La commande SETACTIVE (section 2.8)
sert à rendre un script actif.
Comme la plupart des protocoles, ManageSieve impose un certain
nombre de fonctions qui doivent être mises en
œuvre, et d'autres qui sont
optionnelles (section 1.8). Un serveur ManageSieve annonce ces
capacités à l'établissement de la connexion et
en réponse à la commande
CAPABILITY (section 2.4). Parmi elles, la possibilité de
protéger la session par TLS (obligatoire), la liste des
extensions Sieve acceptées (obligatoire), la langue utilisée pour les
messages d'erreur (optionnelle), etc.
ManageSieve fonctionne sur TCP (section
1.9), le port par défaut étant 4190 (attention, pendant longtemps, c'était le 2000 et plusieurs logiciels ont encore cela par défaut). L'adresse IP du serveur est
trouvée en résolvant d'abord les enregistrements
SRV _sieve._tcp.$DOMAIN
et, si le SRV n'existe pas, en essayant directement une adresse liée
au nom de domaine.
La liste complète des commandes possibles figure en section 2. Deux examples :
PUTSCRIPT (section 2.6) permet de déposer
un script en lui donnant un nom. À noter que le serveur
doit tester la validité syntaxique du script
avant de l'enregistrer.LISTSCRIPTS (section 2.7) qui donne la
liste des scripts Sieve déposés, en indiquant lequel est actif.On peut désigner un serveur ManageSieve, ou bien un script sur un
serveur, avec un URL (section 3). Un exemple
est sieve://example.net/durand/mon-script qui
identifie le script mon-script de l'utilisateur
durand sur le serveur ManageSieve du domaine example.net.
Bien que le RFC vienne de paraître, ManageSieve est un ancien
protocole et est déjà mis en œuvre, côté client dans SquirrelMail,
Emacs, un simple script Perl, les programmes sieve-connect et sieveshell de Cyrus et, côté serveur, dans
Archiveopteryx,
Dovecot, Cyrus (programme timsieved)... Il
existe aussi un serveur semi-autonome en Python, pysieved. Sur la question
générale du filtrage du courrier, on peut consulter l'article « Filtres
côté serveur ».
Première rédaction de cet article le 11 Juillet 2010
Si je paie, très cher, un « expert en référencement » ou « consultant SEO » qui me raconte que mon site Web sera mieux placé dans les résultats de Google grâce à lui, est-ce plus efficace et plus scientifique, que de sacrifier un coq par une nuit de pleine lune ?
Date de publication du RFC : Juillet 2010
Auteur(s) du RFC : V.Dolmatov (Cryptocom)
Chemin des normes
Première rédaction de cet article le 10 Juillet 2010
L'algorithme de signature russe GOST R 34.10-2001 ayant été spécifié en anglais dans le RFC 5832, plus rien ne s'opposait à son utilisation dans DNSSEC. Ce RFC marque donc l'arrivée d'un nouvel algorithme dans les enregistrements DNSSEC, algorithme portant le numéro 12.
La liste originelle des algorithmes DNSSEC figurait dans le RFC 4034, annexe A.1. La liste actuelle est un
registre à l'IANA, http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml#dns-sec-alg-numbers-1. Elle
comprend désormais GOST. Notez que GOST désigne
en fait une organisation de normalisation, le terme correcte serait
plutôt « GOST R 34.10-2001 » pour l'algorithme de signature et « GOST R 34.11-94 »
pour celui de hachage, décrit dans le RFC 5831
(voir la section 1 de notre RFC 5933).
La section 2 décrit le format des enregistrements
DNSKEY avec GOST, dans
lequel on publie les clés GOST R 34.10-2001. Le champ
Algorithme vaut 12, le format de la clé sur le réseau suit le RFC 4491. GOST est un algorithme à courbes
elliptiques, courbes décrites par Q = (x,y). Les 32
premiers octets de la clé sont x et les 32 suivants y (en
petit-boutien, attention, contrairement à la
majorité des protocoles Internet). Les autres paramètres de la clé
figurent dans le RFC 4357.
Les bibliothèques cryptographiques existantes sont parfois capables de lire des clés GOST (section 2.1). Pour OpenSSL, il existe une distribution de GOST (par la même entreprise où travaille l'auteur des RFC GOST).
La section 2.2 donne un exemple de clé GOST publiée dans le DNS mais autant utiliser ici un exemple réel :
% dig DNSKEY m-system.net ; <<>> DiG 9.6-ESV-R1 <<>> DNSKEY m-system.net ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43317 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;m-system.net. IN DNSKEY ;; ANSWER SECTION: m-system.net. 86400 IN DNSKEY 257 3 12 BDtDa2UxLe7cdDs9bX/X1Y/UXuhJnDrGDRuVQW0BBo8QF1Pr959WBI5Q ylNxyKp9Rm4yslb1hj4BQUEUWpOLWw== m-system.net. 86400 IN DNSKEY 256 3 12 vvJWsxH3J5IZ6YEcG1C+MaYGX/YwzIeFoIXgUOuGHx/fvet0SJefkPE0 il40Sm4T4y5aYN8vyZLQgtJYiCYIbQ== ;; Query time: 159 msec ;; SERVER: ::1#53(::1) ;; WHEN: Mon Jun 28 08:59:27 2010 ;; MSG SIZE rcvd: 201
La section 3 décrit le format des enregistrements
RRSIG, les signatures. On
suit les RFC 4490 et RFC 4357. Voici un exemple
actuellement présent dans le DNS :
% dig +dnssec MX m-system.net ; <<>> DiG 9.6-ESV-R1 <<>> +dnssec MX m-system.net ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56828 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 3, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ;; QUESTION SECTION: ;m-system.net. IN MX ;; ANSWER SECTION: m-system.net. 86400 IN MX 10 mail.m-system.net. m-system.net. 86400 IN RRSIG MX 12 2 86400 20100723062450 20100623062450 64666 m-system.net. kfb73QrBWmzQb8p+E25Xkx5NlqqnmzKCrhCj4g97n0VEX08VVBU/zZHB MTUzm2YYwu5r2pVTmUzLc97Xi/T/Rg== ;; AUTHORITY SECTION: m-system.net. 86400 IN NS ns.cplire.ru. m-system.net. 86400 IN NS step.reedcat.net. m-system.net. 86400 IN RRSIG NS 12 2 86400 20100723062450 20100623062450 64666 m-system.net. YQ+taRLlgemXVk6ByN+UwYVoC8cqsrO2VPxt/4WNpX3kQ3OVqStQaquQ ES8sB3YxTLKLO3wC6pt+2i5D90MGMQ== ;; Query time: 219 msec ;; SERVER: ::1#53(::1) ;; WHEN: Mon Jun 28 08:58:57 2010 ;; MSG SIZE rcvd: 331
Attention, une particularité de GOST fait que deux signatures des mêmes données peuvent donner des résultats différents, car un élément aléatoire est présent dans la signature.
La section 4 décrit le format des enregistrements
DS pour GOST. La clé
publique de la zone fille est condensée par GOST R 34.11_94,
algorithme de numéro 3. Je n'ai pas trouvé de DS GOST dans la
nature mais voici l'exemple du RFC, pour la clé 6204 :
example.net. 3600 IN DS 6204 12 3 (
0E6D6CB303F89DBCF614DA6E21984F7A62D08BDD0A05B3A22CC63D1B
553BC61E )
Les sections 5 et 6 couvrent des questions pratiques liées au développement et au déploiement de systèmes GOST, par exemple un rappel sur la taille de la clé (512 bits) et sur celle du condensat cryptographique (256 bits).
GOST peut se valider avec Unbound (au moins depuis la version 1.4.4,
voir l'option de compilation --enable-gost) mais
pas (encore ?) avec BIND. On peut trouver des
conseils pratiques pour l'utilisation de GOST en anglais à http://www.cryptocom.ru/dns/dnssec-cryptocom-en.html.
Date de publication du RFC : Juillet 2010
Auteur(s) du RFC : F. Gont (UTN/FRH)
Pour information
Réalisé dans le cadre du groupe de travail IETF tcpm
Première rédaction de cet article le 7 Juillet 2010
Vous voulez tout savoir sur les attaques qu'on peut perpétrer avec le protocole ICMP contre le protocole de couche 4 TCP ? Ce RFC est pour vous. Il documente les différents mécanismes par lesquels une session TCP, même protégée, peut être attaquée via le protocole de signalisation. Il ne fournit pas de solutions absolues mais documente quelques modifications dans les mises en œuvre de TCP qui peuvent réduire la gravité du problème.
D'où vient le problème ? ICMP (RFC 792) est le protocole de signalisation d'IP et permet d'informer les machines qu'un paquet n'a pas pu être transmis ou bien que le trafic est trop intense. Mais ICMP n'a aucun mécanisme de validation (sauf si on encapsule tout dans IPsec) et il est trivial pour un méchant de fabriquer un faux paquet ICMP et de l'envoyer aux machines qu'il veut attaquer. Le méchant n'a même pas besoin d'espionner le réseau visé (alors que la fabrication d'un faux paquet TCP impose de connaitre un numéro de séquence valide, ce qui est très difficile si on en peut pas lire les paquets échangés), ces attaques sont donc faisables sans qu'on soit sur le chemin attaqué (off-path). Le problème est connu depuis longtemps mais ne semble pas avoir jamais été documenté dans un RFC, avec les contre-mesures possibles (section 1 du RFC). Certaines recommandations apparaissent toutefois dans des documents comme le RFC 4907.
Notre RFC 5927 fait ce travail de documentation et suggère des solutions pour limiter les dégâts, sans modifier le protocole TCP lui-même (bien que, parfois, ces solutions sont aux limites de ce que permet le RFC 793), ce qui est conforme aux règles prudentes du groupe de travail IETF tcpm, qui s'interdit de changer le protocole.
La section 2 de notre RFC rappelle ICMP pour les lecteurs débutants. ICMP sert à signaler les problèmes rencontrés par un paquet lors de sa traversée du réseau (cf. RFC 816). Le message ICMP est typiquement émis par un routeur présent sur le trajet et son adresse IP source n'est donc pas forcément celle de la machine avec laquelle on voulait communiquer. Rien ne garantit que le message ICMP arrive bien : comme tout paquet IP, il peut être filtré, victime de la congestion ou, ce qui est fréquent de nos jours, jamais émis en raison du rate limiting, fréquemment configuré sur les routeurs IP, pour éviter qu'ils ne soient DoSés par l'émission de paquets ICMP. TCP ne peut donc pas compter uniquement sur ICMP pour signaler les problèmes, il doit aussi se débrouiller seul, ICMP accélerant simplement la détection des ennuis. ICMP pour IPv4 est normalisé dans le RFC 792. Il fournit plusieurs types de messages d'erreur que le RFC 1122 a ultérieurement classé en erreurs dures et erreurs douces. Plusieurs protocoles ont été développés en utilisant ICMP dont le plus connu est la découverte de la MTU, dans le RFC 1191. ICMP pour IPv6 est dans le RFC 4443 et, si les codes sont légèrement différents de ceux de IPv4, les principes sont les mêmes. Enfin, il existe des extensions à ICMP comme les messages structurés du RFC 4884.
Le RFC 4301 comprend une annexe D qui étudie en détail ICMP, dans le contexte de la sécurité (voir aussi la section 2.3 de notre RFC). Car, officiellement, les anciens RFC comme le RFC 1122 (dans sa section 4.2.3.9) imposaient aux machines connectés à l'Internet de réagir à certains messages ICMP, sans tenir compte du fait que ces messages ne sont pas authentifiés et sans parler de validation, même sommaire. On peut dire que TCP faisait autrefois une confiance aveugle à ICMP (section 2.2).
Cette confiance n'était pas vraiment justifiée. Comme le rappelle la même section, un attaquant peut facilement fabriquer un paquet ICMP vraisemblable, il suffit de connaître les adresses IP source et destination, ainsi que les ports source et destination. Comme expliqué dans des documents comme le RFC 4953, trouver ces quatre chiffres est parfois assez facile. Par exemple, dans le cas d'une connexion BGP sur un point d'échange, les adresses IP des deux pairs sont en général publiques, l'un des ports est le port bien connu de BGP, 179 et l'autre ne peut prendre que 65536 valeurs possibles (moins que cela, en pratique). Un attaquant, même non situé sur le réseau visé, peut donc créer un paquet ICMP qui a de bonnes chances d'être accepté (le plus simple étant de générer les 65536 paquets possibles...)
Bref, il ne faut pas faire confiance à ICMP, comme documenté dans le RFC 4907. Mais l'équilibre est difficile à trouver : si on ignore tous les paquets ICMP, on ne sera averti que très tard des problèmes sur le réseau, lorsque les délais de garde expireront. Si on les accepte tous, on s'expose à de sérieuses DoS. L'idéal est donc que la politique d'acceptation soit réglable.
Le RFC décrit les attaques ICMP possibles après l'analyse des solutions. Mais il me semble plus logique de faire l'inverse et de continuer avec les sections 5, 6 et 7. La section 5 décrit l'attaque de réinitialisation de la connexion en aveugle (blind connection-reset attack). Elle consiste à envoyer un paquet ICMP de type « erreur dure » par exemple type 3 (Destination Unreachable) avec les codes 2 à 4 (protocol unreachable, port unreachable et fragmentation needed and DF bit set). Selon le RFC 1122, TCP devrait alors couper la connexion (notez que les sections 3.2.2.1 et 4.2.3.9 du RFC 1122 se contredisent...) On a donc avec cette attaque un bon moyen de faire un déni de service sans même avoir besoin d'être situé sur le chemin des paquets (d'où le terme d'attaque en aveugle). Pire, certaines mises en œuvre de TCP/IP coupent non seulement la connexion TCP en cause mais aussi toutes celles avec la même machine. D'autre part, il faut bien se rappeler que l'attaque, étant en ICMP, ne dépend pas de la capacité de l'attaquant à fabriquer des paquets TCP et qu'elle marche donc même si la connexion TCP est protégée par des techniques comme le TCP-AO du RFC 5925.
Alors, quelles sont les solutions contre l'attaque de réinitialisation de la connexion ? La section 5.2 les décrit : compte-tenu du fait qu'un code protocol unreachable et même, dans une large mesure port unreachable n'a de sens qu'au début d'une connexion, la recommandation est d'ignorer ces paquets ICMP une fois la connexion établie. Par un raisonnement similaire, les codes fragmentation needed and DF bit set peuvent être ignorés ou plus exactement considérés comme des erreurs douces. Donc, pour résumer, sauf pour les connexions en cours d'établissement, traiter les erreurs dures comme des erreurs douces supprime l'attaque par réinitialisation. Cela a certes des inconvénients (les vrais problèmes seront détectés moins rapidement) mais rien n'est parfait dans le monde cruel de la sécurité. La robustesse de TCP étant la principale motivation pour son utilisation, le compromis semble raisonnable. À noter qu'il est mis en œuvre dans FreeBSD, NetBSD et Linux depuis de nombreuses années. Notre RFC ne fait que le documenter.
Autre attaque possible en ICMP, moins radicale, la réduction de
débit en aveugle (blind throughput reduction,
section 6. Elle consiste pour l'attaquant à envoyer des paquets ICMP
de type 4 (répression de l'envoi, source
quench). TCP devait réagir en ralentissant le débit, voire
en reprenant comme si la connexion était neuve, avec une fenêtre
d'envoi de petite taille. Là encore, l'attaque est connue depuis
longtemps et, comme toutes les études ont montré que la répression de
l'envoi était une mauvaise technique de contrôle de la congestion
(cf. RFC 1812), les
implémentations de TCP ignorent depuis longtemps ces paquets ICMP,
préférant les mécanismes purement TCP (RFC 5681, RFC 3168), même si c'était formellement une violation de la
norme. Dans le noyau Linux (net/ipv4/tcp_ipv4.c) :
case ICMP_SOURCE_QUENCH: /* Just silently ignore these. */ goto out;
Autre moyen de diminuer les performances, l'attaque contre la découverte de MTU en aveugle (blind performance-degrading attack, section 7). Si l'une des deux machines connectées en TCP met en œuvre l'algorithme PMTUD du RFC 1981 pour découvrir la MTU du chemin, des faux paquets ICMP peuvent la tromper et lui faire adopter une MTU sous-optimale. Si l'attaquant envoie des paquets ICMP de code 3 et de type 4 (fragmentation needed and DF bit set), indiquant une MTU de petite taille, la machine naïve va réduire la taille des paquets qu'elle envoie, s'empêchant ainsi de tirer profit à fond du réseau (les paquets plus petits sont moins efficaces car la part relative des en-têtes augmente et le « coût » par octet augmente puisque le coût de traitement dépend davantage du nombre de paquets que du nombre d'octets).
Si la machine utilise l'algorithme PMTUD, elle ne peut pas ignorer ces paquets ICMP. Que peut-elle alors faire ? Une solution évidente est d'abandonner PMTUD au profit du RFC 4821. Une autre solution moins radicale, mise en œuvre dans NetBSD, est d'ignorer ces paquets ICMP uniquement si la connexion progresse (si les octets envoyés font l'objet d'accusés de réception) et d'en tenir compte si les octets ne passent plus (ce qui peut indiquer effectivement un endroit où la MTU a baissé). Cette contre-mesure est décrite en grand détail dans la section 7.3.
Bon, tout cela n'est pas satisfaisant. Existe t-il une solution à ce problème de la vulnérabilité d'ICMP ? La section 3 expose d'abord les contraintes auxsquelles doit obéir une solution. Comme le paquet ICMP d'erreur ne contient qu'une partie du paquet original (en IPv4, l'en-tête IP, plus 8 octets), le processus qui va prendre la décision d'accepter ou de refuser le paquet ICMP n'a qu'une information limitée. Le RFC 1122 a autorisé les routeurs à envoyer davantage que ces malheureux huit octets mais ce n'est pas forcément ce qu'ils font. Le RFC 1812 est même plus gourmand en suggérant , pour les routeurs, d'utiliser un paquet de taille totale 576 octets. Pour les machines non-routeuses, il n'y a pas de telle recommandation. (IPv6 offre plus de place dans un paquet sans fragmentation et donc offre davantage d'information.) Avec les huit octets, on a tout juste les deux numéros de port (source et destination) et le numéro de séquence.
Ainsi, même si TCP signait ses segments avec le RFC 2385, l'information contenue dans les paquets ICMP d'erreur ne permettrait pas de valider cette signature. IPsec permettrait d'authenfifier les paquets ICMP envoyés par la machine avec laquelle on correspond mais pas forcément ceux des routeurs intermédiaires. Aujourd'hui, vu l'état du déploiement d'IPsec, cette perspective est tout à fait utopique.
La section 4 fournit des idées générales sur les contre-mesures à adopter pour résister à ces attaques. Par exemple, un test évident mais qui n'avait pas été prévu à l'origine, est de vérifier, en utilisant le numéro de séquence TCP contenu dans le message ICMP suspect, s'il correspond à des données actuellement en transit (envoyées mais qui n'ont pas fait l'objet d'un accusé de réception). Un tel test rend très difficile la tâche de l'assaillant, qui doit désormais trouver un numéro de séquence valide. Là encore, tous les Unix libres font ce test depuis longtemps. Évidemment, si l'attaquant peut espionner le réseau (s'il est on-path), trouver un tel numéro est trivial. D'autre part, les connexions TCP à haut débit, utilisant de grandes fenêtres (RFC 1323) restent vulnérables car un plus grand pourcentage de l'espace des numéros de séquence est valide, à un moment donné. Enfin, ce test a à la fois des faux positifs (paquets ICMP légitimes mais arrivant en retard, une fois les données réceptionnées) et des faux négatifs (assaillant chanceux). Ai-je déjà dit qu'il n'existe jamais de solution de sécurité parfaite ?
Autre mesure, l'aléatoirisation du port source (section 4.2). L'attaquant devant deviner le port source, si celui-ci est prévisible (machine allouant les ports sources séquentiellement...), on lui facilite la tâche.
Dernière contre-mesure générique, commune à toutes les attaques
ICMP : les pare-feux pourraient regarder dans
les paquets ICMP l'adresse source du paquet TCP qui a déclenché
l'erreur et jeter le paquet ICMP si cette adresse source ne correspond
pas à une machine du réseau interne (section 4.3). En effet, si un méchant situé sur
le réseau 192.0.2.128/25 veut attaquer la machine
203.0.113.2, il va émettre un faux paquet ICMP
qui porte soi-disant sur un message envoyé par
203.0.113.2. Le pare-feu du réseau utilisé par le
méchant peut donc voir que ce message est illégitime, puisque
203.0.113.2 n'est pas sur son site. Idem si un
attaquant externe tente de perturber des connexions TCP entre machines
internes. L'article de l'auteur du RFC, « Filtering
of ICMP error messages » donne d'autres exemples. Le
pare-feu d'OpenBSD met en œuvre cette
technique.
Ah, et si vous voulez tester ces attaques vous-même, le code est disponible sur le site Web de l'auteur. Si vous voulez uniquement approfondir votre compréhension de la sécurité de TCP, une lecture recommandeé est « CPNI technical note 3/2009 - Security assessment of the Transmission Control Protocol (TCP) ».
Première rédaction de cet article le 4 Juillet 2010
Le DNS est à la base de la plupart des transactions sur Internet. Presque toutes commencent en effet par une requête DNS. Par exemple si vous récupérez un fichier via BitTorrent (dont on pourrait penser qu'il n'utilise pas le DNS), le tracker est souvent trouvé via une URL donc via le DNS. Même si vous utilisez un système récent, tracker-less (celui-ci étant remplacé par une DHT), vous avez probablement trouvé les coordonnées du fichier qui vous intéressait via le Web donc via le DNS. Bref, si le DNS est en panne, il n'y a presque plus rien qui marche. Pourtant, à une époque, l'Internet fonctionnait sans le DNS. Comment s'est faite la transition ? Qu'est-ce qu'il y avait avant ?
Vue l'énorme quantité d'articles soi-disant historiques de vulgarisation sur les origines du DNS, vue la quantité de bêtises journalistiques qui ont été écrites sur ce sujet, il peut sembler difficile de remonter aux vraies origines et de trouver ce qui s'est passé. Pourtant, la plupart des acteurs de ce changement sont encore vivants et beaucoup ont documenté leurs efforts.
Commençons par les pères du DNS eux-même. Paul Mockapetris et Kevin Dunlap ont documenté les débuts de ce protocole en 1988, dans « Development of the Domain Name System » (le fichier PDF en question est une numérisation de l'original papier, il ne semble pas que la forme numérique originale aie été conservée).
Tout commença, racontent les auteurs, en
1982, lorsque l'ancien système de nommage,
HOSTS.TXT (qui était
spécifié dans le RFC 608), montrait trop
clairement ses limites, avec l'augmentation de taille de
l'Internet. Plusieurs candidats avaient été envisagés pour son
remplacement comme IEN 116
ou comme le système
Grapevine de Xerox. Le
premier était jugé trop simple, le second beaucoup trop compliqué (il
essayait de tout faire, contrairement à la méthode qui a assuré le
succès de l'Internet, faire des systèmes simples qui assurent 95 % des
fonctions, sans chercher à tout résoudre). Une curiosité : dans Grapevine, les noms étaient
hiérarchiques, comme dans le DNS, mais le nombre de niveaux était fixe
(alors qu'un nom de domaine peut avoir un seul composant - par exemple
dk, deux, trois, ou plus - par exemple
ns1.dnsar.ati.tn). Le travail commença donc sur
le protocole DNS. (Cela n'apparait pas dans l'article mais, oralement,
Paul Mockapetris raconte qu'il avait hérité de cette tâche car il
était le plus débutant et que ce service DNS n'était pas considéré
comme essentiel.) Et c'est là qu'on dispose d'une autre source, les
fameux RFC puisque tous ont été conservés
(parfois sous forme papier, nécessitant une renumérisation). Le DNS
est donc né officiellement avec les RFC 882 et RFC 883 (la norme actuelle figure dans les RFC 1034 et RFC 1035).
Il semble que ce soit vers 1985 que certaines machines commencèrent à n'utiliser que le DNS pour accéder à l'information. (Je me souviens bien qu'au début des années 1990, il était fréquent que des documents comme les FAQ indiquent les adresses IP des serveurs cités, car certains « vieux de la vieille » n'avaient pas confiance dans le DNS qui, il est vrai, n'avait pas toujours la fiabilité d'aujourd'hui.)
L'article de Mockapetris et Dunlap détaille ensuite les principes
fondateurs du DNS : nommage hiérarchique, compromis entre la
simplicité et les demandes de certains enthousiastes qui voulaient en
faire une vraie base de données distribuée, absence de sémantique dans
les noms (un serveur SMTP n'est pas forcé de
s'appeler smtp.example.net et on ne peut pas
savoir, juste en regardant un nom, où sont les frontières des
zones).
Parmi les choix qui se présentaient aux auteurs du nouveau
protocole, la détermination du niveau de souplesse nécessaire. Il
était prévu que d'autres acteurs que le monde Internet utilisent le
nouveau protocole, ce qui avait mené à l'introduction des
classes. Il y avait même l'idée qu'il y aurait
une classe ISO alors que, finalement, le projet
OSI avait développé sa propre usine à gaz,
X.500, qui a sombré avec le reste de ce
projet. Aujourd'hui, les classes continuent à utiliser deux octets
dans chaque enregistrement DNS, sans servir à rien (et il est probable
que la plupart des logiciels seraient très déroutés par d'autres
classes que la classe IN, contrairement à ce que
pensaient les promoteurs de Net4D).
La fin de l'article décrit le déploiement du DNS en 1988. Le RFC 1031 contenait une liste des mises en œuvre du DNS (les
deux plus importantes étant BIND, toujours là,
et Jeeves, bien oublié). À ce moment, HOSTS.TXT
contenait encore 5 500 noms alors que le DNS en avait... 20 000
(depuis, le comptage est devenu impossible mais il y a certainement
aujourd'hui des centaines de millions de noms).
Une section entière est dédiée aux serveurs de noms de la racine, ceux qui doivent répondre pour tous les noms, en général en renvoyant vers les serveurs du TLD. Ils n'étaient que sept à l'époque (aujourd'hui, il est difficile de donner le nombre exact). Quatre étaient des Unix avec BIND, trois des TOPS-20 avec Jeeves. Le trafic sur un serveur racine atteignait la valeur pharamineuse de... une requête par seconde (aujourd'hui, chaque machine physique voit passer plusieurs milliers, voire dizaines de milliers de requêtes par seconde).
Une fois le protocole défini, il restait une importante décision à prendre, sur le schéma de nommage. Le RFC 920 a été le premier à se pencher sur la question, sur laquelle on peut aussi consulter le passionnant article d'Elizabeth Feinler.
Cela, c'était du protocole et de l'organisation. Et le code ? Il existe d'autres articles sur les premières mises en œuvre du DNS :
Date de publication du RFC : Février 2006
Auteur(s) du RFC : S. Sangli, D. Tappan (Cisco), Y. Rekhter (Juniper)
Chemin des normes
Première rédaction de cet article le 4 Juillet 2010
Depuis 1996, le protocole de routage BGP permet d'étiqueter les routes annoncées avec une ou plusieurs communautés, une suite de chiffres sont la signification dépend en général de l'AS qui l'émet. Ces communautés, normalisées dans le RFC 1997, permettent d'indiquer, par exemple, qu'une route a été initialement apprise à tel point d'échange. Mais elles ont plusieurs limitations et ce RFC normalise donc une version améliorée, les communautés étendues.
Quelles limites des communautés ordinaires sont désormais dépassées (section 1 du RFC) ? QU'apporte notre RFC ? D'abord, une augmentation de taille, qui permet d'encoder davantage de choses. Ensuite, l'ajout d'un champ « Type » qui permet de donner une structure aux communautés. Il autorise également des traitements (comme de filtrer ou, au contraire de laisser passer) appliqués à toutes les communautés d'un type donné (alors que, avec les communautés ordinaires, le traitement doit être spécifié pour chaque communauté, celles-ci n'ayant aucune structure normalisée).
La section 2 décrit notre nouvel attribut BGP, numéro 16, alias « Extended Communities Attribute ». Il comporte huit octets, un ou deux pour le type et le reste pour les données. Pourquoi un nombre variable d'octets pour le type ? Parce qu'il peut y avoir des types ordinaires (un octet) et des types étendus (deux octets). Par exemple, les communautés pour AS de quatre octets, dans le RFC 5668, utilisent les types étendus. En outre, les deux premiers bits du type indiquent des propriétés qui peuvent être comprises même par un routeur qui n'a jamais vu ces communautés de ce type plus tôt. Le premier bit indique le type d'allocation par l'IANA (0 : allocation en « Premier Arrivé, Premier Servi », 1 : allocation plus restrictive). Le second indique si la communauté est transitive ou pas (si elle doit être transmise aux AS voisins ou pas). Ainsi, même sans avoir lu le RFC 5668, un routeur BGP sait que les communautés de type 0x02 sont transitives (puisque le deuxième bit est à zéro, signe de transitivité).
La section 3 passe tout de suite aux applications pratiques en réservant plusieurs types et en décrivant leur structure. La structure des données, elle, dépend en effet du type. Ainsi, la section 3.2 spécifie une communauté attachée à une adresse IPv4. Le type vaut 0x01 (si elle est transitive) ou 0x41, les données contiennent l'adresse (évidemment sur quatre octets) et un champ Local Administrator sur deux octets, qui contient ce que veut l'AS émetteur.
Autre exemple de communauté étendue, les destinataires de routes (section 4) où un routeur qui émet une route indique dans la communauté quels routeurs peuvent recevoir cette annonce (cf. RFC 4364 pour un exemple d'utilisation). Les routeurs acceptés sont indiqués par leur adresse IP. Un mécanisme analogue permet d'indiquer le routeur d'origine (section 5).
L'enregistrement des types possibles se fait dans un registre IANA (cf. section 7). Consulter ce registre permet de voir le grand nombre d'usages de ces communautés étendues. Rappelons que les deux premiers bits indiquent si l'allocation est simplement « Premier Arrivé, Premier Servi » ou plus formelle, et si la communauté est transitive (transmise aux autres AS) ou pas.
À l'heure actuelle, ces communautés étendues semblent rares dans la
nature. Les communautés documentées par les opérateurs (par exemple
par Level 3 ou Cable & Wireless) sont généralement des communautés du type traditionnel. Au passage, un bon outil pour examiner les politiques d'étiquetage par communautés des principaux opérateurs est http://onesc.net/communities/.
Première rédaction de cet article le 30 Juin 2010
En râlant contre un article d'Isabelle Collet dans « Manière de voir », je disais que c'était un peu agaçant qu'on ne cite toujours que les deux mêmes exemples d'informaticienNEs, Ada Lovelace et Grace Hopper. Mentionner toujours les mêmes ne donne pas forcément envie aux filles d'aujourd'hui de faire de l'informatique. Alors, voici quelques exemples de brillantes informaticiennes d'aujourd'hui.
La liste est complètement subjective et basée uniquement sur celles dont j'ai lu ou utilisé le travail. Je cite des femmes qui sont actives en informatique aujourd'hui, pas des disparues comme les deux citées plus haut, pas non plus des femmes qui ont plus ou moins cessé leur activité technique (comme Adele Goldberg, Barbara Liskov ou même Radia Perlman). J'ai essayé de privilégier celles travaillant dans les mondes du logiciel libre et/ou des standards ouverts et qu'on ne cite pas souvent :
Catherine Letondal me recommande le bon article du Wikipédia anglophone « Women in computing ».
Première rédaction de cet article le 29 Juin 2010
Il n'y a plus guère aujourd'hui de vrai FAI pour le particulier ou la petite entreprise, c'est-à-dire de fournisseur qui donnerait accès à l'Internet, pas seulement à un sous-ensemble de celui-ci (par exemple le Web). Ainsi, le filtrage du port 25 en sortie (le port utilisé par le protocole SMTP d'envoi du courrier) est souvent bloqué par défaut, en raison de l'importante quantité de spam envoyé par des zombies. Et le port 53, celui du DNS ?
Il y a bien d'autres violations de la neutralité du réseau par les FAI (cf. RFC 4924). Parfois, d'autres services que le courrier sont interdits (la palme du ridicule à OVH pour son offre d'hébergement où IRC est interdit - apparemment XMPP ou les protocoles de messagerie instantanée fermés ont été oubliés par le juriste d'OVH). Parfois, le client peut ouvrir les ports fermés, le filtrage n'étant que mis par défaut, mais débrayable (c'est le cas, à l'heure actuelle, chez Free avec le port 25, automatiquement et gratuitement).
Jusqu'à présent, l'accès DNS, qui se fait sur le port 53, a toujours été ouvert. Cela risque de changer bientôt. Il y a eu plusieurs alertes (donc certaines se sont révélées être de fausses alertes) comme chez Comcast (voir aussi la discussion sur Slashdot) et il est probable qu'un FAI tentera bientôt de généraliser ce filtrage.
En effet, un document du MAAWG publié en juin 2010, « Overview of DNS security - Port 53 protection » prône ce filtrage. La caution du MAAWG, cartel de gros opérateurs réseau, sera sans doute utilisé comme prétexte. Par contre, pour le client, c'est une mauvaise nouvelle : le MAAWG s'est déjà signalé par ses positions éradicatrices, considérant que le citoyen n'a pas à avoir un accès complet à l'Internet et qu'il faut le forcer à passer par les filtres du fournisseur d'accès. Par exemple, pour le courrier, le MAAWG a toujours prôné, comme approche anti-spam, l'acceptation du courrier uniquement entre gros opérateurs, excluant la réception du courrier envoyé par les serveurs des petits fournisseurs, petites entreprises ou particuliers.
Le titre du rapport du MAAWG est déjà un chef d'œuvre de novlangue, comme de parler de « managing traffic on port 53 » pour dire « interdiction du port 53 ».
Quels sont les arguments du MAAWG ? Que plusieurs logiciels malveillants changent les réglages DNS des machines infectées, pour pointer vers des serveurs DNS contrôlés directement ou indirectement (via un empoisonnement de cache) par un méchant. Bloquer le port 53 forcerait les machines Windows infectées à passer par les résolveurs DNS du FAI, gênant ainsi le logiciel malveillant.
De telles attaques arrivent dans la nature et sont par exemple
documentées dans l'article « Corrupted DNS Resolution Paths: The Rise of a Malicious Resolution Authority
». L'attaquant, via un logiciel malveillant,
change les réglages DNS et le PC de l'utilisateur, sans que ce dernier
s'en rende compte, envoie désormais ses requêtes DNS à un résolveur
géré par le méchant (ou empoisonné par celui-ci). Ce résolveur peut
alors, par exemple, indiquer une fausse adresse IP pour
www.ma-banque.example. Ainsi, l'utilisateur, sans
qu'il y aie eu besoin d'envoyer du spam
prétendument depuis sa banque, peut être dirigé vers un serveur de hameçonnage.
Bien conscient de la restriction de la liberté de choix qui résulte de l'interdiction proposée, le MAAWG propose des exceptions vers les serveurs DNS « bien connus » (legitimate DNS resolvers, sans que cette « légitimité » soit définie). On suppose que cela inclus ceux d'OpenDNS (qui se vante de censurer pour « protéger la famille ») ou de Norton DNS qui affirme mentir sur les réponses DNS pour empêcher l'utilisateur d'aller sur des sites Web dangereux. Est-ce que cela inclura aussi les serveurs de Google DNS, pour lesquels Google s'est engagé à ne pas interférer avec les réponses légitimes ? En tout cas, cette idée d'une « liste blanche » de serveurs officiels est bien dans l'esprit du MAAWG, qui verrait bien l'accès Internet réduit à passer par un petit nombre de fournisseurs. En revanche, le rapport du MAAWG ne mentionne pas une seule fois la possibilité d'opt-out pour le client.
En quoi est-ce un problème de ne pas avoir accès au port 53 ? D'abord, il faut préciser que c'est une restriction du choix : le FAI détermine ce qui est bon pour le client, au lieu de laisser celui-ci se déterminer tout seul. Ensuite, d'un point de vue plus pratique, bloquer le port 53 peut empêcher le client de chercher ailleurs une solution aux dysfonctionnements des résolveurs DNS du FAI, ou à leurs insuffisances (par exemple, chez Free, la moitié des résolveurs ne gère toujours pas EDNS). C'est d'autant plus grave que les défaillances peuvent être volontaires, comme dans le cas des DNS menteurs où le FAI trompe délibérement ses clients. Le rapport du MAAWG mentionne d'ailleurs cette question de manière fort elliptique en indiquant que le bocage du port 53 permet de préserver les revenus provenant de l'exploitation du DNS... (En termes clairs : la publicité sur le site Web vers lequel on redirige les clients.)
Un autre problème du blocage du port 53 concerne DNSSEC. Tant que les résolveurs des FAI ne font pas de validation DNSSEC, la seule solution pour celui qui veut utiliser cette technique de sécurité chez lui est d'installer son propre résolveur (ce qui est très simple aujourd'hui) validant. Le blocage du port 53 empêcherait cela et gênerait donc le déploiement d'une méthode de sécurité intéressante.
À noter que le blocage du port 53 empêcherait immédiatement la technique la plus utilisée aujourd'hui pou contourner les portails captifs de tant d'aéroports et hôtels : le tunnel DNS. Le rapport du MAAWG ne cite pas ce point, sans doute parce qu'il rendrait leurs intentions répressives trop voyantes mais cela a dû compter dans cette recommandation.
Comment savoir si son FAI bloque déjà le port 53 ? Lui demander ne donne jamais aucun résultat (essayez : appelez le support de votre FAI). Lire les CGV a peu de chances de vous apporter des explications claires. Il vaut donc mieux tester. Si, sur une machine Unix, vous pouvez utiliser dig :
% dig @a.nic.fr A www.wikipedia.fr
et récupérer la bonne valeur (une redirection vers les serveurs du domaine de Wikipédia) :
... ;; AUTHORITY SECTION: wikipedia.fr. 172800 IN NS c.dns.gandi.net. wikipedia.fr. 172800 IN NS a.dns.gandi.net. wikipedia.fr. 172800 IN NS b.dns.gandi.net. ...
c'est que vous avez un accès au port 53 : vous pouvez interroger
directement les serveurs faisant autorité. Vous pouvez aussi tester
d'autres TLD que
.fr, bien sûr.
Parfois, le filtrage dépend du contenu. Ainsi, en
Chine, les requêtes DNS sont souvent modifiées
par la censure et il faut donc tester, non seulement avec
www.wikipedia.fr mais également avec des noms
sensibles (en Chine, facebook.com ou
twitter.com). Même si vous avez l'impression que
vous parlez directement au serveur DNS (option @
de dig), des équipements intermédiaires sur le réseau modifient vos
réponses.
Si vous n'avez pas dig, vous pouvez aussi utiliser le service
http://netalyzr.icsi.berkeley.edu/faq.html#nolaunch
(il nécessite Java).
Date de publication du RFC : Juin 2010
Auteur(s) du RFC : Edward Lewis (NeuStar), A. Hoenes (TR-Sys)
Chemin des normes
Réalisé dans le cadre du groupe de travail IETF dnsext
Première rédaction de cet article le 28 Juin 2010
Parmi les protocoles qui forment le socle de l'Internet, une des particularités du DNS est la grande distance entre la norme officielle, vieille désormais de treize ans et jamais révisée intégralement, et la réalité. Celle-ci a nécessité a plusieurs reprises la publication de normes de clarification, détaillant ce que le RFC 1034 avait laissé dans l'ombre. Notre RFC 5936 continue cette tradition pour le cas des transferts de zone où un serveur de noms réclame à un serveur faisant autorité une copie complète de la zone (c'est-à-dire des données DNS). Le principal point vague était le cas où un serveur faisait également autorité pour des zones parentes ou filles de la zone transférée : devait-il tenir compte de ce qu'il avait appris à cette occasion pour « corriger » la zone transférée ? La réponse est clairement désormais non : le serveur doit transférer ce qu'on lui a donné comme contenu de la zone, pas ce qu'il a pu apprendre par ailleurs.
Un peu d'histoire d'abord : le transfert de zones (souvent désigné
par le mnémonique AXFR) était officiellement
normalisé dans des parties du RFC 1034 et RFC 1035 (section 4.3.5 du premier, sections 2.2,
3.2.3 et 4.2 du second). Diverses améliorations avaient été créés
comme le transfert incrémental
(IXFR) du RFC 1995 ou
comme la notification immédiate du RFC 1996. Le protocole avait également été corrigé par la
section 5.5 du RFC 2181. Bien des points étant flous dans les RFC originels,
les programmeurs ont dû petit à petit concevoir une version
non-officielle, mais plus précise, du protocole, et c'est elle que
notre RFC décrit.
Quel est le problème qu'essaie de résoudre le transfert de zones ?
Pour des raisons de fiabilité, toute zone doit être servie par au
moins deux serveurs faisant autorité (et bien plus en
pratique). Évidemment, il faut que ces serveurs disposent des mêmes
informations, soient synchronisés. Il existe plusieurs méthodes pour
cela. Parmi les TLD, par exemple, certains
utilisent rsync, certains utilisent les
mécanismes de réplication de la base de données sous-jacente (comme
Slony pour
PostgreSQL). Mais AXFR (et
IXFR) sont les seuls mécanismes DNS du
lot. Aussi, bien que cela ne soit pas, en toute rigueur, obligatoire,
tous les logiciels serveurs de noms mettent en œuvre cette
technique (section 1.2 du RFC).
Focalisons nous sur AXFR car
IXFR et NOTIFY ne sont pas
traités par ce nouveau RFC. La section 2 de notre RFC 5936 reprend donc le travail et décrit intégralement le
protocole. Un client DNS envoie une requête AXFR
en mettant le QTYPE (Query
TYPE) à la valeur 252 (section 2.1) et en dirigeant la requête vers
un serveur faisant autorité (jamais vers un résolveur). Avec dig,
cela se fait ainsi (ici pour la zone
.uk) :
% dig @ns1.nic.uk AXFR uk.
Le client doit en outre s'assurer de la valeur de certains champs (section 2.1.1). Il peut aussi ajouter une section additionnelle à la question (section 2.1.5) spécifiant l'utilisation d'EDNS (RFC 2671) et/ou d'une technique d'authentification comme TSIG (RFC 2845).
La section 2.2 décrit la réponse à cette requête. C'est une série de messages DNS (lorsqu'il est transporté sur TCP, chaque message DNS est composé d'une longueur, puis de données). Chaque message peut comporter plusieurs enregistrements. Le premier message doit commencer avec l'enregistrement SOA de la zone transférée et le dernier message se terminer avec le même SOA. À part cette règle, l'ordre des enregistrements ou des messages n'a pas de signification (ce n'est donc pas forcément l'ordre du fichier de zone). Voici une partie de la réponse à la requête faite plus haut. Elle ne comporte qu'un seul message, incluant les 195 enregistrements de cette petite zone. La réponse commence bien par le SOA de la zone transférée :
uk. 172800 IN SOA ns1.nic.uk. hostmaster.nic.uk. 1277504551 7200 900 2419200 172800 uk. 3600 IN RRSIG NSEC3PARAM 8 1 3600 20100709182231 20100625172231 44346 uk. dM777Q8sZ9sNshexmw08/cfUIAqzxjMj/MvARyuPxxNW52pfXprZ7AvM 0B27rVpIi6qEsBlypNwzZMOm56bzmDQVGBXnC77eUh9kXGEaI6tLuTta rfFWakGdcS8kn/lUOtIOhbfy6xuQRsD6+Y/iV/HEcwmpShVcea/PnSx8 eQQ= ... _nicname._tcp.uk. 172800 IN SRV 0 0 43 whois.nic.uk. ac.uk. 172800 IN NS ns.uu.net. ... british-library.uk. 172800 IN NS dns1.bl.uk. british-library.uk. 172800 IN NS dns2.bl.uk. co.uk. 172800 IN NS ns1.nic.uk. ... u1fmklfv3rdcnamdc64sekgcdp05bbiu.uk. 172800 IN NSEC3 1 1 0 - 2D51R16SS5MQU6PCG2Q0L05JA7E20FC7 NS SOA RRSIG DNSKEY NSEC3PARAM uk. 172800 IN SOA ns1.nic.uk. hostmaster.nic.uk. 1277504551 7200 900 2419200 172800 ;; Query time: 430 msec ;; SERVER: 2a01:40:1001:35::2#53(2a01:40:1001:35::2) ;; WHEN: Sat Jun 26 18:33:50 2010 ;; XFR size: 195 records (messages 1, bytes 6125)
La réponse se termine bien par le SOA de la zone transférée. Bien que dig ne l'affiche pas lors d'un transfert de zones, certaines options doivent être mises dans l'en-tête, par exemple AA pour Authoritative Answer (section 2.2.1).
Dans l'exemple ci-dessus, la section additionnelle était vide. Mais, si on authentifie le transfert avec TSIG (RFC 2845), ce n'est plus le cas. La signature de la zone transférée apparait alors dans cette section (section 2.2.5 ; mais dig l'affiche à la fin des réponses, ce qui est trompeur. Si on veut voir ce qui passe sur le réseau, il vaut mieux utiliser Wireshark.)
Cela, c'était le protocole. Maintenant, les questions les plus
sérieuses posées par le transfert de zones portaient plutôt sur le
contenu de ce qui est transféré (section 3). Le
principe de base posé par notre nouveau RFC est que le serveur doit
transférer fidèlement ce que lui-même a reçu (via un fichier de zone
- la méthode traditionnelle - ou via un SGBD). Notez que
cette règle semble un enfonçage de porte ouverte mais qu'elle ne l'est
pas : par exemple, si la zone est très dynamique, fabriquée à la
demande, alors un transfert de zones est tout simplement impossible
(section 3.1). Pour prendre un exemple pour rire, c'est le cas de
rp.secret-wg.org.
Mais le principal cas où l'application de la règle est délicate est
celui cité dans la section 3.2 : que faire si le serveur qui fait
autorité pour foo.example fait également autorité
pour bar.foo.example et qu'on lui demande de
transférer foo.example ? Normalement, les
enregistrements NS des deux zones doivent être
identiques. Mais, dans le monde réel, ce n'est pas toujours le cas. Si
foo.example contient :
bar.foo.example. IN NS ns1.example.net.
IN NS ns2.example.net.
(enregistrements qui ne font pas autorité mais sont nécessaire
spour trouver les serveurs de la zone fille)
et que bar.foo.example contient :
bar.foo.example. IN NS ns1.example.net.
IN NS ns3.example.net.
(qui, cette fois, font autorité)
quel jeu d'enregistrements doit renvoyer le serveur lorsqu'on lui
demande foo.example ? Ce n'est pas dit clairement
dans les RFC 1034 (sa section 4.2.1 est ambigue) et RFC 1035 et les serveurs de noms ont souvent eu des
comportements différents sur ce point. Or, celui-ci est crucial, par
exemple pour des zones signées avec
DNSSEC (par exemple, les enregistrements NSEC
et NSEC3 ne seront pas les mêmes, puisque le nom suivant, dans chacune
des deux zones, sera différent). Notre nouveau RFC tranche : on envoie
ce que contenait la zone transférée, pas ce qu'on a pu apprendre parce
qu'on sert d'autres zones. Dit autrement, AXFR
doit être exactement équivalent à un rsync du
fichier de zone.
Pourquoi l'ambiguité a t-elle été tranchée dans ce sens ? Il y a plusieurs raisons parmi lesquelles :
foo.example peuvent
faire autorité également pour bar.foo.example et
d'autres pas. Si le serveur transférait les données « corrigées », les
différents serveurs de foo.example enverraient
donc des contenus différents lors d'un transfert.foo.example et
bar.foo.example) serait bien plus difficile si on
ne pouvait pas accéder aux données brutes stockées sur le
serveur.Même règle (transférer la zone qu'on a reçu, ne pas tenter de la « corriger » avec ce qu'on a appris dans d'autres zones) s'applique aussi à la colle, ces enregistrements d'adresses IP qui, sans faire autorité, doivent parfois être stockés dans la zone parente, pour permettre de trouver un serveur de noms qui figure dans une zone fille (section 3.3).
Il reste deux problèmes liés au contenu de la zone : la compression
de données (RFC 1035, section 4.1.4) lors d'un
transfert ne peut pas
être la même que pour une réponse typique (section 3.4) car elle doit tenir compte
de la casse (le transfert doit désormais transmettre les
noms en respectant leur casse, ce qui n'est pas le cas lors d'une
requête DNS classique). Et enfin, il y a le problème des noms
masqués. Si un serveur permet la mise à jour dynamique (RFC 2136), une nouvelle délégation (la création
dynamique d'enregistrements NS) peut masquer des anciens noms (section
3.5). Ainsi, si la zone contenait
www.toto.foo.example, la création
d'enregistrements NS pour toto.foo.example masque
complètement www.toto.foo.example. Dans ce cas,
le RFC est clair : le transfert de la zone doit inclure les noms
masqués.
Une fois réglé le protocole et le contenu, reste la question du
transport. La section 4 traite
son cas : le transfert de zones a toujours nécessité l'utilisation de
TCP (la section 4.2 explique pourquoi cela
restera le cas). Mais le reste n'est pas clair : par
exemple, peut-on réutiliser la connexion TCP pour un deuxième
transfert de zones ? Les serveurs de noms esclaves font genéralement
une requête SOA avant de demander le transfert de zones, l'examen du
numéro de série que contient le SOA leur permet de savoir si un
transfert est nécessaire. Cette requête SOA peut-elle passer sur la
même connexion TCP que le transfert, si celui-ci a lieu ? Il est
difficile de « faire parler » les vieux RFC sur ce point. Le fait
qu'ils n'exigent pas que le serveur copie la question ou bien le
Query ID dans la réponse semble indiquer que l'idée
était en effet qu'une connexion TCP ne serve qu'au transfert de zone,
et à un seul. Toutefois, notre RFC 5936 choisit de
trancher en autorisant explicitement l'utilisation d'une connexion TCP
pour plusieurs requêtes (pas forcément toutes
AXFR). C'est même l'option recommandée, pour
économiser des ressources sur le serveur.
Lorsque les RFC originels sur le DNS avaient été écrits, on prêtait moins d'attention à la sécurité qu'aujourd'hui. Ces RFC ne mentionnaient donc pas la possibilité de restreindre, voire d'interdire le transfert de zones. Comme l'explique la section 5, cette possibilité est au contraire considérée comme vitale aujourd'hui. (Voir mon article « Récupérer une zone DNS ».) Le RFC demande que l'autorisation de transfert puisse se faire par adresses IP, et par des techniques de signature comme TSIG. La politique par défaut devrait être « pas de transfert ».
Voici un exemple avec le serveur nsd (version 3) qui, comme recommandé par le RFC, ne permet pas de transfert par défaut :
zone:
name: "bortzmeyer.fr"
zonefile: "primary/bortzmeyer.fr"
provide-xfr: 192.134.7.248 NOKEY
Ici, la machine 192.134.7.248 (et elle seule) est autorisée à
transférer la zone (directive provide-xfr). Une
tentative depuis une autre adresse donnera, par exemple sur le serveur :
Jun 28 20:23:58 aetius nsd[25004]: axfr for zone bortzmeyer.fr. \
from client 2a01:e35:8bd9:8bb0:38cf:6d60:b99:4d94 refused, no acl matches
Avec BIND, on s'y prend en général en
définissant des ACL, ici une ACL nommée my-nets :
acl my-nets {
203.0.113.128/26;
127.0.0.0/8;
2001:db8:3003::/48;
};
puis en les utilisant dans les paramètres de la zone :
zone "bortzmeyer.fr" {
allow-transfer {
my-nets;
};
...
};
et une tentative par une autre machine sera rejetée, le serveur notant :
Jun 28 20:27:41 lilith named[20452]: \
client 2a01:e35:8bd9:8bb0:38cf:6d60:b99:4d94#51619: \
zone transfer 'bortzmeyer.fr/AXFR/IN' denied
Et l'intégrité des données transférées ? La section 6 se penche sur la question et spécifie qu'un transfert doit être complet, et avec succès, pour que la zone ainsi transférée soit utilisée (en d'autres termes, le transfert doit être atomique).
On l'a vu, l'ancienne norme était loin d'être claire sur tous les points. La nouvelle est, on l'espère, plus précise. Mais alors, n'y a t-il pas des risques de mauvaise entente entre anciens serveurs et nouveaux clients (ou le contraire) ? La section 7 du RFC est consacrée à ce problème de compatibilité. Elle commence par noter qu'il est difficile de donner des garanties, puisque la sous-spécification du transfert de zones fait que les anciens logiciels présentent une grande variété de comportements. Souvent, cet ancien comportement n'est pas facilement détectable automatiquement, donc la règle est qu'un nouveau logiciel qui souhaite interagir avec les anciens doit le faire via une option de configuration. Limitons nous au point de vue du serveur (section 7.1). Il ne peut pas savoir si le client accepte plusieurs enregistrements par message et l'interaction avec des clients qui n'y arrivent pas nécessite donc une option spécifique (mais qui ne doit pas être activée par défaut). (Pour le point de vue du client, voir la section 7.2.)
Première rédaction de cet article le 24 Juin 2010
Il y a déjà eu d'innombrables livres, articles dans la presse papier et sur les blogs, bavardages à la radio, pontifications à la télé, sur l'identité nationale. En sait-on plus sur ce concept flou, désormais ? Pas sûr. Mona Ozouf l'aborde par le biais de l'autobiographie. Elle décrit son enfance en Bretagne dans les années 30, et en profite pour se demander ce que signifie « être française ».
C'est que son identité n'est pas évidente : la petite Mona Sohier est fille d'un militant breton, à la fois partisan déterminé de la liberté de la Bretagne, mais aussi instituteur à une époque où l'école républicaine et laïque participait activement à la destruction des langues régionales. Ce père qu'elle a peu connu, quelles étaient exactement ses opinions politiques ? À part sur la langue bretonne, elles ont varié, épousant la difficulté de se définir lorsque on est breton et progressiste, coincé entre la France dominatrice et nivelleuse, et la réaction bretonne et catholique. Mort trop tôt, Yann Sohier n'a pas eu l'occasion de se déterminer par rapport à l'occupant nazi, certains militants bretons choisissant la collaboration, d'autres la résistance. Les pages les plus intéressantes sont consacrées à des questions politiques comme « Qu'aurait fait mon père en 1940 ? »
Mona Ozouf a donc été surtout élevée par sa mère, qui, elle, était bretonnophone de naissance (son père, né en pays gallo, avait appris le breton plus tard) et qui était également institutrice. Un rève d'ascenseur social puisque les arrière-grands-parents étaient simples paysans, les grands parents (tout) petits commerçants, les parents instituteurs (Anne le Den terminera directrice d'école) et Mona Ozouf sera, elle, chercheuse au CNRS. Mais cette ascension sociale ne se fera pas dans la joie et bien des choses devront être abandonnées en cours de route. Était-ce nécessaire ?
C'est là qu'on revient à l'identité nationale. En caricaturant un peu (ce que l'auteur fait rarement mais, ici, c'est mon blog), on peut dire qu'il y a deux façons de définir « la France ». L'une est que c'est plus ou moins un hasard, la réunion de peuples divers qui n'étaient pas forcément volontaires. L'autre est que c'est un choix délibéré effectué par ses habitants, comme si « la France » était un parti politique, dont tous les membres partageraient les mêmes choix (sans qu'on dise jamais lesquels : l'amour du football ?). Cette seconde vision sert surtout à intimer aux immigrés l'ordre de s'« intégrer », là encore sans qu'on sache trop bien ce que cela peut être, à part qu'on est traité de « communautariste » dès qu'on exprime son scepticisme.
Mona Ozouf considère qu'il ne faut pas chercher trop d'idéologie dans la construction d'un pays : celle-ci s'est faite en bricolant, en agrégeant des gens divers et qui le sont parfois restés, et que chercher un sens, un but, à un pays, revient souvent à enfermer ses habitants dans l'idéologie dominante.
Ah, et il n'y a pas que la politique, c'est aussi un très beau livre sur l'enfance, sans nostalgie (à cette époque, être enfant n'était pas toujours drôle, on ne se sentait pas obligé de leur fournir des distractions et des activités...) mais sans rancœur.
Première rédaction de cet article le 24 Juin 2010
Peut-on attaquer un HSM au point de récupérer la clé privée, qui ne devrait jamais sortir ? Oui, montre cet article, qui a réussi contre un modèle de HSM particulièrement mal fait du point de vue matériel (mais plus sérieux sur le logiciel).
Les HSM sont devenus des composants indispensables des systèmes de sécurité basés sur la cryptographie. Par exemple, la grande majorité des registres de noms de domaines qui signent leur zone avec DNSSEC utilisent un HSM.
Ces engins spécialisés génèrent des couples clé privée / clé publique et gardent la clé privée à l'intérieur, sans aucun moyen de la sortir sans qu'elle soit chiffrée. Des protections matérielles garantissent que même un méchant qui a un accès physique au HSM ne pourra l'ouvrir ou que, s'il le fera, la clé privée sera automatiquement effacée (si le HSM est conforme à la norme « FIPS 140-2 level 4 »). Comme la clé privée ne sort pas, toutes les opérations cryptographiques (signature, par exemple) doivent être faites dans le HSM, qui dispose donc d'un processeur pour cela.
En matière de sécurité, il n'y a pas de solution parfaite, pas de système invulnérable, pas de bouclier sans épée capable de le percer. Les HSM n'echappent pas à cette règle et l'article « Unwrapping the Chrysalis » explique une attaque réussie.
J'ai été plutôt déçu par la partie matérielle de cet article, où j'espérais apprendre des méthodes de très haute technologie, genre roman de Michael Crichton : le HSM en question, un Luna Chrysalis, a été percé en un rien de temps, malgré sa certification FIPS 140-2 level 3. L'article date de 2004, j'espère que les HSM ont progressé depuis et que les certificateurs font leur travail plus sérieusement !
La partie logicielle, quoique pas spécifique aux HSM (c'est de la rétro-ingénierie de code ARM classique) est la partie la plus longue de l'article, et celle qui a causé le plus de difficultés aux auteurs. Pourtant, le logiciel n'utilisait apparemment aucune des techniques de dissimulation dont se servent, par exemple, les auteurs de virus. Mais il était très complexe, d'autant plus qu'il devait gérer beaucoup de cas. Les auteurs ont donc dû entamer une longue et douloureuse route, notant soigneusement tout ce qu'ils découvraient, pour établir peu à peu une carte du logiciel.
N'étant pas familier avec les techniques de rétro-ingéniérie, j'ai appris des choses, comme l'importance de nommer tous les objets identifiés. Par exemple, chaque fonction repérée dans le code reçoit un nom, même sans sémantique (comme « Fred », « George » ou « Juliet »). Cela facilite grandement les communications au sein de l'équipe.
Ils ont fini par reconstituer le protocole qui permet à deux de ces HSM de synchroniser leurs clés et cela a permis de finir par sortir une clé privée (avec la complicité d'un Security Officer, toutefois). Les HSM ne sont donc pas invincibles.
Articles des différentes années : 2010 2009 2008 2007 2006 2005 2004 Précédentes années
Syndication : Flux Atom avec seulement les résumés et Flux Atom avec tout le contenu