Utilizzare IPtables o route null per inserire nella blacklist circa 1 milione di indirizzi IP?


22

Mi sono imbattuto in una situazione in cui un client deve inserire nella blacklist un insieme di poco meno di 1 milione di singoli indirizzi IP (senza subnet) e le prestazioni della rete sono un problema. Mentre suppongo che le regole di IPTables abbiano meno impatto sulle prestazioni rispetto alle route, si tratta solo di congetture.

Qualcuno ha prove concrete o altre giustificazioni per favorire le IPTables o il routing null come soluzione per la lista nera di lunghi elenchi di indirizzi IP? In questo caso, tutto è automatizzato, quindi la facilità d'uso non è davvero un problema.

MODIFICA 26-Nov-11

Dopo alcuni test e sviluppi, sembra che nessuna di queste opzioni sia praticabile. Sembra che entrambe le ricerche di route e iptables eseguano ricerche lineari attraverso il set di regole e impieghino troppo tempo per elaborare queste regole. Su hardware moderno, l'inserimento di elementi 1M in una lista nera di iptables rallenta il server a circa 2 dozzine di pacchetti al secondo. Quindi IPTables e route null sono fuori.

ipset, come raccomandato da Jimmy Hedman, sarebbe fantastico, tranne per il fatto che non ti consente di tracciare più di 65536 indirizzi in un set, quindi non posso nemmeno provare a usarlo a meno che qualcuno non abbia idee.

Apparentemente l'unica soluzione per bloccare così tanti IP è fare una ricerca indicizzata nel livello dell'applicazione. Non è così?


Maggiori informazioni:

Il caso di utilizzo in questo caso sta impedendo a un elenco di indirizzi IP di "autori di reati noti" di accedere al contenuto statico su un server Web. FWIW, fare il blocco attraverso Apache Deny fromè altrettanto lento (se non di più) in quanto esegue anche una scansione lineare.


Cordiali saluti: La soluzione di lavoro finale era usare il mod_rewrite di apache in congiunzione con una mappa berkeley DB per fare ricerche contro la lista nera. La natura indicizzata dei DB berkeley ha permesso all'elenco di scalare con le prestazioni O (log N).


5
Ipset ( ipset.netfilter.org ) non è meno progettato per gestire questo tipo di problema?
Jimmy Hedman,

@JimmyHedman: dovresti dare una risposta. E poi aggiungi un suggerimento al benchmark facendo tutto in 3 modi :)
MikeyB,

Sono curioso di sapere se puoi fornire qualche informazione in più su quale problema stai cercando di risolvere? Forse bloccare gli indirizzi IP 1M non è il modo per risolvere il problema?
SpacemanSpiff

Aiuterebbe molto sapere perché vuoi bloccare questi indirizzi e se vuoi filtrare il traffico INPUT o FORWARD.
Juliano,

Qui puoi vedere come ipset rende le regole di iptables circa 11 volte più veloci delle normali regole di iptables. daemonkeeper.net/781/mass-blocking-ip-addresses-with-ipset Spero che questo aiuto.
Alien Torres,

Risposte:


15

prova a usare iptables e costruisci un albero multi-livello per ridurre il numero di ricerche.

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

e così via - aggiunta di livelli di annidamento; ovviamente avrai bisogno di un modo automatico di costruire le regole e dovresti avere catene solo per le reti in cui hai uno o più criminali - in questo modo puoi ridurre il numero di ricerche che devono essere fatte in modo abbastanza significativo e penso che potrebbe funziona davvero.


Questo suona come se potesse funzionare, riducendo efficacemente la complessità temporale della ricerca delle regole del firewall da O (n) a O (log n), costruendo efficacemente un albero di ricerca in iptables.
Per von Zweigbergk,

Se decidi di seguire questa strada, sarebbe probabilmente utile utilizzare un algoritmo per creare un albero di ricerca binaria bilanciato dall'elenco degli indirizzi IP, quindi scaricare semplicemente la struttura di tale albero di ricerca come un insieme di regole IPtables.
Per von Zweigbergk,

@Per von Zweigbergk - anzi ... o pota l'albero presto dove non c'è bisogno di fare ricerche più profonde. anche se caricare quella quantità empia di regole richiederà molto tempo.
pQd

Questo è un ottimo approccio. Ovviamente richiede un po 'di elaborazione da mantenere, ma è l'idea giusta, credo.
tylerl,

3
@pQd dopo precedenti errori con iptables et al., ho implementato una soluzione in apache usando un RewriteMap con il database Berkeley. Ma il mio meccanismo più veloce usando iptables in un loop ha caricato circa 100 regole al secondo, mentre iptables-restore ha fatto l'intero set in circa 4 secondi. Questo è su un computer desktop top di gamma. Il meccanismo RewriteMap ha un impatto irrimediabilmente basso sulle prestazioni.
tylerl,

11

Questo è esattamente ciò che ipsetserve.

Dal suo sito web http://ipset.netfilter.org/ :

Se lo desidera

  • memorizzare più indirizzi IP o numeri di porta e confrontarli con la raccolta di iptables in un colpo solo;
  • aggiornare dinamicamente le regole di iptables contro indirizzi IP o porte senza penalità di prestazione;
  • esprimere complessi indirizzi IP e set di regole basati su porte con un'unica regola iptables e trarre vantaggio dalla velocità dei set IP

allora ipset potrebbe essere lo strumento giusto per te.

È stato scritto da Jozsef Kadlecsik, membro del core team di netfilter (che ha anche scritto l'obiettivo REJECT), quindi questa è la scelta migliore che mi viene in mente.

È anche incluso nei kernel recenti.


Per quanto ho visto, ipset supera a 65k indirizzi IP. Esiste un tipo di set in grado di gestire voci 1M?
tylerl,

7
Se usi il tipo di hash: ip set puoi avere un numero molto grande di indirizzi. Ho provato 1000000 e le prestazioni sono state abbastanza buone. Se si imposta una regola ESTABLISHED -m state --state prima di controllare il proprio set, è possibile assicurarsi di controllare il set solo su nuove connessioni che aumenterebbero le prestazioni quando si ha a che fare con un numero elevato di pacchetti.
Matthew Ife,

Vale la pena ricordare che l'utilizzo della memoria di un ipset con indirizzi 1M inizia a diventare grande. Secondo questo post sulla mailing list di netfilter, l'attuale formula 2015 per la dimensione dell'hash dell'ipset è H * 40byte + (N/4 + N%4) * 4 * element sizedi circa 64 MB per gli indirizzi 1M in un hash dello slot di 1,5 m. L'uso della soluzione apache / berkdb archivia i dati sul disco e carica solo le pagine degli indirizzi attivi.
M Conrad,

5

Non l'ho provato io stesso, ma quando ho sentito la descrizione del tuo problema ho pensato subito " pf" (come da OpenBSD).

pfha il concetto di tabelle di indirizzi che potrebbero essere proprio quello che stai cercando.

Secondo alcune ricerche molto superficiali che ho fatto, sembrerebbe che questo abbia il potenziale per ridimensionarsi meglio di ipset. Secondo il capitolo FAQ di PF sulle opzioni di runtime , pronto all'uso senza messa a punto, pf supporta un totale di 1.000 tabelle, con un totale di 200.000 voci su tutte le tabelle per impostazione predefinita. (100.000 se il sistema ha <100 MB di memoria fisica). Questo mi porta a credere che valga la pena provare a provare questo per vedere se funziona a qualsiasi livello utile.

Ovviamente, suppongo che tu stia eseguendo i tuoi server su Linux, quindi dovresti avere un firewall box separato che esegue un sistema operativo con pf (come OpenBSD o FreeBSD). Potresti anche essere in grado di migliorare la velocità eliminando qualsiasi tipo di filtro dei pacchetti con stato.


La conversione dell'architettura del server del client in BSD non è in realtà un'opzione. Almeno per pensare fuori dagli schemi.
tylerl,

2
Non dovresti convertire l'intera architettura del server in BSD, sarebbe sufficiente costruire un firewall da mettere davanti al server reale. (Abbastanza facile da fare in una macchina virtuale.)
Per von Zweigbergk,

2

Hai studiato utilizzando un FIB_TRIE invece di FIB_HASH.

FIB_TRIE dovrebbe adattarsi molto meglio ai conteggi dei prefissi. (/ 32s null null sono ancora prefissi, solo molto specifici)

Potrebbe essere necessario compilare il proprio kernel per usarlo, ma aiuta.

Note FIB_TRIE


2

Per i posteri: secondo i ipsetdocumenti, la dimensione predefinita di un set è 65536, che può essere modificata dalle opzioni.

maxelem Questo parametro è valido per il comando create di tutti i set di tipi di hash. Definisce il numero massimo di elementi che possono essere memorizzati nel set, valore predefinito 65536. Esempio:ipset create test hash:ip maxelem 2048.

L'ho messo qui poiché non posso ancora commentare.


1

Alcune note utili per chiunque si imbatte in questo problema in futuro:

Prima di tutto, non analizzare il traffico che non è necessario. Se stai bloccando il traffico TCP, ad esempio, filtra solo i pacchetti SYN, in questo modo colpisci il filtro solo una volta per connessione. Puoi usarlo -m statese lo desideri, ma il tracciamento della connessione ha il suo overhead che potresti voler evitare se le prestazioni sono un problema.

Secondo, inserire un milione di regole in iptables richiede molto tempo: diversi minuti. Se devi tenere traccia di così tante entità, probabilmente ti conviene tenerlo fuori da netfliter. La semplice dimensione del set di regole fa la differenza.

In terzo luogo, l'obiettivo è evitare scansioni lineari; ma sfortunatamente, sia iptables che iproute2 sono intrinsecamente lineari. Puoi dividere le tue regole in stile albero binario in un gran numero di catene, il che limita il numero di regole che devi consultare, ma anche iptables non è adatto a questa dimensione del problema. Essa funzionerà , ma è uno spreco di risorse preziose.

In quarto luogo, e soprattutto, spingere il carico di lavoro nello spazio utenti non è una cattiva idea. Ciò consente di scrivere il proprio codice stretto o di utilizzare una soluzione standard adattata al set di problemi. La mia soluzione a questo problema, come detto, era usare le ricerche BDB attivate attraverso il sistema mod_rewrite di apache. Ciò ha avuto l'ulteriore vantaggio di innescare una sola ricerca per sessione e solo dopo aver inviato una richiesta valida. In questo caso, le prestazioni sono state estremamente veloci e il costo della blocklist era quasi trascurabile.

È possibile eseguire una manipolazione simile dello spazio utente con iptables utilizzando la -j QUEUEdestinazione insieme a libnetfilter_queue. Questo strumento è potente, semplice e scarsamente documentato. Consiglierei di leggere il più possibile da quante più fonti puoi trovare, in quanto c'è un sacco di materiale interessante sparso sul web che non fa parte di alcuna documentazione ufficiale.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.