IPSet - znany i nieznany


== Sytuacja: ==
Masz firewall/router oparty o netfilter/iptables. Filtrujesz ruch pomiędzy wieloma stacjami, do tego masz masę vlanów, róźne klasy adresowe, sieci przyłączone itd itp - liczba oraz poziom skomplikowania twoich reguł rośnie wykładniczo a co za tym idzie wydajność twojego fw/routera przy dużym ruchu spada.



Jednym z problemów może być koszt przeszukiwania długiego łańcucha reguł by trafić na tą pasującą. Przykładowo filtrujemy stacje po ich adresach źródłowych celem dostępu do konkretnej uslugi np. http (tcp/80):


iptables -A FORWARD -p tcp -s 192.168.0.2 -m state --state NEW -j do-http
iptables -A FORWARD -p tcp -s 192.168.0.3 -m state --state NEW -j do-http
iptables -A FORWARD -p tcp -s 192.168.0.4 -m state --state NEW -j do-http
...
iptables -A FORWARD -p tcp -s 192.168.1.2 -m state --state NEW -j do-http
...
iptables -A FORWARD -p tcp -s 192.168.0.2 -m state --state NEW -j do-http
...
iptables -A FORWARD -p tcp -s 10.0.0.2 -m state --state NEW -j do-http
...

i tak kolejno dla każdego klienta, vlanu, sieci , blablabla.
Super działa. Wydajnie? hmm. Dla małej ilości reguł oraz małego ruchu tak, ale gdy reguły zaczynamy liczyć w setkach, tysiącach a wykorzystanie pasma przekracza kilkadziesiąt lub kilkaset Mbit/s - taka polityka może "zatkać" nam maszynę.

Jest na to sposób.
TaaaaDAaaaaaa - **IPSet** (http://ipset.netfilter.org/)

Jest to narzędzie pozwalające nam użyć tablic (umiejscowionych w kernel-space) wypełnionych danymi. Następnie całość wykorzystać w naszych regułach iptables.

== Typy struktur i tablic w IPSet. ==
* ipmap - przechowuje adresy IP (max 65535), tworząc podajemy klasę lub przedział adresów
* macimap - przechowuje adresy IP + adresy mac - tworzymy tak jak ipmap
* portmap - przechowujemy w niej porty bądź zestawy portów
* iphash - przechowuje adresy IP, ale w odróżnieniu od ipmap jest to dynamiczna tablica hashowa
* nethash - "hash" zawierający maski sieci (CIDR)
* ipporthash - "hash" dla pary : adres IP + port
* ipportiphash - "hash" dla tripletu: adres IP + port + adres IP
* ipportnethash - "hash" dla tripletu: adres IP + port + maska sieci (CIDR)
* iptree - drzewo adresów IP (opcjonalnie możemy podać czas przechowywania wpisu w drzewie)
* iptreemap - podobnie do iptree używa drzew do przechowywania jednak ostatni oktet adresu zapisany jest za pomocą mapy bitowej
* setlist - lista w której trzymamy inne "sety"

== Używamy IPSet ==

Dla powyższego przykładu możemy użyć np. ipshash.

* ładujemy moduł
modprobe ip_set_iphash
* tworzymy nasz set o nazwie np. "httpclients"
ipset -N httpclients iphash
* Super, mamy nasz "set", wypełnijmy go teraz danymi.
ipset -A httpclients 192.168.0.2
...
ipset -A httpclients 10.0.0.2
...
ipset -A httpclients 123.123.123.1

* całość wykorzystujemy w naszym łańcuchu iptables
iptables -A FORWARD -m set --match-set httpclients -m state --state NEW -m comment --comment "Klienci z dostepem do http" -j do-http

Prosto, szybko, przejrzyście.
Wystarczającą dokumentację można znaleźć w man-ie bądź na http://ipset.netfilter.org/