Lorsque l'on veut transporter des données de façon sécurisée, il faut s'assurer de deux choses. D'une part, que les données reçues n'ont pas été altérées – volontairement ou non –, d'autre part qu’elles ne puissent pas être lues par des tiers, on parle alors de chiffrement. En fonction des choix effectués, nous verrons que sur la totalité d’une trame des morceaux plus ou moins grands sont chiffrés et/ou authentifiés. Les trois solutions de VPN que nous avons retenues : OpenVPN, IPSec et WireGuard utilisent des modus operandi différents que nous allons passer en revue.
1. OpenVPN
1.1 Considérations préliminaires
OpenVPN est un VPN SSL. Il n'est en rien compatible avec IPSec ou autres. Et pour cause, car si la plupart des protocoles classiques sont prévus pour être implémentés au niveau noyau, OpenVPN tourne à 100 % en espace utilisateur. Les paquets rentrent et sortent via les interfaces spécifiques tun ou tap et sont traités en dehors du kernel. Cette option permet d'avoir un logiciel facilement portable du moment que le système d'exploitation supporte au moins l'un des deux types d'interfaces spécifiques. On pourrait légitimement craindre une vitesse moindre par rapport aux implémentations de VPN dans le noyau, mais tous les tests disponibles prouvent que, si la différence est parfois notable, le désagrément à l'usage est négligeable, à moins d'y faire transiter de gros volumes. Le choix d'un VPN est lié aux besoins.
1.2 Le header
Étant donné qu’OpenVPN ne fait l’objet d’aucune RFC, une description claire de son protocole est compliquée à trouver. On sait cependant qu’il utilise TLS pour le chiffrement et qu’il peut fonctionner sur UDP ou TCP. Par ailleurs, on sait aussi qu’il met les données chiffrées dans des trames IP, ce qui le rend très difficile à détecter.
Sachant cela et en examinant les trames avec Wireshark, on peut en déduire le format d’une trame OpenVPN en prenant l’exemple des options TLS par défaut :
En-tête IP |
|||
En-tête UDP |
|||
Packet tag |
HMAC-SHA1 signature |
Vecteur d’initialisation |
N° de séquence |
En-têtes d’origine (IP + UDP/TCP) |
|||
Données |
En examinant ce schéma, on s’aperçoit qu’OpenVPN rajoute un « overhead » d’environ 69 octets. Je dis « environ », car bien entendu cela dépend fortement du chiffrement et du digest utilisés. Il est à noter que les nombreuses options d'OpenVPN peuvent entraîner des changements notables dans ce schéma qui est donc à prendre à titre indicatif.
1.3 Zoom sur les devices tun et tap
Les devices tun (pour tunnel) simulent un périphérique réseau opérant au niveau 3 du modèle OSI, c’est-à-dire le niveau « réseau », par exemple IP dans le cadre d’un réseau TCP/IP.
Les devices tap (pour tapping, dans le sens d’écoutes téléphoniques) simulent eux un périphérique de niveau 2 – Ethernet par exemple – qui sont prévus pour capturer et renvoyer tout le trafic réseau qui passe par eux.
Les paquets envoyés par le système d’exploitation via un périphérique tun ou tap sont remis au programme tournant en espace utilisateur qui est connecté à ce device. Ce même programme peut bien entendu envoyer lui aussi des données vers les périphériques tun/tap et, dans ce cas, les données envoyées sont injectées directement dans la pile réseau.
OpenVPN utilise les devices tun lorsqu’il travaille en mode tunnel et les devices tap lorsqu’il travaille en mode bridge. La description de ces deux modes de fonctionnement est faite dans les chapitres consacrés à la configuration d’OpenVPN.
Comme on le voit, nul besoin ici de grands développements de protocoles plus ou moins alambiqués pour créer une solution de VPN fiable, performante et surtout très souple. L’usage de SSL/TLS pour le chiffrement, d’algorithmes HMAC (pour Hash-based Messages Authentication Code) bien connus, de l’encapsulation pour le tunneling et des interfaces étudiées ci-dessus permettent de faire en sorte que tout le code d’OpenVPN tourne en espace utilisateur et soit facilement portable.
1.4 Les flux de données et de contrôle
OpenVPN fonctionne en multiplexant les tunnels sur un seul port TCP ou UDP, mais aussi en entrelaçant des trames de données et des trames de contrôle. L'information sur le type de paquet se trouve dans le premier octet nommé plus haut « packet tag ». Cet octet contient deux informations : le « packet opcode » qui tient sur les 5 bits de poids fort et le « key ID » sur les 3 bits de poids faible. Dans le cas où OpenVPN est en mode serveur TLS - le plus fréquent - si l'opcode indique que le paquet contient des données, le key ID est utilisé pour trouver l'état TLS local auquel il est associé. Si l'état en question indique que la communication est active, authentifiée et que le client est bien celui attendu, alors seulement les informations nécessaires au déchiffrement sont chargées.
Si l'opcode signale au contraire une trame de contrôle alors le paquet est authentifié puis en fonction de l'opcode et du session ID l'une des actions suivantes est effectuée :
- un hard reset du serveur ;
- un hard reset du client ;
- un soft reset du client.
Le session ID est constitué par les 8 octets suivants le packet tag. Il est lu directement dans le cas d'une trame de contrôle.
Ces actions peuvent entraîner une renégociation de la clé de session pour le canal de données en cas de besoin.
1.5 Conclusion
Comme on le voit, le mode de fonctionnement d'OpenVPN est fort simple et basé principalement sur des protocoles éprouvés et surtout bien tenus à jour. Le code source est lisible et commenté de partout, ce qui permet un debug relativement facile. Son approche n'est certes pas très académique, mais il est un peu aux VPN ce que Linux est aux systèmes d'exploitation, un produit de geek, pensé pour des geeks, mais dont la popularité et le déploiement dépassent plus que largement du cadre prévu initialement.
2. IPSec
2.1 Protocoles d’authentification et de chiffrement
IPSec utilise deux protocoles pour authentifier et chiffrer. Le premier s’appelle AH pour Authentication Header (authentification), le second ESP pour Encapsulating Security Payload (chiffrement).
Le protocole AH fournit un mécanisme dédié uniquement à l’authentification. Il permet de vérifier l’intégrité et l’origine des données et possède un système optionnel contre le re-jeu de paquets. L’intégrité des données est assurée par l’utilisation d’un « digest » qui est généré par un algorithme tel que MD5 ou SHA. Un digest est une suite de caractères plus ou moins longue qui possède la propriété de changer énormément d’un message à l’autre même si la différence entre les deux messages est minime. Par exemple, tapez ces deux commandes dans un terminal :
Vous voyez la différence entre les trois sommes md5 alors que les modifications du message initial sont presque invisibles. C’est le principe du digest.
L’authentification de la provenance des données est elle assurée par l’utilisation d’une clé secrète partagée pour créer le digest. Enfin, la protection contre le re-jeu consiste en la présence d’un champ pour un identifiant de séquence dans l’entête de AH.
Le re-jeu est un système assez simple dans lequel l’attaquant, en écoutant la communication, vole le digest du mot de passe de l’un des interlocuteurs. Il lui est simple ensuite d’usurper son identité, car il lui suffit de présenter le digest volé à la troisième personne pour que le mot de passe soit reconnu. Si on ajoute un identifiant unique de séquence dans l’en-tête (ou ailleurs) le re-jeu est impossible, car le digest présenté par l’attaquant sera bon, mais pas l’identifiant. C’est ainsi que procède AH.
AH authentifie le payload et les entêtes à l’exception des champs pouvant légitimement être modifiés au cours de la transmission comme le champ du TTL par exemple.
Le protocole ESP, quant à lui, fournit la couche de confidentialité des données, c’est-à-dire le chiffrement, et l’authentification. ESP peut être utilisé soit pour le chiffrement seul, soit pour l’authentification seule, soit les deux. Cependant, contrairement à AH, l’authentification ne porte que sur la partie datagramme IP du paquet et non l’ensemble du paquet, en-têtes compris. Les algorithmes d’authentification sont les mêmes que ceux utilisés par AH.
Ces deux protocoles peuvent être utilisés seuls ou ensemble pour protéger un paquet IP.
2.2 Architecture et méthodes d’implémentation
Ayant été conçu pour cela, IPSec peut facilement être implémenté dans une pile IPv6 de façon à rendre son fonctionnement parfaitement transparent. Cependant, le portage en IPv4 ne permet pas ce mode de fonctionnement, car il faudrait revoir entièrement la pile IP, ce qui ne serait pas franchement pratique. Pour intégrer IPSec dans une pile IPv4, il existe donc deux méthodes. La première nommée BITS pour « Bump In The Stack » fonctionne en rajoutant une couche IPSec entre la couche IP et la couche liaison (Ethernet, ppp, token ring…). Elle a l’avantage d’être facile à intégrer, mais a l’inconvénient de dupliquer l’effort à plusieurs endroits.
L’autre méthode nommée « Bump in the Wire » ou BITW consiste simplement à rajouter des machines sur le trajet des paquets qui vont les chiffrer au passage. On peut voir ça tout simplement comme des routeurs chiffreurs.
Hormis ces méthodes d’implémentation dans le réseau, IPSec possède aussi deux modes de fonctionnement : le mode Transport et le mode Tunnel. En mode Transport, comme son nom le suggère, IPSec protège le message venant de la couche Transport (TCP, UDP, etc.). Dans ce cas, le message est authentifié et/ou chiffré par AH et ESP et les headers appropriés sont rajoutés avant les en-têtes TCP ou UDP. L’en-tête IP est lui rajouté ensuite.
En mode Tunnel, IPSec est utilisé pour protéger une trame IP complète, header IP compris. Dans ce mode, le header IPSec est rajouté à la trame IP normale et un nouveau header IP est rajouté. On fait de l’encapsulation IP dans IP. L’avantage de ce mode est que la totalité de la trame IP d’origine est sécurisée.
De par leur fonctionnement, le mode Transport est la plupart du temps utilisé dans les implémentations IP intégrant la couche IPSec, IPv6 en général, tandis que le mode Tunnel se retrouve dans les implémentations de type « Bump in the Stack » et « Bump in the Wire ».
2.3 Security Associations, Security Policies, Selectors et Security Parameter Index
Au moins là, on est presque sûrs qu’on est en train de parler de sécurité… Ces notions sont importantes à comprendre avant d’aborder IPSec plus en profondeur, elles sont là pour contrôler les échanges entre les machines, la façon dont IPSec travaille et s’assure que les trames entrantes et sortantes sont convenablement traitées.
Les échanges sur un réseau classique n’ont pas tous besoin du même niveau de confidentialité. Si vous pingez une machine vous n’avez cure que la NSA le sache, en revanche si vous envoyez une copie de votre relevé de compte vous préférez que cela reste aussi confidentiel que possible. Au niveau d’IPSec, c’est le rôle de ces Security que de savoir si la trame nécessite qu’on rajoute un bon nombre d’octets pour la sécuriser ou non.
Pour gérer ces complexes subtilités, IPSec est équipé d’un système puissant et flexible lui permettant de savoir comment il doit traiter les différents types de trames. Afin de comprendre comment tout ceci fonctionne, il nous faut d’abord définir deux concepts majeurs :
- Les Security Policies (SP) ou Politiques de Sécurité : il s’agit de règles intégrées dans l’implémentation d’IPSec qui indiquent comment traiter les différentes trames reçues par le système. Par exemple, ces règles sont utilisées pour décider si tel paquet a besoin d’être traité par IPSec, si on utilise AH et ESP, etc. Si une sécurisation est demandée, ces règles donnent aussi des indications générales sur comment sécuriser. Les politiques de sécurité d’une machine sont stockées dans une base de données appelée Security Policy Database ou SPD. Il existe une SPD par interface réseau sur lesquelles IPSec est activé et il peut même y en avoir deux, une pour le trafic entrant et une pour le trafic sortant. Les SPD doivent être consultées pour tout le trafic, y compris celui qui n’est pas IPSec.
- Les Security Associations (SA) ou Associations de Sécurité : il s’agit là d’informations de sécurité décrivant chacune un type particulier de connexion sécurisée entre plusieurs machines. Elles précisent les divers mécanismes de sécurité à mettre en œuvre pour tel ou tel type de connexion. Les Associations de Sécurité d’une machine sont stockées dans une base de données appelée Security Associations Database ou SAD. Les SA sont partagées entre toutes les machines ayant besoin de communiquer entre elles.
La principale différence entre une SP et une SA est que la SP porte sur les aspects généraux tandis qu’une SA s’occupe du détail de chaque type de connexion. Afin de déterminer comment traiter une trame, IPSec va premièrement interroger sa SPD. Il se peut, en fonction du type de trame, que cette dernière fasse référence à la SAD qui sera à ce moment-là interrogée, la SA extraite et utilisée par IPSec.
Tout ceci est beau et bon, mais la question se pose : comment IPSec peut déterminer la SA à utiliser pour la trame qui vient d’arriver ? C’est là qu’interviennent les Selectors. Il s’agit de structures comprenant un certain nombre de critères (adresse source, adresse de destination, port, etc.) et un pointeur sur une SA. Les critères peuvent être multiples et plus ou moins précis, par exemple on peut parfaitement donner une plage d’adresses comme critère 1 et un port précis comme critère 2. À partir de ces sélecteurs, IPSec est donc en mesure de déterminer quelle SA appliquer. Cependant, il faut savoir que les SA sont unidirectionnelles et totalement dépendantes de la machine sur laquelle elles sont installées. En clair, si la machine A communique avec la machine B, on aura une SA sur A pour le trafic de A vers B sortant de A, une autre sur A pour le trafic de B vers A entrant sur A, encore une autre sur B pour le trafic de A vers B entrant sur B et enfin, une sur B pour le trafic de B vers A sortant de B. Donc on aura quatre SA pour un seul trafic bidirectionnel.
Pour les désigner, les SA n’ont pas de nom, mais sont définies par trois paramètres appelés triplet :
- Le Security Parameter Index ou SPI : il s’agit d’un nombre sur 32 bits qui va identifier de manière unique la SA utilisée. Ce SPI est transporté dans les en-têtes AH et ESP afin d’être disponible à l’arrivée pour y être utilisé dans le but de trouver la SA idoine.
- Adresse IP de destination : c’est l’adresse de destination de la machine pour laquelle la SA est établie.
- Le Security Protocol Identifier : il indique si l’association est pour AH ou pour ESP. Si les deux sont utilisés conjointement ils auront chacun leur propre SA.
Les associations de sécurité sont donc utilisées pour chiffrer et déchiffrer les messages. Elles doivent donc être connues de tous les périphériques concernés. C’est là le travail du protocole nommé Internet Key Exchange ou IKE que nous verrons plus bas.
2.4 Les en-têtes
2.4.1 L’en-tête AH
Comme nous l’avons vu, AH s’occupe de fournir un mécanisme d’authentification pour tout ou partie des trames IP en rajoutant un header qui est calculé en fonction de la valeur des différents éléments de la trame. Ce protocole fonctionne presque comme les CRC que l’on utilise pour les détections d’erreur à ceci près que l’algorithme est spécifique au hachage des données et qu’on y associe une clé de chiffrement connue uniquement de l’émetteur et du récepteur. Une SA est mise en place entre les deux interlocuteurs afin de préciser comment effectuer les opérations d’authentification, ainsi seuls les deux protagonistes seront capables de s’y retrouver. Sur la source, AH effectue les calculs et met le résultat nommé Integrity Check Value ou ICV dans un en-tête spécial. À l’autre bout, le destinataire effectue les mêmes calculs en utilisant la clé qu’ils partagent, ce qui lui permet de voir immédiatement si la trame a été altérée ou non.
Il est très important de noter que AH n’effectue aucun chiffrement et que les données ne sont nullement modifiées par son action. Il se contente juste de permettre la vérification de leur intégrité.
La méthode de calcul du header AH est similaire pour IPv4 et pour IPv6, la principale différence réside dans le mécanisme utilisé pour insérer l’en-tête dans la trame et pour lier les en-têtes entre eux.
En IPv6, il existe un mécanisme d’extensions prévu de base dans le protocole et AH en fait bon usage (voir l’en-tête IPv6 dans le chapitre sur la théorie TCP/IP). Dans les deux modes de fonctionnement d’IPSec (tunnel et transport), tous les champs sont authentifiés.
Pour IPv4, l’astuce consiste à utiliser le champ « Protocole » dans l’en-tête. Ce champ désigne le protocole encapsulé dans le payload IP. Il va être recopié dans l’en-tête AH et remplacé par le numéro désignant le protocole AH lui-même, soit 51. C’est nettement plus parlant avec la figure 4.
On remarque bien ici la notion de « tunnel » où la trame d’origine est presque camouflée au sein de la nouvelle trame.
Nous pouvons maintenant voir comment est formé le fameux header AH (pléonasme) :
Prochain en-tête |
Taille des données |
Réservé |
Security Parameter Index |
||
Numéro de séquence |
||
Integrity Check Value |
La taille de l’ICV est variable en fonction de l’algorithme choisi pour ce faire et de la taille des différentes trames possibles, mais elle doit être un multiple de 32 bits. De même, la taille totale du header doit être un multiple de 32 bits en IPv4 et de 64 bits en IPv6. Pour atteindre cet objectif, il est possible de rajouter des octets de bourrage (padding) au champ ICV.
Champ |
Taille
|
Description |
Prochain en-tête |
1 |
Contient le n° de protocole du prochain header après AH. Est utilisé pour lier les headers entre eux. |
Taille des données |
1 |
Taille du header d’authentification, pas du payload. |
Réservé |
2 |
Non utilisé, mis à zéro. |
Security Parameter Index |
4 |
Valeur sur 32 bits qui, combinée avec l’adresse de destination et le type de protocole de sécurité, permet d’identifier l’association de sécurité (SA) à utiliser pour cette trame. |
Numéro de séquence |
4 |
Compteur initialisé à zéro quand une association de sécurité est formée entre deux appareils puis incrémenté pour chaque trame envoyée en utilisant ce SA. Son unicité identifie chaque trame pour un SA donné et fournit une protection contre les attaques par re-jeu. |
Integrity Check Value |
Variable |
Contient le résultat de l’algorithme de hachage utilisé par AH. |
2.4.2 L’en-tête ESP
Autant le protocole AH sait assurer l’intégrité des données, autant il ne peut rien faire pour les rendre confidentielles. Ce travail est à la charge d’un autre protocole nommé Encapsulating Security Payload ou ESP. Avec ESP, un algorithme de chiffrement mélange les données de la trame avec une clé pour les encoder. Le résultat est réarrangé pour être transmis au destinataire qui pourra les décoder. ESP dispose aussi de son propre système d’authentification ou peut être utilisé en collaboration avec AH.
Contrairement à AH qui se contente de rajouter un en-tête, ESP va rajouter trois composants :
- Un header qui contient deux champs, le Security Parameter Index et le numéro de séquence (Sequence Number). Ces informations sont placées avant les données chiffrées ;
- Un trailer qui regroupe les octets de padding pour l’alignement et le champ « Prochain en-tête » pour ESP ;
- Une zone nommée données d’authentification ESP (ESP Authentification Data) qui contient l’ICV calculé de manière similaire à AH. Ce champ n’est présent que lorsque la fonctionnalité optionnelle d’authentification d’ESP est activée.
Il y a deux bonnes raisons à ce que ces informations soient réparties en trois blocs. La première est que certains algorithmes de chiffrement exigent de travailler sur des blocs de données de taille précise et donc les octets de bourrage doivent être positionnés après les données. La seconde est que le contenu du champ ESP Authentification Data contrôle l’intégrité des données chiffrées, y compris le header et le trailer. Il doit donc se situer en dehors complètement.
Pour s’insérer dans des trames IP, ESP travaille en gros comme AH. En IPv6, il profite du mécanisme d’extensions intégré au protocole et en IPv4, il utilise le même « subterfuge » que AH à ceci près qu’il rajoute un header et un trailer et que le pointeur vers le header TCP (en mode transport) ou IP (en mode tunnel) est situé dans le trailer.
Comme on le voit sur la figure 5, le trailer ESP est ajouté à la trame avant de réaliser le chiffrement. Par conséquent, le trailer est lui aussi chiffré, seul le header ESP – et bien sûr le nouveau header IP – restent en clair.
Le header et le trailer ESP sont relativement simples à comprendre et sont constitués ainsi :
Header |
Security Parameter Index (SPI) |
||
Numéro de séquence |
|||
Payload |
Données du payload ESP |
||
Trailer |
Bourrage |
Taille du bourrage |
En-tête suivant |
Données d’authentification ESP |
Les noms des divers champs parlent plus ou moins d’eux-mêmes, mais voici quelques précisions utiles :
Section |
Champ |
Taille
|
Description |
Header |
SPI |
4 |
Valeur sur 32 bits qui, combinée avec l’adresse de destination et le type de protocole de sécurité, permet d’identifier l’association de sécurité (SA) à utiliser pour cette trame. |
Numéro de séquence |
4 |
Compteur initialisé à zéro quand une association de sécurité est formée entre deux appareils puis incrémentée pour chaque trame envoyée en utilisant ce SA. Son unicité identifie chaque trame pour un SA donné et fournit une protection contre les attaques par re-jeu. |
|
Payload |
Données du payload |
Variable |
Toutes les données chiffrées constituées par les messages des couches plus hautes ou par une trame IP encapsulée. Peut aussi inclure des données spécifiques comme un vecteur d’initialisation requis par certaines méthodes de chiffrement. |
Trailer |
Bourrage |
Variable (0 à 255) |
Octets rajoutés en fonction des besoins de l’algorithme de chiffrement ou d’alignement. |
Taille du bourrage |
1 |
Nombre d’octets servant de bourrage. |
|
En-tête suivant |
1 |
Contient le numéro de protocole du prochain en-tête dans la trame. Il s’agit en général d’un en-tête TCP ou UDP en mode transport ou IP en mode tunnel. |
|
Données d’authentification |
Variable |
Contient l’ICV issu de l’algorithme d’authentification optionnel. |
2.5 Internet Key Exchange
Plus connu sous le nom d’IKE, ce protocole permet d’échanger les SA entre deux machines de manière aussi sécurisée que possible. Défini dans la RFC 2409 pour la version 1 et dans la RFC 4306 pour la version 2, IKE est l’un des protocoles les plus compliqués à comprendre de tous ceux utilisés par IPSec. En effet, il faut un bon bagage en mathématiques et en cryptographie pour espérer s’en sortir. Étant donné les très nombreuses différences entre IKEv1 et IKEv2, nous allons nous concentrer sur ce dernier.
Le protocole IKEv2 établit et maintient dynamiquement un état partagé entre l’émetteur et le récepteur d’une trame IP. Il effectue l’authentification mutuelle entre les deux parties et établit l’association de sécurisation (SA) pour IKE. Celui-ci, que l’on va appeler IKE-SA pour le distinguer des autres SA, utilise des informations secrètes partagées qu’il stocke pour remplir deux fonctions différentes :
- établir les « CHILD-SA » pour ESP et AH (les SA dont nous avons parlé plus haut) ;
- définir les algorithmes de chiffrement qui seront utilisés par les SA.
IKEv2 est un protocole qui fonctionne par paires de requête/réponse qui sont appelées échanges. Le demandeur porte la responsabilité de garantir la fiabilité. Si une réponse n’est pas reçue, le demandeur peut soit renvoyer la requête, soit fermer la connexion. IKEv2 dispose de quatre types d’échanges :
- IKE_SA_INIT : il s’agit du premier échange qui établit le IKE-SA. Il doit absolument être accompli avant de commencer n’importe quel autre échange. Il assure trois fonctions dans la mise en place de l’IKE-SA :
- la négociation des paramètres de sécurité pour l’IKE-SA ;
- l’envoi des nonces ;
- l’envoi des données Diffie-Hellman.
Les nonces (number used once) sont des nombres arbitraires destinés à être utilisés une seule fois. Il s'agit souvent d'un nombre aléatoire ou pseudo-aléatoire servant à garantir que les anciennes communications ne peuvent pas être réutilisées dans des attaques par rejeu.
- IKE_AUTH : ce deuxième échange doit lui aussi absolument être terminé avant de poursuivre plus avant. Il assure trois fonctions essentielles :
- l’envoi des identités ;
- la preuve de la connaissance des secrets liés aux protagonistes ;
- l’établissement de la première – et en général unique – CHILD-SA pour AH et/ou ESP.
- CREATE_CHILD_SA : cet échange est simplement utilisé pour créer d’autres CHILD-SA en fonction des besoins ;
- INFORMATIONAL : échange de maintenance concernant les SA. Parmi ses fonctions, nous pouvons noter :
- suppression des SA quand besoin il y a ;
- rapport d’erreurs ;
- vérification des durées de vie des SA ;
- etc.
Une fois les deux premiers échanges obligatoires effectués dans l’ordre, tous les autres peuvent intervenir dans n’importe quel ordre.
IKEv2 utilise un grand nombre de protocoles de chiffrement pour accomplir ses missions. Il est basé sur le protocole de gestion de clés Diffie-Hellman [2].
Il resterait encore beaucoup à dire à ce sujet, mais cela nécessiterait de trop rentrer dans les détails. Je ne peux qu’encourager le lecteur intéressé et courageux à aller lire les RFC indiquées.
3. WireGuard
Nouveau venu – ou presque – dans le monde assez fermé des solutions de VPN open source, WireGuard se caractérise par une philosophie un peu différente que l'on pourrait résumer ainsi :
- Tout le code est écrit « from scratch » avec pour objectif d'être le plus rapide et le plus robuste possible (moins de 4000 lignes de code à l'heure actuelle).
- Utilisation d'un module kernel pour l'implémentation de l'interface virtuelle.
- UDP uniquement et aucun choix laissé à l'utilisateur sur les ciphers ou les digests. Le principe de chiffrement et d'authentification des machines connectées se fait de manière très originale.
3.1 Les principes sous-jacents
3.1.1 Les « Cryptokey routing tables »
WireGuard n'est pas un VPN de type client-serveur, mais de type peer to peer. Chaque machine peut être vue à la fois comme un client et comme un serveur.
Le principe fondamental utilisé est de maintenir une table d'association entre les peers, identifiés de façon stricte par une clé 32 bits de type Curve25519, et les adresses IP qui peuvent en provenir. Cela signifie qu'il existe un mappage d'association simple entre les clés publiques et un ensemble d'adresses IP autorisées. Ces tables sont appelées des « Cryptokey routing tables ». Exemple :
Interface Public Key |
Interface Private Key |
Listening UDP Port |
HIgo...8ykw |
yAnz...fBmk |
41414 |
Peer Public Key |
Allowed Source IPs |
|
xTIB...p8Dg |
10.192.122.3/32, 10.192.124.0/24 |
|
TrMv...WXX0 |
10.192.122.4/32, 192.168.0.0/16 |
|
gN65...z6EA |
10.10.10.230/32 |
|
L'interface elle-même a une clé privée et un port UDP sur lequel elle écoute, suivi d'une liste de peers. Chaque peer est identifié par sa clé publique. Chacun dispose alors d'une liste d'adresses IP source autorisées.
Lorsqu'un paquet sortant est transmis sur une interface WireGuard, wg0 par exemple, cette table est consultée pour déterminer quelle clé publique il faut utiliser pour le chiffrement. Par exemple, un paquet avec une adresse IP de destination de 10.192.122.4 sera chiffré à l'aide de la session sécurisée dérivée de la clé publique TrMv...WXX0. Inversement, lorsque wg0 reçoit un paquet chiffré, après l'avoir déchiffré et authentifié, il ne l'acceptera que si son adresse IP source est mentionnée dans la table référençant la clé publique utilisée dans la session sécurisée pour le déchiffrer. Par exemple, si un paquet est déchiffré en utilisant la clé xTIB...qp8D, il ne sera autorisé que s'il provient de 10.192.122.3 ou d'une adresse dans la plage 10.192.124.0 à 10.192.124.255 ; sinon il est droppé.
Ceci est un aperçu rapide du mode d'authentification et de routage utilisé par WireGuard. Des mécanismes complémentaires optionnels sont utilisés pour traverser les routeurs et ainsi sortir sur le Grand Ternet. WireGuard possède un mécanisme de découverte des endpoints et de roaming qu'il serait vraiment trop long d'expliquer ici.
3.1.2 Émission/réception des données
- Le paquet à émettre arrive en clair sur l'interface wg0. Il est à destination de l'adresse 192.168.87.21 par exemple.
- Son adresse IP est dans la plage 192.168.0.0/16 renseignée dans la cryptokey table et correspond à la clé TrMv...WXX0. Si aucune correspondance n'avait été trouvée, une erreur standard ICMP de type « No route to host » aurait été émise et le paquet droppé.
- Le paquet est chiffré avec la clé symétrique correspondant à TrMv...WXX0 et le nonce de la session en utilisant le cipher authentifiant ChaCha20-Poly1305 (ceci n'est pas une blague, ce cipher existe réellement !).
- Un header spécifique est ajouté au paquet chiffré.
- Cet ensemble est envoyé en UDP sur le réseau.
En réception, le mécanisme inverse est utilisé.
3.2 Overhead
Les deux niveaux d'encapsulation utilisés par WireGuard (header + paquet) ne provoquent qu'un overhead minime. En effet, l'en-tête utilisé est réduit au maximum :
type : 0x4 (1 octet) |
réservé : 0 (3 octets) |
Adresse du destinataire (4 octets) |
|
Compteur (8 octets) |
|
Paquet chiffré |
Ce qui nous fait un total de 16 octets d'overhead réel.
3.3 Quelques mots sur WireGuard
Le mode de fonctionnement de WireGuard est très différent de ce que l'on peut rencontrer ailleurs. Aller plus loin dans la description demanderait presque un numéro complet de Linux Pratique, de bonnes connaissances en cryptographie et une non-allergie prouvée aux notations mathématiques. Ce rapide descriptif peut vous laisser sur votre faim, aussi pour ceux que ċa intéresse, je recommande vivement le papier en référence [3] (en anglais) qui explique aussi clairement que possible ce qui est mis en œuvre au sein de ce très joli logiciel.
4. Comparatif rapide
Nous venons de passer en revue les trois principaux VPN disponibles en open source. La question en suspens est : lequel faut-il choisir ? La réponse est simple et limpide : celui qui vous convient le mieux. Avec ça, je sûr de mécontenter tout le monde… Aussi voici un petit récapitulatif sous forme de tableau :
|
OpenVPN |
IPSec |
WireGuard |
Infrastructure |
Client – Serveur |
LAN to LAN |
Peer to Peer |
Choix des ciphers et authentifiers |
Oui |
Oui |
Non |
Usage |
Générique |
Interconnexion de réseaux |
Interconnexion de machines |
Attention, les données de ce tableau, principalement la ligne « Usage » sont volontairement caricaturales. On peut parfaitement interconnecter deux terminaux avec IPSec et plusieurs réseaux avec WireGuard, il ne faut pas se méprendre. La meilleure preuve est qu'un grand fournisseur de VPN dont le nom commence par « N » et finit par « VPN » utilise WireGuard et en fait la publicité.
Lorsque vous établissez votre propre ensemble de VPN, vous êtes libres de choisir la solution qui vous plaît le mieux. La seule chose à ne jamais oublier est qu'il ne faut surtout pas faire arriver et/ou partir un VPN depuis un firewall. Ce dernier ne doit être accessible qu'en SSH depuis le LAN et avec une clé, pas un mot de passe. Un firewall se traverse uniquement !
Conclusion
Les quelques pages que vous venez de lire ne reflètent même pas la partie émergée de l’iceberg. J’ai essayé d’être le plus clair possible en passant sous silence bon nombre de détails dont l’explication nous aurait emmenés beaucoup trop loin. La cryptographie est une science à part entière avec son vocabulaire, ses codes et ses gourous (ceux qui méditent et les autres… ;-) ) Si vous vous sentez attirés par ce monde-là, potassez vos mathématiques et lisez beaucoup ; étudiez la documentation, mais aussi le code existant afin de comprendre comment les algorithmes ont été implémentés. Bonne découverte…
Références
[1] https://community.openvpn.net/openvpn/wiki/RelatedProjects
[2] https://fr.wikipedia.org/wiki/%C3%89change_de_cl%C3%A9s_Diffie-Hellman