[Wstecz: Tabele]
[Spis treści]
[Dalej: Translacje adresów (NAT)]
PF: Filtrowanie pakietów
Spis treści
Wstęp
Filtrowanie pakietów to selektywne przepuszczanie lub blokowanie pakietów
przechodzących przez interfejs sieciowy. Kryteria, którymi kieruje się
pf(4) podczas sprawdzania pakietów, są oparte o Warstwę 3
(IPv4 i
IPv6) oraz Warstwę 4 nagłówków
(TCP,
UDP,
ICMP, i
ICMPv6). Najczęstszym kryterium jest źródłowy i docelowy adres,
źródłowy i docelowy port, oraz protokół.
Reguły filtrujące określają kryteria według których podejmowana jest
konkretna akcja wobec pakietu: przepuść (ang. pass) lub blokuj
(ang. block). Reguły filtrujące są porównywane sekwencyjnie, od
pierwszej do ostatniej. Z wyjątkiem sytuacji, gdy pakiet pasuje
do reguły ze słowem kluczowym quick, pakiety są porównywane
z wszystkimi regułami filtrującymi zanim ostateczna akcja
zostanie podjęta. Ostatnia pasująca reguła jest "zwycięzcą" i decyduje
o podjętej akcji. Jeśli na początku zestawu reguł znajduje się bezwarunkowe
pass all, wówczas wszystkie pakiety, które nie pasowały do
żadnej z reguł, będą przepuszczane.
Składnia reguł
Ogólna, bardzo uproszczona składnia reguł filtrujących
wygląda następująco:
action [direction] [log] [quick] [on interface]
[af] [proto protocol] \
[from src_addr [port src_port]] [to
dst_addr [port dst_port]] \
[flags tcp_flags] [state]
- action
- Akcja, która ma być podejmowana wobec pasujących pakietów, albo
pass albo block. Akcja pass przepuszcza
pakiety z powrotem do jądra systemu do dalszego przetwarzania,
podczas gdy akcja block podejmuje działanie zgodne z
ustawieniem opcji domyślnej polityki blokowania
block-policy.
Domyślna akcja może być jawnie zmieniona poprzez podanie słów
kluczowych block drop lub block return.
- direction
- Kierunek, w którym dany pakiet zmierza na interfejsie sieciowym, albo
in (poł. wchodzi) albo out (poł. wychodzi).
- log
- Określa, że dany pakiet powinien być zapisany w logach przez
pflogd(8). Jeśli reguła zawiera opcję keep state,
modulate state lub synproxy state, wówczas
jedynie pakiet, który rozpoczyna połączenie stanowe
jest odnotowywany w logach.
Aby bezwzględnie zapisywać w logach wszystkie pakiety,
należy zastosować opcję log (all).
- quick
- Jeśli pakiet pasuje do reguły ze słowem kluczowym quick,
wówczas reguła ta jest uznawana za ostatnią pasującą i podejmowana jest
odpowiednia akcja action.
- interface
- Nazwa interfejsu sieciowego, lub grupa takich urządzeń, przez który
przechodzi pakiet.
Grupa urządzeń jest określana tak samo jak nazwa urządzenia z tym że
bez numeru konkretnego interfejsu znajdującego się normalnie na końcu
nazwy.
Na przykład: ppp lub fxp.
Spowoduje, że reguła będzie pasować do dowolnego pakietu przechodzącego
przez odpowiednio, interfejs
ppp lub fxp.
- af
- Rodzina adresów: inet dla IPv4 lub inet6
dla IPv6. PF jest zwykle w stanie zidentyfikować ten parametr na podstawie
adresu(ów) źródłowych/przeznaczenia.
- protocol
- Protokół Warstwy 4 pakietu:
- tcp
- udp
- icmp
- icmp6
- Poprawna nazwa protokołu z
/etc/protocols
- Numer protokołu z przedziału od 0 do 255
- Zbiór protokołów zapisany w postaci listy.
- src_addr, dst_addr
- Adres źródłowy/docelowy w nagłówku IP. Adres może być podany jako:
- Pojedynczy adres IPv4 lub IPv6.
- Blok sieci CIDR.
- W pełni określona domena, która będzie rozwijana przez DNS w czasie
ładowania zestawu reguł. Wszystkie zwrócone adresy IP będą wstawione do reguły.
- Nazwa interfejsu sieciowego. Wszystkie adresy IP przypisane do urządzenia
będą wprowadzone podczas ładowania zestawu reguł.
- Nazwa interfejsu sieciowego wraz z maską sieciową
(np /24). Każdy adres IP danego interfejsu jest łączony
z każdą maską sieciową aby utworzyć odpowiedni blok sieci CIDR,
który będzie wprowadzony podczas ładowania zestawu reguł.
- Nazwa interfejsu sieciowego w nawiasach ( ). Mówi to PF,
aby odświeżać regułę, jeśli adres(y) IP tego interfejsu ulegnie zmianie.
Jest to bardzo przydatne gdy zewnętrzne urządzenie otrzymuje swój
adres IP przez DHCP lub dial-up, ponieważ zestaw reguł
nie musi być przeładowywany za każdym razem, gdy zmienia się IP.
- Nazwa interfejsu sieciowego wraz z maską sieciową
(np /24). Każdy adres IP danego interfejsu jest łączony
z każdą maską sieciową aby utworzyć odpowiedni blok sieci CIDR,
który będzie wprowadzony podczas ładowania zestawu reguł.
- Nazwa interfejsu sieciowego z dopisanym na końcu jednym z poniższych
wyrażeń:
- :network - odpowiada blokowi sieci CIDR (np
192.168.0.0/24)
- :broadcast - odpowiada adresowi rozgłoszeniowemu podsieci
(np 192.168.0.255)
- :peer - odpowiada adresowi IP węzła na drugim końcu połączenia
point-to-point
- Dodatkowo, wyrażenie :0 może zostać dodane na końcu
zarówno nazwy interfejsu jak i któregokolwiek z wymienionych słów
kluczowych aby nie były brane pod uwagę dodatkowe, wskazujące adresy IP
(ang. aliased IP addresses) podczas przetwarzania reguł.
Oznaczenia te mogą także być użyte wewnątrz wyrażeń w nawiasach.
Przykład: fxp0:network:0
- Tabela.
- Którykolwiek z powyższych, lecz zanegowany przy pomocy modyfikatora
! ("not").
- Zestaw adresów w postaci listy.
- Słowo kluczowe any oznaczające wszystkie adresy.
- Słowo kluczowe all stanowiące skrót from any to
any.
- src_port, dst_port
- Port źródłowy/docelowy w Warstwie 4 nagłówka pakietu. Porty mogą
być podawane jako:
- Liczba z zakresu od 1 do 65535
- Poprawna nazwa usługi, zdefiniowana w
/etc/services
- Zestaw portów w postaci listy
- Przedział:
- != (różny)
- < (mniejszy niż)
- > (większy niż)
- <= (mniejszy lub równy)
- >= (większy lub równy)
- >< (przedział)
- <> (poza przedziałem)
- Ostatnie dwa są operatorami binarnymi (wymagają dwóch argumentów) oraz
nie mogą mieć parametrów w postaci przedziałów.
- : (obejmujący zasięg)
- Operator obejmujący zasięg jest operatorem binarnym, nie obejmuje
on jednak końców przedziałów stanowiących jego argumenty.
- tcp_flags
- Określa flagi, które muszą być ustawione w nagłówku TCP gdy używamy
proto tcp. Są one podawane w postaci:
flags check/mask. Na przykład: flags
S/SA - PF bierze pod uwagę jedynie flagi S i A (SYN i ACK),
a reguła jest dopasowana jeśli tylko flaga SYN jest ustawiona.
- state
- Określa, czy informacje o stanie połączenia są przechowywane, gdy
pakiety są dopasowywane do tej reguły.
- keep state - działa z TCP, UDP, i ICMP.
- modulate state - działa jedynie z TCP. PF wygeneruje
trudny do przewidzenia Inicjujący Numer Sekwencyjny (ang. Initial Sequence
Number - ISN) dla pakietów pasujących do tej reguły.
- synproxy state - pośredniczy w odbieraniu nadchodzących
połączeń TCP aby pomóc zabezpieczyć serwery przed atakami "TCP SYN flood".
Opcja ta zawiera także funkcjonalności keep state i
modulate state.
Domyślne blokowanie
Zaleca się przyjmować domyślną politykę blokowania wszystkiego, a
jedynie selektywne przepuszczanie konkretnego ruchu. Takie podejście
zalecane jest nie tylko ze względów bezpieczeństwa, ale sprawia, że
pisanie zestawu reguł jest znacznie prostsze.
Aby wprowadzić domyślną politykę blokowania pierwsze dwie reguły
powinny wyglądać tak:
block in all
block out all
Spowoduje to blokowanie całego ruchu na wszystkich interfejsach w
obu kierunkach.
Przepuszczanie ruchu
Ruch musi być precyzyjnie przepuszczany przez firewall albo będzie
zatrzymany przez domyślną politykę blokowania. W tym miejscu do akcji
wchodzą kryteria takie jak port źródłowy/docelowy, adres źródłowy/docelowy
oraz protokół. Jeśli jakiś ruch ma być przepuszczany przez firewall,
to reguły powinny być napisane tak restrykcyjnie jak to tylko
możliwe. Ma to zapewnić przepuszczanie pożądanego i tylko pożądanego ruchu.
Kilka przykładów:
# Przepuść ruch na dc0 z sieci lokalnej, 192.168.0.0/24,
# zmierzający do 192.168.0.1. Przepuść także cały powracający
# do tej sieci ruch 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
# Przepuść ruch TCP z zewnątrz na fxp0 zmierzający do serwera www.
# Nazwa interfejsu, fxp0, jest użyta jako adres docelowy, więc
# pakiety będą pasować do tej reguły jedynie jeśli są przeznaczone
# dla tej maszyny OpenBSD.
pass in on fxp0 proto tcp from any to fxp0 port www
Słowo kluczowe quick
Jak już zostało to wcześniej napisane, każdy pakiet jest porównywany
z całym zestawem reguł od góry do dołu. Domyślnie, pakiet
po porównaniu jest przekazywany do kolejnej reguły, i dlatego
może być wielokrotnie zmieniany jego status, zanim osiągnie
koniec zestawu reguł. "Ostatnia pasująca reguła wygrywa".
Jest od tego wyjątek: opcja quick w regule filtrującej
skutkuje przerwaniem dalszego porównania i powoduje
podjęcie akcji z obecnej reguły. Oto kilka przykładów:
Źle:
block in on fxp0 proto tcp from any to any port ssh
pass in all
W tym przypadku, linia block może być porównywana, ale nigdy
nie będzie miała żadnego efektu, ponieważ po niej znajduje się linia,
która wszystko przepuszcza.
Lepiej:
block in quick on fxp0 proto tcp from any to any port ssh
pass in all
Te reguły są porównywane nieco inaczej. Jeśli linia block
pasuje, dzięki opcji quick, pakiet będzie zablokowany,
a reszta reguł tego zestawu będzie zignorowana.
Śledzenie stanów
Jedną z ważnych możliwości Packet Filter jest śledzenie stanów
(ang. keeping state) lub kontrolowanie stanów (ang. stateful
inspection). Kontrolowanie stanów odnosi się do zdolności PF do
śledzenia stanu, lub przebiegu, połączenia sieciowego. Poprzez
przechowywanie informacji o każdym połączeniu w tabeli stanów,
PF jest w stanie szybko określić, czy pakiet przechodzący przez
firewall należy do już nawiązanego połączenia. Jeśli tak jest,
pakiet jest przepuszczany bez przechodzenia zestawu reguł.
Śledzenie stanów ma wiele zalet, włączając uproszczenie zestawu
reguł i lepszą wydajność filtrowania pakietów. PF jest w stanie
dopasowywać pakiety poruszające się w obu kierunkach danego
połączenia, co oznacza, że reguły przepuszczające powracający ruch
nie są potrzebne. A ponieważ pakiety pasujące do połączenia stanowego
nie przechodzą zestawu reguł, czas zużywany na przetwarzanie tych
pakietów może być bardzo znacząco zmniejszony.
Gdy reguła posiada opcje keep state, pierwszy pakiet
pasujący do niej tworzy "połączenie stanowe" pomiędzy nadawcą i
odbiorcą. Wówczas, nie tylko pakiety pochodzące od nadawcy,
zmierzające do odbiorcy, ale i pakiety odbiorcy, skierowane do
nadawcy pasują do reguły i nie są sprawdzane przez zestaw reguł
filtrujących. Na przykład:
pass out on fxp0 proto tcp from any to any keep state
Zezwala to na wychodzenie ruchu TCP na interfejsie fxp0
i przepuszcza ruch powrotny pakietów stanowiących odpowiedź.
Śledzenie stanów poza swoją funkcjonalnością, zapewnia także
znaczący wzrost wydajności firewalla, ponieważ wyszukania
stanów są dużo szybsze niż porównywanie pakietu z zestawem reguł
filtrujących.
Opcja modulate state działa podobnie do keep state
z tą różnicą, że odnosi się jedynie do pakietów TCP. Przy użyciu
modulate state, Inicjujący Numer Sekwencyjny (ISN)
wychodzącego połączenia jest losowy. Jest to przydatne do ochrony
połączeń nawiązanych przez różne systemy operacyjne, które nie najlepiej
radzą sobie z generowaniem numeru ISN.
Począwszy od OpenBSD 3.5, opcja modulate state może być
używana w regułach, które odnoszą się także do innych niż TCP protokołów.
Śledź stan wychodzących pakietów TCP, UDP i ICMP oraz generuj ISN dla TCP:
pass out on fxp0 proto { tcp, udp, icmp } from any \
to any modulate state
Inną zaletą śledzenia stanów jest to, iż odpowiedni ruch ICMP będzie
przepuszczany przez firewall. Na przykład, jeśli keep state
jest zdefiniowane dla połączenia TCP i nadejdzie komunikat ICMP
"gaszący źródło" (ang. source-quench) odwołujący się do tego połączenia,
będzie on dopasowany do odpowiedniego wpisu stanowego i przepuszczony
przez firewall.
Zakres (ang. scope) wpisów w tabeli stanów jest globalnie kontrolowany
poprzez opcje czasu wykonywania
state-policy,
niemniej można go określić dla poszczególnych reguł indywidualnie
poprzez słowa kluczowe reguł śledzenia stanów: if-bound,
group-bound i floating.
Słowa kluczowe użyte dla pojedynczej reguły mają to samo znaczenie co
w przypadku globalnej polityki stanów state-policy.
Przykład:
pass out on fxp0 proto { tcp, udp, icmp } from any \
to any modulate state (if-bound)
Reguła ta narzuca wymóg, aby pakiety które pasują do tej reguły
były przekazywane przez interfejs fxp0.
Proszę zwrócić uwagę, że reguły nat,
binat, i
rdr bezwarunkowo tworzą stan dla
pasujących połączeń tak długo, jak dane połączenie jest
przekierowywane przez daną regułę.
Śledzenie stanów dla UDP
Każdy od czasu do czasu słyszy opinie, że "nie można utworzyć stanu
z UDP, ponieważ UDP jest bezstanowym protokołem!". Mimo iż jest
prawdą, że sesje komunikacyjne UDP nie mają żadnej formy stanu
(formalnego rozpoczęcia i zakończenia komunikacji), nie ma to
żadnego wpływu na zdolność PF do tworzenia stanowych sesji UDP.
W tym przypadku protokołów bez pakietów "inicjujących" i "kończących"
połączenie, PF po prostu śledzi ile czasu upłynęło odkąd pasujący
pakiet został przepuszczony. Jeśli czas przekroczy ustaloną wartość,
wpis stanu jest usuwany. Czas "przeterminowania" może być dostrojony
w sekcji opcje pliku pf.conf.
Opcje dla śledzenia stanów
Kiedy reguła filtra tworzy wpis o stanie poprzez użycie któregokolwiek
z kluczy keep state, modulate state, lub synproxy state,
pewne opcje mogą być użyte do kontroli zachowania tworzonego stanu.
Dostępne są poniższe opcje:
- max number
- Ogranicza liczbę stanów jakie dana reguła może utworzyć do maksymalnej
wartości ustalonej przez number.
Jeżeli to maksimum zostało osiągnięte, pakiety które normalnie utworzyłyby
nowy stan są blokowane aż do czasu gdy liczba aktualnych stanów zostanie
zmniejszona.
- source-track
- Opcja ta włącza śledzenie liczby utworzonych stanów dla każdego
źródłowego adresu IP.
Opcja ta posiada dwa formaty:
- source-track rule - Maksymalna liczba stanów utworzonych
przez tą regułę jest ograniczona przez opcje max-src-nodes
oraz max-src-states. Tylko wpisy stanów utworzone przez tą
regułę obliczają zbliżanie się do limitu.
- source-track global - Liczba stanów utworzonych przez
wszystkie reguły które używają tej opcji jest ograniczona. Każda reguła
może posiadać różną wartość opcji max-src-nodes i
max-src-states, jednakże wpisy stanów utworzone przez każdą
uczestniczącą regułę odlicza w kierunku indywidualnych limitów dla
każdej reguły.
Całkowita liczba źródłowych adresów IP śledzonych globalnie, może być
kontrolowana poprzez
opcję startową src-nodes.
- max-src-nodes number
- Kiedy korzystamy z opcji source-track, parametr max-src-nodes
będzie ograniczał liczbę źródłowych adresów IP, które mogą jednocześnie
generować stan.
Opcja ta może być użyta tylko w połączeniu z source-track rule.
- max-src-states number
- Kiedy wykorzystywana jest opcja source-track, max-src-states
będzie ograniczało liczbę jednoczesnych wpisów w tabeli stanów które mogą być
utworzone przez pojedyńczy źródłowy adres IP.
Zakres tego limitu (tj. stany utworzone tylko przez tą regułę lub stany
utworzone przez wszystkie reguły które korzystają z source-track)
jest zależny od użycia opcji source-track.
Przykład:
pass in on $ext_if proto tcp to $web_server \
port www flags S/SA keep state \
(max 200, source-track rule, max-src-nodes 100,
max-src-states 3)
Powyższy przykład powoduje:
- Ograniczenie absolutnej maksymalnej liczby stanów jakie ta reguła
może utworzyć do 200
- Włącza śledzenie źródła; ogranicza tworzenie stanów opartych tylko
na stanach utworzonych przez tą regułę
- Ogranicza maksymalną liczbę węzłów które mogą jednocześnie tworzyć
stan do 100
- Ogranicza maksymalną liczbę jednoczesnych stanów dla źródłowego IP do 3
Dodatkowe ograniczenia mogą być ustawione dla śledzenia połączeń TCP
dla których zakończyła się negocjacja protokołu.
- max-src-conn number
- Ogranicza maksymalna liczbę jednoczesnych połączeń TCP, które
zakończyły negocjację połączenia, dla pojedyńczego hosta.
- max-src-conn-rate number / interval
- Ogranicza tempo powstawania nowych połączeń do konkretnej wartości
w jednostce czasu (interval).
Każda z tych opcji automatycznie przywołuje opcję source-track rule,
oraz jest niekompatybilna z source-track global.
Ponieważ opcje te dotyczą tylko połączeń TCP które zakończyły negocjację,
bardziej agresywne zachowania mogą być użyte dla przestępczego adresu IP.
- overload <tablica>
- Umieści adres IP przestępczego hosta w tablicy.
- flush [global]
- Zabije wszystkie stany pasujące do tej reguły i utworzone przez ten
adres IP.
Kiedy podane jest global, zostaną zabite wszystkie stany pasujące
do tego źródłowego adresu IP, niezależnie od tego jaka reguła utworzyła stan.
Przykład:
table <abusive_hosts> persist
block in quick from <abusive_hosts>
pass in on $ext_if proto tcp to $web_server \
port www flags S/SA keep state \
(max-src-conn 100, max-src-conn-rate 15/5,
overload <abusive_hosts> flush)
Powyższe reguły wykonują:
- Ograniczenie maksymalnej liczby połączeń dla pojedynczego źródła do 100.
- Ograniczenie tempa połączeń do 15 w ciągu każdych 5 sekund.
- Umieszczenie każdego adresu IP który przełamuje powyższy limit do
tablicy <abusive_hosts>.
- Dla każdego grzesznego adresu IP, czyści wszystkie stany utworzone
przez tą regułę.
Flagi TCP
Dopasowanie pakietów TCP na podstawie flag jest najczęściej
wykorzystywane przy filtrowaniu pakietów, które otwierają
nowe połączenie. Flagi TCP i ich nazwy są podane poniżej:
- F : FIN - Finish; zakończenie sesji
- S : SYN - Synchronize; sygnalizuje prośbę o rozpoczęcie sesji
- R : RST - Reset; porzuć połączenie
- P : PUSH - Push; pakiet jest wysyłany bezzwłocznie
- A : ACK - Acknowledgement; potwierdzenie
- U : URG - Urgent; ponaglenie
- E : ECE - Explicit Congestion Notification Echo
- W : CWR - Congestion Window Reduced
Aby PF sprawdzał flagi TCP podczas przetwarzania reguł filtrujących
wykorzystywane jest słowo kluczowe flags. Jego składnia jest
następująca:
flags check/mask
Część mask mówi PF aby sprawdzać jedynie podane flagi, a
część check określa która flaga(i) powinny być "ustawione"
w nagłówku, aby dopasowanie miało miejsce.
pass in on fxp0 proto tcp from any to any port ssh flags S/SA
Powyższa reguła przepuszcza ruch TCP z ustawioną jedynie flagą SYN,
biorąc pod uwagę tylko flagi SYN i ACK. Pakiet z flagami SYN i ECE
będzie pasował do powyższej reguły, jednak pakiet z SYN i ACK lub
tylko ACK już nie.
Uwaga: we wcześniejszych wersjach OpenBSD, następująca zapis był
poprawny:
. . . flags S
Nie jest to już prawdziwe. Maska zawsze musi być podana.
Flagi często są stosowane w połączeniu z regułami keep state,
aby wspomóc kontrolę tworzenia stanów:
pass out on fxp0 proto tcp all flags S/SA keep state
Reguła ta zezwala na tworzenie stanu dla wychodzących pakietów TCP
z ustawioną jedynie flagą SYN i przy braniu pod uwagę SYN oraz ACK.
Przy korzystaniu z flag trzeba być bardzo ostrożnym - należy rozumieć
co się robi i dlaczego, no i należy uważać na rady innych,
ponieważ często są one błędne. Niektórzy np. sugerują tworzenie stanu
"jedynie gdy flaga SYN jest ustawiona, i żadna inna". Taka reguł
wyglądała by tak:
. . . flags S/FSRPAUEW to zły pomysł!!
W teorii, tworzy się połączenie stanowe na początku sesji TCP, a sesja
powinna rozpocząć się od flagi SYN, i żadnej innej. Problem polega
na tym, że niektórzy użytkownicy rozpoczynają połączenia wraz z flagą
ECN, i będą odrzuceni przez taką regułę. Dużo lepszą praktyką jest:
. . . flags S/SAFR
Jest to praktyczne i bezpieczne. Jeśli ruch podlega normalizacji
scrub, wówczas można nie sprawdzać także
flag FIN i RST. Normalizacja powoduje, że PF porzuca nadchodzące
pakiety z nieprawidłową kombinacja flag (taką jak SYN i FIN lub
SYN i RST) a także normalizuje potencjalnie niejasne kombinacje
(takie jak SYN i FIN).
Zaleca się zawsze normalizować przychodzący ruch
przy pomocy scrub:
scrub in on fxp0
.
.
.
pass in on fxp0 proto tcp from any to any port ssh flags S/SA \
keep state
TCP SYN Proxy
Domyślnie gdy klient nawiązuje połączenie TCP z serwerem PF przepuszcza
pakiety związane z
"potrójnym uzgodnieniem" (ang. handshake) pomiędzy dwoma uczestniczącymi
końcami gdy tylko nadejdą.
PF ma jednak zdolność do pośredniczenia (ang. to proxy) w "potrójnym
uzgodnieniu".
Dzięki temu, to PF dokona poprawnego "potrójnego uzgodnienia" z klientem,
następnie zainicjuje "potrójne uzgodnienie" z serwerem i dopiero wtedy
zacznie przekazywać pakiety pomiędzy oboma węzłami.
Najważniejszą korzyścią tego procesu jest to, iż żaden pakiet nie
zostanie wysłany do serwera zanim klient nie dokona poprawnego
"potrójnego uzgodnienia".
Eliminuje to zagrożenie ataków typu "TCP SYN flood" na serwer
danej usługi.
"TCP SYN proxy" jest uruchamiane przy pomocy słów kluczowych
synproxy state w regułach filtrujących.
Na przykład:
pass in on $ext_if proto tcp from any to $web_server port www \
flags S/SA synproxy state
Tu, połączenia do serwera WWW będą nawiązywanie za pośrednictwem
"TCP SYN proxy" przez PF.
Ze względu na swoje działanie, synproxy state zawiera
funkcjonalności keep state i modulate state.
"SYN proxy" nie będzie działać jeśli PF jest uruchomiony na moście (ang.
bridge(4)).
Blokowanie sfałszowanych pakietów
Fałszowaniem (ang. spoof) określa się zmianę adresu źródłowego pakietu mające
na celu albo ukrycie prawdziwego pochodzenia datagramu, albo podszycie się
pod inny segment sieci. Gdy użytkownik pomyślnie podszyje się pod inny adres,
może rozpocząć sieciowy atak bez ujawniania jego prawdziwego źródła lub
spróbować uzyskać kontrolę nad usługami, które są dostępne dla wąskiej grupy
konkretnych adresów IP.
PF oferuje pewną ochronę przed podszywaniem się pod inne adresy
poprzez słowo kluczowe antispoof:
antispoof [log] [quick] for interface [af]
- log
- Określa, że pasujące pakiety powinny być logowane przez
pflogd(8).
- quick
- Jeśli pakiet pasuje do tej reguły, wówczas jest jest ona uznawana za
regułę "zwycięską" i nie następuje dalsze porównywanie reguł z zestawu.
- interface
- Nazwa interfejsu sieciowego na którym ma być aktywowana ochrona przed
spoofing-iem. Może to być także lista
interfejsów sieciowych.
- af
- Rodzina adresów dla której ma być aktywowana ochrona przed
spoofing-iem. inet dla IPv4 lub inet6 dla IPv6.
Przykład:
antispoof for fxp0 inet
Gdy zestaw reguł jest ładowany, każde wystąpienie antispoof
jest rozszerzane do dwóch reguł filtrujących. Zakładając, że interfejs
fxp0 ma adres IP 10.0.0.1 i maskę podsieci 255.255.255.0 (np, /24),
powyższa reguła antispoof byłaby przekształcona w:
block in on ! fxp0 inet from 10.0.0.0/24 to any
block in inet from 10.0.0.1 to any
Reguły te realizują dwa zadania:
- Blokują cały ruch przychodzący z sieci 10.0.0.0/24, który
nie przechodzi przez fxp0. Ponieważ sieć 10.0.0.0/24 jest na
interfejsie fxp0, pakiety z adresem źródłowym z tego bloku
sieci nie powinny nigdy nadchodzić z żadnego innego interfejsu
sieciowego.
- Blokują cały ruch przychodzący z 10.0.0.1, adresu IP interfejsu
fxp0. Host nigdy nie powinien wysyłać pakietów do samego
siebie przez zewnętrzny interfejs, dlatego nadchodzące pakiety
z adresem źródłowym należącym do tej maszyny mogą być uznane za
podejrzane.
UWAGA: Reguły filtrujące, w które antispoof się
przekształca będą blokować także pakiety wysyłane przez interfejs
zwrotny (ang. loopback) na lokalny adres.
W każdym razie najlepiej opuszczać filtrowanie pakietów na interfejsie
zwrotnym, a staje się to konieczne w przypadku korzystania z reguł
antispoof:
set skip on lo0
antispoof for fxp0 inet
Korzystanie z antispoof powinno być ograniczone do interfejsów,
które mają przypisany adres IP. Użycie antispoof na interfejsie
bez adresu IP spowoduje powstanie następujących reguł filtrujących:
block drop in on ! fxp0 inet all
block drop in inet all
Przy takich regułach istnieje ryzyko blokowania całego nadchodzącego
ruchu na wszystkich interfejsach.
Pasywne rozpoznawanie systemów operacyjnych
Pasywne rozpoznawanie systemów operacyjnych (ang. Passive OS Fingerprinting,
OSFP) to sposób pasywnego rozpoznawania systemu operacyjnego zdalnego
węzła na podstawie pewnych charakterystycznych cech jego pakietów TCP SYN.
Informacje te mogą być wykorzystywane jako kryteria w regułach filtrujących.
PF rozpoznaje system operacyjny zdalnego węzła dzięki porównywaniu
jego charakterystyk pakietów TCP SYN z
plikiem "odcisków palców"
(ang. fingerprints file) różnych systemów operacyjnych, którym domyślnie
jest /etc/pf.os.
Jeśli PF jest włączony, aktualna lista "odcisków" może być wyświetlona
poniższą komendą:
# pfctl -s osfp
W regule filtrującej, rozpoznawanie "odcisków" może być określane
poprzez rodzinę systemów operacyjnych, wersje lub gałąź/poziom
poprawek.
Każda z tych składowych jest wylistowana na wyjściu dopiero co
wyżej wspomnianej komendy pfctl. Aby określić "odcisk"
systemu w regule filtrującej, używamy słowa kluczowego
os:
pass in on $ext_if from any os OpenBSD keep state
block in on $ext_if from any os "Windows 2000"
block in on $ext_if from any os "Linux 2.4 ts"
block in on $ext_if from any os unknown
Specjalna klasa systemów unknown pozwala dopasować
pakiety, dla których "odciski" nie zostały rozpoznane.
WARTO PAMIĘTAĆ następujące fakty:
- "Odciski" systemów operacyjnych są niekiedy błędne z powodu
podszywania się i/lub preparowania pakietów, w taki sposób, aby wyglądały
na pochodzące z konkretnego systemu operacyjnego.
- Pewne wydania lub poprawki systemowe mogą zmienić charakterystyki
"odcisków" i spowodować nierozpoznanie systemu lub wręcz jego błędne
rozpoznanie.
- OSFP działa jedynie na podstawie pakietów TCP SYN, dlatego nie będzie
działać poprawnie na innych protokołach czy też już nawiązanych połączeniach.
Opcje IP
Domyślnie PF blokuje wszystkie pakiety IP z ustawionymi opcjami.
Może to utrudnić rozpoznanie systemu operacyjnego przez takie
narzędzia jak nmap. Jeśli zachodzi konieczność uruchomienia aplikacji, która
wymaga przepuszczania tych pakietów, jak np. wysyłanych do grupy odbiorców
(ang. multicast) lub IGMP, można skorzystać z dyrektywy allow-opts:
pass in quick on fxp0 all allow-opts
Przykład zestawu reguł filtrujących
Poniżej znajduje się przykład zestawu reguł filtrujących.
Maszyna z PF pełni rolę firewalla oddzielającego małą sieć
wewnętrzną od Internetu. Poniżej przedstawiona jest tylko
konfiguracja odpowiadająca za filtrowanie, regułki
kolejkowanie,
nat,
rdr
itp zostały pominięte.
ext_if = "fxp0"
int_if = "dc0"
lan_net = "192.168.0.0/24"
# table containing all IP addresses assigned to the firewall
table <firewall> const { self }
# nie filtruj na interfejsie zwrotnym (loopback)
set skip on lo0
# normalizacja przychodzących pakietów
scrub in all
# ustawienie polityki domyślnego blokowania
block all
# aktywuj ochronę przed spoofing-iem dla interfejsu wewnętrznego.
antispoof quick for $int_if inet
# zezwalaj na połączenia ssh z sieci lokalnej jedynie z zaufanego
# hosta - 192.168.0.15. korzystaj z "block return", aby TCP RST
# od razu było wysyłane w odpowiedzi na blokowane połączenia
# korzystaj z "quick", aby reguła nie była nadpisana przez
# znajdujące się poniżej reguły "pass"
block return in quick on $int_if proto tcp from ! 192.168.0.15 \
to $int_if port ssh flags S/SA
# przepuszczaj cały ruch z i do lokalnej sieci przeznaczony dla
# maszyny będącej firewall-em
pass in on $int_if from $lan_net to $int_if
pass out on $int_if from $int_if to $lan_net
# wypuszczaj tcp, udp i icmp na interfejsie zewnętrznym (Internet).
# śledź stan dla udp i icmp oraz moduluj stan dla 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
# zezwalaj na połączenia ssh na interfejsie zewnętrznym pod warunkiem,
# że NIE są one skierowane do firewall-a (np, nie są skierowane
# do maszyny z sieci lokalnej). twórz logi dla pakietów inicjujących
# połączenia, aby można było potem stwierdzić, kto próbował się
# połączyć. używamy "tcp syn proxy" dla nadchodzących połączeń.
pass in log on $ext_if proto tcp from any to ! <firewall> \
port ssh flags S/SA synproxy state
|
[Wstecz: Tabele]
[Spis treści]
[Dalej: Translacje adresów (NAT)]
www@openbsd.org
$OpenBSD: filter.html,v 1.16 2006/05/19 09:13:25 jufi Exp $