Paketový filtr v Linuxu

Ivo Studenský <xstudens@fi.muni.cz>



Co je to paketový filtr?

Paketový filtr je kus kódu, který kontroluje hlavičky přichozích a odchozích paketů a podle jejího obsahu rozhoduje, jak se s každým jednotlivým paketem naloží, zda bude paket akceptován, zahozen a podobně.

Podpora filtrování paketů v Linuxu

V Linuxu je paketový filtr zakomponován přímo v jádře už od verze 1.1. První implementace byla založena na ipfw systému BSD. Ve verzi 2.0 přibyl jednoduchý uživatelský nástroj 'ipfwadm' pro nastavování filtrovacích pravidel, který byl později, ve verzi 2.2, rozšířen nástrojem 'ipchains'. V nových verzích Linuxu byl firewalling kód zcela přepsán, a proto ve 2.4 verzích jádra (přesněji od verze 2.3.15 a výš) se používá pro nastavování filtrovacích pravidel nástroj 'iptables'. IP tables je rozšířením ipfwadm a ipchains.

Netfilter

Základem nové implementace je netfilter framework, který je součástí jádra. (CONFIG_NETFILTER) Ten definuje na cestě packetu TCP/IP stackem pět bodů, ve kterých se mohou moduly jádra přihlásit k jejich odběru a rozhodnout, zda packetu dají šanci postoupit dál, nebo zda bude zlikvidován. V každém bodě může být přihlášeno libovolné množství modulů, a packety, pokud nejsou některým zlikvidovány, jsou předány postupně všem. Ty body jsou pre_routing, forward, post_routing, local_in, local_out. A to je vše, co se děje na této základní úrovni. Netfilter kromě toho nabízí už jen základní infrastrukturu pro komunikaci userspace vs. kernel, kterou lze použít k předávání parametrů do modulů a zpětnému získávání stavových informací. Stejně jako u ipchains lze předávat packety do userspace k dalšímu zpracování. Vlastní filtr packetů je implementován sadou modulů jádra, které je nutno zavést před vlastním vytvářením filtrovacích pravidel

Iptables

Iptables slouží k nastavení a správě tabulek filtrovacich pravidel v jádře Linuxu. Tabulky obsahují několik předdefinovaných řetězců pravidel a mohou taky obsahovat uživatelsky definované řetězce. Řetězec je pak pojmenovaným seznamem pravidel. Každé pravidlo uvádí podmínky, které musí paket splňovat a cíl, který se vykoná v připadě shody. Cílem může být například DROP (zahození paketu), ACCEPT (akceptování paketu), nebo taky skok do dalšího řetezce a mnohé jiné. Jestliže paket nesplňuje podmínky pravidla, zkouší se na něj postupně další pravidla v aktuálním řetězci. Pokud takto projde celým řetězcem, aniž by vyhovoval jakémukoliv pravidlu, vrátí se řízení zpět do nadřazeného řetezce, ze kterého byl aktuální řetězec volán. V případě, že se tímto způsobem dostane až na konec nějakého předdefinovaného řetězce, uplatní se na něj "implicitní cíl" tohoto řetězce - obvykle ACCEPT.

Cesta paketu filtrovacím kódem

Po startu jádra jsou v základní tabulce 'filter' k dispozici tři předdefinované řetězce pravidel: INPUT, OUTPUT a FORWARD, které nelze smazat.
  1. Když přijde nový paket (řekněme, třeba přes síťovou kartu), jádro se nejprve podívá na jeho cílovou adresu.
  2. Pokud je adresován pro náš počítač, putuje paket do řetězce INPUT a jestliže bude akceptován, bude doručen nějakému lokálnímu procesu.
  3. Pokud není adresován pro náš počítač a nemáme v kernelu povolen forwarding nebo nevíme, jak ho forwardovat, bude paket zahozen (DROP). Pokud ovšem forwarding povolen máme a paket je adresován na jiné síťové rozhraní, poputuje paket do řetězce FORWARD, kde v případě, že bude akceptován, bude odeslán ven.
  4. A konečně, i lokálně běžící program může poslat paket. Ten půjde bezpstrostředně do řetězce OUTPUT a pokud tam bude akceptován, bude poslán ven.
Výhodou oproti předchozím implementacím je, že paket procházející řetězcem FORWARD, ve kterém se v běžných případech bude odehrávat většina filtrování, ví, jak o vstupním, tak o výstupním rozhraní, neboť již bylo rozhodnuto o jeho směrování.

Základní operace nad řetězci

  1. vytvoření nového řetězce: iptables -N retezec
  2. smazání prázdného řetězce: iptables -X retezec
  3. změna "implicitního cíle" předdefinovaného řetězce: iptables -P retezec cil
  4. výpis pravidel v řetězci: iptables -L retezec
  5. vyprázdnění řetězce: iptables -F retezec

Operace nad pravidly a vytváření pravidel

  1. přidání pravidla do řetězce: iptables -A retezec spec. pravidla
  2. vložení pravidla na určité pozici: iptables -I retezec pozice spec. pravidla
  3. smazání pravidla na určité pozici: iptables -D retezec pozice
  4. nahrazení pravidla na určité pozici: iptables -R retezec pozice spec. pravidla
  5. smazání prvního vyhovujícího pravidla: iptables -D retezec spec. pravidla
Vytváření filtrovacích pravidel se nijak zvlášť neliší od ipchains. Každé pravidlo specifikuje množinu podmínek, které musí paket splňovat, a cíl, který se vykoná v případě shody. Podmínky mohou být např. '-p' na specifikaci protokolu (př. '-p tcp'), '-s' na specifikaci zdrojové adresy a '-d' pro cílovou adresu,'-i' určuje vstupní rozhraní, přes které paket přišel (pouze u INPUT nebo FORWARD řetezců) a '-o' určuje vystupní rozhraní paketu (FORWARD a OUTPUT řetězce), podmínka '-f' se zase uplatní jen u druhého či pozdnějšího fragmentu fragmentovaných paketů. Navíc lze podmínky i negovat a vymezit tak například všechny protokoly až na TCP ('-p ! TCP').

Cíle v pravidlech mohou být jednak "odkazy" na další řetězce (např. '-j dalsi_retezec'), jednak některé ze speciálních cílů jako je:


V čem se iptables liší od ipchains

První významnou, a zřejmě nejdůležitější změnou, oproti ipchains je stavové filtrování. Při konstrukci filtrovacího pravidla můžete zohlednit stav socketu, ke kterému procházející paket patří. Rozlišované stavy jsou tyto:

Další důležitá změna, kterou iptables přinesly, je možnost rozlišovat jednotlivé flagy v TCP hlavičce a filtrovat pakety podle nich. V ipchains bylo možné detekovat pouze nastavený SYN flag. Budeme-li tedy např. chtít zvýšit odolnost systému proti stealth port scanům, můžeme to zajistit tím, že budeme likvidovat pakety s nastaveným FIN flagem a stavem INVALID.

Dále je možné filtrovat podle TCP options nebo MAC adresy.

A konečně je zde pravidlo limit, které je možné použít například k omezení logování v některém řetězci. U toho pravidla můžeme nastavit maximální počet shod za sekundu a omezit tak přeplňování logu v řetězci, u kterého lze očekávat velký počet shod.


NAT a iptables

NAT (síťový překlad adres) lze rozdělit na dva typy. Struktura netfilter frameworku proto umožňuje, vytvářet filtrovací pravidla firewallu nezávisle na na překladu adres, neboť k němu dochazí buďto před nebo až po routování, a proto filtrovací pravidla pracují se skutečnými zdrojovými i cílovými adresami.

Překladová pravidla

Pro nastavování překladových pravidel pomocí iptables je nutný modul iptable_nat a zapnutá podpora forwardování ('echo 1 > /proc/sys/net/ipv4/ip_forward'). Pravidla pro překlad adres se ukládají v tabulce 'nat', (iptables -t nat) narozdíl od pravidel firewallu, které jsou uloženy v základní tabulce iptables, v tabulce 'filter'. Tabulka 'nat' obsahuje tři předdefinované řetězce: řetězec PREROUTING pro překlad cílových adres, řetězec POSTROUTING pro překlad zdrojových adres a OUTPUT řetězec pro překlad cílových adres lokálně generovaných paketů. Při vytváření pravidel pro překlad adres je možné pakety rozlišovat podle zdrojové či cílové adresy, vstupního či výstupního rozhraní, podle protokolu a dalších.

Pro překlad zdrojových adres (POSTROUTING řetězec) je určen buď cíl SNAT '-j SNAT', za kterým musí být uvedena volba '--to adresa:port' a ip adresa (případně rozsah ip adres), na kterou má být překlad proveden (za adresou může být nepovinně uveden port nebo rozsah portů) nebo cíl MASQUERADE používaný při dynamicky přidělované IP adrese, typicky pro modemem vytáčená spojení. MASQUERADE narozdíl od SNAT zapomene veškerá spojení v případě spadnutí linky.

Podobně pro překlad cílové adresy (PREROUTING a OUTPUT řetězec) je určen cíl DNAT '-j DNAT' a za ním stejně jako u překladu zdrojové adresy následuje volba '--to adresa:port'


Zdroje