[Předchozí: Přesměrování trafficu] [Obsah] [Dále: Logování]
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.
action direction [log] [quick] on int [af] [proto protocol] \
from src_addr [port src_port] to dst_addr [port dst_port] \
[tcp_flags] [state]
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.
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 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.
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
Š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.
PF naíbízí ochranu proti spoofování adres pomocí klíčového slova antispoof:
antispoof [log] [quick] for interface [af]
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.
pass in quick on fxp0 all allow-opts
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í]