Utiliser IPtables ou null route pour mettre sur liste noire environ 1 million d'adresses IP?

22

Je suis tombé sur une situation où un client doit mettre sur liste noire un ensemble d'un peu moins d'un million d'adresses IP individuelles (pas de sous-réseaux), et les performances du réseau sont une préoccupation. Bien que je suppose que les règles IPTables auraient moins d'impact sur les performances que les routes, ce n'est qu'une conjecture.

Quelqu'un a-t-il des preuves solides ou une autre justification pour favoriser IPTables ou le routage nul comme solution pour mettre sur liste noire les longues listes d'adresses IP? Dans ce cas, tout est automatisé, donc la facilité d'utilisation n'est pas vraiment un problème.

EDIT 26-Nov-11

Après quelques tests et développements, il semble qu'aucune de ces options ne soit réalisable. Il semble que les recherches d'itinéraire et iptables effectuent des recherches linéaires dans l'ensemble de règles et prennent tout simplement trop de temps pour traiter ces nombreuses règles. Sur le matériel moderne, mettre 1M d'éléments dans une liste noire iptables ralentit le serveur à environ 2 douzaines de paquets par seconde. Les IPTables et les routes nulles sont donc sortis.

ipset, comme recommandé par Jimmy Hedman, serait génial, sauf qu'il ne vous permet pas de suivre plus de 65536 adresses dans un ensemble, donc je ne peux même pas essayer de l'utiliser à moins que quelqu'un n'ait des idées.

Apparemment, la seule solution pour bloquer autant d'IP consiste à effectuer une recherche indexée dans la couche application. N'est-ce pas?


Plus d'information:

Dans ce cas, le cas d'utilisation empêche une liste d'adresses IP de "contrevenants connus" d'accéder à du contenu statique sur un serveur Web. FWIW, le blocage via Apache Deny fromest tout aussi lent (sinon plus) car il effectue également un balayage linéaire.


FYI: La solution de travail finale consistait à utiliser le mod_rewrite d'apache en conjonction avec une carte berkeley DB pour effectuer des recherches sur la liste noire. La nature indexée des bases de données berkeley a permis à la liste d'évoluer avec les performances O (log N).

tylerl
la source
5
L'ipset ( ipset.netfilter.org ) n'est-il pas moins conçu pour gérer ce type de problème?
Jimmy Hedman
@JimmyHedman: Vous devriez en faire une réponse. Et puis ajoutez une suggestion pour faire un benchmark en le faisant des 3 façons :)
MikeyB
Je suis curieux de savoir si vous pouvez donner un peu plus d'informations sur le problème que vous essayez de résoudre? Peut-être que le blocage des adresses IP 1M n'est pas le moyen de résoudre le problème?
SpacemanSpiff
Il serait très utile de savoir pourquoi vous souhaitez bloquer autant d'adresses et si vous souhaitez filtrer le trafic INPUT ou FORWARD.
Juliano
Ici, vous pouvez voir comment l'ipset rend les règles iptables environ 11 fois plus rapides que les règles iptables standard. daemonkeeper.net/781/mass-blocking-ip-addresses-with-ipset J'espère que cette aide.
Alien Torres

Réponses:

15

essayez d'utiliser iptables et de créer une arborescence à plusieurs niveaux pour réduire le nombre de recherches.

iptables -N rules_0_0_0_0_2
iptables -N rules_64_0_0_0_2
iptables -N rules_128_0_0_0_2
iptables -N rules_192_0_0_0_2
iptables -N rules_0_0_0_0_4
iptables -N rules_16_0_0_0_4

iptables -A INPUT -p tcp --dport 80 -s 0.0.0.0/2 -j rules_0_0_0_0_2
iptables -A INPUT -p tcp --dport 80 -s 64.0.0.0/2 -j rules_64_0_0_0_2
iptables -A INPUT -p tcp --dport 80 -s 128.0.0.0/4 -j rules_128_0_0_0_2
iptables -A INPUT -p tcp --dport 80 -s 192.0.0.0/4 -j rules_192_0_0_0_2

iptables -A rules_0_0_0_0_2 -s 0.0.0.0/4 -j rules_0_0_0_0_4
iptables -A rules_0_0_0_0_2 -s 16.0.0.0/4 -j rules_16_0_0_0_4

et ainsi de suite - ajout de niveaux d'imbrication; évidemment, vous aurez besoin d'un moyen automatique de construire les règles et vous devriez avoir des chaînes uniquement pour les réseaux où vous avez un ou plusieurs délinquants - de cette façon, vous pouvez réduire le nombre de recherches qui doivent être faites de manière assez significative et je pense que cela pourrait fonctionne réellement.

pQd
la source
Cela semble fonctionner, réduisant efficacement la complexité temporelle de la recherche de règles de pare-feu de O (n) à O (log n), créant efficacement une arborescence de recherche dans iptables.
Per von Zweigbergk
Si vous décidez de suivre cette voie, il serait probablement utile d'utiliser un algorithme pour créer une arborescence de recherche binaire équilibrée à partir de la liste des adresses IP, puis de simplement vider la structure de cette arborescence de recherche sous la forme d'un ensemble de règles IPtables.
Per von Zweigbergk
@Per von Zweigbergk - en effet ... ou simplement élaguer l'arbre tôt où il n'est pas nécessaire d'effectuer des recherches plus approfondies. bien que charger cette quantité impie de règles prendra beaucoup de temps.
pQd
C'est une très bonne approche. Évidemment, cela nécessite un peu de traitement, mais c'est la bonne idée, je pense.
tylerl
3
@pQd après les échecs précédents avec iptables et al., j'ai implémenté une solution dans apache en utilisant un RewriteMap avec la base de données Berkeley. Mais mon mon mécanisme le plus rapide utilisant iptables dans une boucle a chargé environ 100 règles par seconde, tandis que iptables-restore a fait l'ensemble en environ 4 secondes. C'est sur un ordinateur de bureau haut de gamme. Le mécanisme RewriteMap a un impact indétectablement faible sur les performances.
tylerl
11

C'est exactement pour ça ipset.

Depuis son site Web http://ipset.netfilter.org/ :

Si tu veux

  • stockez plusieurs adresses IP ou numéros de port et comparez-les à la collection par iptables d'un seul coup;
  • mettre à jour dynamiquement les règles iptables par rapport aux adresses IP ou aux ports sans perte de performances;
  • exprimer des ensembles de règles complexes basés sur des adresses IP et des ports avec une seule règle iptables et bénéficier de la vitesse des ensembles IP

alors l'ipset peut être l'outil approprié pour vous.

Il est écrit par un membre de l'équipe de base de Netfilter, Jozsef Kadlecsik (qui a également écrit la cible REJECT), c'est donc le meilleur choix auquel je puisse penser.

Il est même inclus dans les noyaux récents.

cstamas
la source
Pour autant que je l'ai vu, l'ipset dépasse les adresses IP 65k. Existe-t-il un type d'ensemble capable de gérer les entrées 1M?
tylerl
7
Si vous utilisez le type de jeu hash: ip, vous pouvez avoir un très grand nombre d'adresses. J'ai essayé 1000000 et la performance était assez bonne. Si vous configurez une règle -m state --state ESTABLISHED avant de vérifier votre ensemble, vous pouvez vous assurer de ne vérifier l'ensemble sur de nouvelles connexions qui augmenteraient les performances lors du traitement d'un grand nombre de paquets.
Matthew Ife
Il convient de mentionner cependant que l'utilisation de la mémoire d'un ipset avec des adresses 1M commence à devenir importante. Selon cet article sur la liste de diffusion netfilter, la formule actuelle de 2015 pour la taille de hachage de l'ipset est H * 40byte + (N/4 + N%4) * 4 * element sized'environ 64 Mo pour 1M d'adresses dans un hachage de 1,5 m. L'utilisation de la solution apache / berkdb stocke les données sur disque et ne charge que les pages des adresses actives.
M Conrad
5

Je n'ai pas testé cela moi-même, mais quand j'ai entendu la description de votre problème, j'ai immédiatement pensé " pf" (comme d'OpenBSD).

pf a le concept de tables d'adresses qui peut être juste ce que vous cherchez.

Selon certaines recherches très sommaires que j'ai faites, il semblerait que cela puisse évoluer mieux que ipset. Selon le chapitre de la FAQ de PF sur les options d'exécution, prêt à l'emploi sans réglage, pf prend en charge un total de 1 000 tables, avec un total de 200 000 entrées sur toutes les tables par défaut. (100 000 si le système a une mémoire physique <100 Mo). Cela m'amène à croire qu'il vaut au moins la peine d'essayer de tester cela pour voir s'il fonctionne à un niveau utile.

Bien sûr, je suppose que vous exécutez vos serveurs sous Linux, vous devez donc disposer d'un pare-feu séparé exécutant un système d'exploitation avec pf (comme OpenBSD ou FreeBSD). Vous pouvez également améliorer le débit en supprimant tout type de filtrage de paquets avec état.

Per von Zweigbergk
la source
La conversion de l'architecture du serveur du client en BSD n'est pas vraiment une option. Penser hors de la boîte au moins, cependant.
tylerl
2
Vous n'auriez pas à convertir toute l'architecture du serveur en BSD, il suffirait de construire un pare-feu à mettre devant le vrai serveur. (Assez facile à faire dans une machine virtuelle.)
Par von Zweigbergk
2

Avez-vous étudié l'utilisation d'un FIB_TRIE au lieu de FIB_HASH.

FIB_TRIE devrait évoluer beaucoup mieux pour le nombre de préfixes. (Les routes nulles / 32s sont toujours des préfixes, juste très spécifiques)

Vous devrez peut-être compiler votre propre noyau pour l'utiliser, mais cela aide.

FIB_TRIE Notes

Joel K
la source
2

Pour la postérité: selon les ipsetdocuments, la taille par défaut d'un ensemble est 65536, cela peut être modifié par les options.

maxelem Ce paramètre est valide pour la commande create de tous les ensembles de types de hachage. Il définit le nombre maximal d'éléments pouvant être stockés dans l'ensemble, 65536 par défaut. Exemple:ipset create test hash:ip maxelem 2048.

Je mets ceci ici car je ne peux pas encore commenter.

plitter
la source
1

Quelques notes utiles pour tous ceux qui tomberont sur ce problème à l'avenir:

Tout d'abord, n'analysez aucun trafic dont vous n'avez pas besoin. Si vous bloquez le trafic TCP, par exemple, ne filtrez que les paquets SYN, de cette façon vous n'appuyez sur le filtre qu'une seule fois par connexion. Vous pouvez l'utiliser -m statesi vous le souhaitez, mais le suivi des connexions a sa propre surcharge que vous pouvez éviter si les performances sont un problème.

Deuxièmement, mettre un million de règles dans iptables prend beaucoup de temps: plusieurs minutes. Si vous avez besoin de suivre autant d'entités, vous feriez probablement mieux de les garder hors de Netfliter. La taille même de l'ensemble de règles fait une différence.

Troisièmement, l'objectif est d'éviter les balayages linéaires; mais malheureusement, iptables et iproute2 sont intrinsèquement linéaires. Vous pouvez diviser vos règles en style arbre binaire en un grand nombre de chaînes, ce qui limite le nombre de règles que vous devez consulter, mais même quand même, iptables n'est pas bien adapté à cette taille de problème. Cela fonctionnera , mais c'est un gaspillage de ressources précieuses.

Quatrièmement et surtout, pousser votre charge de travail vers l'espace utilisateur n'est pas une mauvaise idée. Cela vous permet d'écrire votre propre code serré ou d'utiliser une solution standard adaptée à votre ensemble de problèmes. Ma propre solution à ce problème, comme mentionné, était d'utiliser des recherches BDB déclenchées par le système mod_rewrite d'Apache. Cela avait l'avantage supplémentaire de déclencher une seule recherche par session, et uniquement après qu'une demande valide avait été soumise. Dans ce cas, les performances étaient extrêmement rapides et le coût de la liste de blocage était presque négligeable.

Vous pouvez effectuer une manipulation similaire de l'espace utilisateur avec iptables en utilisant la -j QUEUEcible conjointement aveclibnetfilter_queue . Cet outil est puissant, simple et mal documenté. Je recommanderais de lire autant que possible à partir d'autant de sources que vous pouvez trouver, car il y a beaucoup de documents intéressants dispersés sur le Web qui ne font partie d'aucune documentation officielle.

tylerl
la source