|
Strona 1 z 4 "IPFW, oprogramowanie dołączone do FreeBSD pełni funkcję
filtra pakietów oraz systemu rozliczania z generowanego ruchu. IPFW jest
zintegrowany z jądrem, a interakcję z użytkownikiem zapewnia narzędzie pracujące
w przestrzeni użytkownika, ipfw(8). Razem umożliwiają one definiowanie i
sprawdzanie reguł używanych przez jądro w procesie podejmowania decyzji o
routingu pakietów.
IPFW składa się z dwóch części. Pierwsza zajmuje się filtrowaniem pakietów.
Druga zajmuje się rozliczaniem z ruchu IP i umożliwia nadzorowanie pracy routera
na podstawie reguł filtra pakietów. Dzięki temu możliwe staje się sprawdzenie np.
ile ruchu generowanego jest przez określoną maszynę lub jak dużo ruchu do i z
serwerów WWW router przekazuje.
Dzięki takiej a nie innej konstrukcji IPFW, możesz używać IPFW również na
maszynach nie pełniących funkcje routera do filtrowania pakietów w połączeniach
przychodzących i wychodzących. Jest to specyficzne zastosowanie IPFW, ale
konfigurowane dokładnie tak jak konfiguruje się filtr do innych zastosowań."
0. Tytułem wstępu
Na potrzeby tego tekstu zakładam, że Czytelnik dysponuje
łączem ADSL 128/512Kbit/s oraz systemem FreeBSD 4.9-STABLE oraz podstawami
wiedzy z zakresu sieci opartych o protokół TCP/IP. Ma także poprawnie
skonfigurowany do pracy sieciowej system.
1. Komendy ipfw
Zanim dowiesz się jak pisać regułki dobrze jest zapoznać się z
poleceniami obsługującymi działanie pakietu ipfw. Najważniejsze to:
ipfw zero - zeruje liczniki dla wszystkich regułek (każda regułka
podczas działania zlicza pasującą do niej ilość pakietów i ich sumaryczny
rozmiar w bajtach).
ipfw flush - czyści (kasuje) wszystkie regułki oprócz domyślnych. Przed
każdą większą zmianą regułek (np. za pomocą skryptu) dobrze jest wyczyścić
regułki aby nowe nie nakładały się na stare.
ipfw show - pokazuje wszystkie aktualnie działające regułki oraz ich
statystyki (ilość pakietów i danych pasujących do tej regułki).
ipfw show - pokazuje tylko regułkę numer "" (np. ipfw
show 100).
2. Firewall
Pakiet ipfw został stworzony na potrzeby ścian ogniowych (firewalls).
Przyjrzyjmy mu się zatem bliżej.
Aby móc korzystać z funkcjonalności firewall opartego o ipfw należy wkompilować
w jądro opcje:
Należy też w pliku "/etc/rc.conf" dodać/zmienić opcje:
firewall_enable="YES"
firewall_rules="/etc/firewall.rules" |
gdzie "firewall_rules" określa nam nazwę pliku, z którego będą
wczytywane regułki firewalla przy starcie systemu. W naszym przypadku będzie to
plik "/etc/firewall.rules".
Należy też do pliku "/etc/make.conf" dodać:
Składnia poleceń ipfw jest bardzo zbliżona do naturalnego
języka angielskiego (co będzie można zaobserwować w przykładach poniżej), dzięki
czemu pisanie regułek za jego pomocą jest bardzo proste. W ipfw występują trzy
interesujące nas rodzaje akcji związanych z regułką: regułke można dodać (add),
zmienić (modify) oraz usunąć (delete). Każda z regułek w momencie dodania jej do
konfiguracji dostaje swój własny "numer identyfikacyjny" (np. regułka może mieć
numer 100), dzięki czemu możemy się do niej później w prosty sposób odwoływać.
Jeśli w konfiguracji danej regułki nie podamy jej numerka jest on przypisywany
automatycznie na zasadzie "dostajesz pierwszy wolny".
Następnie po zdefiniowaniu akcji dodania lub modyfikacji (przy kasowaniu regułki
nie podajemy żadnego parametru poza numerem, czyli np. "ipfw delete 100" skasuje
nam regułkę numer 100 bez zaglądania, co w niej się znajduje) należy zdefiniować
parametry danej regułki. Mogą to być: rodzaj akcji jaka ma być podjęta (zezwalaj
- allow, odrzóć - deny, przekieruj - fwd, zliczaj - count, odrzuć z informacją
dla nadawcy - reject oraz reset) protokół dla jakiego ma działać regułka (np. ip,
tcp, udp, icmp), adres źródłowy pakietu, adres docelowy pakietu, kierunek
przepływu pakietu ("in" lub "out"), interfejs oraz kilka innych które poznamy za
chwile.
Przykładowa regułka o numerze 100, która pozwala na przepuszczenie dowolnego
ruchu (czyli z dowolnego adresu do dowolnego adresu) w protokole ip (czyli
zarówno tcp jak i udp czy icmp) przez interfejs xl0 wyglądać może tak:
ipfw add 100 allow ip from any to
any via xl0
Jeśli natomiast przykładowo chcemy, żeby wszystkie pakiety
przychodzące do nas w protokole tcp na port 80 były odrzucane ale reszta była
akceptowana musimy dodać już dwie regułki:
ipfw add 100 deny tcp from any to me
80 via xl0
ipfw add 200 allow ip from any to any via xl0
Co się dzieje po dodaniu powyższego zapisu? Załóżmy, że do
naszego komputera na port 21 przez interfejs xl0 przychodzi pakiet z adresu
111.222.333.444 z portu 1025. Trafia do regułek naszego firewalla i jest
sprawdzany. Najpierw sprawdzany jest przez regułkę 100, czyli: jeśli pakiet jest
pakietem tcp (nasz jest, więc regułka sprawdza go dalej) i pochodzi z dowolnego
adresu (111.222.333.444 to jakby nie patrzeć dowolny adres) z dowolnego portu
(1025 to też dowolny port) a przychodzi na mój adres ("me" oznacza wszystkie
możliwe adresy ip przypisane do mojego komputera na wszystkich interfejsach;
nasz pakiet to spełnia, bo przyszedł przez interfejs xl0) na port 80 (pakiet
jest skierowany na port 21, czyli nie spełnia tego kryterium). W związku z
niespełnieniem kryterium portu docelowego (80) regułka stwierdza, że pakiet nie
spełnia jej kryteriów, więc kieruje go do następnej w kolejności regułki, czyli
200. W regułce 200 sprawdzane jest: jeśli pakiet jest w protokole ip (tcp
zalicza się do ip, więc jest to spełnione) i pochodzi z dowolnego adresu z
dowolnego portu a zaadresowany jest do dowolnego przypisanego do mojego
komputera adresu i przeszedł przez interfejs xl0 to przepuść go. Jest to
spełnione, czyli pakiet jest przepuszczany i opuszcza kod firewalla (poza
osobnym przypadkiem, kiedy tak nie jest - patrz "Dwa w jednym").
Jak widać zapis regułek jest bardzo wygodny i intuicyjny. Widać też, że zgodnie
z powyższym przykładem pakiet jest sprawdzany po kolei z każdą regułką aż trafi
na pierwszą, do której pasuje. Wtedy podejmowana jest związana z tą regułką
akcja i pakiet opuszcza ipfw.
Oprócz zaprezentowanych akcji, czyli "allow", która przepuszcza pakiet oraz "deny",
która "wyrzuca" pakiet bez jakiejkolwiek informacji zwrotnej dla nadawcy
istnieją też (wspomniane na początku) akcje "reject" oraz "reset". Akcja "reject"
powoduje, że pakiet zostaje odrzucony a do nadawcy odsyłana jest informacja
"host unreachable", czyli wygląda to dla nadawcy tak, jakby nasz komputer był
wyłączony (dla danego pakietu). Akcja "reset" powoduje odrzucenie pakietu i
wysłanie do nadawcy pakietu tcp "RST". Do czego to może się nam przydać? Otóż
zobaczmy to na przykładzie portu 113 (ident), który jest często przepytywany
przez np. serwery FTP podczas łączenia się z nimi. Kiedy użyjemy dla tego portu
akcji "drop" pakiet z serwera FTP przyjdzie i zostanie skasowany ale serwer FTP
nie dostanie żadnej informacji o tym, więc będzie czekał, aż nasz komputer wyśle
mu odpowiedz na jego pakiet. Taka odpowiedz nigdy nie nadejdzie, więc serwer FTP
będzie czekał aż upłynie czas przewidziany na powrót informacji zwrotnej i
dopiero wtedy zakłada, że nasz port 113 jest zamknięty. Nie jest to zbyt dobre,
gdyż powoduje wydłużenie czasu łączenia się z serwerem (nawet o kilka sekund).
Rozwiązaniem jest wysłanie informacji zwrotnej do serwera FTP, że nasz port 113
jest zamknięty. Nie będzie on wtedy niepotrzebnie czekał i od razu przejdzie do
negocjacji już konkretnie połączenia ftp. Regułka ipfw, która wysyła pakiet RST
jako informacje zwrotną do serwera FTP może mieć postać:
ipfw add reset tcp from any to me
113
Ciekawym parametrem regułki jest też "limit". Pozwala on na
limitowanie ilości połączeń o takich parametrach jak zdefiniowane w regułce
(zachowanie to jest zachowaniem związanym z tzw. regułkami dynamicznymi, o czym
niżej). Przykładowo regułka pozwalająca na nawiązanie maksymalnie 10 połączeń na
port 80 z naszej sieci (np. 192.168.0.0/24) może wyglądać tak:
ipfw add allow tcp from
192.168.0.0/24 to any 80 limit src-addr 10
Parametr "src-addr" określa, że limit ma się tyczyć połączeń
nawiązanych z naszej sieci. Istnieje też możliwość zdefiniowania limitu
odwrotnego, czyli limitu połączeń na dany adres w sieci 192.168.0.0/24 ("dst-addr"),
przykładowo:
ipfw add allow tcp from any to
192.168.0.0/24 80 limit dst-addr 10
oraz zdefiniowanie limitu na poszczególny port ("src-port"
oraz "dst-port").
Wspomnieliśmy o zachowaniu związanym z regułkami dynamicznymi.
Spróbujmy się temu przyjrzeć bliżej. Specyfika protokołu TCP/IP jest taka, że po
nawiązaniu połączenia zmienia się jego status. Przykładowo załóżmy, że łączymy
się z serwerem WWW. Zakładamy, że nasze regułki ipfw pozwalają (teoretycznie jak
się zaraz okaże) tylko na komunikację z serwerami WWW:
ipfw add allow tcp from me to any 80
ipfw add deny ip from any to any
Nasz komputer bez problemu wysyła pakiet nawiązujący
połączenie na port 80 zdalnego serwera (pierwsza regułka pasuje) ale już
potwierdzenie ze strony owego serwera zostanie skasowane (nie pasuje do
pierwszej regułki, bo przychodzi z adresu "any" z portu 80 na adres mojego
komputera, czyli w odwrotną stronę niż zakłada regułka), czyli połączenie nie
zostanie nawiązane. Żeby uniknąć takiego zachowania wprowadza się właśnie
regułki dynamiczne, czyli regułki, które są generowane na podstawie innych. W
naszym przykładzie aby transmisja mogła mieć miejsce należy zmienić zapis
regułek na:
ipfw add allow tcp from me to any 80
setup keep-state
ipfw add deny ip from any to any
Będzie to oznaczało, że ipfw ma dla każdego połączenia
nawiązywanego ze zdalnym serwerem WWW na port 80 (setup - połączenie
nawiązywane) utworzyć regułke na podstawie oryginalnej regułki (keep-state),
która będzie wykonywała oryginalną akcję (u nas "allow"). Czyli zapisanie tylko
jednostronnej regułki (bo tylko dla pakietów wychodzących od nas) umożliwia
dwustronną transmisję. Całą "logiką" takiego połączenia zajmie się sam ipfw.
Dodatkowo w przypadku regułek dynamicznych możemy definiować połączenie za
pomocą jego aktualnego stanu. Przykładowo zapis:
ipfw add 100 check-state
ipfw add 200 allow tcp from me to any setup
ipfw add 300 allow tcp from any to any established
ipfw add 400 deny ip from any to any
powoduje, że na samym początku pakiet jest sprawdzany pod
względem stanu w jakim się znajduje (istnieją trzy możliwe stany - pakiet może
być "nowy", czyli nawiązujący połączenie, "powiązany" z danym połączeniem np. w
przypadku FTP oraz "nawiązany", czyli powstały w następstwie poprawnego
wynegocjowania połączenia przez pakiet "nowy") za pomocą komendy "check-state" a
następnie ipfw posiadając informacje o stanie pakietu może go dopasowywać dalej.
U nas regułka 200 pozwala na wysyłanie pakietów nawiązujących połączenie (pakiet
"nowy") a regułka 300 pozwala na ruch pakietów należących do już nawiązanych
połączeń bez ograniczeń. Warto zaznaczyć, że sprawdzanie stanu możliwe jest
tylko dla pakietów tcp oraz udp a nie dla icmp.
Posiadając wiedzę o budowie regułek tak statycznych jak i
dynamicznych spróbujmy skonstruować prosty firewall do ochrony stacji roboczej
pracującej w sieci o adresie 192.168.0.0/24. Stacja taka nie udostępnia żadnych
usług sieciowych na zewnątrz poza SAMBą (pracuje w sieci Microsoft Network i
jest jej to potrzebne do komunikacji z innymi komputerami w sieci). Przykładowa
konfiguracja może wyglądać tak:
ipfw add 100 allow tcp from
192.168.0.0/24 137,138,139 to me setup keep-state
ipfw add 200 allow udp from 192.168.0.0/24 137,138,139 to me
setup keep-state
ipfw add 300 allow tcp from me to any setup keep-state
ipfw add 400 allow ucp from me to any setup keep-state
ipfw add 500 allow icmp from any to any
ipfw add 600 deny ip from any to any
Po kolei: regułki 100 i 200 oznaczają, że inne komputery mogą
łączyć się z naszym za pomocą protokołu tcp oraz udp z portów 137,138,139 (porty
używane przez Microsoft Network oraz Sambę) na dowolny port i w efekcie tych
połączeń powstaną regułki dynamiczne. Regułki 300 i 400 pozwalają naszemu
komputerowi łączyć się z dowolnym adresem na protokole tcp oraz udp bez
ograniczeń. Regułka 500 pozwala na dowolną transmisję protokołem icmp. Regułka
600 kasuje wszystkie pakiety, które nie pasowały do żadnej z powyższych regułek
(czyli powinny się do niej kwalifikować pakiety przychodzące do nas ale nie
powiązane z żadnym nawiązanym przez nas połączeniem).
Spróbujmy też stworzyć zestaw regułek dla komputera pełniącego
role prostej bramy internetowej. Komputer taki w przeciwieństwie do naszej
stacji roboczej nie powinien przepuszczać transmisji z/do sieci Microsoft
Network ale z kolei ma uruchomioną na porcie 22 usługę serwera SSH, która
powinna być dostępna zarówno z sieci lokalnej jak i z Internetu. Komputer ten ma
dwa interfejsy sieciowe: xl0 podłączony do modemu ADSL (adres 81.21.31.41) oraz
xl1 do sieci LAN (sieć 192.168.0.0/24). Przykładowa konfiguracja może to
wyglądać tak:
ipfw add 100 check-state
ipfw add 200 allow ip from any to any via xl1
ipfw add 300 reset tcp from any to 192.168.0.0/24,81.21.31.41
113 in recv xl0
ipfw add 400 deny tcp from any to any 137,138,139,445
ipfw add 500 deny udp from any to any 137,138,139
ipfw add 600 allow tcp from any to 192.168.0.0/24,81.21.31.41
via xl0 established
ipfw add 700 allow udp from any to 192.168.0.0/24,81.21.31.41
via xl0 established
ipfw add 800 allow tcp from 192.168.0.0/24 to any via xl0
setup
ipfw add 900 allow udp from 192.168.0.0/24 to any via xl0
setup
ipfw add 1000 allow icmp from any to any
ipfw add 1100 allow tcp from any to 81.21.31.41 22 via xl0
setup
ipfw add 65000 deny ip from any to any
W powyższych regułkach widzimy, że jako adres źródłowy lub
docelowy możemy wpisać pojedynczy adres, adres całej sieci lub kilka adresów
oddzielonych przecinkami.
|