La réalisation technique d'un tel
couplage entre l'infrastructure réelle et l'infrastructure simulée
repose principalement sur deux points :
être capable de recevoir et de produire, sur le système hôte
hébergeant la simulation, des trames réseau qui ne concernent pas
l'hôte en lui même mais les éléments simulés,
pouvoir réutiliser, sur le système hôte, des logiciels réseau
existants de telle sorte qu'ils utilisent les propriétés réseau des
dispositifs simulés en lieu et place de celles du système hôte.
Le premier point technique, pouvant
être qualifié de "couplage matériel'', est relativement bien maîtrisé;
il suffit d'utiliser des sockets de niveau liaison (ethernet) en mode promiscuous.
Ceci permet de capturer toutes les informations qui parviennent aux
interfaces réseau physiques du système hôte et d'émettre sur ces
interfaces des trames fabriquées à notre convenance.
Le couplage matériel permettant de recevoir et d'émettre sur la machine
hôte des trames qui ne la concernent pas directement étant
techniquement possible, il nous est désormais nécessaire de nous
interroger sur la manière dont les machines simulées doivent consommer
et produire de telles trames afin de présenter sur le réseau des
comportements similaires à ceux que produiraient des machines réelles.
Ces comportements sont essentiellement la manifestation du
fonctionnement d'outils (du domaine des réseaux) sur de telles
machines. Dans la pratique, ces outils sont principalement des clients
et des serveurs (HTTP, SSH, ...) ou des outils d'investigation voire d'attaque ("Nmap - Free Security Scanner For Network Exploration, http://www.insecure.org/nmap/", "Nessus - Open Source Security Scanner, http://www.nessus.org/",
...). Etant donné que ces machines sont simulées par un programme
informatique, la première démarche qui pourrait sembler envisageable
consisterait à simuler également l'exécution de ces outils.
Bien que techniquement possible, cette solution représente un travail
de réécriture colossal qui est raisonnablement irréalisable dans la
pratique. Une solution qui permettrait de réutiliser les outils
existants semble plus intéressante pour deux raisons. Tout d'abord cela
éviterait le travail de réécriture évoqué ici. Le second intérêt de
cette solution vient du fait que les outils utilisés en l'état
conserveront leurs caractéristiques propres (notamment leurs
vulnérabilités).
Ce dernier point va tout à fait dans le sens d'une simulation qui soit aussi semblable que possible à la réalité.
Toutefois, l'utilisation pure et simple des outils existants implique
leur exécution dans le contexte de la machine hôte qui normalement doit
être complètement étrangère aux machines simulées. Ceci implique entre
autres que les accès au réseau se feront par l'intermédiaire du système
et des ressources de la machine hôte, c'est à dire que les trames échangées
concerneront l'identité de la machine hôte, les protocoles de
résolution d'adresse (ARP) et de nom (DNS) et le routage seront également dépendant de la configuration et de l'état de la machine hôte.
Il est donc nécessaire de trouver un moyen pour que l'exécution de ces
outils n'interfère pas avec le système hôte et à ce propos, il est
légitime de s'interroger sur la possibilité d'avoir recours à des émulateurs complets tels que VMware ("Virtual Infrastructure Software, http://www.vmware.com/"), Bochs ("Bochs - The Open Source IA-32 Emulation Project, http://bochs.sourceforge.net/"), PearPC ("PearPC - PowerPC Architecture Emulator, http://pearpc.sourceforge.net/"), UML ("UML - User Mode Linux, http://usermodelinux.org/"),
... Ceux-ci permettent effectivement d'émuler une machine complète dans
laquelle il est possible de faire fonctionner des systèmes variés.
Cependant l'utilisation de plusieurs de ces émulateurs sur la même
machine hôte est extrêmement pénalisante en terme de performances. De
plus, chaque machine émulée doit être configurée et utilisée une à une
comme s'il s'agissait d'autant de machines physiques. Il n'est pas
question dans ces conditions d'avoir un logiciel de simulation unifié
qui représente l'ensemble d'un parc informatique (machines,
commutateurs, ponts, connectique, ...) reconfigurable à volonté. On
fait juste l'économie du prix (les licences logicielles devant
toujours être en règle) et de l'encombrement des machines physiques.
Nous ne retiendrons donc pas cette solution d'émulation de système
complet et nous nous concentrerons uniquement sur la simulation de la
partie réseau qui constitue le centre d'intérêt principal de nos
travaux.
Il est possible de créer sur le système hôte des interfaces réseau
virtuelles qui ne sont directement associées à aucun périphérique de
communication. C'est le cas par exemple des réseaux privés virtuels (VPN)
qui traitent les trames reçues et émises sur une interface virtuelle
pour les insérer dans un flux véhiculé par une interface physique. De
telles interfaces virtuelles peuvent êtres configurées et ainsi sevoir
attribuer leurs propres adresses matérielle (MAC) et réseau (IP).
Il serait donc tentant d'attribuer à chaque machine simulée une telle
interface afin que les outils exécutés communiquent via celle-ci.
Seulement, cette solution n'est envisageable que pour un nombre très
restreint d'outils (principalement d'investigation et d'attaque)
qui permettent de choisir explicitement l'interface réseau à utiliser.
La plupart des applications clientes ou serveurs utilisent l'API socket pour une communication de niveau transport (TCP ou UDP);
or à ce niveau d'abstraction, le choix de l'interface réseau à utiliser
est entièrement délégué au système. De plus, les résolutions ARP et DNS
ainsi que le routage sont toujours entièrement pris en charge par le
système hôte (les interfaces virtuelles jouent le même rôle que les
interfaces physiques). Cette solution ne pourra donc pas être retenue.
Nous venons ici d'identifier le point crucial de notre problème de couplage logiciel : la pile TCP/IP
du système hôte forme une entité unique qui n'est exploitable de
manière cohérente que par une machine unique. Si nous souhaitons
conserver les services réseau en bon état de fonctionnement pour la
machine hôte, il est nécessaire de fournir une nouvelle pile TCP/IP
pour chaque machine simulée. L'implémentation de celle-ci doit être
totalement décorellée de celle du système hôte afin qu'il n'y ait
aucune interférence.
La seule interaction doit se situer au niveau de la capture et de
l'injection de trames par le couplage matériel déjà présenté.
L'implémentation d'une telle pile TCP/IP
représente un travail délicat mais tout à fait envisageable si l'on se
concentre sur les fonctionnalités essentielles. Il reste donc à
discuter la manière dont on peut contraindre les outils à utiliser
cette pile TCP/IP en lieu et place de celle du système hôte.
Dans un premier temps il paraît raisonnable de recenser les outils dont
nous souhaitons disposer dans le cadre de l'expérimentation autour de
la sécurité des systèmes d'informations. Ainsi ces quelques outils
pourront être très partiellement modifiés (dans leur code source) afin
que les appels à l'API socket
usuels soient remplacés par des appels à la nouvelle implémentation. Le
nombre de ces modifications est dans la pratique très restreint; il ne
s'agit la plupart du temps que des opérations d'ouverture, de
fermeture, de lecture, d'écriture et d'attente sur les canaux de
communications.
Un raffinement supplémentaire pourrait consister à détourner
automatiquement ces appels par le mécanisme de préchargement de
symboles liés dynamiquement. Cette dernière solution offre l'avantage
d'éviter d'avoir à adapter les outils mais elle nécessite alors que
l'implémentation de la pile TCP/IP simulée soit en mesure de gérer toutes les subtilités de l'API socket (ioctl, fcntl, setsockopt,
...) auxquelles les applications pourraient avoir recours. Ce dernier
point représente un volume de travail comparable à la réécriture d'une
portion non négligeable d'un système d'exploitation. Ce raffinement ne
pourrait donc être envisagé dans la pratique qu'après avoir modifié un
grand nombre d'outils afin de recenser petit à petit parmi toutes ces
subtilités lesquelles sont les plus souvent utilisées.
Une difficulté technique supplémentaire concerne la cohérence
temporelle de la simulation. Tout d'abord, les éléments simulés doivent
interagir dans une échelle de temps qui reste compatible avec les
éléments réels afin que les opérateurs humains puissent se sentir en
situation opérationnelle; dans ces conditions la simulation a lieu en
"temps réel". Toutefois, un autre mode de simulation doit pouvoir être
envisagé; il s'agit d'un "temps virtuel" dans lequel chaque opération
doit être datée selon un temps qui n'a rien à voir avec le temps de
calcul nécessaire à la simulation de cette opération. Dans ces
conditions, il est alors envisageable de quantifier très finement les
caractéristiques des flux en terme de débit, de temps de réponse, ...
mais ceci ne peut se faire que dans la cadre de la simulation sans
aucun couplage avec les dispositifs physiques. Cette seconde difficulté
est d'un ordre plus théorique que la précédente et nécessite
principalement un travail de recherche.