Hlavní navigace

Stavíme firewall (1)

18. 12. 2001
Doba čtení: 8 minut

Sdílet

Dnešním článkem začíná krátký seriál, ve kterém se dozvíme, jak funguje paketový filtr v linuxovém jádře, a ukážeme si, jak nejlépe poskládat filtrovací pravidla pro nasazení v paketovém firewallu.

V roce 2001 jsme publikovali seriál článků „Stavíme firewall“, který inspiroval překvapivé množství linuxových administrátorů ke tvorbě vlastního firewallu. Součástí článků byl i ukázkový script, který doporučoval mj. zablokovat adresní rozsah 96.0.0.0/4, který v té době byl rezervovaný. Protože nyní při nedostatku IPv4 adresního prostoru došlo k přerozdělování i těchto rozsahů může dojít k problémům, pokud jej váš firewall stále blokuje. Pokud jste tedy uvedený skript použili jako základ pro váš firewall, ujistěte se, že neblokujete nyní korektní rozsahy adres.

Budeme vycházet z modelové situace, kdy máme linuxový router se dvěma síťovými kartami (eth0 a eth1), přičemž na jedné straně je Internet a na druhé lokální síť. Taková konfigurace je v prostředí malých firem velice častá, nezřídka bývá na routeru provozován zároveň také WWW server a další služby, které mají být přístupné z Internetu. Proto se budeme tohoto případu držet i v našem miniseriálu.

Každý IP datagram s sebou nese vyjma vlastních užitečných dat také hlavičku, obsahující zejména IP adresu původce i adresáta, zdrojový a cílový port specifikující program, kterému je datagram určen, a další informace popisující komunikaci, ke které datagram náleží. Paketový firewall je pak jakýmsi filtrem, který na základě těchto informací rozhoduje o tom, které pakety mohou být připuštěny až k programům, nebo které naopak smějí opustit počítač.

tabulka

Každý paket, ať už je jeho původ jakýkoliv, prochází systémem řetězců (chainů), které tvoří tzv. filtrovací tabulku, jak je to vidět na přiloženém obrázku. Pro ozřejmění si můžeme představit paketový filtr jako potrubí a jednotlivé řetězce jako ventily propouštějící pouze vybrané pakety.

  • Na začátku se snaží jádro rozhodnout, zda-li je příchozí paket určen pro tento počítač, nebo jestli je potřeba jej routovat jinam.
  • Je-li adresátem on sám, předá paket k dalšímu zpracování do vstupního (INPUT) řetězce. Pokud vyhoví tamějším filtrovacím pravidlům, dostane jej ke zpracování některý z lokálních programů poslouchající na cílovém portu.
  • Pokud je datagram určen někomu jinému a počítači je zkonfigurován jako router, tedy pokud je povoleno routování paketů proměnnou /proc/sys/net­/ipv4/ip_forward == 1, paket bude postoupen do řetezce FORWARD a počítač se jej pak pokusí podle svých možností doručit příjemci. Pokud je směrování paketů zakázáno (implicitní stav), bude paket zahozen.
  • Poslední možností je, že datagram vytvořil některý z lokálních programů. Potom je nutné, aby paketový filtr opustil přes řetezec OUTPUT.

Kromě zmíněných řetezců INPUT, OUTPUT a FORWARD existují ještě další dva, a to PREROUTING a POSTROUTING, které se ovšem používají především k jiným účelům než k filtrování paketů. Jak je patrné z názvů, PREROUTING je aktivní v době před routováním, tedy procházejí jím jak pakety určené pro lokální stroj, tak i ty, které budou směrovány jinam. Podobně POSTROUTINGem protékají pakety odcházející z našeho počítače, stejně jako směrované datagramy. Tyto řetězce mají zvláštní význam při překladu adres (NAT). Více se o NATu dozvíme v příštím dílu.

iptables

K nastavování pravidel slouží nástroj iptables, který je součástí snad všech nových distribucí. Jeho použití je vázáno na jádra verzí 2.4. Ačkoliv je možné na těchto verzích používat také starší program ipchains, nemohu to s klidným svědomím doporučit, protože podpora ipchains na nových kernelech je pouze přechodnou záležitostí a navíc se tím připravujete o některé nové vlastnosti iptables.

Použití iptables možná působí na první pohled složitě, ale ve skutečnosti je velice intuitivní a logické. Program voláme s několika parametry. Prvním je místo určení, kam chceme pravidlo zařadit. Chceme-li například nějaké pravidlo přidat (append) do řetězce INPUT, uděláme to nějak takhle:

iptables -A INPUT pravidlo

pravidlo je určeno specifikací, se kterou se zkoumaný paket porovnává. Například zápisu:

-p TCP -i eth0 -s 192.168.0.2 --dport 80

vyhovují všechny IP datagramy, které byly přijaty síťovou kartou eth0, mají jako odesílatele uvedenu stanici 192.168.0.2 a jsou určeny pro libovolného příjemce a jeho TCP port číslo 80. Všimněme si, že pokud nekterý parametr explictně neuvedeme, bude pravidlo vyhovovat libovolnému paramateru z množiny možných. Pokud tedy například neurčíme cílovou IP adresu pomocí „-d“, výchozí hodnotou bude 0/0, tedy libovolná IP adresa.

Dalším parametrem bývá „-j“, kterým určujeme, co má jádro udělat, pokud zkoumaný paket danému pravidlu vyhovuje. Možností, jak s ním naložit, je celá řada. Nejpoužívanější cíl (target) bývá DROP (paket bude zahozen) nebo ACCEPT (paket bude propuštěn). Dalším cílem může být například REJECT (paket bude zahozen, ale jeho původce bude o tomto informován pomocí chybového hlášení ICMP) nebo LOG (záhlaví paketu je zapsáno do systémového logu).
Nyní si tedy ukažme, jak vypadá taková kompletní definice pravidla:

iptables -A OUTPUT -i eth1 -p TCP -s 192.168.0.1 --sport 3000 \
   --d 192.168.0.2 --dport 25 -j DROP

Přeloženo do přirozeného jazyka: Pokud se v řetězci OUTPUT objeví TCP segment, který bude mít v úmyslu opustit počítač přes rozhraní eth1, jeho odesílatelem bude 192.168.0.1 port 3000 a příjemcem port 25 adresy 192.168.0.2, tak jej nepouštěj.

Jak vidíte, syntaxe iptables může být velice různorodá a způsobů, jak specifikovat množinu datagramů, může být mnoho. Vyčerpávající popis parametrů iptables naleznete kromě obligátní manuálové stránky iptables(8) také v Linux 2.4 Packet Filtering HOWTO. Pokud dáváte přednost české dokumentaci, sáhněte po podařeném článku Martina Mačoka na undergroundu.

Jaké pakety vlastně filtrovat?

Otázka by spíše měla znít: Jaké pakety propouštět? Firewall je totiž vhodné koncipovat ve smyslu věty „co není výslovně povoleno, je zakázáno“. Znamená to, že implicitní politikou ve všech základních řetezcích by mělo být zahazování všech paketů, které nevyhovují některému z pravidel. Opačným přístupem by bylo povolit všechen provoz a filtrovat pouze nežádoucí toky. My se však přidržíme prvního způsobu, který většinou bývá bezpečnější. Začneme tedy zápisem:

iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

Pakety ve vstupním (INPUT) řetězci filtrujeme podle cílového portu, kterému je paket určen. Pokud má být na našem počítači ze strany Internetu dostupný WWW a SMTP server, povolí se tyto služby takto:

iptables -N tcp_segmenty
iptables -A INPUT -p TCP -i eth0 -j tcp_segmenty
iptables -A tcp_segmenty -p TCP --dport 80 -j ACCEPT
iptables -A tcp_segmenty -p TCP --dport 25 -j ACCEPT

Význam tohoto zápisu je asi následující: Vytvoří (-N) se nový řetězec, který bude zpracovávat všechny TCP segmenty přicházející přes rozhraní eth0. Do tohoto řetězce přidáme (-A) pravidla, která stanovují, že pokud přijde segment adresovaný portu 80 (HTTP) nebo 25 (SMTP), propustí ho. Obdobně by mohl vypadat zápis pro služby používající UDP:

iptables -N udp_pakety
iptables -A INPUT -p UDP -i eth0 -j udp_pakety
iptables -A udp_pakety -p UDP --dport 53 -j ACCEPT

Obecně není nutné vytvářet nové řetězce a pravidla lze psát přímo do mateřského INPUTu, pokud si ale dáme tu práci a uspořádáme pravidla, která spolu souvisejí, bude nám odměnou vyšší přehlednost. Později si ukážeme další užitečná využití takového způsobu zápisu.

Zvláštním případem datagramů jsou ICMP, tedy servisní pakety používané pro přenos diagnostických a chybových zpráv. Pro správné fungování je potřeba propouštět přinejmenším ICMP typ 3 – „destination unreachable“. Vhodné je povolit také 0 – „Echo reply“, 8 – „Echo request“ a 11 – „Time exceeded“, které používají užitečné programy ping a traceroute. Ostatní ICMP zprávy můžete s klidným svědomím filtrovat.

iptables -A INPUT -p ICMP -i eth0 --icmp-type 0 -j ACCEPT
iptables -A INPUT -p ICMP -i eth0 --icmp-type 3 -j ACCEPT
iptables -A INPUT -p ICMP -i eth0 --icmp-type 8 -j ACCEPT
iptables -A INPUT -p ICMP -i eth0 --icmp-type 11 -j ACCEPT

Pokud máme počítač připojený rovněž do LAN nebo jiné důvěryhodné sítě, můžeme povolit pakety přicházející přes rozhraní eth1, stejně jako přes systémové (loopback) rozhraní lo.

iptables -A INPUT -p ALL -i eth1 -j ACCEPT
iptables -A INPUT -p ALL -i lo -j ACCEPT

Všechny ostatní příchozí datagramy jsou v souladu s implicitní politikou zamítnuty, proto je budeme logovat, abychom podle nich mohli diagnostikovat případné problémy.

iptables -A INPUT -j LOG

U jednodušších firewallů se nemusíme zabývat nějakým složitým filtrováním v řetězci OUTPUT, neboť datagramy, které tudy procházejí, mají svůj původ v našem počítači, proto nepředstavují nějaké zvlášťní bezpečnostní riziko. Pro začátek bude stačit něco takového:

iptables -A OUTPUT -p ALL -s 127.0.0.1 -j ACCEPT
iptables
-A OUTPUT -p ALL -s 192.168.0.1 -j ACCEPT
iptables -A OUTPUT -p ALL -s 1.2.3.4 -j ACCEPT
iptables -A OUTPUT -j LOG

Tím jsme propustili všechny pakety, jejichž odesílatelem je náš počítač. (Adresa 127.0.0.1 je adresou loopbacku, adresa 1.2.3.4 zde zastupuje naši veřejnou IP adresu, a konečně předpokládejme, že 192.168.0.1 je adresa našeho routeru na místní LAN.) Případné ostatní pakety budou zahozeny a logovány.

Řetězec FORWARD má svůj význam v případě, kdy máme v počítači více síťových rozhraní a chceme směrovat pakety z jedné sítě do druhé. Pokud má být náš firewall routerem mezi Internetem dostupným z rozhraní eth0 a vnitřní sítí na eth1, použijeme následující zápis:

iptables -A FORWARD -i eth1 -j ACCEPT
iptables -A FORWARD -i eth0 -o eth1 -m state \
  --state ESTABLISHED,RELATED -j ACCEPT

Tím povolíme neomezené směrování paketů z vnitřní sítě. Pakety v opačném směru budou propuštěny pouze v případě, že patří k nějakému již existujícímu spojení. Syntaxí „-m state“ si zatím nemusíte příliš lámat hlavu, vězte, že je určena stavovému firewallu, o němž si budeme detailně povídat později.

Pokud je jednou ze sítí Internet a druhou LAN s privátními IP adresami, které se nedají používat pro komunikaci s vnějším světem, musíme zkonfigurovat ještě maškarádu neboli SNAT:

root_podpora

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Zápis znamená, že router bude pakety odcházející přes rozhraní eth0 „maskovat“ svojí IP adresou (1.2.3.4). Zvenku to bude vypadat tak, že všechny pakety budou po Internetu putovat s IP adresou 1.2.3.4 a teprve na našem firewallu se budou překládat na adresy vnitřní sítě.

Tím už se ale dostáváme do oblasti, kdy pakety nejenom filtrujeme, ale také modifikujeme. Podrobněji se na tyto a další pokročilejší techniky NATu podíváme v příští části článku.

Byl pro vás článek přínosný?