- předchozí článek - následující článek - obsah -

Linuxové noviny Březen 1998

Filtrování paketů v Linuxu

Pavel Kaňkovský, 3. března 1998

V linuxovém jádře je vestavěna poměrně silná a flexibilní podpora pro filtrování paketů (speciálně IP datagramů, i když je možno filtrovat i jiné protokoly, např. IPX) zpracovávaných síťovým subsystémem jádra. Filtrování je možno provádět ve třech různých fázích: bezprostředně po přijetí datagramu ze sítě, během jeho přesměrování do jiné sítě a před vysláním datagramu do sítě. Pro aktivaci těchto funkcí je třeba zapnout volby Network firewalls a IP firewalling. Poznamenejme, že není nutné, aby byl uzel nakonfigurován jako router (IP forwarding/gatewaying), i když je to obvyklé.

Pro protokol IP znázorňuje postavení jednotlivých filtrů (jsou označeny modrou barvou) vzhledem k ostatním komponentám (v konkrétní konfiguraci nemusí být některé přítomny) tento diagram:

[ schéma ]

Datagram je po svém přijetí některým síťovým rozhraním zpracován vstupním filtrem (input). Pokud je jeho adresa lokální (nebo vstupní filtr nařizuje přesměrování datagramu na lokální port, tzv. transparent proxying), je provedeno "odmaskování" cílové adresy-tj. pokud je v činnosti překlad adres (NAT, v Linuxu označováno jako masquerade, tedy maškaráda). Pokud je pod cílovou adresou datagramu skryta jiná adresa, je tato "odmaskována" a datagram je přesměrován na své skutečné místo určení. Jinak je (pokud je to možné) doručen na příslušný lokální port a převzat lokálně bežícím procesem.

Pokud není cílová adresa datagramu lokální (ani nemá dojít k jeho přesměrování na lokální port), je datagram směrován a zkontrolován předávacím filtrem (forward). Pokud to filtr vyžaduje, je provedeno "maskování" zdrojové adresy datagramu. Všechny datagramy, které mají být vyslány do sítě, jsou ještě před svým předáním síťovému rozhraní zkontrolovány výstupním filtrem (output).

Jednotlivé filtry popsané v předchozím textu jsou vyvolávány v procedurách síťových protokolů (pokud filtrování podporují) pomocí následujících funkcí:

int call_fw_firewall(int pf, \
   struct device *dev, void *phdr, void *arg);
int call_in_firewall(int pf, \
   struct device *dev, void *phdr, void *arg);
int call_out_firewall(int pf, \
   struct device *dev, void *phdr, void *arg);
kde parametr pf určuje síťový protokol (např. PF_INET), dev určuje zařízení, odkud byl datagram přijat, pro vstupní filtr resp. zařízení, kam bude datagram odeslán, pro předávací a výstupní filtr, phdr ukazuje na začátek dat v datagramu (z pohledu síťového protokolu) a arg je pomocný parametr (který je např. u vstupních filtrů pro protokol IP použit pro přesměrování na lokální porty).

Každá z těchto funkcí vrací jednu z následujících hodnot:

FW_BLOCK  odmítni datagram bez náhrady
FW_ACCEPT  akceptuj datagram
FW_REJECT  odmítni datagram a zašli oznámení, že nelze doručit (má-li to smysl)
FW_REDIRECT  přesměruj datagram na lokální port
FW_MASQUERADE "zamaskuj" zdrojovou adresu

Pro protokol IP má hodnota FW_REDIRECT smysl pouze u vstupních filtrů a hodnota FW_MASQUERADE pouze u předávacích filtrů. Protokol IPX tyto hodnoty nerozeznává vůbec.

Pro každý protokol je definována prioritní fronta filtrů, které jsou popsány strukturou firewall_ops (viz výpis Struktura firewall_ops).


  struct firewall_ops
  {
          struct firewall_ops *next;
          int (*fw_forward)(struct firewall_ops *this, int pf,
                          struct device *dev, void *phdr, void *arg);
          int (*fw_input)(struct firewall_ops *this, int pf,
                          struct device *dev, void *phdr, void *arg);
          int (*fw_output)(struct firewall_ops *this, int pf,
                          struct device *dev, void *phdr, void *arg);
          int fw_pf;              /* Protocol family                      */
          int fw_priority;        /* Priority of chosen firewalls         */
  };

Výpis 1: Struktura firewall_ops

Funkce call_..._firewall vyvolávají odpovídající metody zaregistrovaných filtrů podle jejich priority (od nejmenší k největší), dokud není hodnota vrácená metodou různá od FW_SKIP. Pokud ani jeden filtr ve frontě nerozhodne o osudu datagramu, je vrácena předdefinovaná hodnota (FW_ACCEPT).

Všechny zmíněné definice je možno nalézt v souboru include/linux/firewall.h.

Standardní IP filtr a příkaz ipfwadm

Přímo ve standardním linuxovém jadře (v souboru net/ipv4/ipfw.c) je možno nalézt jednoduchou implementaci bezstavového filtru pro protokol IP. Kód pochází z BSD UNIXu verze 4.4 (a byl portován do Linuxu ještě v době, kdy výše popsané obecné mechanismy ještě neexistovaly).

Každý filtr je definován jako seznam pravidel (rules), která se skládají z podmínky (určující, kdy je pravidlo použito) a akce (určující, jak má být s datagramem naloženo), a jedné implicitní akce (default policy). Pro každý datagram je seznam pravidel procházen dokud není nalezeno pravidlo, jehož podmínka je splněna, a pak je použita jeho direktiva. Pokud není žádné takové pravidlo nalezeno, je použita implicitní akce.

Podmínka je tvořena (v závorkách jsou uvedeny odpovídající parametry příkazu ipfwadm, o kterém bude řeč později):

  • zdrojovou a cílovou IP adresou s maskou (-S, -D)
  • specifikací protokolu: libovolný, UDP, TCP, ICMP (-P)
  • množinou zdrojových a cílových portů pro protokoly UDP a TCP, maximální počet všech portů v podmínce je 10, ale je možno specifikovat i interval (-S, -D)
  • údajem, zda shodu adres a portů testovat i v opačném směru (-b)
  • příznaky pro rozlišení nových a již otevřených TCP spojení (-k, -y)
  • množinou typů zpráv pro protokol ICMP (-S)
  • jménem resp. adresou síťového rozhraní (-W, -V)

Explicitní akci pak tvoří:

  • způsob, jakým má být s datagramem naloženo: akceptovat (accept), tiše zamítnout (deny), zamítnout a poslat zpět oznámení pomocí protokolu ICMP (reject)
  • údaj, zda má být datagram přesměrován na lokální port, a pokud ano, tak na který (-r)
  • údaj, zda má být proveden překlad zdrojové adresy (-m)
  • údaj, zda má být o aplikaci pravidla na datagram zapsána informace do logu (-o)
  • modifikace příznaků typu služby (TOS) (-t)

Implicitní akce se skládá pouze ze způsobu, jakým má být s datagramem naloženo, tj. zda má být datagram akceptován nebo zamítnut (s oznámením nebo bez něj).

Mimoto je možno definovat tzv. účtovací pravidla (pokud je v konfiguraci jádra zapnuto IP accounting), která mají stejné podmínky, ale žádné direktivy. Účtovací pravidla jsou dvou druhů: vstupní a výstupní. Pro jejich vyvolávání není použit mechanismus filtrů, neboť jsou explicitně volána ze subsystému protokolu IP.

Se seznamy pravidel je možno pracovat pomocí systémových volání popsaných v manuálové stránce ipfw(4). To ovšem není příliš praktické pro běžné použití, a proto existuje program ipfwadm, který tyto funkce zpřístupňuje. Pomocí tohoto programu je možno konfigurovat filtrovací a účtovací pravidla, zjišťovat údaje o nakonfigurovaných pravidlech a testovat je. Syntaxe všech jeho parametrů je detailně popsána v manuálové stránce ipfwadm(8), stručný přehled je možno získat zadáním příkazu ipfwadm -h. Nutné minimum představují následující varianty:

ipfwadm filtr -p výsledek
ipfwadm filtr -a výsledek parametry...
ipfwadm filtr -f
ipfwadm filtr -l

První varianta nastavuje implicitní akci pro zadaný filtr. Filtr je -I pro vstupní filtr, -O pro výstupní a -F pro předávací. Výsledek je accept pro přijetí, deny pro odmítnutí, nebo reject pro odmítnutí se zasláním oznámení. Druhá varianta přidává na konec seznamu nové pravidlo, jehož podmínka a další atributy akce jsou popsány parametry. Nahrazením volby -a je možno pravidla přidávat na začátek seznamu (-i) nebo ze seznamu odebírat (-d). Třetí varianta zcela vyprázdní seznam zadaného filtru. Poslední varianta vypíše obsah zadaného filtru, spolu se statistikou použití jednotlivých pravidel (pomocí voleb -l a -e je možno získat detailnější informace).

Nyní si ukážeme několik příkladů.

Triviální vstupní filtr

Tento příklad ukazuje, jak inicializovat nejjednodušší vstupní filtr, který zabraňuje podvržení lokální síťové adresy (address spoofing). Předpokládejme, že počítač má dvě síťová rozhraní: lo s adresou 127.0.0.1 a eth0 s adresou 1.2.3.4.

ipfwadm -I -p deny
ipfwadm -I -f
ipfwadm -I -a accept -S 127.0.0.0/8 -W lo
ipfwadm -I -a accept -S 1.2.3.4 -W lo
ipfwadm -I -a deny -S 127.0.0.0/8
ipfwadm -I -a deny -S 1.2.3.4
ipfwadm -I -p accept

Vstupní filtr je inicializován pravidly, která zabraňují, aby vyjmenované zdrojové adresy byly použity na jiném zařízení než je loopback. Nastavení implicitní direktivy na začátku a na konci demonstruje ošetření nestabilního stavu v průběhu inicializace, kdy by mohlo být možno filtr obejít. Všechna zamítnutí jsou definována jako deny, neboť zdrojová adresa není platná, a proto nemá smysl na ni nic posílat.

Složitější kontrola adres

Předpokládejme, že propojujeme síť 1.2.3.0/8 s Internetem. Chceme-li zajistit, aby z vnějšku nebylo možno podvrhnout vnitřní adresy a naopak. Také chceme odfiltrovat neplatné adresy. Lokální síť je zapojena na eth0, ven směřuje ppp0.

ipfwadm -I deny -b -S 10.0.0.0/8 -o
ipfwadm -I deny -b -S 172.16.0.0/12 -o
ipfwadm -I deny -b -S 192.168.0.0/16 -o
ipfwadm -I deny -b -S 0.0.0.0 -o
ipfwadm -I deny -b -S 255.255.255.255 -o

ipfwadm -I accept -S 1.2.3.0/8 -W eth0
ipfwadm -I deny -W eth0 -o
ipfwadm -I deny -S 1.2.3.0/8 -o

První blok filtruje privátní a neplatné IP adresy, a to jak zdrojové, tak cílové. Druhý blok zajišťuje, že adresy 1.2.3.0/8 mohou používat pouze počítače v lokální síti, přičemž jim není dovoleno používat jiné adresy. Výskyt nežádoucích adres je zaznamenán do logu.

Omezení přístupu na určité adresy a protokoly

Chceme umožnit, aby počítače z vnitřní sítě mohly navazovat TCP spojení bez omezení, ale v opačném směru je dovolen pouze přístup na porty 100 a 101 na adrese 1.2.3.4. Je povoleno použití příkazu ping bez omezení. Nic jiného povoleno není.

ipfwadm -F accept -P tcp -k -D 1.2.3.4 100 101
ipfwadm -F accept -P tcp -k -S 1.2.3.0/8
ipfwadm -F accept -P tcp -y
ipfwadm -F accept -P icmp -S 0.0.0.0/0 0 8
ipfwadm -F -p reject

Pravidla jsou v této ukázce umístěna do předávacího filtru, takže ovlivňují komunikaci mezi vnitřní sítí a vnějškem, ale neomezují možnosti samotného firewallu a procesů na něm bežících (což může-ale nemusí-být žádoucí). První dvě pravidla povolují zahajovat TCP spojení, pokud je cílem jeden z povolených portů na počítači 1.2.3.4 nebo zdroj leží ve vnitřní síti (předpokládá se, že již byla učiněna opatření proti podvrženým adresám). Třetí pravidlo povoluje neomezený provoz pro již zahájená spojení. Čtvrté pravidlo povoluje průchod zpráv ECHO (8) a ECHO REPLY (0) protokolu ICMP (v praxi by bylo vhodnější méně restriktivní pravidlo). Nakonec je nastavena implicitní akce na odmítnutí datagramu, čili všechno, co dosud nebylo povoleno, je zakázáno.

Překlad adres a přesměrování provozu na lokální port

Máme lokální síť s adresou 192.168.5.0/8 (pozor, změna!) a chceme počítačům na ní umožnit komunikaci s Internetem pomocí překladu adres. Zároveň chceme všechna spojení z lokální sítě směrovaná na port 80 přesměrovat na lokálně běžící HTTP proxy (takový, který to podporuje - např. squid) poslouchající na portu 1234.

 ipfwadm -I accept -P tcp -D 0.0.0.0/0 80 -W eth0 -r 1234
 ipfwadm -F accept -S 192.168.5.0/8 -m
 ipfwadm -M -s 120 60 120

První pravidlo "odchytává" spojení z lokální sítě na port 80 na libovolné adrese a přesměrovává je na lokální port 1234. Druhé pravidlo zajišťuje překlad privátních adres z lokální sítě. Třetí pravidlo demonstruje nastavení časových parametrů "maškarády" (pro zvláště pomalé spojení).

Testování filtru

Program ipfwadm je také možno použít pro ověření, zda filtr akceptuje, či odmítne určitý datagram. Je nutno uvést všechny parametry, včetně adresy síťového rozhraní. Následující příkaz ověří, zda je (z hlediska vstupního filtru) přípustné zahájit TCP spojení z adresy 1.2.6.7, portu 1234 na adresu 1.2.6.7, port 7, přičemž datagram je přijat přes rozhraní eth0.

 ipfwadm -I -c -P tcp -S 1.2.3.4 1234 \
 -D 1.2.6.7 7 -k -V 1.2.3.1 -W eth0

Pokud to možné je, pak program odpoví:

 packet accepted

Alternativní filtry

Výše popsaná implementace filtrů není jediná možná. K dispozici je vylepšená varianta pod názvem IP firewall chains http://www.adelaide.net.au/~rustcorp/ipfwchains, která především umí lépe pracovat s fragmentovanými datagramy, zavádí některé nové druhy podmínek, umožňuje hierarchicky strukturovat seznamy pravidel a dovoluje provádět změny seznamů pravidel atomicky. Modul je koncipován jako náhrada standarního filtru. Obsažena je obdoba programu ipfwadm pod názvem ipchains.

Naprosto nezávislou implementaci filtru pro protokol IP představuje sf Firewall ftp://ftp.switch.ch/software/sources/network/sf. K hlavním rysům patří sledování stavu komunikačních protokolů (např. TCP), schopnost dynamického vytváření pravidel na základě jiných pravidel, bohatý konfigurační jazyk s širokým repertoárem podmínek a akcí a možnost efektivní rekonfigurace za běhu. Na druhou stranu ale není (ve verzi 0.2.9) podporován překlad adres ani přesměrování na lokální port.

Pro Linux je též dostupný multiplatformní balík IP Filter http://cheops.anu.edu.au/~avalon/. K jeho zajímavým vlastnostem patří podpora pro detailní kontrolu obsahu hlaviček datagramů, sledování stavu komunikačních protokolů, sdružování pravidel do skupin a podpora pro zachycování podezřelých datagramů a jejich zpracování externím procesem. *


- předchozí článek - následující článek - obsah -