Comment les arbres de base bloquent les ips 5000 fois plus rapidement – sqreen blog sécurité des applications modernes aretha franklin sens

Pour la plupart des gens, ce que vous apprenez au cours de vos études universitaires n’aide pas beaucoup votre travail quotidien. Cela étant dit, vous rencontrez parfois un problème qui aurait pu être un exemple utilisé par un professeur de CS lors de l’introduction de notions de base. C’est un exemple en ce qui concerne les structures de données. Qu’est-il arrivé

Il y a quelque temps, l’un de nos clients a subi une attaque assez intense. Bien que nous ayons détecté et identifié les attaquants sur la liste noire comme prévu, les performances de l’application ont été optimisées. Au cours de l’autopsie, nous nous sommes rendus compte que, lors de l’attaque, nous avions bloqué environ dix mille ips. Le mécanisme de blocage IP peut être en cause. Plus précisément, celui intégré aux agents de sqreen, un composant logiciel installé sur les serveurs de nos clients.


Comment sqreen avait l’habitude de bloquer ips

Chaque fois qu’une menace est détectée et bloquée, nos agents insèrent l’adresse IP bloquée dans une liste. Cette liste était ensuite vérifiée de manière séquentielle chaque fois qu’une demande était évaluée par un agent, augmentant ainsi le temps de latence de l’application de notre client. C’était une opération O (n) qui est devenue problématique pour le téléchargement de musique éthiopienne une fois que nous avons trouvé environ cinq mille adresses IP bloquées, beaucoup plus tôt que prévu. Comment avons-nous amélioré sqreen?

L’informatique est très souvent une histoire de compromis. Dans notre cas, nous devions effectuer des recherches très rapidement (elles sont dans notre hot-path), mais nous étions disposés à accepter une pénalité de performance (raisonnable) lors de l’insertion de nouvelles adresses. Les meilleurs candidats sont les arbres binaires et, en particulier, une structure commune aux routeurs de réseau appelée arbre à base de données. Un arbre? &# 127795;

Fondamentalement, prenez un nœud (8). Ce nœud sera la racine de votre arbre. Ce nœud peut être relié à deux autres nœuds (3 et 10), appelés «enfants». Chacun de ces nœuds peut avoir jusqu’à deux enfants, etc. Tout le réseau, à partir de la racine, est l’arborescence. Cela s’appelle binaire car les nœuds ne peuvent avoir que deux enfants. Un arbre binaire dans son habitat naturel des arbres de recherche binaires

Afin de rendre notre décision plus claire sur l’architecture ethereum, je dois couvrir un type d’arbres binaires appelés arbres de recherche binaires et leur variante d’auto-équilibrage. L’arbre ci-dessus est un arbre de recherche binaire. Sa particularité réside dans la manière dont les nœuds sont disposés. Plus précisément, vous pouvez trouver n’importe quel nœud en suivant un algorithme très simple:

La partie auto-équilibrée intervient lors de l’insertion de nouveaux nœuds. Le problème de l’insertion naïve de nouveaux nœuds dans un arbre binaire est que votre arbre peut être très profond. Essayez d’insérer 12 dans l’arborescence ci-dessus: suivez la logique de recherche et insérez le nouveau noeud partout où vous vous attendez à trouver l’enfant pdf du protocole Ethernet. Vous devez le placer sous 13, ce qui rend l’arbre très profond (et comme notre temps d’accès dépend de la profondeur de l’arbre, regarder plus lentement une valeur). L’arbre de recherche binaire ci-dessus dans lequel 12 a été inséré naïvement

Les arbres Radix incorporent leurs données dans la séquence des arêtes menant au nœud. Cela signifie que seules les feuilles (les nœuds en bas) représentent réellement une valeur codée. Ceci étant dit, la valeur codée n’est pas la valeur de la feuille (1, 4 ou 7) mais bien le chemin qui y conduit: le nœud 4 code en fait la valeur 8 3 6 4, comme vous pouvez le voir dans l’animation ci-dessous . Cela rend les arbres très économes en espace, car les feuilles ne doivent pas stocker leurs préfixes. Par exemple, 8 3 6 est commun aux valeurs codées par 4 et 7, mais ne doit être écrit qu’une fois dans l’arborescence.

Les arbres Radix utilisent également ce que l’on appelle «compression de chemin»: dans notre arbre, 10 n’a aucune raison de devenir un nœud indépendant: nous pouvons économiser sur la charge du nœud en le fusionnant avec 13 et en créant un seul nœud 10 13. En effet, seules les feuilles (12 et 14) spécifient une valeur et tout le reste code le préfixe de ces feuilles. La compression du chemin d’exposition de l’arbre de base et l’accès à la valeur contenue dans la feuille 4 sont corrects, donc un arbre de base est un arbre binaire optimisé. Est-ce vraiment mieux cependant?

Bien qu’elles soient représentées comme une suite de nombres décimaux (127.0.0.1, ipv4) ou hexadécimaux (e3e7: 682: c209: 4cac: 629f: 6fbe: d82c: 7cd, ipv6), les adresses IP sont en interne un seul nombre (codé à 32 bits) , 2130706433 pour ipv4 ou 128 bits, 302934307671667531413257853548643485645 pour ipv6).

Cela signifie qu’il peut facilement être représenté sous forme binaire. Le fait de pouvoir représenter chaque adresse ipv4 à l’aide d’une séquence ordonnée de 32 bits facilite la construction de l’arbre de bases. Chaque nœud contient un ou plusieurs bits et le prochain enfant à choisir ethan dolan dépend du prochain bit de l’adresse recherchée. Mais qu’en est-il mixte ipv4 et ipv6?!

Belle prise. Notre structure de données contient deux arbres, un pour chaque type d’adresse. Ces arbres sont fonctionnellement identiques, mais assurons-nous que les données de chaque arbre aient un nouveau film éthiopien d’une longueur fixe (32 bits pour l’arbre ipv4, 128 bits pour ipv6). Cela nous permet d’optimiser le code de recherche.

Chaque fois qu’une nouvelle adresse arrive et que nous devons vérifier la liste noire, nous prenons l’arbre approprié et commençons à l’explorer. Nous parcourons le chemin correspondant à notre préfixe, en recherchant un nœud sur lequel nous divergent. Un nœud diverge lorsque le préfixe qu’il représente diffère de celui de l’adresse que nous comparons. Par exemple, dans l’exemple ci-dessous, si nous recherchions l’adresse 8 10 11 12, nous en ferions correspondre 8, mais pas 10 13, cela se produit lorsque de tous les ips que nous avons ajoutés, aucun ne partage le même préfixe que le nôtre (les seules valeurs dans cet arbre commençant par le préfixe 8 10 sont 8 10 13 12 et 8 10 13 14). La même chose se produirait dans l’arbre si la compression du chemin n’était pas utilisée. Arbre de base qui tente de rechercher 8 10 11 12 et échoue lorsque le préfixe diverge, indiquant que les données n’existent pas dans l’arbre (ce qui est correct)

Si nous essayons d’insérer un nouveau nœud, nous devons trouver le nœud divergent. Ensuite, nous l’avons divisé au point où nous avons différé afin que le nœud soit coupé entre un nœud parent et un enfant. Le nœud parent correspond à notre préfixe tandis que l’enfant contient tous les anciens enfants du nœud d’origine. Nous créons ensuite un nouveau nœud représentant l’adresse que nous ajoutons et l’insérons dans l’emplacement maintenant libre du nœud parent.

De plus, en raison de la complexité intrinsèque de la structure en termes de temps, le temps de recherche augmentera également beaucoup plus lentement (opérations log (N) par rapport à N / 2 en moyenne, où N est le nombre d’ips bloqués) par rapport à l’ancienne structure, ce qui accroît les performances. encore plus grand à mesure que le nombre d’adresses bloquées augmente. Combien de comparaisons (itérations) faut-il pour trouver une correspondance dans l’arbre, en fonction du nombre d’adresses

Enfin, étant donné que l’arborescence de bases ne tient pas compte des doublons, la valeur maximale de N pour une arborescence de racines est de 2 32 pour macbeth act 1 scène 4 résumé ipv4 et de 2 128 pour ipv6. Ce sont des valeurs astronomiques quand on regarde N ou N / 2, mais log (N) les réduit à… 32 et 128 &# 128516 ;. Dans le pire des cas, il faudra 128 problèmes éthiques dans les itérations de soins de santé pour trouver une correspondance dans un arbre à base de radix, contre 3… suivi de 38 zéros dans l’ancien système.

En revanche, le temps d’insertion a été considérablement réduit (entre 2 et 5 fois, bien que cette pénalité ne s’aggrave pas de manière significative lorsqu’on bloque plus d’adresses). La mémoire requise pour stocker la structure de données a également légèrement augmenté (en fonction du temps d’exécution, entre quelques pour cent et le double de l’espace requis). Toutefois, comme les insertions plus lentes ne rendent pas les applications de nos clients moins réactives, le passage à un blocage IP basé sur un arbre à base de bases est un très bon résultat. Pourquoi n’avez-vous pas utilisé X?

Les tables de hachage ne nous convenaient pas bien, car les plages de réseaux nous obligeaient à effectuer 32 recherches (pour ipv4, mais 128 pour ipv6!) Et étaient plus onéreuses en termes de mémoire. De plus, les implémentations les plus courantes ne garantissent pas un temps d’accès constant (surtout si vous êtes malchanceux et que beaucoup d’ips se retrouvent dans le même seau).

Les filtres Bloom étaient de bons prétendants, mais nous aurions tout de même demandé que nous recherchions la liste lors d’un match, ouvrant ainsi la porte à une attaque de type DOS par des attaquants via l’épuisement du processeur. C’était une mesure d’atténuation intéressante que nous pourrions envisager à nouveau à l’avenir, mais ne nous débarrassait pas vraiment du problème.

Stocker les ips dans une base de données en mémoire n’a pas été sérieusement envisagé, principalement parce que nous pensions que l’exploration d’Ethereum Blockchain était très lourde, en particulier du point de vue de la mémoire. Ils rencontreraient le même problème que les tables de hachage (jusqu’à 128 recherches pour une correspondance négative). Nous voulions également éviter de créer une saturation de sqreen avec trop de dépendances.

Nous avons eu quelques suggestions ésotériques supplémentaires que nous n’avons pas prises en compte en raison des coûts de maintenance, car nous aurions à les écrire et les maintenir pour chaque langue que nous prenons en charge. De plus, ils ne seraient généralement pas beaucoup plus rapides qu’un arbre à base, ce qui les rendrait encore moins attrayants pour nous. Mots finaux

Rendre Internet plus sécurisé n’est pas une tâche facile. Bien que notre position avantageuse au sein des applications de nos clients nous aide, cela signifie que toute inefficacité de nos logiciels constitue une responsabilité pour les leurs. L’exemple que j’ai détaillé au début de cet article en est une parfaite illustration: l’application était déjà attaquée et la protection de sqreen a commencé à la ralentir.