Správa linuxového serveru: Linuxový firewall, základy iptables

Správa linuxového serveru: Linuxový firewall, základy iptables

Firewall v Linuxu je tvořen projektem Netfilter, který pracuje na úrovni jádra a umožňuje filtrovat pakety na základě mnoha kritérií. Základním nástrojem pro nastavení paketového filtru je známý řádkový nástroj iptables. Předesílám, že existuje řada projektů, která se snaží práci s iptables usnadnit, popřípadě generovat vlastní pravidla a uživatele od tohoto nástroje co nejvíce odstínit. Některé z těchto nástrojů časem představím, nicméně v tomto článku se budu zabývat samotným nástrojem iptables a principy, na jakých jeho funkce stojí.

Je nutné rovněž předeslat, že Netfilter není pouze firewall, je to především paketový filtr, který umožňuje provádět řadu věcí, z nichž jedna možnost je vytvořit pravidla, která budou zastávat funkci firewallu. Některé z funkcí, které nejsou typické pro firewall, nýbrž pro paketový filtr jako takový, vám v průběhu tohoto seriálu také představím, i když se budu zaměřovat primárně na užití Netfiltru pro konstrukci firewallu.

Varování

Pokud se budete učit pracovat s iptables a experimentovat, určitě tak čiňte na počítači, ke kterému máte fyzický přístup. Pracovat s iptables na ostrém serveru v datacentru je velké riziko, pokud nevíte přesně, co děláte a jaké to bude mít důsledky. Může se velmi jednoduše stát, že si pod sebou "uříznete větev" a na server už se vzdáleně nepřihlásíte, abyste to mohli opravit.

Základy fungování Netfiltru

Řetězy a politika

Jedna z dřívějších verzí nástroje iptables se jmenovala ipchains, a jsou to právě řetězy (chains), které tvoří pilíř fungování paketového filtru v Linuxu. Jejich funkci ilustruje následující obrázek:

Schéma funkce řetězu v linuxovém paketovém filtru

Schéma funkce řetězu v linuxovém paketovém filtru

Jak je patrné z obrázku, tyto řetězy jsou tvořeny jednotlivými pravidly. Paket, který je zachycen v některém z řetězů, putuje od prvního pravidla k následujícímu, dokud některému z pravidel nevyhoví. Pokud některému z pravidel vyhoví, provede se některá z možných akcí, v rámci které může být paket zahozen (DROP), odmítnut (REJECT), přijat (ACCEPT) nebo předán jinému řetězu.

Pokud nevyhoví žádnému z pravidel v daném řetězu, může se stát jedna ze dvou věcí. Jedná-li se o některý ze základních/vestavěných řetězů (viz dále), pak o jeho dalším osudu rozhodne politika daného řetězu (k dispozici jsou dvě možnosti: přijmout paket - ACCEPT nebo zahodit paket - DROP). Pokud se jedná o uživatelsky definovaný řetěz, je paket vrácen tam, odkud byl uživatelsky definovanému řetězu poslán (RETURN).

Základní řetězy

Základní vestavěné řetězy, primární řetězy, které tvoří základ fungování Netfiltru. Mezi tyto řetězy patří řetěz INPUT, řetěz FORWARD a řetěz OUTPUT. Jejich význam vám osvětlí následující obrázek:

Schéma funkce řetězu v linuxovém paketovém filtru

Schéma funkce řetězu v linuxovém paketovém filtru

Jak je z obrázku patrné, jakmile paket dorazí na některé ze síťových rozhraní a je předán přes ovladač jádru, je provedeno směrovací rozhodnutí. Je-li paket určen místnímu počítači, směřuje do řetězu INPUT. Je-li určen nějakému jinému počítači, směřuje do řetězu FORWARD. Dlužno dodat, že předávání paketů (tj. funkcionalita směrovače/routeru) je třeba explicitně povolit v jádře. Bez tohoto povolení pakety předávány nebudou, a průchozí pakety budou zahozeny. K tomu se ale ještě dostaneme. V tuto chvíli je pro nás podstatný řetěz INPUT, kam směřují pakety určené pro tento počítač. Pokud tyto pakety projdou řetězem INPUT a budou povoleny (ať již explicitně pravidlem nebo politikou), budou předány příslušné aplikaci.

Pro úplnost dodám, že existují kromě výše uvedených ještě dva další řetězy, PREROUTING a POSTROUTING, které jsem zamlčel, ale těm se budu blíže věnovat později.

Pravidla

V jednotlivých řetězech lze definovat pravidla, která provádí vlastní filtrování paketů. Tato pravidla mají určité podmínky, resp. kritéria, kterým musí paket vyhovět, a příslušnou akci, která se má provést, pokud paket pravidlu vyhověl. Kupříkladu:

iptables -A INPUT -s 1.2.3.4 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j DROP

Tyto dva příkazy přidají dvě pravidla na konec řetězu INPUT. První pravidlo zachytí pakety se zdrojovou adresou 1.2.3.4 (-s 1.2.3.4) a propustí je (-j ACCEPT), tj. příslušný paket již nebude procházet žádnými dalšími pravidly. Pokud paket toto kritérium nesplní, přijde na řadu druhé pravidlo, kterému vyhoví jakýkoliv TCP paket s cílovým portem 22 (-p tcp --dport 22), přičemž tyto pakety budou zahozeny (-j DROP). Pokud byste chtěli paket odmítnout, tj. sice zahodit, ale současně poslat zpět ICMP zprávu o důvodu odmítnutí, použili byste následující příkaz:

iptables -A INPUT -p tcp --dport 22 -j REJECT --reject-with icmp-admin-prohibited

A teď, kontrolní otázka. Podívejte se na následující sadu pravidel a popřemýšlejte, co se stane s TCP paketem směřujícím na port 22 - bude vygenerována ICMP zpráva o důvodu odmítnutí, nebo bude paket "tiše" zahozen?

iptables -A INPUT -s 1.2.3.4 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j DROP
iptables -A INPUT -p tcp --dport 22 -j REJECT --reject-with icmp-admin-prohibited

Správnou odpovědí je ona druhá možnost - takový paket bude zahozen, protože vyhoví druhému pravidlu z tohoto seznamu, bude zahozen a ke třetímu pravidlu, které by příslušnou ICMP zprávu vygenerovalo, se už nedostane.

Přehled základních operací

Nyní, když rozumíte základním principům práce s Netfiltrem, uvedu několik "taháků" se základními prvky pravidel. Nejprve přidávání a mazání pravidel:

# přidat pravidlo na konec řetězu INPUT
iptables -A INPUT ...
# přidat pravidlo na začátek řetězu INPUT
iptables -I INPUT ...
# odebrat pravidlo - specifikovat můžete pořadové číslo nebo pravidlo opsat:
iptables -D INPUT <pořadové číslo pravidla>
iptables -D INPUT ...
# vymazat všechna pravidla z řetězce INPUT
iptables -F INPUT

Odebrání pravidel by asi zasluhovalo bližší vysvětlení. Existující pravidlo může být vymazáno buď zadáním pořadového čísla pravidla, nebo prostě tak, že celé pravidlo opíšete, ale volbu -A nebo -I zaměníte za -D, takto:

# přidání pravidla
iptables -A INPUT -i eth0 -s 10.0.1.5 -p tcp --dport 22 -j ACCEPT
# odebrání pravidla
iptables -D INPUT -i eth0 -s 10.0.1.5 -p tcp --dport 22 -j ACCEPT

Pravidla si můžete nechat vypsat následujícím příkazem:

iptables -L -n -v

Volba -L zařídí vypsání pravidel, volba -n bude adresy a porty uvádět číselně a volba -v zařídí podrobnější výpis. Následuje seznam nejčastěji používaných kritérií:

# zdrojová adresa
-s 1.2.3.4
# cílová adresa
-d 4.3.2.1
# TCP paket, cílový port 25
-p tcp --dport 25
# UDP paket, zdrojový port 53
-p udp --sport 53
# paket přichází z rozhraní eth0
-i eth0
# paket směřuje na rozhraní eth1
-o eth1

A na úplný závěr výpis základních akcí, které lze s pakety provádět.

# přijmout paket
-j ACCEPT
# odmítnout paket s přísloušnou ICMP zprávou
-j REJECT --reject-with <typ ICMP zprávy>
# tiše zahodit paket
-j DROP

Příklad nejjednoduššího, nestavového firewallu

Tento díl zakončím příkladem nejjednoduššího firewallu, který lze sestavit. Nejprve vyčistím všechna pravidla:

iptables -F

Nyní specifikuji jednotlivá pravidla. Povolím veškerý provoz z místního rozsahu 10.0.0.0/8. Přístup k SSH povolím pouze z IP adresy 11.22.33.44. Dále povolím přístup k webserveru a k SMTP serveru.

iptables -A INPUT -s 10.0.0.0/8 -j ACCEPT
iptables -A INPUT -s 11.22.33.44 -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 25 -j ACCEPT

Nakonec specifikuji výchozí politiku ve všech třech základních řetězech. Pro konstrukci firewallu se hodí strategie "vše zakázat, a povolit to nejnutnější", takže nastavím u řetězu INPUT politiku DROP:

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

Tímto bych tento díl ukončil. Příště vám představím stavový firewall a ukážu, jak pomocí něj zkonstruovat podstatně dokonalejší formu firewallu než tu, kterou jsem představil výše.