[OpenBSD]

[Předchozí: Přesměrování trafficu] [Obsah] [Dále: Logování]

PF: Filtrování paketů


Obsah


Úvod

Filtrování paketů je selektivní průchod nebo blokování datových paketů tím jak procházejí síťovým interfacem. Kriteria, která pf(4) používá když provádí inspekci paketů jsou založenna na Layer 3 (IPv4 a IPv6) a Layer 4 (TCP, UDP, ICMP, a ICMPv6) hlavičkách. Nejčastěji používaná kriteria jsou zdrojová a cílová adresa, zdrojový a cílový port a protokol.

Filtrovací pravidla specifikují kriteria, která musí paket splňovat a akci, buď povolit nebo zakázat, která je provedena, pokud je pravidlo splněno. Filtrovací pravidla jsou vyhodnocována v sekvenčním pořadí, od prvního do posledního. Dokud není nalezeno pravidlo obsahující klíčové slovo quick, paket bude vyhodnocován oproti všem filtrovacím pravidlům předtím než bude provedena konečná akce. Poslední pravidlo, které vyhovuje, "vyhrává" a bude diktovat jaká akce se s paketem provede. Na konci množiny filtrovacích pravidel je implicitní pass all, což znamená, že pokud paket nebude splňovat žádné pravidlo, výsledná akce bude pass.

Syntax pravidel

Obecná, velmi zjednodušená syntax pro filtrovací pravidla je:
action direction [log] [quick] on int [af] [proto protocol] \
   from src_addr [port src_port] to dst_addr [port dst_port] \
   [tcp_flags] [state]
action
Akce, která bude provedena na pakety splňující pravidlo, buď pass nebo block. Akce pass nechá projít paket zpátky do kernelu pro další zpracování, zatímco akce block bude reagovat v závislosti na volbě block-policy. Defaultní rekace může být přepsána buď specifikováním block drop nebo block return.
direction
Směr paketu jakým jde na interface, buď in nebo out.
log
Specifikuje že by paket měl být zalogován via pflogd(8). Pokud pravidlo specifikuje volbu keep state nebo modulate state pak pouze pokud paket nastaví stav, je stav zalogován. K logování všech paketů, nehledě na to jestli nastaví stav nebo ne, použijte log-all.
quick
Pokud pakket matchuje pravidlo obsahující quick pak je toto pravidlo považováno za poslední splňující a je provedena akce specifikovaná v tomto pravidle.
int
Jméno síťového interface, kterým prochází paket.
af
Address family paketu, buď inet pro IPv4 nebo inet6 pro IPv6. PF je obvykle schopen zjistit tento parametr v závislosti na zdrojové a cílové adrese (adresách).
protocol
Layer 4 protokol:
src_addr, dst_addr
Zdrojová/cílová adresa v IP hlavičce. Adresy mohou být specifkovány jako:
src_port, dst_port
Zdrojový/cílový port v Layer 4 hlavičce paketu. Porty mohou být specifikovány jako:
tcp_flags
Specifikuje flagy, které musí být nastaveny v TCP hlavičce při použití proto tcp. Flagy jsou specifikovány jako flags check/mask. Např. : flags S/SA - to řekne PF aby se díval pouze na flagy S a A (SYN a ACK) a matchoval pokud je "nahozen" SYN flag.
state
Specifikuje zda je udržována informace o stavu paketů splňujících toto pravidlo.

Default Deny

Doporučená praxe pro nastavení firewallu je "default deny". To znamená, zakázat všechno a pak selektivně povolit určitý traffic skrz firewall. Tento přístup je doporučený, protože zmenšuje pravděpodobnost chyby v množině pravidel a také dělá množinu pravidel přehlednější.

Pro vytvoření filtrovací politiky default deny, první dvě pravidla by měla být

block in  all
block out all

To bude blokovat všechen traffic na všech interfacech v obou směrech.

Passing Traffic

Traffic musí být explicitně povolen skrz firewall nebo bude zahozen default deny politikou. Toto je chvíle, kdy se ke slovu dostávají zdrojový/cílový port, zdrojová/cílová adresa, a protokol. Kdykoliv je traffic povolen skrz firewall nějakým pravidlem, toto pravidlo by mělo být napsáno co nejrestriktivněji. Toto zajistí, že projde jen a pouze traffic, který chceme nechat projít.

Nějaké příklady:

# Povol traffic na dc0 z lokální sítě, 192.168.0.0/24,
# na IP adresu OpenBSD storje 192.168.0.1. Dále povol
# vracející se traffic na dc0.
pass in  on dc0 from 192.168.0.0/24 to 192.168.0.1
pass out on dc0 from 192.168.0.1 to 192.168.0.0/24


# Povol TCP traffic na fxp0 na web server běžící na
# OpenBSD stroji. Jméno interface, fxp0, je použito jako
# cílová adresa, takže pakety budou splňovat toto pravidlo pouze tehdy,
# když jsou určeny pro tento OpenBSD stroj.
pass in on fxp0 proto tcp from any to fxp0 port www

Udržování stavu

Jedna z důležitých schopností Packet filtru je "udržování stavu" nebo "stavová inspekce". Stavová inspekce se vztahuje k schopnosti PF udržovat přehled o stavu nebo průběhu síťového spojení. Uložením informace o každém spojení do stavové tabulky, je PF schopen rychle zjistit, zda paket procházející firewallem patří do již ustaveného spojení. Pokud patří, projde firewallem bez vyhodnocování rulesetu.

Udržování stavu má mnoho výhod včetně jednodušších množin pravidel a lepšího výkon filtrování. PF je schopno poznat pakety jdoucí v obou směrech v rámci stavové tabulky, což znamená, že pravidla pro vracející se traffic nemusí být v množině pravidel uvedena. A protože pakety vyhovující stavovým spojením nemusí projít vyhodnocováním rulesetu, čas který PF stráví zpracováním takových paketů může být hodně snížen.

Pokud obsahuje pravidlo volbu keep state, první paket, který vyhovuje tomuto pravidlo vytvoří "stav" mezi odesilatelem a příjemcem. Od té chvíle nejenom pakety jdoucí od odesilatele k příjemmcci splňují záznam ve stavové tabulce, ale také pakety jdoucí od příjemce k odesilateli. Např.:

pass out on fxp0 proto tcp from any to any keep state

To povolí jakýkoliv odchozí TCP traffic na interface fxp0 a dále povolí traffic v opačném směru. Udržování stavu je hezká fíčura, jež znatelně zlepší výkon firewallu, protože vyhledávání stavů je rychlejší než vyhodnocování rulesetu.

Volba modulate state pracuje jako keep state s tou výjimkou, že se vztahuje pouze k TCP paketům. S modulate state, Initial Sequence Number (ISN) odchozích spojení je náhodné. To je užitečné pro ochranu spojení iniciovaných určitými operačními systémy, které mají ubohý způsob volby ISN čísel.

Keep state na odchozích TCP, UDP, a ICMP paketech a modulace TCP ISNs:

pass out on fxp0 proto tcp from any to any modulate state
pass out on fxp0 proto { udp, icmp } from any to any keep state

Další výhodou udržování stavu je že korespondující ICMP traffic projde firewallem. Např. pokud je keep state specifikován pro TCP spojení a přijde ICMP source-quennch zpráva vztahující se k tomuto TCP spojení, bude vyhovovat přislušnému áznamu ve stavové tabulce a povolena.

Je důležité poznamenat, že stavové konence jsou limitované na interface, na kterém byly vytvořeny. To je obzvláště důležití na routerech a firewallech běžících PF, zvlášť když je implementována politika "default deny" jak je naznačeno výše. Pokud firewall udržuje stav na všech odhchozích spojeních na externím interface, tyto pakety musí být explicitně povoleny skrz interní interface.

Pravidla nat, binat, a rdr implicitně vytváří stav pro vyhovující spojení tak dlouho jak je spojení povoleno množinou filtrovaích pravidel.

Udržování stavu pro UDP

Někdo jednou řekl, že "Nelze vytvořit stav pro UDP, protože UDP je bezstavový protokol!" I když je pravda, že UDP komunikace nemá žádný stavový koncept (nebo expliticní začátek a konec komunikace), to nemá vliv na schopnost PF vytvořit stav pro UDP session. V případě protkolů bez "start" a "end" paketů, PF jednoduše sleduje kolik uplynulu času od posledního pektu, který vyhovoval pravidlu. Pokud vypršel timeout, dojde ke smazání stavu. Hodnoty timeoutů mohou být nastaveny v sekci options v souboru /etc/pf.conf.

TCP Flagy

Vyhodnocování TCP paketů založené na flags je nejčastěji použito k filtrování TCP paketů, které se pokouší u ustavení spojení. TCP flagy a jejich význam je zde:

Aby PF prováděl inspekci TCP flagů během vyhodnocování pravidla, je použito klíčové slovo flags s následující syntaxí:

flags check/mask

mask řekne PF aby se prováděla inspekce pouze specifikovaných flagů a check specifikuje které flagy musí být "nahozeny" v hlavičce aby pravidlo vyhovovalo.

pass in on fxp0 proto tcp from any to any port ssh flags S/SA

Výše uvedené pravidlo pustí TCP traffic s nastaveným SYN flagem, zkoumá pouze přítomnost SYN a ACK flagů. Paket s SYN a ECE flagy bude výše uvedenému pravidlu vyhovovat a paket s SYN a ACK nebo jenom ACK nebude.

Poznámka: v předchozích verzích OpenBSD, následující syntax byla podporovaná:

. . . flags S

To už neplatí. Maska musí být nyní vždy specifikována.

Flagy jsou často použity ve spojení s pravidly obsahujícími keep state pro snadnější vytváření záznamů ve stavové tabulce:

pass out on fxp0 proto tcp all flags S/SA keep state

Toto povolí vytváření stavu pro odchozí TCP pakety s nastaveným SYN flagem z SYN a ACK flagů.

Měli byste být opatrní při používání flagů -- rozumějte tomu, co děláte a proč a buďte opatrní s radami, které dostanete, protože spousta z nich je špatných. Někteří lidé navrhují vytvoření stavu "pouze pokud je nastaven SYN flag a ne ostatní". Takové pravidlo by skončilo takto:

     . . . flags S/FSRPAUEW  špatný nápad!!

Teorie je, že stav se vytváří pouze na začátku TCP session a session by měla začínat pouze SYN flagem a ne ostatnímmi. Problém je v tom, že některé stroje začínají používat ECN flag a pokud se takový stroj pokusí připojit, bude takovým pravidlem odmítnuta. O moc lepší pravidlo je:

. . . flags S/SAFR

Zatímco toto je praktické a bezpečné, je také nezbytné kontrolovat FIN a RST flagy pokud traffic také podléhá scrub. Scrub proces způsobí, že PF bude zahazovat jakékoliv příchozí pakety s ilegální kombinací TCP flagů (jako např. SYN a FIN nebo SYN a RST). Je důrazně doporučeno vždcky používat scrub na příchozí traffic:

scrub in on fxp0
.
.
.
pass in on fxp0 proto tcp from any to any port ssh flags S/SA \
   keep state

Klíčové slovo quick

Jak bylo naznačeno dříve, každý paket je vyhodnocovaný oproti množině filtrovacích pravidel od shora dolů. Defaultně, paket je označen pro průchod, což může být změměno nějakým pravidlem a může být změněno tam a zpátky předtím než vyhodnocování dorazí na konec množiny pravidel. Poslední pravidlo, které vyhovuje "vyhrává". K tomuto chování existuje výjimka: Volba quick ve filtrovacím pravidle ukončí zpracování a vede k provedení akce s paketem. Podívejme se na několik příkladů:

Špatně:

block in on fxp0 proto tcp from any to any port ssh
pass  in all

V tomto případě, může být řádek s block vyhodnocen, ale nikdy nebude mít žádný efekt, protože následuje řádek, který povolí všechno.

Lepší:

block in quick on fxp0 proto tcp from any to any port ssh
pass  in all

Tato pravidla budou vyhodnocována trochu odlišně. Pokud řádek s block vyhovuje, kvůli volbě quick bude paket zablokován a zbytek množiny pravidel bude ignorován.

Blokování Spoofnutých Paketů

"spoofování" adres je když nehodný uživatel zfalšuje zdrojovou IP adresu v paketech, které přenáší za účelem schovat svoji skutečnou adresu nebo vydávat se za nějaký jiný uzel na sítí. Jakmile uživattel spoofnul svoji adresu, může spustit síťový útok bez toho, že by odhalil skutečn zdroj útoku nebo se může pokusit získat přístup k síťovým službám, které jsou restringovány na určité IP adresy.

PF naíbízí ochranu proti spoofování adres pomocí klíčového slova antispoof:

antispoof [log] [quick] for interface [af]
log
Specifikuje že vyhovující pakety mají být zalogovány via pflogd(8).
quick
Pokud paket vyhovuje tomuto pravidlu, pak bude považováno "výherce" a vyhodnocování rulesetu se zastaví.
interface
Síťový interface na kterém aktivovat ochranu proti spoofování. Zde může být seznam interfaců via list.
af
Address family pro kterou aktivovat ochranu proti spoofování, buď inet pro IPv4 nebo inet6 pro IPv6.

Příklad:

antispoof for fxp0 inet

Když je množina pravidel nahrána, všechny výskyty klíčového slova antispoof jsou expandovány do dvou filtrovacích pravidel. Předpokládejme, že interface fxp0 má IP adresu 10.0.0.1 a masku podsítě 255.255.255.0 (tj. /24), pak výše uvedené antispoof pravidlo se rozvine do:

block in on ! fxp0 inet from 10.0.0.0/24 to any
block in inet from 10.0.0.1 to any

Tato pravidla provedou dvě věci:

POZNÁMKA: Filtrovací pravidla do kterých se expanduje pravidlo antispoof budou také blokovat pakety poslané přes loopback interface na lokální adresu. Tyto adresy by měly být explicitně povoleny. Např.:

pass in quick on lo0 all

antispoof for fxp0 inet

Použití antispoof by mělo být omezeno na interfacy, které mají přiřazenu IP adresu. Použití antispoof na interface bez IP adresy vyústí v filtrovací pravidla jako

block drop in on ! fxp0 inet all
block drop in inet all

S těmito pravidly riskujete blokování veškerého příchozího trafficu na všech interfacech.

IP Options

Defaultně, PF blokuje všechny pakety s nastavenými IP options. To může být dobré pro detekci "OS fingerprinting" utilitami jako nmap. Pokud provozujete aplikaci, která vyžaduje povolení takových paketů jako např. multicast nebo IGMP, může použít direktivu allow-opts:
pass in quick on fxp0 all allow-opts

Příklad množiny filtrovacích pravidel

Níže je uveden přiklad množiny filtrovacích pravidel. Stroj, na kterém běží PF funguje jako firewall mezi malou interní sítí a Internetem. Uvedena jsou pouze filtrovcí pravidla. queueing, nat, rdr, atd., byly v tomto příkladu vynechány.

ext_if  = "fxp0"
int_if  = "dc0"
lan_net = "192.168.0.0/24"

# scrub incoming packets
scrub in all

# nastav politiku default deny 
block in  all
block out all

# povol traffic na loopback interface v obou směrech
pass quick on lo0 all

# aktivuj ochranu proti spoofování na interním interface.
antispoof quick for $int_if inet

# povol pouze ssh spojení z lokální sítě pokud je to důveryhodný počítač
# 192.168.0.15. použij "block return" takže je poslán TCP RST 
# pro uzavřených blokovaných spojení. použij "quick" aby nebylo toto
# pravidlo přepsáno některým z "pass" pravidel pod ním.
block return in quick on $int_if proto tcp from ! 192.168.0.15 \
   to $int_if port ssh flags S/SA

# povol všechen traffic z a do lokální sítě
pass in  on $int_if from $lan_net to any
pass out on $int_if from any to $lan_net

# povol tcp, udp, a icmp z externího (Internet) interface. 
# keep state pro udp a icmp a modulate state pro tcp.
pass out on $ext_if proto tcp all modulate state flags S/SA
pass out on $ext_if proto { udp, icmp } all keep state

# povol ssh spojení na externí interface pokud NENÍ určen 
# pro firewall (tj. jsou určeny pro stroj v lokální síti)
# loguj iniciální pakety takže můžeme později říci, kdo se pokoušel
# napojit
pass in log on $ext_if proto tcp from any to { !$ext_if, !$int_if } \
   port ssh flags S/SA keep state

[Předchozí: Přesměroování Trafficu] [Obsah] [Další: Logování]


[back] www@openbsd.org
Originally [OpenBSD: filter.html,v 1.13 ]
$Translation: filter.html,v 1.3 2003/11/10 13:34:59 horacio Exp $
$OpenBSD: filter.html,v 1.3 2003/11/10 14:42:48 horacio Exp $