Génération de trafic dans l'espace utilisateur


Génération de trafic à l'aide de MoonGen + DPDK + Lua dans la vue de l'artiste

La neutralisation des attaques DDoS en conditions rĂ©elles nĂ©cessite des tests prĂ©liminaires et des tests de diverses techniques. L'Ă©quipement et les logiciels rĂ©seau doivent ĂȘtre testĂ©s dans des conditions artificielles proches des conditions rĂ©elles - avec des flux de trafic intensifs simulant des attaques. Sans de telles expĂ©riences, il est extrĂȘmement difficile d'obtenir des informations fiables sur les caractĂ©ristiques spĂ©cifiques et les limites de tout outil complexe.

Dans cet article, nous allons révéler certaines des méthodes de génération de trafic utilisées dans Qrator Labs.

AVERTISSEMENT

Nous recommandons fortement au lecteur de ne pas essayer d'utiliser les outils mentionnés pour attaquer des objets d'une infrastructure réelle. L'organisation d'attaques DoS est punie par la loi et peut entraßner des sanctions sévÚres. Qrator Labs effectue tous les tests dans un environnement de laboratoire isolé.

Niveau technique moderne


Une tĂąche importante dans notre domaine consiste Ă  saturer l'interface Ethernet 10G avec de petits paquets, ce qui implique un traitement de 14,88 Mpps (millions de paquets par seconde). Ci-aprĂšs, nous considĂ©rons les plus petits paquets de rĂ©seau Ethernet - 64 octets - car notre principal intĂ©rĂȘt est de maximiser le nombre de paquets transmis par unitĂ© de temps. Un calcul simple montre que nous avons seulement environ 67 nanosecondes pour traiter un tel paquet.

À titre de comparaison, cette fois-ci est proche de ce dont un processeur moderne a besoin pour obtenir un morceau de donnĂ©es de la mĂ©moire s'il manque le cache. Tout devient encore plus compliquĂ© lorsque nous commençons Ă  travailler avec des interfaces Ethernet 40G et 100G et essayons de les saturer complĂštement jusqu'au dĂ©bit de ligne (les performances dĂ©clarĂ©es maximales possibles du pĂ©riphĂ©rique rĂ©seau).

Étant donnĂ© que dans le cas habituel, le flux de donnĂ©es passe par l'application dans l'espace utilisateur (espace utilisateur), puis par le noyau, pour finalement entrer dans le contrĂŽleur rĂ©seau (NIC), la premiĂšre et la plus simple idĂ©e est d'essayer de configurer la gĂ©nĂ©ration de paquets directement dans le noyau. Un exemple d' une telle solution est le module nuclĂ©aire pktgen [2]. Cette mĂ©thode vous permet d'amĂ©liorer considĂ©rablement les performances, mais pas assez flexible, car le moindre changement dans le code source dans le noyau entraĂźne un long cycle de construction, un redĂ©marrage des modules du noyau ou mĂȘme du systĂšme entier et, en fait, des tests, ce qui rĂ©duit la productivitĂ© globale (c'est-Ă -dire que cela nĂ©cessite plus de temps de la part du programmeur et effort).

Une autre approche possible consiste à obtenir un accÚs direct de l'espace utilisateur aux tampons de mémoire du contrÎleur de réseau. Ce chemin est plus compliqué, mais vaut l'effort pour atteindre une productivité plus élevée. Les inconvénients incluent une grande complexité et une faible flexibilité. Des exemples de cette approche sont netmap , PF_RING et DPDK [4].

Un autre moyen efficace, quoique trÚs coûteux, d'atteindre des performances élevées consiste à utiliser un équipement non universel, mais spécialisé. Exemple: Ixia .

Il existe également des solutions basées sur DPDK utilisant des scripts, ce qui augmente la flexibilité dans le contrÎle des paramÚtres du générateur et vous permet également de varier le type de packages générés au démarrage. Ci-dessous, nous décrivons notre propre expérience avec l'un de ces outils - MoonGen.

Architecture MoonGen


Les caractéristiques distinctives de MoonGen sont:

  1. Le traitement des données DPDK dans l'espace utilisateur est la principale raison du gain de performances;
  2. Lua [ 5 ] pile avec des scripts simples au niveau supérieur et des liaisons à la bibliothÚque DPDK écrite en C, en bas;
  3. Grùce à la technologie JIT (juste à temps), les scripts Lua fonctionnent assez rapidement, ce qui contredit quelque peu les idées généralement acceptées sur l'efficacité des langages de script.

MoonGen peut ĂȘtre considĂ©rĂ© comme un wrapper Lua autour de la bibliothĂšque DPDK. Au moins les opĂ©rations DPDK suivantes sont visibles au niveau de l'interface utilisateur Lua:

  • Configuration des contrĂŽleurs de rĂ©seau;
  • Allocation et accĂšs direct aux pools et tampons de mĂ©moire, qui, Ă  des fins d'optimisation, doivent ĂȘtre allouĂ©s dans des zones alignĂ©es en continu;
  • AccĂšs direct aux files d'attente RSS des contrĂŽleurs de rĂ©seau;
  • API de gestion des flux de calcul, prenant en compte l'hĂ©tĂ©rogĂ©nĂ©itĂ© des accĂšs mĂ©moire (NUMA et affinitĂ© CPU) [ 12 ].



Architecture MoonGen, schéma à partir du matériau [ 1 ].

Moongen


MoonGen est un gĂ©nĂ©rateur de paquets haute vitesse scriptĂ© basĂ© sur la bibliothĂšque DPDK. Les scripts Lua contrĂŽlent l'ensemble du processus: le script créé par l'utilisateur est responsable de la crĂ©ation, de la modification et de l'envoi des packages. GrĂące Ă  la bibliothĂšque de traitement de paquets LuaJIT et DPDK trĂšs rapide, cette architecture vous permet de saturer une interface Ethernet de 10 gigabits avec des paquets de 64 octets en utilisant un seul cƓur du CPU. MoonGen vous permet d'atteindre cette vitesse mĂȘme lorsque le script Lua modifie chaque package. Il n'utilise pas d'astuces comme la rĂ©utilisation du mĂȘme tampon du contrĂŽleur rĂ©seau.

MoonGen peut Ă©galement recevoir des paquets, c'est-Ă -dire vĂ©rifier quels paquets ont Ă©tĂ© abandonnĂ©s par le systĂšme testĂ©. Étant donnĂ© que la rĂ©ception des paquets est contrĂŽlĂ©e exclusivement par un script Lua personnalisĂ©, il peut Ă©galement ĂȘtre utilisĂ© pour crĂ©er des scripts de test plus complexes. Par exemple, vous pouvez utiliser deux instances de MoonGen pour Ă©tablir une connexion entre elles. Une telle configuration peut notamment ĂȘtre utilisĂ©e pour tester les boĂźtiers dits intermĂ©diaires (Ă©quipements entre le point d'envoi et de rĂ©ception du trafic), par exemple les pare-feu. MoonGen se concentre sur quatre domaines principaux:

  • Haute performance et Ă©volutivitĂ© multicƓur: plus de 20 millions de paquets par seconde sur un seul cƓur de processeur;
  • FlexibilitĂ©: chaque package est gĂ©nĂ©rĂ© en temps rĂ©el sur la base d'un script Lua créé par l'utilisateur;
  • Horodatage exact: sur le matĂ©riel ordinaire (marchandise), le marquage horaire est effectuĂ© avec une prĂ©cision de la milliseconde;
  • ContrĂŽle prĂ©cis des intervalles entre les paquets envoyĂ©s: gĂ©nĂ©ration fiable des modĂšles et types de trafic requis sur du matĂ©riel ordinaire.

DPDK


DPDK signifie Data Plane Development Kit et se compose de bibliothÚques dont les fonctions principales sont d'augmenter les performances de génération de paquets réseau sur une grande variété d'architectures de processeur central.

Dans un monde oĂč les rĂ©seaux informatiques deviennent le fondement de la communication humaine, les performances, la bande passante et la latence deviennent des paramĂštres de plus en plus critiques pour des systĂšmes tels que les rĂ©seaux sans fil et l'infrastructure de cĂąbles, y compris tous leurs composants individuels: routeurs, Ă©quilibreurs de charge, pare-feu; ainsi que des domaines d'application: transfert mĂ©dia (streaming), VoIP, etc.

DPDK est un moyen léger et pratique de créer des tests et des scripts. Le transfert de données dans l'espace utilisateur est quelque chose que nous n'observons pas si souvent, principalement parce que la plupart des applications communiquent avec les équipements réseau via le systÚme d'exploitation et la pile du noyau, ce qui est l'opposé du modÚle DPDK.

Lua


Le principal objectif de l'existence de Lua est de fournir des outils expressifs simples et flexibles qui sont extensibles pour des tùches actuelles spécifiques, au lieu d'un ensemble de primitives applicables dans un seul paradigme de programmation. En conséquence, la langue de base est trÚs légÚre - l'intégralité de l'interpréteur ne prend que 180 Ko sous forme compilée et s'adapte facilement à un large éventail d'implémentations possibles.

Lua est un langage dynamique. Il est si compact qu'il peut ĂȘtre placĂ© sur presque n'importe quel appareil. Lua prend en charge un petit ensemble de types: valeurs boolĂ©ennes, nombres (virgule flottante double prĂ©cision) et chaĂźnes. Les structures de donnĂ©es classiques, telles que les tableaux, les ensembles et les listes, peuvent ĂȘtre reprĂ©sentĂ©es par la seule structure de donnĂ©es intĂ©grĂ©e dans Lua - une table, qui est un tableau associatif hĂ©tĂ©rogĂšne.

Lua utilise la compilation JIT (juste à temps), donc, étant un langage de script, il affiche des performances comparables aux langages compilés tels que C [ 10 ].

Pourquoi moongen


En tant qu'entreprise spécialisée dans la neutralisation des attaques DDoS, Qrator Labs a besoin d'un moyen fiable pour créer, mettre à niveau et tester ses propres solutions de sécurité. C'est pour ces derniers, les tests, que diverses méthodes de génération de trafic simulant des attaques réelles sont nécessaires. Cependant, il n'est pas si facile de simuler une attaque par inondation dangereuse, mais simple, aux 2-3 niveaux du modÚle OSI, principalement en raison des difficultés à atteindre des performances élevées dans la génération de paquets.

En d'autres termes, pour une entreprise engagée dans la disponibilité et la neutralisation continues des DDoS, simuler diverses attaques DoS dans un environnement de laboratoire isolé est un moyen de comprendre comment les différents équipements qui font partie des systÚmes matériels de l'entreprise se comporteront dans la réalité.

MoonGen est un bon moyen de gĂ©nĂ©rer des valeurs de trafic proches de la limite pour le contrĂŽleur de rĂ©seau avec un minimum de cƓurs de processeur. Le transfert de donnĂ©es dans l'espace utilisateur amĂ©liore considĂ©rablement les performances de la pile en question (MoonGen + DPDK), par rapport Ă  de nombreuses autres options pour gĂ©nĂ©rer des valeurs de trafic Ă©levĂ©es. L'utilisation de DPDK pur nĂ©cessite beaucoup plus d'efforts, vous ne devez donc pas ĂȘtre surpris de notre dĂ©sir d'optimiser les performances. Nous prenons Ă©galement en charge un clone [ 7 ] du rĂ©fĂ©rentiel MoonGen d'origine afin d'Ă©tendre la fonctionnalitĂ© et la mise en Ɠuvre de nos propres tests.

Afin d'obtenir une flexibilitĂ© maximale, la logique de gĂ©nĂ©ration des packages est dĂ©finie par l'utilisateur Ă  l'aide du script Lua, qui est l'une des principales fonctionnalitĂ©s de MoonGen. Dans le cas d'un traitement de paquets relativement simple, cette solution fonctionne assez rapidement pour saturer l'interface 10G sur un seul cƓur de processeur. Une façon typique de modifier des packages entrants et d'en crĂ©er de nouveaux consiste Ă  travailler avec des packages du mĂȘme type, dans lesquels seuls certains des champs changent.

Un exemple est le test l3-tcp-syn-ack-flood, dĂ©crit ci-dessous. Notez que toute modification du package peut ĂȘtre effectuĂ©e dans le mĂȘme tampon, oĂč le package gĂ©nĂ©rĂ© ou reçu Ă  l'Ă©tape prĂ©cĂ©dente s'est avĂ©rĂ© ĂȘtre. En effet, de telles conversions de paquets sont effectuĂ©es trĂšs rapidement, car elles n'impliquent pas d'opĂ©rations coĂ»teuses, telles que des appels systĂšme, l'accĂšs Ă  des sections de mĂ©moire potentiellement non mises en cache, etc.

Tests sur le matériel Qrator Labs


Qrator Labs effectue tous les tests en laboratoire sur divers équipements. Dans ce cas, nous avons utilisé les contrÎleurs d'interface réseau suivants:

  • Intel 82599ES 10G
  • Mellanox ConnectX-4 40G
  • Mellanox ConnectX-5 100G

Nous notons sĂ©parĂ©ment que lorsque vous travaillez avec des contrĂŽleurs de rĂ©seau fonctionnant sur des normes supĂ©rieures Ă  10G, le problĂšme de performances devient plus aigu. Aujourd'hui, il n'est pas possible de saturer l'interface 40G avec un seul cƓur, bien qu'avec un petit nombre de cƓurs, cela soit dĂ©jĂ  rĂ©aliste.

Dans le cas des contrĂŽleurs de rĂ©seau fabriquĂ©s par Mellanox, il est possible de modifier certains paramĂštres et rĂ©glages de l'appareil Ă  l'aide du guide de rĂ©glage [ 3 ] fourni par le fabricant. Cela vous permet d'augmenter les performances et, dans certains cas particuliers, d'approfondir le comportement de la carte rĂ©seau. D'autres fabricants peuvent avoir des documents similaires pour leurs propres appareils hautes performances destinĂ©s Ă  un usage professionnel. MĂȘme si vous ne trouvez pas un tel document dans le domaine public, il est toujours judicieux de contacter directement le fabricant. Dans notre cas, les reprĂ©sentants de la sociĂ©tĂ© Mellanox ont Ă©tĂ© trĂšs gentils et, en plus de fournir de la documentation, ont rapidement rĂ©pondu Ă  nos questions, grĂące auxquelles nous avons rĂ©ussi Ă  utiliser Ă  100% la bande, ce qui Ă©tait trĂšs important pour nous.

Test d'inondation TCP SYN


L3-tcp-syn-ack-flood est un exemple de simulation d'une attaque comme SYN flood [ 6 ]. Il s'agit d'une version étendue de Qrator Labs du test l3-tcp-syn-flood du référentiel principal MoonGen, qui est stocké dans notre clone de référentiel.

Notre test peut exécuter trois types de processus:

  1. Générez un flux de paquets TCP SYN à partir de zéro, en faisant varier les champs requis, tels que l'adresse IP source, le numéro de port source, etc.
  2. Créez une réponse ACK valide pour chaque paquet SYN reçu selon TCP;
  3. Créez une réponse SYN-ACK valide pour chaque paquet ACK reçu conformément au protocole TCP.

Par exemple, la boucle de code interne (respectivement, la «plus chaude») pour créer des réponses ACK est la suivante:

local tx = 0 local rx = rxQ:recv(rxBufs) for i = 1, rx do local buf = rxBufs[i] local pkt = buf:getTcpPacket(ipv4) if pkt.ip4:getProtocol() == ip4.PROTO_TCP and pkt.tcp:getSyn() and (pkt.tcp:getAck() or synack) then local seq = pkt.tcp:getSeqNumber() local ack = pkt.tcp:getAckNumber() pkt.tcp:unsetSyn() pkt.tcp:setAckNumber(seq+1) pkt.tcp:setSeqNumber(ack) local tmp = pkt.ip4.src:get() pkt.ip4.src:set(pkt.ip4.dst:get()) pkt.ip4.dst:set(tmp) 
 -- some more manipulations with packet fields tx = tx + 1 txBufs[tx] = buf end end if tx > 0 then txBufs:resize(tx) txBufs:offloadTcpChecksums(ipv4) -- offload checksums to NIC txQ:send(txBufs) end 

L'idĂ©e gĂ©nĂ©rale de crĂ©er un ensemble de rĂ©ponses est la suivante. Tout d'abord, vous devez supprimer le paquet de la file d'attente RX, puis vĂ©rifier si le type de paquet correspond Ă  celui attendu. En cas de coĂŻncidence, prĂ©parez une rĂ©ponse en modifiant certains champs du package d'origine. Enfin, placez le paquet créé dans la file d'attente TX en utilisant le mĂȘme tampon. Pour amĂ©liorer les performances, au lieu de prendre les paquets un par un et de les modifier un par un, nous les agrĂ©gons, en extrayant tous les paquets disponibles de la file d'attente RX, en crĂ©ant les rĂ©ponses correspondantes et en les mettant tous dans la file d'attente TX. MalgrĂ© un nombre assez important de manipulations sur un mĂȘme package, les performances restent Ă©levĂ©es, principalement en raison du fait que Lua JIT compile toutes ces opĂ©rations dans un petit nombre d'instructions de processeur. De nombreux autres tests, non seulement TCP SYN / ACK, fonctionnent sur le mĂȘme principe.

Le tableau ci-dessous montre les résultats du test SYN flood (génération SYN sans tentatives de réponse) à l'aide de Mellanox ConnectX-4. Cette carte réseau possÚde deux ports 40G avec un plafond de performances théorique de 59,52 Mpps sur un port et 2 * 50 Mpps pour deux ports. L'implémentation spécifique de la connexion de la carte réseau au PCIe limite quelque peu la bande passante (donnant 2 * 50 au lieu des 2 * 59,52 attendus).
cƓurs par port1 port, Mpps2 ports, Mpps pour chaque port
12019
23836
356,547
459,550

Test d'inondation SYN; Carte réseau: famille Mellanox Technologies MT27700 (ConnectX-4), double port 40G; Processeur: Processeur IntelŸ XeonŸ Silver 4114 à 2,20 GHz

Le tableau suivant montre les rĂ©sultats du mĂȘme test d'inondation SYN effectuĂ© sur un Mellanox ConnectX-5 avec un port 100G.
noyauxMpps
135
269
3104
4127
5120
6131
7132
8144

Test d'inondation SYN; Carte réseau: famille Mellanox Technologies MT27800 (ConnectX-5), port 100G unique; Processeur: Processeur IntelŸ XeonŸ Silver 4114 à 2,20 GHz

Notez que dans tous les cas, nous atteignons plus de 96% du plafond de performance thĂ©orique sur un petit nombre de cƓurs de processeur.

Capturez le trafic entrant et enregistrez-le dans des fichiers PCAP


Un autre exemple du test est rx-to-pcap, qui tente de capturer tout le trafic entrant et de l'enregistrer dans un certain nombre de fichiers PCAP [ 8 ]. Bien que ce test ne concerne pas spĂ©cifiquement la gĂ©nĂ©ration de packages en tant que tels, il sert de dĂ©monstration du fait que le maillon le plus faible dans l'organisation du transfert de donnĂ©es via l'espace utilisateur est le systĂšme de fichiers. MĂȘme le systĂšme de fichiers virtuel tmpfs ralentit considĂ©rablement le flux. Dans ce cas, 8 cƓurs du processeur central sont nĂ©cessaires pour utiliser 14,88 Mpps, tandis qu'un seul cƓur suffit pour recevoir (et rĂ©initialiser ou rediriger) la mĂȘme quantitĂ© de trafic.

Le tableau suivant montre la quantité de trafic (en Mpps) qui a été reçue et enregistrée dans des fichiers PCAP situés dans le systÚme de fichiers ext2 sur le SSD (deuxiÚme colonne) ou sur le systÚme de fichiers tmpfs (troisiÚme colonne).
noyauxsur SSD, Mppssur tmpfs, Mpps
11,481,62
244.6
36,948.1
49,7511,65
512,113,8
613,3814,47
714,414,86
814,8814,88

Test Rx-to-pcap; Carte réseau: Intel 82599ES 10 Gigabit; CPU: IntelŸ XeonŸ CPU E5-2683 v4 @ 2.10GHz

Modification de MoonGen: tman Task Manager


Nous aimerions Ă©galement prĂ©senter au lecteur notre propre extension de la fonctionnalitĂ© MoonGen, qui fournit une autre façon de lancer un groupe de tĂąches pour les tests. L'idĂ©e principale ici est de sĂ©parer la configuration gĂ©nĂ©rale et les paramĂštres spĂ©cifiques Ă  chaque tĂąche, vous permettant d'exĂ©cuter un nombre arbitraire de tĂąches diffĂ©rentes (c'est-Ă -dire des scripts Lua) en mĂȘme temps. Dans notre clone du rĂ©fĂ©rentiel MoonGen, l'implĂ©mentation de MoonGen avec le gestionnaire de tĂąches [ 9 ] est prĂ©sentĂ©e, nous ne listerons ici que briĂšvement ses principales fonctions.

La nouvelle interface de ligne de commande vous permet d'exécuter simultanément plusieurs tùches de différents types. Le scénario de base est le suivant:

 ./build/tman [tman options...] [-- <task1-file> [task1 options...]] [-- <task2-file> [task2 options...]] [-- ...] 

De plus, ./build/tman -h fournit une aide détaillée.

Cependant, il existe une limitation: les fichiers de travail Lua standard ne sont pas compatibles avec l'interface tman . Le fichier de travail tman doit définir clairement les objets suivants:

  • La fonction configure (analyseur) qui dĂ©crit les paramĂštres du travail;
  • La fonction de tĂąche (taskNum, txInfo, rxInfo, args), qui dĂ©crit le processus de tĂąche rĂ©el. Ici, txInfo et rxInfo sont des tableaux de files d'attente RX et TX, respectivement; args contient les paramĂštres du gestionnaire de tĂąches et la tĂąche elle-mĂȘme.
  • Des exemples peuvent ĂȘtre trouvĂ©s dans examples / tman.

L'utilisation du gestionnaire de tùches vous donne plus de flexibilité pour exécuter des tests hétérogÚnes.

Conclusions


La méthode proposée par MoonGen s'est avérée bien adaptée à nos objectifs et a satisfait les employés avec les résultats obtenus. Nous avons obtenu un outil trÚs performant, tout en maintenant à la fois l'environnement de test et le langage assez simples. Les performances élevées de cette configuration sont obtenues grùce à deux caractéristiques principales: l'accÚs direct aux tampons du contrÎleur d'interface réseau et la technique de compilation Just-In-Time dans Lua.

En rĂšgle gĂ©nĂ©rale, la rĂ©alisation d'un plafond thĂ©orique pour les performances d'un contrĂŽleur d'interface rĂ©seau est une tĂąche rĂ©alisable. Comme nous l'avons montrĂ©, un seul cƓur peut suffire Ă  saturer un port 10G, tandis qu'une charge complĂšte d'un port 100G ne prĂ©sente pas de problĂšme particulier avec un plus grand nombre de cƓurs.

Nous sommes particuliÚrement reconnaissants à l'équipe Mellanox pour leur aide avec leur équipement et à l'équipe MoonGen pour leur réaction à la correction des erreurs.

Matériaux


  1. MoonGen: A Scriptable High-Speed ​​Packet Generator - Paul Emmerich et al., Internet Measurement Conference 2015 (IMC'15), 2015
  2. Pktgen
  3. Guide de réglage Mellanox
  4. Kit de développement de plan de données
  5. Lua
  6. Syn flood
  7. Clone du référentiel MoonGen de Qrator Labs
  8. Format de fichier PCAP
  9. Gestionnaire de tĂąches
  10. Performances Lua
  11. Livre blanc sur la virtualisation des fonctions réseau
  12. NUMA, accÚs mémoire non uniforme

Source: https://habr.com/ru/post/fr423957/


All Articles