Użyć tabeli IP lub trasy zerowej do umieszczenia na czarnej liście około 1 miliona adresów IP?

22

Zetknąłem się z sytuacją, w której klient musi umieścić na czarnej liście zestaw nieco poniżej 1 miliona pojedynczych adresów IP (bez podsieci), a wydajność sieci stanowi problem. Chociaż przypuszczam, że reguły IPTables będą miały mniejszy wpływ na wydajność niż trasy, to tylko przypuszczenie.

Czy ktoś ma jakieś solidne dowody lub inne uzasadnienie faworyzowania IPTables lub zerowego routingu jako rozwiązania dla czarnej listy długich list adresów IP? W tym przypadku wszystko jest zautomatyzowane, więc łatwość użytkowania nie jest tak naprawdę problemem.

EDYCJA 26-lis-11

Po kilku testach i pracach rozwojowych wydaje się, że żadna z tych opcji nie jest wykonalna. Wygląda na to, że zarówno przeszukiwanie trasy, jak i iptables przeszukują liniowo zestaw reguł, a przetworzenie tak wielu reguł zajmuje zbyt długo. Na nowoczesnym sprzęcie umieszczenie 1 mln pozycji na czarnej liście iptables spowalnia serwer do około 2 tuzinów pakietów na sekundę. Więc IPTables i trasy zerowe są niedostępne.

ipset, jak zaleca Jimmy Hedman, byłoby świetnie, z tym wyjątkiem, że nie pozwala ci śledzić więcej niż 65536 adresów w zestawie, więc nie mogę nawet próbować go używać, chyba że ktoś ma jakieś pomysły.

Najwyraźniej jedynym rozwiązaniem blokującym tak wiele adresów IP jest indeksowane wyszukiwanie w warstwie aplikacji. Czy to nie tak?


Więcej informacji:

Przypadkiem użycia w tym przypadku jest blokowanie listy adresów IP znanych przestępców przed dostępem do zawartości statycznej na serwerze sieciowym. FWIW, blokowanie przez Apache'a Deny fromjest równie powolne (jeśli nie bardziej), ponieważ wykonuje również skanowanie liniowe.


FYI: Ostatnim działającym rozwiązaniem było użycie mod_rewrite apache w połączeniu z mapą DB Berkeley do wyszukiwania na czarnej liście. Zindeksowana natura baz danych Berkeley pozwoliła na skalowanie listy z wydajnością O (log N).

tylerl
źródło
5
Czy ipset ( ipset.netfilter.org ) nie jest mniej zaprojektowany do obsługi tego typu problemów?
Jimmy Hedman
@ JimmyHedman: Powinieneś udzielić odpowiedzi. A potem dodaj sugestię do testu porównawczego, robiąc to na 3 sposoby :)
MikeyB
Jestem ciekawy, czy możesz podać trochę więcej informacji na temat problemu, który próbujesz rozwiązać? Być może blokowanie adresów IP 1M nie jest sposobem na rozwiązanie problemu?
SpacemanSpiff
Bardzo pomogłoby wiedzieć, dlaczego chcesz zablokować tak wiele adresów, a także chcesz filtrować ruch INPUT lub FORWARD.
Juliano
Tutaj możesz zobaczyć, w jaki sposób ipset tworzy reguły iptables około 11 razy szybciej niż zwykłe reguły iptables. daemonkeeper.net/781/mass-blocking-ip-addresses-with-ipset Mam nadzieję, że ta pomoc.
Alien Torres,

Odpowiedzi:

15

spróbuj użyć iptables i zbuduj drzewo wielopoziomowe, aby zmniejszyć liczbę wyszukiwań.

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

i tak dalej - dodawanie poziomów zagnieżdżania; oczywiście potrzebujesz automatycznego sposobu budowania reguł i powinieneś mieć łańcuchy tylko dla sieci, w których masz jednego lub więcej przestępców - w ten sposób możesz zmniejszyć liczbę wyszukiwań, które trzeba wykonać dość znacząco i myślę, że może faktycznie działa.

pQd
źródło
Brzmi to tak, jakby mogło działać, skutecznie zmniejszając złożoność czasową wyszukiwania reguł zapory z O (n) do O (log n), skutecznie budując drzewo wyszukiwania w iptables.
Per von Zweigbergk
Jeśli zdecydujesz się pójść tą drogą, prawdopodobnie przydatne byłoby użycie jakiegoś algorytmu do zbudowania zrównoważonego drzewa wyszukiwania binarnego z listy adresów IP, a następnie po prostu zrzucenie struktury tego drzewa wyszukiwania jako zestawu reguł IPtables.
Per von Zweigbergk
@Per von Zweigbergk - rzeczywiście ... lub po prostu przycinaj drzewo wcześnie, tam, gdzie nie ma potrzeby głębszego wyszukiwania. chociaż ładowanie tej bezbożnej ilości reguł zajmie dużo czasu.
pQd
To bardzo dobre podejście. Oczywiście utrzymanie wymaga nieco przetwarzania, ale myślę, że to dobry pomysł.
tylerl
3
@pQd po poprzednich awariach w iptables i wsp., zaimplementowałem rozwiązanie w apache przy użyciu RewriteMap z bazą danych Berkeley. Ale mój najszybszy mechanizm wykorzystujący iptables w pętli ładował około 100 reguł na sekundę, podczas gdy iptables-restore wykonał cały zestaw w około 4 sekundy. Jest to najwyższej klasy komputer stacjonarny. Mechanizm RewriteMap ma niewykrywalnie mały wpływ na wydajność.
tylerl
11

Właśnie po to ipsetjest.

Ze strony internetowej http://ipset.netfilter.org/ :

Jeśli chcesz

  • przechowuj wiele adresów IP lub numerów portów i dopasuj do kolekcji za pomocą iptables za jednym zamachem;
  • dynamicznie aktualizuj reguły iptables względem adresów IP lub portów bez obniżania wydajności;
  • ekspresowe złożone adresy IP i zestawy reguł oparte na portach za pomocą jednej reguły iptables i skorzystaj z prędkości zestawów IP

ipset może być dla Ciebie odpowiednim narzędziem.

Jest napisany przez członka zespołu podstawowego filtra sieci Jozsefa Kadlecsika (który również napisał cel REJECT), więc jest to najlepszy wybór, jaki mogę wymyślić.

Jest nawet zawarty w najnowszych jądrach.

cstamas
źródło
O ile widziałem, ipset osiąga 65 000 adresów IP. Czy jest jakiś typ zestawu, który może obsługiwać wpisy 1M?
tylerl
7
Jeśli używasz typu skrótu: ip, możesz mieć bardzo dużą liczbę adresów. Próbowałem 1000000 i wydajność była całkiem dobra. Jeśli ustawisz regułę -m stan --state ESTABLISHED przed sprawdzeniem zestawu, możesz upewnić się, że sprawdzasz go tylko na nowych połączeniach, co zwiększyłoby wydajność w przypadku dużej liczby pakietów.
Matthew Ife
Warto jednak wspomnieć, że zużycie pamięci przez ipset z adresami 1M zaczyna być coraz większe. Zgodnie z tym postem na liście mailingowej netfilter obecna formuła na 2015 r. Dla rozmiaru skrótu ipset wynosi H * 40byte + (N/4 + N%4) * 4 * element sizeokoło 64 MB dla 1M adresów w mieszaniu 1,5-milimetrowym. Korzystanie z rozwiązania apache / berkdb przechowuje dane na dysku i ładuje tylko strony aktywnych adresów.
M Conrad,
5

Sam tego nie testowałem, ale kiedy usłyszałem opis twojego problemu, natychmiast pomyślałem „ pf” (jak z OpenBSD).

pfma pojęcie tabel adresowych, które mogą być właśnie tym, czego szukasz.

Według niektórych bardzo pobieżnego badania zrobiłem, wydaje się, że ma potencjał do skali lepiej niż ipset. Według rozdziału PF FAQ na temat opcji środowiska wykonawczego , po wyjęciu z pudełka bez dostrajania, pf obsługuje w sumie 1000 tabel, domyślnie łącznie 200 000 wpisów we wszystkich tabelach. (100 000, jeśli system ma <100 MB pamięci fizycznej). To prowadzi mnie do przekonania, że ​​warto przynajmniej spróbować przetestować to, aby sprawdzić, czy działa na jakimkolwiek użytecznym poziomie.

Oczywiście zakładam, że używasz swoich serwerów w systemie Linux, więc będziesz musiał mieć oddzielne zapory ogniowe z systemem operacyjnym z pf (takim jak OpenBSD lub FreeBSD). Możesz także poprawić przepustowość, eliminując w ogóle wszelkiego rodzaju stanowe filtrowanie pakietów.

Per von Zweigbergk
źródło
Konwersja architektury serwera klienta na BSD nie jest tak naprawdę opcją. Przynajmniej myślenie nieszablonowe.
tylerl
2
Nie trzeba konwertować całej architektury serwera na BSD, wystarczy zbudować zaporę ogniową, aby umieścić ją przed prawdziwym serwerem. (Łatwo to zrobić na maszynie wirtualnej.)
Per von Zweigbergk
2

Czy korzystałeś z FIB_TRIE zamiast FIB_HASH.

FIB_TRIE powinien skalować się znacznie lepiej dla liczby prefiksów. (/ 32s trasy zerowe są nadal prefiksami, tylko bardzo specyficzne)

Może być konieczne skompilowanie własnego jądra, aby z niego korzystać, ale to pomaga.

FIB_TRIE Notes

Joel K.
źródło
2

Dla potomnych: zgodnie z ipsetdokumentami domyślny rozmiar zestawu to 65536, można to zmienić za pomocą opcji.

maxelem Ten parametr obowiązuje dla polecenia create wszystkich zestawów typów skrótów. Definiuje maksymalną liczbę elementów, które mogą być przechowywane w zestawie, domyślnie 65536. Przykład:ipset create test hash:ip maxelem 2048.

Umieściłem to tutaj, ponieważ nie mogę jeszcze komentować.

plitter
źródło
1

Kilka przydatnych uwag dla każdego, kto natknie się na ten problem w przyszłości:

Przede wszystkim nie analizuj ruchu, którego nie potrzebujesz. Jeśli na przykład blokujesz ruch TCP, filtruj tylko pakiety SYN, w ten sposób filtrujesz tylko raz dla każdego połączenia. Możesz użyć, -m statejeśli chcesz, ale śledzenie połączeń ma swój własny narzut, którego możesz uniknąć, jeśli problem stanowi wydajność.

Po drugie, umieszczenie miliona reguł w iptables zajmuje dużo czasu: kilka minut. Jeśli chcesz śledzić tak wiele podmiotów, prawdopodobnie najlepiej trzymaj to z dala od netfliter. Sama wielkość zestawu reguł robi różnicę.

Po trzecie, celem jest uniknięcie skanowania liniowego; ale niestety zarówno iptables, jak i iproute2 są z natury liniowe. Możesz podzielić swoje reguły w stylu drzewa binarnego na dużą liczbę łańcuchów, co ogranicza liczbę reguł, z którymi musisz się zapoznać, ale nawet iptables nie są odpowiednie dla tego rozmiaru problemu. To będzie działać , ale to strata cennych zasobów.

Po czwarte, a co najważniejsze, przeniesienie obciążenia do przestrzeni użytkownika nie jest złym pomysłem. Umożliwia to pisanie własnego ścisłego kodu lub korzystanie z gotowego rozwiązania dostosowanego do zestawu problemów. Moje własne rozwiązanie tego problemu, jak wspomniano, polegało na użyciu wyszukiwania BDB wyzwalanego przez system mod_rewrite Apache. Dało to dodatkową korzyść polegającą na uruchamianiu tylko jednego wyszukiwania na sesję i dopiero po przesłaniu prawidłowego żądania. W tym przypadku wydajność była bardzo szybka, a koszt listy bloków był prawie znikomy.

Możesz wykonywać podobne operacje w przestrzeni użytkownika za pomocą iptables, używając -j QUEUEcelu w połączeniu z libnetfilter_queue. To narzędzie jest wydajne, proste i słabo udokumentowane. Poleciłbym przeczytać jak najwięcej z jak największej liczby źródeł, ponieważ w sieci jest wiele interesujących materiałów, które nie są częścią żadnej oficjalnej dokumentacji.

tylerl
źródło