<!doctype linuxdoc system>

<article>

<title>Filtrowanie pakietów w Linuksie 2.4</title>

        <author>Rusty Russell, lista pocztowa <tt>netfilter@lists.samba.org</tt></author>
        <date>Wersja oryginalna: $Revision: 1.21 $ $Date: 2001/08/15 11:03:17 $</date>
        <p>Oryginał tego dokumentu znajduje się pod adresem: <url url="http://netfilter.filewatcher.org/"></p>
        <author>Tłumaczenie: Łukasz Bromirski, <tt>l.bromirski@mr0vka.eu.org</tt></author>
        <date>Wersja tłumaczenia: 2.0, 2001/11/02 22:35:00</date>
        <p>Oryginał tego tłumaczenia znajduje się pod adresem: <url url="http://mr0vka.eu.org/tlumaczenia/linux24-pf.html"></p>

<abstract>
Dokument ten opisuje zastosowanie narzędzia iptables w
filtrowaniu niepożądanych pakietów, w Linuksie z jądrem 2.4.
</abstract>

<!-- Table of contents -->
<toc>

<!-- Begin the document -->

<sect>Wprowadzenie<label id="intro">

<p>
Witam Szanownego czytelnika.
</p>

<p>Zakładam, że wiesz co to adres IP, adres sieciowy, maska sieciowa,
ruting i DNS. Jeśli nie, polecam przeczytanie HOWTO Network Concepts.
</p>

<p>To HOWTO oscyluje na granicy delikatnego wprowadzenia (które sprawi,
że poczujesz się zadowolony z siebie, ale niezabezpieczony przed Światem
Rzeczywistym) i surowego, pełnego opisu (które oszczędzi tylko
największych twardzieli, a reszta będzie zmieszana, w stanie paranoi i
poszukiwać będzie ciężkiego uzbrojenia).
</p>

<p>Twoja sieć nie jest <bf>bezpieczna</bf>. Problem umożliwienia
szybkiej i wygodnej wymiany informacji a jednocześnie ograniczenia
jej tylko do właściwych zastosowań, jest porównywalny do innych
problemów takich jak zapewnienie wolność wypowiedzi i jednocześnie
zapobieganiu wznoszenia okrzyków w stylu 'Pali się!' w zatłoczonym
kinie. Ten problem nie zostanie rozwiązany w tym HOWTO.
</p>

<p>Zatem tylko ty możesz zadecydować jak wyglądać będzie kompromis.
Spróbuję poinstruować cię w użytkowaniu dostępnych narzędzi,
poinformuję o pewnych słabościach z których trzeba sobie zdawać
sprawę, a wszystko to w nadziei że użyjesz tych informacji dla
dobrych, a nie złych celów. Kolejny problem porównywalny z tym
powyżej.
</p>

<p>(C) 2000 Paul `Rusty' Russell.  Na licencji GNU GPL.

<sect>Gdzie jest oficjalna strona WWW? Czy jest lista e-mail?

<p>Są trzy oficjalne strony:
<itemize>
<item>Dzięki <url url="http://netfilter.filewatcher.org/" name="Filewatcher">.
<item>Dzięki <url url="http://netfilter.samba.org/" name="Zespołowi Samba i SGI">.
<item>Dzięki <url url="http://netfilter.gnumonks.org/" name="Harald'owi Welte">.
</itemize>

<p>Oficjalna lista pocztowa znajduje się na
<url url="http://lists.samba.org/" name="serwerze list Samba">.

<sect>To co to jest Filtr Pakietów?

<p>Filtr pakietów to takie oprogramowanie, które sprawdza <bf>nagłówki</bf>
(ang. <em>header</em>) pakietów w trakcie jak przechodzą przez maszynę
na której działa i decyduje o ich losie. Może zdecydować, że pakiet zostanie
<bf>odrzucony</bf> (ang. <em>DROP</em>, tzn. tak jakby pakiet nigdy nie
dotarł), <bf>zaakceptowany</bf> (ang. <em>ACCEPT</em>, tzn. pozwoli mu
przejść), lub coś bardziej skomplikowanego.
</p>

<p>W Linuksie, filtrowanie pakietów jest wbudowane w kernel (jako moduł
lub po prostu wbudowane) i jest parę jeszcze sprytniejszych rzeczy które możesz
zrobić, ale generalnie idea polega na sprawdzaniu nagłówków i decydowaniu
o losie pakietów.
</p>

<sect1>Dlaczego mógłbym chcieć filtrować pakiety?

<p>
Kontrola. Bezpieczeństwo. Czujność.
</p>

<p>
<descrip>
<tag/Kontrola:/ kiedy używasz Linuksa by połaczyć twoją wewnętrzną sieć z
inną siecią (powiedzmy z Internetem) masz okazję wpuścić trochę różnych
typów ruchu i odrzucić inne. Na przykład, nagłówek pakietu posiada adres
docelowy pakietu, więc możesz odrzucać pakiety które podróżują do określonych
części sieci zewnętrznej. Innym przykładem może być to: używam Netscape do
oglądania archiwów Dilbert'a. Jest tam masa reklam pochodzących z adresu
doubleclick.net, więc Netscape traci czas by je ładować. Pouczenie filtra
pakietów by nie wpuszczał pakietów podróżujących do i z tego adresu
rozwiązuje ten problem (jednakże jest parę innych sposobów by zrobić to
lepiej, sprawdź Junkbuster).

<tag/Bezpieczeństwo:/ kiedy Twój Linuks jest jedynym komputerem pomiędzy
chaosem Internetu i twoją ładną, uporządkowaną siecią, miło jest wiedzieć
że możesz obłożyć restrykcjami to co nadchodzi do twych drzwi. Na przykład,
możesz pozwolić by wszystko wychodziło z twojej sieci, ale możesz być
zaniepokojony znanym atakiem 'Ping of Death' nadchodzącym od różnych
złośliwych użytkowników sieci. Innym przykładem może być twoje życzenie,
by nie zezwalać na telnet'owanie się na Twój komputer, mimo że wszystkie
konta mają hasła; prawdopodobnie chcesz być (jak większość ludzi) raczej
obserwatorem w Internecie a nie serwerem - po prostu nie dawać się nikomu do Ciebie
dołączać, poprzez filtrowanie nadchodzących pakietów służących do ustanawiania
połączeń.

<tag/Czujność:/ czasami źle skonfigurowana maszyna w sieci lokalnej
zadecyduje o skierowaniu paru pakietów do sieci zewnętrznej. Miło jest
móc poinstruować filtr pakietów by dał Ci znać o takich anormalnych
zachowaniach; może będziesz chciał coś z tym zrobić, albo jesteś po
prostu ciekawy z natury.
</descrip>

<sect1>Jak filtrować pakiety pod Linuksem?<label id="filter-linux">

<p>Kernele Linuksa miały wbudowane filtrowanie pakietów od serii 1.1.
Pierwsza generacja, bazująca na ipfw z BSD, została przeniesiona przez
Alana Cox'a pod koniec 1994. Została ona rozbudowana przez Jos'a Vos'a
i innych dla Linuksa wersji 2.0; narzędzie działające w przestrzeni
użytkownika '<tt>ipfwadm</tt>' kontrolowało reguły filtrujące. W połowie
1998, dla Linuksa 2.2, zmieniłem dosyć mocno kernel, z pomocą Michael'a
Neuling'a, i wprowadziłem narzędzie również działające w przestrzeni
użytkownika nazwane '<tt>ipchains</tt>'. Ostatecznie, w połowie 1999 dla
Linuksa 2.4 stworzono kolejne narzędzie '<tt>iptables</tt>'. Jest to
właśnie to <tt>iptables</tt> na którym skoncentrowane jest to HOWTO.
</p>

<p>Potrzebujesz kernel z infrastrukturą netfilter: netfilter to ogólny
szkielet w kernelu Linuksa do którego mogą dołączać się inne moduły
(takie jak moduł iptables). Oznacza to że potrzebujesz kernel w wersji
2.3.15 lub późniejszej, i w czasie konfiguracji kernela musisz
zaznaczyć '<tt>Y</tt>' przy opcji '<tt>CONFIG_NETFILTER</tt>'.
</p>

<p>Narzędzie <tt>iptables</tt> wstawia i kasuje reguły z tabeli
filtrowania pakietów kernela. Oznacza to, że cokolwiek do niej
wstawisz, zostanie stracone po restarcie; zajrzyj do
<ref id="permanent" name="sekcji w której opisujemy zapisywanie reguł">
po informacje jak upewnić się że po kolejnym starcie Linuks
odtworzy je.
</p>

<p><tt>iptables</tt> zastępuje <tt>ipfwadm</tt> i <tt>ipchains</tt>: zajrzyj
do <ref id="oldstyle" name="sekcji opisującej używanie ipfwadm i ipchains">
po informacje jak bezboleśnie uniknąć przesiadania się na <tt>iptables</tt>
jeśli używasz jednego z tych narzędzi.
</p>

<sect2>Zapisywanie reguł na stałe<label id="permanent">

<p>Twoje aktualne ustawienia ściany ogniowej zapisane są w kernelu i w
związku z tym znikną po restarcie. Możesz wypróbować skrypty
<tt>iptables-save</tt> i <tt>iptables-restore</tt> by odpowiednio
zapisać je do i odtworzyć z pliku.
</p>

<p>Innym sposobem może być umieszczenie komend wymaganych by ustawić
twoje reguły w skrypcie wykonywanym w czasie startu. Upewnij się, że zrobi
on coś inteligentnego w wypadku gdyby coś poszło nie tak
(zwykle wywołanie '<tt>exec /sbin/sulogin</tt>').

<sect>Kim u diabła jesteś i dlaczego bawisz się moim kernelem?

<p>Jestem Rusty Russell; człowiek odpowiedzialny za ścianę ogniową IP
Linuksa i jeszcze jeden koder który znalazł się we właściwym miejscu
we właściwym czasie. Napisałem <tt>ipchains</tt> (zajrzyj do sekcji
<ref id="filter-linux" name="Jak filtrować pakiety pod Linuksem?">)
powyżej by sprawdzić kto tak naprawdę to wszystko stworzył) i
nauczyłem się wystarczająco dużo by tym razem filtrowanie
pakietów wyszło dobrze. Tak sądzę.
</p>

<p>Doskonała firma WatchGuard <url url="http://www.watchguard.com" name="WatchGuard">
sprzedająca ściany ogniowe Firebox, zaoferowała że będzie płacić mi za nic,
więc mogłem spędzać swój czas pisząc ten dokument i zajmować się poprzednimi
rzeczami. Przewidywałem że zajmie to 6 miesięcy, zajęło 12, ale na końcu
czuję że zostało to zrobione Właściwie. Wiele razy przepisywane od początku,
padnięty twardy dysk, ukradziony laptop, parę uszkodzonych systemów plików
i jeden zniszczony ekran, ale jest.

<p>Póki jeszcze tu jestem, chciałbym wyklarować mylne wrażenia
niektórych ludzi: nie jestem guru kernela. Wiem to wszystko, ponieważ moja
praca spowodowała że kontaktowałem się z ludźmi którzy są guru:
David'em S. Miller'em, Aleksiej'em Kuziecow'em, Andi Kleen'em, Alan'em
Cox'em. Są zajęci uprawianiem głębokiej magii, a ja mogłem pobawić się na
płytkich wodach, tam gdzie jest bezpiecznie.
</p>

<sect>Bardzo krótki przewodnik Rusty'ego do filtrowania pakietów

<p>Większość ludzi ma pojedyńcze połączenie PPP do Internetu, i nie
chce by ktokolwiek mógł łączyć się do nich, lub do ściany ogniowej:

<tscreen><verb>
## Załaduj moduły śledzenia połączeń (niepotrzebne jeśli wbudowane w kernel)
# insmod ip_conntrack
# insmod ip_conntrack_ftp

## Stwórz łańcuch blokujący nowe połączenia, z wyjątkiem tych od środka
# iptables -N block
# iptables -A block -m state --state ESTABLISHED,RELATED -j ACCEPT
# iptables -A block -m state --state NEW -i ! ppp0 -j ACCEPT
# iptables -A block -j DROP

## Do łańcuchów INPUT i FORWARD dodaj skok do tego nowego łańcucha
# iptables -A INPUT -j block
# iptables -A FORWARD -j block
</verb></tscreen>

<sect>Jak pakiety podróżują przez filtry

<p>Kernel rozpoczyna pracę z trzema listami reguł w tabeli filtrującej;
nazywane sa one <bf>łańcuchami ściany ogniowej</bf>, lub po prostu
<bf>łańcuchami</bf>. Te trzy nazwane zostały <bf>INPUT</bf> (<bf>wejściowy</bf>),
<bf>OUTPUT</bf> (<bf>wyjściowy</bf>) i <bf>FORWARD</bf> (<bf>przekazujący</bf>).
</p>

<p>Dla fanów ASCII-art, łańcuchy ułożone są w następujący sposób:
<bf>(UWAGA: Wygląda to zupełnie inaczej niż w kernelach 2.0 i 2.2!</bf>

<verb>
                          _____
Incoming                 /     \         Outgoing
       -->[Decyzja ]--->|FORWARD|------->
          [Rutingu ]     \_____/        ^
               |                        |
               v                       ____
              ___                     /    \
             /   \ 	             |OUTPUT|
            |INPUT|	              \____/
             \___/                       ^
               |                         |
                ----> Proces lokalny  ----
</verb>

Trzy koła reprezentują trzy łańcuchy o których wspomniałem
wyżej. Kiedy pakiet dociera do koła na diagramie, sprawdzany jest łańcuch reguł by
zdecydować o losie pakietu. Jeśli łańcuch mówi że należy odrzucić (DROP)
pakiet, jest on odrzucany tutaj, ale jeśli łańcuch mówi by zaakceptować
pakiet (ACCEPT), kontynuuje on swoją podróż po diagramie.
</p>

<p>Łańcuch to lista <bf>reguł</bf>. Każda reguła mówi 'jeśli nagłówek
pakietu wygląda tak, to zrobimy z tym pakietem następującą rzecz'.
Jeśli reguła nie pasuje do pakietu, sprawdzana jest następna.
Na koniec, jeśli nie ma więcej reguł, kernel sprawdza politykę
(ang. <em>policy</em>) danego łańcucha. W systemie w którym dba się o
bezpieczeństwo, polityka mówi zwykle kernelowi by odrzucić (DROP) pakiet.
</p>

<p>
<enum>
<item>Kiedy pakiet dociera do maszyny (powiedzmy, przez kartę Ethernetową),
kernel sprawdza najpierw adres przeznaczenia pakietu: nazywa się to
routingiem.

<item>Jeśli pakiet przeznaczony jest do tego kompuera, pakiet zostaje
przepuszczony do łańcucha INPUT (wejściowego). Jeśli przejdzie go,
otrzymuje go proces do którego był adresowany.

<item>W innym przypadku, jeśli kernel nie ma włączonego <bf>przekazywania</bf>
(ang. <em>forwarding</em>), lub nie wie jak przekazać pakiet, jest on
odrzucany. Jeśli przekazywanie jest włączone i pakiet jest przeznaczony
do innego interfejsu sieciowego (jeśli w ogóle masz jeszcze jeden), pakiet
przechodzi w prawo na naszym diagramie do łańcucha FORWARD (przekazującego).
Jeśli zostaje zaakceptowany (ACCEPT), zostanie wysłany dalej.

<item>Na koniec, program pracujący na tym komputerze może również wysyłać własne
pakiety. Przejdą one od razu do łańcucha OUTPUT (wyjściowego): jeśli
stwierdzi on że zaakceptuje pakiet (ACCEPT), pakiet przechodzi do właściwego
interfejsu sieciowego.
</enum>

<sect>Używanie iptables

<p><tt>iptables</tt> ma całkiem szczegółowy podręcznik (<tt>man iptables</tt>),
do którego warto zajrzeć jeśli chodzi ci o coś konkretnego. Ci z was którzy
znają <tt>ipchains</tt> mogą po prostu zajrzeć do <ref id="Appendix-A"
name="różnic pomiędzy iptables i ipchains">; oba narzędzia są bardzo
podobne.
</p>

<p>Istnieje wiele rzeczy które możesz zrobić przy użyciu <tt>iptables</tt>.
Zaczynasz z trzema wbudowanymi łańcuchami <tt>INPUT</tt>, <tt>OUTPUT</tt> i
<tt>FORWARD</tt>, których nie możesz skasować. Spójrzmy na listę możliwych
operacji na całych łańcuchach:

<enum>
<item> Stworzenie nowego łańcucha (-N).
<item> Skasowanie pustego łańcucha (-X).
<item> Zmiana polityki dla wbudowanego łańcucha (-P).
<item> Wylistowanie reguł w łańcuchu (-L).
<item> Wyczyszczenie łańcucha z reguł (-F).
<item> Wyzerowanie liczników pakietów i bajtów we wszystkich regułach w łańcuchu (-Z).
</enum>

Jest również parę sposobów na manipulowanie regułami w obrębie łańcucha:

<enum>
<item> Dodanie nowej reguły do łańcucha (-A).
<item> Wstawienie nowej reguły na pewnej pozycji w łańcuchu (-I).
<item> Zamiana reguły na pewnej pozycji w łańcuchu (-R).
<item> Skasowanie reguły na pewnej pozycji w łańcuchu (-D).
<item> Skasowanie pierwszej reguły pasującej do podanej w łańcuchu (-D).
</enum>
</p>

<sect1>Co zobaczysz gdy wystartujesz komputer

<p>iptables może być modułem, ('<tt>iptable_filter.o</tt>'), który powinien
być automatycznie ładowany gdy po raz pierwszy uruchomisz <tt>iptables</tt>.
Może być również skompilowany w kernelu.
</p>

<p>Zanim nie zostaną wykonane jakieś komendy (zwróć uwagę, że niektóre
dystrybucje wykonują już operacje z <tt>iptables</tt> w skryptach
startowych) nie ma żadnych reguł we wbudowanych łańcuchach
('INPUT', 'FORWARD' i 'OUTPUT') i wszystkie mają domyślną
politykę ACCEPT. Możesz zmienić domyślną politykę łańcucha
FORWARD przez podanie opcji '<tt>forward=0</tt>' do modułu
<tt>iptable_filter</tt>.

<sect1>Operacje na pojedyńczej regule

<p>Manipulowanie regułami to bułka z masłem filtrowania pakietów.
Najczęściej będziesz zapewne dodawał (<tt>-A</tt>) i kasował (<tt>-D</tt>).
Inne komendy (<tt>-I</tt> dla wstawiania i <tt>-R</tt> do
zamieniania) są prostymi rozwinięciami tych koncepcji.
</p>

<p>Każda reguła jest zestawem warunków które pakiet musi spełnić i
zawiera informację co zrobić jeśli tak się stało (czyli <bf>cel</bf>,
ang. <em>target</em>). Na przykład, możesz chcieć odrzucać wszystkie
pakiety ICMP nadchodzące z adresu IP 127.0.0.1. W tym przypadku naszymi
warunkami są zatem: protokołem musi być ICMP, a adresem źródłowym
127.0.0.1. Naszym celem będzie 'DROP'.

<p>127.0.0.1 to adres <bf>pętli zwrotnej</bf> (ang. <em>loopback</em>),
który posiadasz nawet wtedy gdy nie masz żadnego połączenia sieciowego.
Możesz użyć programu 'ping' by wygenerować pakiety takie jak powyżej.
Polecenie wysyła pakiety ICMP typ 8 - żądanie echa
(ang. <em>echo request</em>) na które wszystkie współpracujące hosty
odpowiedzą pakietem ICMP typu 0 - echo. To sprawia, że polecenie
to jest wygodne dla testów.

<tscreen><verb>
# ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.2 ms

--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.2/0.2/0.2 ms
# iptables -A INPUT -s 127.0.0.1 -p icmp -j DROP
# ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes

--- 127.0.0.1 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
#
</verb></tscreen>

<p>Widać powyżej że pierwszy ping dociera (opcje '<tt>-c 1</tt>'
powoduje wysłanie tylko jednego pakietu).
</p>

<p>Dodajemy teraz (<tt>-A</tt>) do łańcucha 'INPUT' regułę, która mówi
że pakiety z 127.0.0.1 ('<tt>-s 127.0.0.1</tt>') protokołu ICMP
('<tt>-p icmp</tt>') powinny zostać przeznaczone do wyrzucenia
('<tt>-j DROP</tt>').
</p>

<p>Testujemy następnie działanie naszej reguły, wykonując drugi ping.
Nastąpi pauza po której program się podda, po krótkim oczekiwaniu
na odpowiedź która nigdy nie nadejdzie.
</p>

<p>Możemy skasować naszą regułę na dwa sposoby. Po pierwsze,
ponieważ wiemy że jest to jedyna reguła w łańcuchu wejściowym, możemy użyć
numerowania reguł, tak jak poniżej:
<tscreen><verb>
	# iptables -D INPUT 1
	#
</verb></tscreen>
<p>Co spowoduje skasowanie reguły numer 1 w łańcuchu INPUT.</p>

<p>Drugi sposób to dokładne przepisanie poleceń po opcji <tt>-A</tt>, ale
zamiast opcji <tt>-A</tt> podajemy opcję <tt>-D</tt>. Przydaje się to w
przypadku gdy masz skomplikowany zestaw reguł i nie chce ci się liczyć
ich wszystkich by ustalić w końcu że chcesz pozbyć się reguły numer 37.
W tym wypadku użyjemy:
<tscreen><verb>
	# iptables -D INPUT -s 127.0.0.1 -p icmp -j DROP
	#
</verb></tscreen>
Składnia polecenia <tt>-D</tt> musi dokładnie odpowiadać opcjom
które podałeś przy poleceniu <tt>-A</tt> (lub <tt>-I </tt> czy <tt>-R</tt>).
Jeśli istnieje wiele identycznych reguł w tym samym łańcuchu,
tylko pierwsza pasująca zostania skasowana.
</p>

<sect1>Specyfikacja filtrowania

<p>Widzieliśmy już jak używać opcji '<tt>-p</tt>' by wskazać protokół
i '<tt>-s</tt>' by wskazać adres źródłowy, ale są jeszcze inne opcje
których możemy użyć by scharakteryzować pakiet. Poniżej znajdziesz
wyczerpujące kompendium.

<sect2>Wskazanie adresów IP: źródłowego i docelowego

<p>
Adres IP źródłowy ('<tt>-s</tt>', '<tt>--source</tt>' lub '<tt>--src</tt>')
i docelowy ('<tt>-d</tt>', '<tt>--destination</tt>' lub '<tt>--dst</tt>')
mogą być podane na cztery sposoby. Najczęściej robi się to przez podanie
pełnej nazwy, takiej jak 'localhost' czy `www.linuxhq.com'. Drugim sposobem
jest podanie adresu IP, tak jak np. '127.0.0.1'.

<p>Trzeci i czwarty sposób pozwalają na wskazanie grupy adresów IP,
tak jak na przykład '199.95.207.0/24' lub `199.95.207.0/255.255.255.0'.
Oba wskazują na zakres adresów IP od 199.95.207.0 do 199.95.207.255
włącznie; cyfry po '/' mówią która część adresu IP ma znaczenie.
'/32' czy inaczej `/255.255.255.255' jest domyślne (i mówi że wszystkie
liczby w adresie IP są ważne). By wskazać dowolny adres, można użyć
'/0' tak jak poniżej:
<tscreen><verb>
	[ UWAGA: `-s 0/0' jest tu całkowicie zbędne. ]
	# iptables -A INPUT -s 0/0 -j DROP
	#
</verb></tscreen>
Ale takich konstrukcji używa się rzadko, ponieważ efekt jest dokładnie
taki sam jak w przypadku nie podania opcji '<tt>-s</tt>' w ogóle.

<sect2>Inwersja

<p>Wiele flag, włączając '<tt>-s</tt>' (lub '<tt>--source</tt>') i
'<tt>-d</tt>' ('<tt>--destination</tt>') można poprzedzić znakiem '<tt>!</tt>'
(wymawianym 'nie') by wskazać adresy <bf>nie</bf> pasujące do tych podanych.
Na przykład '<tt>-s ! localhost</tt>' będzie
pasować do wszystkich pakietów nie pochodzących z localhost.</p>

<sect2>Protokół

<p>Protokół podaje się po parametrze '<tt>-p</tt>' (lub '<tt>--protocol</tt>').
Protokół może być numerem (jeśli znasz wartości numeryczne protokołów IP) lub
nazwą dla 'TCP', 'UDP' i 'ICMP'. Wielkość liter nie ma znaczenia,
więc 'tcp' działa tak samo jak 'TCP'.
</p>

<p>Nazwa protokołu może być poprzedzona przez znak '<tt>!</tt>' by
wskazać na wszystkie oprócz wymienionego, tak jak na przykład
'<tt>-p ! TCP</tt>' (warunek dotyczy wszystkich protokołów prócz TCP).

<sect2>Interfejs

<p>Opcje '<tt>-i</tt>' (lub '<tt>--in-interface</tt>' czyli interfejs
wejściowy) i '<tt>-o</tt>' (lub '<tt>--out-interface</tt>' czyli interfejs
wyjściowy) używane są dla wskazania interfejsu. Interfejs to
fizyczne urządzenie do którego pakiety przychodzą ('<tt>-i</tt>') i
z którego są wysyłane ('<tt>-o</tt>'). Możesz użyć programu
<tt>ifconfig</tt> by wylistować interfejsy które są 'podniesione'
(tzn. aktualnie pracujące).
</p>

<p>Pakiety podróżujące w łańcuchu <tt>INPUT</tt> nie mają interfejsu
wyjściowego, więc podanie opcji '<tt>-o</tt>' w regule w tym łańcuchu
spowoduje że nie będzie ona pasować do żadnego pakietu. Podobnie,
pakiety podróżujące przez łańcuch <tt>OUTPUT</tt> nie mają interfejsu
wejściowego, więc podanie opcji '<tt>-i</tt>' w regule tego
łańcucha spowoduje że nie będzie ona nigdy pasowała.
</p>

<p>Tylko pakiety podróżujące przez łańcuch <tt>FORWARD</tt> mają
zarówno interfejs wejściowy i wyjściowy.

<p>Jest całkowicie poprawne wskazanie interfejsu który aktualnie
nie istnieje; reguła nie będzie pasowała do niczego, dopóki
interfejs nie zostanie podniesiony. Jest to bardzo przydatne
dla połączeń wdzwanianych PPP (zwykle interfejs ma nazwę
<tt>ppp0</tt>) i podobnych.

<p>Można również wskazać interfejs kończąc jego nazwę przez '<tt>+</tt>'
co spowoduje że reguła będzie pasowała do wszystkich interfejsów których
nazwa zaczyna się od podanego ciągu znaków (bez znaczenia czy interfejs
aktualnie istnieje czy nie). Na przykład, by wskazać regułę która pasuje
do wszystkich interfejsów PPP użyć należy polecenia '<tt>-i ppp+</tt>'.

<p>Interfejs może być poprzedzony przez '<tt>!</tt>' ze spacjami wokół,
co spowoduje że pasować będą pakiety które nie są powiązane ze
wskazanym interfejsem (tzn. pakiet nim nie dotarł do systemu, lub
nie zamierza nim go opuścić), np. <tt>-i ! ppp+</tt>.

<sect2>Fragmenty
<p>Czasami pakiet jest zbyt duży by zmieścić się cały w jednostce
transmisji. Kiedy się tak dzieje, jest on dzielony na <bf>fragmenty</bf> i
wysyłany jako osobne pakiety. Komputer docelowy składa fragmenty by
zrekonstrukować cały pakiet.
</p>

<p>Problem z fragmentami polega na tym, że pierwszy fragment posiada
komplet pól nagłówka (IP+TCP, UDP i ICMP) który można sprawdzać, ale
następne fragmenty mają tylko podzbiór nagłówków (IP bez dodatkowych pól
specyficznych dla protokołów które przenosi pakiet). W związku z tym
niemożliwe jest analizowanie pewnych informacji z nagłówków
fragmentów (tak jak robi się to dla typowych pakietów TCP, UDP i ICMP).
</p>

<p>Jeśli prowadzisz śledzenie połączeń lub NAT, to wszystkie
fragmenty zostaną najpierw złożone a dopiero później przekazane do
kodu filtrującego pakiety, więc nie powinieneś się martwić fragmentami.
</p>

<p>W każdym innym przypadku ważne jest by zrozumieć jak fragmenty
traktowane są przez reguły filtrujące. Każda reguła która ma
sprawdzić informacje których nie posiadamy dla danego pakietu, <bf>nie
będzie</bf> pasowała. Oznacza to, że tylko pierwszy fragment
traktowany jest tak, jak można by się tego spodziewać. Drugi pakiet
i kolejne już nie będą. W związku z tym reguła '<tt>-p TCP --sport www</tt>'
(podająca port źródłowy '<tt>www</tt>') nigdy nie będzie pasowała
do fragmentu pakietu (innego niż pierwszy). Nie będzie również
pasować reguła odwrotna '<tt>-p TCP --sport ! www</tt>'.
</p>

<p>Możesz jednak dodać reguły specjalnie dla drugiego i następnych
fragmentów, poprzez użycie opcji '<tt>-f</tt>' (lub '<tt>--fragment</tt>').
Poprawne jest również dodanie reguły która nie pasuje do drugiego i
następnych fragmentów, przez poprzedzenie opcji '<tt>-f</tt>'
opcją '<tt>!</tt>'.

<p>Zwykle uważa się za bezpieczne umożliwienie drugiemu i następnym
fragmentom przejść, ponieważ filtrowanie zajmie się pierwszym
fragmentem i w związku z tym zapobiegnie złożeniu pakietu na maszynie
docelowej; z drugiej strony znane były pluskwy które powodowały
zawieszanie się maszyn tylko poprzez wysyłanie do nich fragmentów.
To twoja decyzja.
</p>

<p>Mała uwaga do speców od sieci: pakiety zniekształcone (TCP, UDP i ICMP
które są zbyt krótkie by kod ściany ogniowej mógł odczytać porty, czy w
przypadku ICMP kod i typ) są również wyrzucane gdy prowadzone są takie
analizy. Dokładnie tak samo jest z fragmentami TCP które rozpoczynają
się od pozycji 8.

<p>Jako przykład, poniższa reguła wyrzuci wszystkie fragmenty
przeznaczone dla 192.168.1.1:

<tscreen><verb>
# iptables -A OUTPUT -f -d 192.168.1.1 -j DROP
#
</verb></tscreen>

<sect2>Rozszerzenia do iptables: Nowe cele i nowe testy

<p><tt>iptables</tt> są <bf>rozszerzalne</bf>, co oznacza że
funkcjonalność zarówno kernela jak i narzędzia iptables może być
rozszerzana by dodać nowe opcje.
</p>

<p>Niektóre rozszerzenia są standardowe, inne są trochę bardziej
egzotyczne. Oczywiście, mogą być one dodawane przez innych ludzi i
dystrybuowane niezależnie dla użytkowników niszowych.
</p>

<p>Fizycznie rozszerzenia znajdują się zwykle w podkatalogu modułów
kernela, tak jak na przykład
'<tt>/lib/modules/2.4.0-test10/kernel/net/ipv4/netfilter</tt>'.
Ladowane są na żądanie gdy kernel został skompilowany z opcją
CONFIG_KMOD, więc nie powinno być potrzeby ładowania ich ręcznie.

<p>Rozszerzenia do narzędzia iptables są współdzielonymi
bibliotekami, które znajdują się zwykle w '<tt>/usr/local/lib/iptables/</tt>',
choć dystrybucje mogą umieścić je w katalogach takich jak
'<tt>/lib/iptables/</tt>' czy '<tt>/usr/lib/iptables</tt>'.
</p>

<p>Rozszerzenia mogą należeć do jednego z dwóch typów: nowych celów,
lub nowych testów (porozmawiamy o nowych celach za moment). Niektóre
protokoły oferują automatycznie nowe testy: aktualnie są nimi
TCP, UDP i ICMP tak jak pokażemy to poniżej.
</p>

<p>Możesz dla nich podać nowe testy w linii poleceń po opcji
'<tt>-p</tt>', który ładuje rozszerzenie. Dla samodzielnych
nowych testów, używa się opcji '<tt>-m</tt>' by załadować
rozszerzenie, po której dostępne są nowe opcje.

<p>By uzyskać pomoc do rozszerzenia, użyj opcji ładującej go
('<tt>-p</tt>', '<tt>-j</tt>' lub '<tt>-m</tt>') po której podaj
'<tt>-h</tt>' lub '<tt>--help</tt>', np.:
<tscreen><verb>
# iptables -p tcp --help
#
</verb></tscreen>

<sect3>Rozszerzenia TCP

<p>Rozszerzenia TCP ładowane są automatycznie gdy podano opcję
'<tt>-p tcp</tt>'. Dodają one następujące opcje (z których
żadna nie pasuje do fragmentów).

<p>
<descrip>
<tag>--tcp-flags</tag> Po której następuje opcjonalny znak '<tt>!</tt>',
a następnie dwa ciągi flag które pozwalają wskazać zestaw
flag do zbadania. Drugi ciąg mówi, które mają być ustawione.
Na przykład:

<tscreen><verb>
# iptables -A INPUT --protocol tcp --tcp-flags ALL SYN,ACK -j DROP
</verb></tscreen>

mówi że sprawdzone powinny zostać wszystkie flagi ('<tt>ALL</tt>'
to synonim dla '<tt>SYN,ACK,FIN,RST,URG,PSH</tt>'), ale tylko
flagi <tt>SYN</tt> i <tt>ACK</tt> powinny być ustawione. Istnieje
również argument '<tt>NONE</tt>' który oznacza że żadna flaga
nie może być ustawiona.

<tag>--syn</tag> opcjonalnie poprzedzona przez '<tt>!</tt>', jest
skrótem dla '<tt>--tcp-flags SYN,RST,ACK SYN</tt>'.

<tag>--source-port</tag> po której następuje opcjonalny '<tt>!</tt>',
a następnie pojedyńczy port lub grupa portów TCP. Porty mogą być
wskazywane przez nazwy takie jak w <tt>/etc/services</tt> lub przez
numery. Grupy portów wskazuje się albo przez dwie nazwy portów
podzielone przez '<tt>:</tt>', lub (by wskazać większe lub równe
wskazanemu) przez port z dodanym '<tt>:</tt>', lub (by wskazać
mniejsze lub równe wskazanemu), port poprzedzany przez '<tt>:</tt>'.

<tag>--sport</tag> to synonim '<tt>--source-port</tt>'.

<tag>--destination-port</tag> i <tag>--dport</tag> mają takie
same opcje jak powyżej, ale określają port przeznaczenia.

<tag>--tcp-option</tag> po którym następuje opcjonalny znak
<tt>!</tt> i numer, które wskazują na opcję TCP równą wskazanemu
numerowi. Pakiet który nie posiada kompletnego nagłówka TCP
jest automatycznie odrzucany jeśli wykonana zostanie próba
sprawdzenia jego opcji TCP.
</descrip>

<sect4>Parę słów wyjaśnienia o flagach TCP

<p>Czasami użyteczne jest, by zezwolić na połączenia TCP w jednym
kierunku ale nie w drugim. Na przykład, możesz chcieć zezwolić na
połączenia do zewnętrznego serwera WWW, ale nie połączenia od tego
serwera.
</p>

<p>Naiwnym rozwiązaniem byłoby blokowanie pakietów TCP nadchodzących z
tego serwera. Niestety, połączenia TCP wymagają by pakiety mogły
poruszać się w jedną i w drugą stronę.
</p>

<p>Rozwiązaniem jest blokowanie tylko pakietów używanych do nawiązania
połączenia. Nazywa się je pakietami <bf>SYN</bf> (dobrze,
technicznie rzecz biorąc są to pakiety z ustawioną flagą SYN i
zgaszonymi flagami RST i ACK, ale nazywamy je pakietami SYN by
było krócej). Poprzez zabronienie ruchu tylko tym pakietom,
możemy zapobiec takim połączeniom u samego ich źródła.
</p>

<p>
Używa się do tego opcji '<tt>--syn</tt>': która jest dozwolona
tylko dla reguł które wskazują na protokół TCP. Na przykład,
by wskazać połączenia TCP z 192.168.1.1:

<tscreen><verb>
-p TCP -s 192.168.1.1 --syn
</verb></tscreen>

<p>Działnie flagi można odwrócić poprzedzając ją '<tt>!</tt>',
co oznacza, że chodzi nam o pakiety różne od tych które
inicjują połączenie.

<sect3>Rozszerzenia UDP

<p>Są one ładowane automatycznie po podaniu '<tt>-p udp</tt>'.
Udostępniają opcję '<tt>--source-port</tt>', '<tt>--sport</tt>',
'<tt>--destination-port</tt>' i '<tt>--dport</tt>', dokładnie
takie same jak dla TCP powyżej.

<sect3>Rozszerzenia ICMP

<p>
Ładowane automatycznie po podaniu '<tt>-p icmp</tt>'.
Udostępniają one tylko jedną nową opcję:

<p>
<descrip>
<tag>--icmp-type</tag> po której następuje opcjonalny znak '<tt>!</tt>',
a następnie albo nazwa typu pakietu ICMP (np. '<tt>host-unreachable</tt>', czyli
<em>komputer nieosiągalny</em>), lub numer typu (np. '<tt>3</tt>'), lub numer
typu i kod oddzielone przez '/' (np. '<tt>3/3</tt>'). Lista dostępnych
nazw typów ICMP dostępna jest po podaniu '<tt>-p icmp --help</tt>'.
</descrip>

<sect3>Inne rozszerzenia testowe

<p>Inne rozszerzenia w paczce netfiltera są rozszerzeniami
demonstracyjnymi, które (jeśli je zainstalowano) mogą być
wywołane poprzez opcję '<tt>-m</tt>'.

<descrip>
<tag>mac</tag> Moduł ten musi być wskazany przez '<tt>-m mac</tt>' lub
'<tt>--match mac</tt>'. Używa się go do sprawdzania źródła
Ethernetowego (tzw. adresu MAC) adresu nadchodzącego pakietu i w
związku z tym działa tylko w łańcuchach PREROUTING i INPUT.
Udostępnia on tylko jedną opcję:

  <descrip>
  <tag>--mac-source</tag> po którym następuje opcjonalny
  '<tt>!</tt>' a następnie adres ethernetowy w formacie
  heksdecymalnym oddzielanym dwukropkami, np.
  `<tt>--mac-source 00:60:08:91:CC:B7</tt>'.
  </descrip>

<tag>limit</tag>Moduł ten musi być wskazany przez '<tt>-m limit</tt>'
lub '<tt>--match limit</tt>'. Używa się go do ograniczania częstotliwości
pasowania reguły, tak jak na przykład do ograniczanie wiadomości generowanych
do logów. Spowoduje że pakiety będą pasować z taką częstotliwością jak
podana w tej opcji w czasie jeden sekundy (domyślnie 3 krotnie na godzinę,
z serią 5). Moduł umożliwia podanie dwóch argumentów opcjonalnych:

  <descrip>
  <tag>--limit</tag>po którym następuje numer; określa maksymalny
  średni numer testów pozytywnych na sekundę. Numer może również
  wskazywać wprost jednostki, przez użycie '<tt>/second</tt>',
  '<tt>/minute</tt>', '<tt>/hour</tt>' lub '<tt>/day</tt>', albo
  ich skrótów (np. '<tt>5/second</tt>' to to samo co '<tt>5/s</tt>').

  <tag>--limit-burst</tag> po którym następuje numer, określający
  maksymalną serię po której powyższy limit się włącza.
  </descrip>

Używa się tego testu zwykle w połączeniu z celem LOG by zrealizować
ograniczone logowanie. By zrozumieć jak to działa, popatrzmy jak działa
następująca reguła, która loguje pakiety z domyślnymi limitami:

<tscreen><verb>
# iptables -A FORWARD -m limit -j LOG
</verb></tscreen>

Gdy pierwszy raz dochodzimy do reguły, pakiet jest logowany; tak
naprawdę, ponieważ domyślną serią jest 5, pierwsze pięć pakietów
zostanie zalogowane. Następnie, minie dwadzieścia minut zanim
zalogowany zostanie następny pakiet pasujący do tej reguły,
niezależnie od tego ile pakietów do niej dotrze. Jednocześnie,
każde dwadzieścia minut które minie bez pakietu który pasowałby
do tej reguły, spowoduje odnowienie jednego numeru z serii;
jeśli żaden pakiet nie dotrze do reguły w ciągu 100 minut,
seria zostanie w pełni odnowiona; do 5 sztuk, tak jak zaczęliśmy.

<p>Nota: nie możesz aktualnie stworzyć reguły które ma czas
odnawiania się powyżej 59 godzin, więc jeśli ustawisz średnią
częstotliwość na jeden pakiet na dzień, numer serii musi być
mniejszy niż 3.

<p>Możesz również użyć tego modułu by zapobiec rozmaitym atakom
Odmowy Usługi (ang. <em>Denial of Service</em>), z większym
współczynnikiem częstotliwości by zwiększyć szybkość reakcji.

<p>Zabezpieczenie przed powodzią pakietów SYN (ang. <em>Syn-flood</em>):
<tscreen><verb>
# iptables -A FORWARD -p tcp --syn -m limit --limit 1/s -j ACCEPT
</verb></tscreen>

Skaner portół Furtive:
<tscreen><verb>
# iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT
</verb></tscreen>

Ping of death:
<tscreen><verb>
# iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT
</verb></tscreen>

Moduł ten działa jak "drzwi histerii", tak jak pokazano to na diagramie
poniżej.

<tscreen><verb>
       rate (pkt/s)
             ^        .---.
             |       / DoS \
             |      /       \
Edge of DoS -|.....:.........\.......................
 = (limit *  |    /:          \
limit-burst) |   / :           \         .-.
             |  /  :            \       /   \
             | /   :             \     /     \
End of DoS  -|/....:..............:.../.......\..../.
 = limit     |     :              :`-'         `--'
-------------+-----+--------------+------------------> time (s)
   LOGIC =>  Match | Didn't Match |    Match
</verb></tscreen>

Powiedzmy że pasuje jeden pakiet na sekundę z serią pięciu
pakietów, ale pakiety zaczynają dochodzić w ilości czterech
na sekundę przez trzy sekundy, a następnie znowu po trzech
sekundach.

<tscreen><verb>


        <--Flood 1-->           <---Flood 2--->

Total  ^                   Line  __--      YNNN
Packets|               Rate  __--      YNNN
       |            mum  __--      YNNN
    10 |        Maxi __--         Y
       |         __--            Y
       |     __--               Y
       | __--    YNNN
       |-    YNNN
     5 |    Y
       |   Y                                Key:  Y -> Matched Rule
       |  Y                                       N -> Didn't Match Rule
       | Y
       |Y
     0 +-------------------------------------------------->  Time (seconds)
        0   1   2   3   4   5   6   7   8   9  10  11  12
</verb></tscreen>

Widać, że pierwsze pięć pakietów przekracza limit jednego pakietu
na sekundę, a następnie włącza się ograniczanie (limit). Jeśli nastąpi
pauza, kolejna seria zostanie wpuszczona ale nie powyżej maksymalnej
częstotliwości określonej przez regułę (1 pakiet na sekundę po tym
jak dotarła seria).

<tag>owner (ang. właściciel)</tag> Ten moduł stara się ustalić pewne
charakterystyki twórcy pakietu, dla pakietów generowanych lokalnie.
Jego użycie jest możliwe tylko w łańcuchu OUTPUT, a nawet nie dla
wszystkich pakietów (takich jak odpowiedzi na ICMP ping) które mogą
nie mieć właściciela, a w związku z tym nie będą pasowały.

<descrip>
	<tag>--uid-owner userid</tag>
Pasuje dla pakietów stworzonych przez proces ze wskazanym efektywnym
(numerycznym) identyfikatorem użytkownika.
	<tag>--gid-owner groupid</tag>
Pasuje dla pakietów stworzonych przez proces ze wskazanym efektywnym
(numerycznym) identyfikatorem grupy.
	<tag>--pid-owner processid</tag>
Pasuje dla pakietów stworzonych przez proces ze wskazanym efektywnym
(numerycznym) identyfikatorem procesu.
	<tag>--sid-owner sessionid</tag>
Pasuje dla pakietów stworzonych przez proces we wskazanej grupie sesji.
</descrip>

<tag>unclean (ang. brudny)</tag> Jest to eksperymentalny moduł którego
używa się przez podanie '<tt>-m unclean</tt>' lub '<tt>--match unclean</tt>'.
Wykonuje różne losowe testy sprawdzające na pakiecie. Moduł ten nie
był sprawdzany i nie powinien być używany jako test związany z
bezpieczeństwem (prawdopodobnie sprawia że wszystko wygląda jeszcze
gorzej, ponieważ sam może mieć pluskwy). Nie udostępnia żadnych opcji.
</descrip>

<sect3>Test Stanu

<p>Najbardziej użytecznym testem jest ten dostarczany przez rozszerzenie
'<tt>state</tt>', który interpretuje analizę śledzenia połączeń modułu
'<tt>ip_conntrack</tt>'. Generalnie bardzo zaleca się jego
wykorzystanie.

<p>Podanie w regule opcji '<tt>-m state</tt>' udostępnia dodatkową
opcję '<tt>--state</tt>', która jest listą oddzielonych stanów do
przetestowania (opcja '<tt>!</tt>' wskazuje na pakiety <bf>nie pasujące</bf>
do wskazanych stanów). Stanami które można sprawdzać są:

<descrip>
<tag>NEW (NOWY)</tag> Pakiet który tworzy nowe połączenie.

<tag>ESTABLISHED (NAWIĄZANY)</tag> Pakiet który należy do istniejącego
połączenia (np. pakiet odpowiedzi, lub pakiet wychodzący w połączeniu
które otrzymało już odpowiedzi).

<tag>RELATED (POWIĄZANY)</tag> Pakiet który jest powiązany z
istniejącym połączeniem, ale nie jest jego częścią, tj. np pakiet
z błędem ICMP, lub (jeśli załadowany jest moduł FTP) pakiet
ustanawiający połączenie ftp dla danych.

<tag>INVALID (BŁĘDNY)</tag> Pakiet który nie może być zidentyfikowany
z jakiś powodów: mogą to być wyczerpanie się pamięci, lub błędy
ICMP które nie należą do żadnego znanego połączenia. Generalnie,
pakiety tego typu powinno się odrzucać.
</descrip>

<sect1>Cel

<p>Znamy już testy które możemy przeprowadzić na pakiecie,
potrzebujemy zatem sposobu by wskazać co robić z pakietami które
pasują do naszych testów. Nazywa się to <bf>celem</bf>
(ang. <em>target</em>) reguły.

<p>Są dwa proste wbudowane cele : DROP (wyrzucić) i ACCEPT
(zaakceptować). Już je widzieliśmy. Jeśli reguła pasuje do
pakietu a jej cel jest jednym z tych dwóch, nie analizuje
się już innych reguł: los pakietu został już określony.

<p>Istnieją jeszcze dwa inne typy celów: rozszerzenia i łańcuchy
zdefiniowane przez użytkownika.

<sect2>Łańcuchy zdefiniowane przez użytkownika

<p>Bardzo potężną własnością którą <tt>iptables</tt> dziedziczy z
<tt>ipchains</tt> jest możliwość tworzenia przez użytkownika nowych
łańcuchów, oprócz wbudowanych (INPUT, FORWARD i OUTPUT).
Zgodnie z przyjętą konwencją, wszystkie łańcuchy generowane przez
użytkownika pisane są małymi literami by odróżnić je od wbudowanych
(opiszemy jak tworzyć nowe łańcuchy użytkownika poniżej,
w sekcji <ref id="chain-ops" name="Operacje na całym łańcuchu">).

<p>Kiedy do reguły dociera pakiet który pasuje, a cel tej reguły
zdefiniowany jest jako łańcuch zdefiniowany przez użytkownika,
rozpoczyna on testy w tym właśnie łańcuchu. Jeśli w obrębie tego
łańcucha los pakietu nie zostanie zdecydowany, przemierzanie
reguł rozpoczyna się w pierwotnym łańcuchu, w miejscu w którym
zostało przerwane (dokładnie od następnej reguły).

<p>Czas na trochę rysunków ASCII. Rozważmy dwa (śmiesznie proste)
łańcuchy: <tt>INPUT</tt> (łańcuch wbudowany) i <tt>test</tt>
(łańcuch zdefiniowany przez użytkownika).

<tscreen><verb>
	 `INPUT'			 `test'
	----------------------------	----------------------------
	| Rule1: -p ICMP -j DROP   |	| Rule1: -s 192.168.1.1    |
	|--------------------------|	|--------------------------|
	| Rule2: -p TCP -j test    |	| Rule2: -d 192.168.1.1    |
        |--------------------------|	----------------------------
	| Rule3: -p UDP -j DROP    |
	----------------------------
</verb></tscreen>

<p>Rozważmy pakiet TCP nadchodzący z 192.168.1.1 i wysłany do 1.2.3.4.
Wchodzi on do łańcucha <tt>INPUT</tt> i rozpoczyna się sprawdzanie.
Reguła 1 (Rule1) nie pasuje, natomiast druga tak. Ponieważ cel zdefiniowany
jest jako '<tt>test</tt>', następna reguła która jest sprawdzana pochodzi
z łańcucha '<tt>test</tt>'. Pierwsza reguła w tym łańcuchu pasuje ale nie
podaje celu, więc sprawdzana jest następna reguła. Ona nie pasuje i
osiągany jest koniec łańcucha '<tt>test</tt>'. Wracamy do łańcucha
<tt>INPUT</tt>, w którym ostatnio sprawdzaliśmy regułę drugą, teraz więc
sprawdzamy trzecią która również nie pasuje.

<p>
Zatem droga pakietu wygląda w sposób następujący:
<tscreen><verb>
                                v    __________________________
	 `INPUT'		|   /	 `test'                v
	------------------------|--/	-----------------------|----
	| Rule1                 | /|	| Rule1                |   |
	|-----------------------|/-|	|----------------------|---|
	| Rule2                 /  |	| Rule2                |   |
        |--------------------------|	-----------------------v----
	| Rule3                 /--+___________________________/
	------------------------|---
                                v
</verb></tscreen>

<p>Łańcuchy zdefiniowane przez użytkownika mogą jako cel wskazywać
inne łańcuchy również zdefiniowane przez użytkownika (ale nie mogą
tworzyć pętli: twój pakiet zostanie wyrzucony jeśli okaże się że
jest sprawdzany w pętli).

<sect2>Rozszerzenia do iptables: Nowe Cele

<p>Innym typem celu jest rozszerzenie. Rozszerzenie składa się z modułu
kernela i opcjonalnych rozszerzeń <tt>iptables</tt>, które zapewniają
opcje dla linii poleceń. Jest kilka takich rozszerzeń w standardowej
dystrybucji netfilter:

<descrip>
<tag>LOG</tag> Moduł ten zapewnia logowanie w kernelu pasujących pakietów.
Udostępnia następujące opcje:
  <descrip>
  <tag>--log-level</tag> Po którym następuje nazwa poziomu logowania
    lub odpowiednik numeryczny. Prawidłowymi nazwami są (wielkość
    liter nie jest ważna) '<tt>debug</tt>', '<tt>info</tt>', '<tt>notice</tt>',
    '<tt>warning</tt>', '<tt>err</tt>', '<tt>crit</tt>',
    '<tt>alert</tt>' i '<tt>emerg</tt>', którym odpowiadają cyfry
    od 7 do 0. Sprawdź stronę podręcznika <tt>syslog.conf</tt>
    by dowiedzieć się co oznaczają poszczególne poziomy.

  <tag>--log-prefix</tag> po którym następuje ciąg do 29 znaków,
    który dodawany jest do logowanej informacji by umożliwić jej
    jednoznaczną identyfikację.
  </descrip>

  Moduł ten używany jest najczęściej z testem limit, dzięki czemu
  nie zaśmiecasz sobie logów.

<tag>REJECT (ODRZUĆ)</tag>Moduł ten ma takie samo działanie jak
'DROP', poza tym że to nadawcy pakietu odsyłany jest pakiet
ICMP 'port unreachable'. Weź jednak pod uwagę fakt, że błąd
ICMP nie zostanie odesłany jeśli (sprawdź RFC 1122):

<itemize>
<item> Pakiet którego dotyczy ta reguła jest wiadomością ICMP o
błędzie, lub nieznanym typem wiadomości ICMP

<item> Pakiet którego dotyczy ta reguła był drugim lub dalszym
fragmentem.

<item> Wysłaliśmy już ostatnio zbyt dużo wiadomości o błędach
ICMP do tego nadawcy
</itemize>

Do REJECT można również dodać opcjonalny argument '<tt>--reject-with</tt>'
który pozwala na zadeklarowanie jaki dokładnie pakiet ICMP ma zostać
odesłany zamiast domyślnego '<tt>port unreachable</tt>'. Sprawdź
stronę podręcznika.
</descrip>

<sect2>Specjalne cele wbudowane

<p>Są dwa wbudowane specjalne cele: <tt>RETURN</tt> (POWRÓT) i
<tt>QUEUE</tt> (KOLEJKA).

<p><tt>RETURN</tt> ma dokładnie ten sam efekt jak zakończenie sprawdzania
łańcucha: dla reguły w łańcuchu wbudowanym sprawdzana jest wtedy polityka.
Dla reguły w zdefiniowanym przez użytkownika łańcuchu, oznacza to
powrót do poprzedniego łańcucha, zaraz po regule która spowodowała skok
do tego łańcucha.

<p><tt>QUEUE</tt> to cel który kolejkuje pakiety dla przetwarzania w
przestrzeni użytkownika. Żeby można było ten cel zastosować, potrzebne
są jeszcze dwa składniki:

<itemize>
<item>program <bf>obsługujący kolejkę</bf> (ang. <em>queue handler</em>),
który zajmie się mechaniką przekazywania pakietów pomiędzy kernelem i
<bf>przestrzenią użytkownika</bf> (ang. <em>userspace</em>); oraz

<item>aplikacja działająca w przestrzeni użytkownika która będzie
potrafiła obsłużyć przyjęcie, ewentualną modyfikację i opcjonalne
wydanie werdyktu w sprawie pakietu.
</itemize>

Standardowym programem obsługującym kolejki dla IPv4 jest w iptables
moduł <tt>ip_queue</tt>, który dystrybuowany jest z kernelem i
oznaczony jako eksperymentalny.

<p>Poniżej przedstawiono krótki przykład jak użyć iptables z
kolejką pakietów do przetwarzania w przestrzeni użytkownika:
<tscreen><verb>
# modprobe iptable_filter
# modprobe ip_queue
# iptables -A OUTPUT -p icmp -j QUEUE
</verb></tscreen>
W powyższych regułach, pakiety ICMP generowane lokalnie (tak jak na
przykład przy użyciu polecenia ping) przekazywane są do modułu
<tt>ip_queue</tt>, który stara się dostarczyć pakiety do aplikacji
działającej w przestrzeni użytkownika. Jeśli nie ma takiej
aplikacji, pakiety są wyrzucane.

<p>By napisać taką aplikację, należy użyć API libipq. Dystrybuowana
jest ona razem z iptables. Kod przykładowy znajduje się w narzędziach
testsuite (np. <tt>redirect.c</tt>) z CVS.

<p>Status modułu ip_queue może być sprawdzony przez wywołanie:
<tscreen><verb>
/proc/net/ip_queue
</verb></tscreen>
Maksymalna długość kolejki (tzn. ilość pakietów dostarczonych do
przestrzeni użytkownika bez odpowiedzi) może być kontrolowana przez:
<tscreen><verb>
/proc/sys/net/ipv4/ip_queue_maxlen
</verb></tscreen>
Domyślną wartością jest 1024. Kiedy zostaje osiągnięty limit,
nowe pakiety będą wyrzucane dopóki długość kolejki nie spadnie poniżej wartości
maksymalnej. Dobre protokoły takie jak TCP interpretują wyrzucane pakiety
jako tłok i prawdopodobnie dadzą sobie spokój gdy kolejka się wypełni.
Można oczywiście trochę poeksperymentować by wyznaczyć idealną maksymalną
długość kolejki dla określonej sytuacji, jeśli domyślna wartość jest
zbyt mała.

<sect1>Operacje na całym łańcuchu<label id="chain-ops">

<p>Bardzo przydatną opcją w <tt>iptables</tt> jest możliwość grupowania
reguł w łańcuchy. Możesz je nazwać jak chcesz, ale zalecam raczej używanie
małych liter by nie pomylić ich z wbudowanymi łańcuchami i celami.
Nazwy ograniczone są do 31 liter.

<sect2>Tworzenie nowego łańcucha

<p>Stwórzmy nowy łańcuch. Ponieważ jestem kolesiem z wyobraźnią,
nazwijmy go '<tt>test</tt>'. Możemy użyć albo '<tt>-N</tt>' albo
'<tt>--new-chain</tt>':

<tscreen><verb>
# iptables -N test
#
</verb></tscreen>

<p>Proste. Możesz teraz dodać do niego swoje reguły tak jak to już
opisano.

<sect2>Kasowanie łańcucha

<p>Kasowanie łańcucha również jest proste, używa się do tego opcji
'<tt>-X</tt>' lub '<tt>--delete-chain</tt>'. A dlaczego '<tt>-X</tt>'?
Cóż, wszystkie dobre literki były już zajęte.

<tscreen><verb>
# iptables -X test
#
</verb></tscreen>

<p>Jest jednak parę ograniczeń dotyczących kasowania łańcuchów:
muszą być puste (sprawdź sekcję <ref id="flushing" name="Opróżnianie łańcucha">
poniżej) i nie mogą być wskazywane jako cel w innej regule. Nie
możesz również skasować żadnego z trech wbudowanych łańcuchów.

<p>Jeśli nie podasz nazwy łańcucha, skasowane zostaną w miarę
możliwości wszystkie łańcuchy zdefiniowane przez użytkownika.

<sect2>Opróżnianie łańcucha<label id="flushing">

<p>Istnieje oczywiście również sposób by wykasować wszystkie reguły
z łańcucha. Używa się do tego opcji '<tt>-F</tt>' (lub '<tt>--flush</tt>').

<tscreen><verb>
# iptables -F FORWARD
#
</verb></tscreen>

<p>Jeśli nie wskażesz konkretnego łańcucha, opróżnione zostaną
wszystkie.

<sect2>Listowanie zawartości łańcucha

<p>Możesz wylistować reguły w łańcuchu, używając opcji '<tt>-L</tt>'
(lub '<tt>--list</tt>').

<p>Pozycja '<tt>refcnt</tt>' przy każdym łańcuchu zdefiniowanym
przez użytkownika podaje numer reguł które odwołują się do tego
łańcucha. Wartość ta musi być równa zero (a łańcuch musi być pusty),
by taki łańcuch można było skasować.

<p>Jeśli pominięto nazwę łańcucha, wylistowane zostaną wszystkie
łańcuchy, nawet te puste.

<p>Istnieją trzy opcje które mogą towarzyszyć opcji '<tt>-L</tt>'.
Opcja '<tt>-n</tt>' (numerycznie) jest o tyle przydatna, że
zapobiega sprawdzaniu nazw odpowiadającym adresom IP przez <tt>iptables</tt>,
co może spowodować duże zwłoki jeśli twój DNS (a zakładamy że
używasz DNS jak większość ludzi) nie jest prawidłowo skonfigurowany,
lub odfiltrowałeś zapytania DNS. Powoduje ona również podanie portów
TCP i UDP numerycznie zamiast nazw.

<p>Opcja '<tt>-v</tt>' pokazuje wszystkie detale reguł, takie jak
liczniki pakietów i bajtów, porównania TOS (Typu Usługi, ang.
<em>Type of Service</em>) i interfejsy. Bez tej opcji wszystkie
te informacje zostaną pominięte.

<p>Zwróć uwagę że liczniki pakietów i bajtów drukowane są przy
użyciu suffiksów 'K', 'M' lub 'G', dla odpowiednio 1000, 1,000,000
i 1,000,000,000. Poprzez użycie opcji '<tt>-x</tt>' (rozwiń liczby)
można uzyskać pełne liczby, bez względu na to jak są duże.

<sect2>Resetowanie (zerowanie) liczników

<p>Czasami przydatne jest móc wyzerować liczniki. Wykonuje się to przez
użycie opcji '<tt>-Z</tt>' (lub '<tt>--zero</tt>').

<p>
Rozważ poniższy przykład:

<tscreen><verb>
# iptables -L FORWARD
# iptables -Z FORWARD
#
</verb></tscreen>

Pewna liczba pakietów mogłaby przejść pomiędzy wydaniem polecenia z opcją
'<tt>-L</tt>' a '<tt>-Z</tt>'. W związku z tym, możesz tych opcji używać
<bf>razem</bf>, by wyzerować liczniki dokładnie w momencie ich wyświetlenia.

<sect2>Określanie polityki<label id="policy">

<p>Wspomnieliśmy już co dzieje się gdy pakiet dociera do końca
wbudowanego łańcucha, kiedy rozmawialiśmy o tym jak pakiet podróżuje przez
łańcuchy. W tym przypadku o losie pakietu decyduje <bf>polityka</bf> dla
łańcucha. Tylko wbudowane łańcuchy (<tt>INPUT</tt>, <tt>OUTPUT</tt>
i <tt>FORWARD</tt>) mają przypisaną politykę, ponieważ jeśli pakiet
dociera do końca łańcucha zdefiniowanego przez użytkownika, sprawdzanie
wraca do poprzedniego łańcucha.

<p>
Polityką może być <tt>ACCEPT</tt> lub <tt>DROP</tt>, na przykład:

<tscreen><verb>
# iptables -P FORWARD DROP
#
</verb></tscreen>

<sect>Używanie ipchains i ipfwadm<label id="oldstyle">

<p>W dystrybucji netfilter znajdują się moduły ipchains.o i ipfwadm.o.
Można załadować je do kernela (UWAGA: są niekompatybilne z modułem
ip_tables.o!). Możesz następnie używać ich tak jak za starych
dobrych czasów.

<p>Będą one wspierane jeszcze przez jakiś czas. Wydaje mi się że
sensownym wzorem jest 2*[notka o zastąpieniu-pierwsza stabilna
dystrybucja], po którym to czasie dostępna jest stabilna wersja
nowego odpowiednika. Oznacza to że wsparcie dla tych modułów
skończy się wraz z pojawieniem się Linuksa 2.6 lub 2.8.

<sect>Łączenie filtrowania pakietów i NAT

<p>Zwykle używa się jednocześnie Translacji Adresów Sieciowych (NAT,
zajrzyj do NAT HOWTO) i filtrowania pakietów. Dobra wiadomość jest
taka że łączy się je bardzo dobrze.

<p>Projektujesz swój filtr pakietów kompletnie ignorując NAT. Adresy
źródłowe i przeznaczenia które będzie sprawdzał filtr pakietów będą 'prawdziwymi'
adresami. Na przykład, jeśli prowadzisz DNAT i wysyłasz połączenia do 1.2.3.4 na port
80 przez 10.1.1.1 port 8080, filtr pakietów zobaczy pakiety podróżujące do
10.1.1.1 na port 8080 (prawdziwy adres przeznaczenia), a nie 1.2.3.4 na port 80.
Podobnie, możesz zignorować masquerading (maskaradę): z punktu widzenia
filtra pakietów pakiety będą nadchodziły z prawdziwych wewnętrznych adresów
IP (powiedzmy 10.1.1.1) a odpowiedzi wracały gdzie powinny.

<p>Możesz używać testu stanu ('state') bez dostarczania dodatkowej pracy
filtrowi pakietów, ponieważ NAT wymaga i tak śledzenia połączeń
(ang. <em>connection tracking</em>). By rozszerzyć prosty przykład
maskarady z NAT HOWTO o zabronienie kreowaniu nowych połączeń z
interfejsu ppp0, zrobiłbyś tak:

<tscreen><verb>
# Masquerade out ppp0
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE

# Disallow NEW and INVALID incoming or forwarded packets from ppp0.
iptables -A INPUT -i ppp0 -m state --state NEW,INVALID -j DROP
iptables -A FORWARD -i ppp0 -m state --state NEW,INVALID -j DROP

# Turn on IP forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward
</verb></tscreen>

<sect>Różnice pomiędzy iptables i ipchains<label id="Appendix-A">

<p>
<itemize>
<item> Po pierwsze, nazwy wbudowanych łańcuchów zostały zmienione z
małych na DUŻE litery, ponieważ łańcuchy INPUT i OUTPUT otrzymują tylko pakiety
kierowane do maszyny lokalnej lub pakiety generowane lokalnie. Do tej pory
używano ich dla wszystkich pakietów przychodzących i wychodzących.

<item> Opcja '<tt>-i</tt>' oznacza teraz interfejś wejściowy i
działa tylko w łańcuchach INPUT i FORWARD. Reguły w łańcuchach
FORWARD i OUTPUT zamiast dotychczasowego '<tt>-i</tt>'
używają '<tt>-o</tt>'.

<item> Porty TCP i UDP podaje się teraz przez opcje <tt>--source-port</tt>
lub <tt>--sport</tt> (czy też <tt>--destination-port</tt>/<tt>--dport</tt>)
i zapisuje po wskazaniu protokołu ('<tt>-p tcp</tt>'
lub '<tt>-p udp</tt>') ponieważ dopiero one ładują rozszerzenia
odpowiednio TCP i UDP

<item> Opcję TCP '<tt>-y</tt>' zmieniono na '<tt>--syn</tt>', i
należy ją zapisać po '<tt>-p tcp</tt>'.

<item> Cel DENY w końcu nazywa się DROP (WYRZUCIĆ).

<item> Działa zerowanie pojedyńczych łańcuchów z jednoczesnym
wylistowaniem ich zawartości.

<item> Działa zerowanie wbudowanych łańcuchów łącznie z kasowaniem
liczników wywołania polityki dla danego łańcucha

<item> Listowanie łańcuchów dostarcza ci 'atomowego' zdjęcia
(ang. <em>snapshot</em>) liczników.

<item> REJECT i LOG są teraz celami rozszerzonymi, co oznacza że są
osobnymi modułami kernela.

<item> Nazwy łańcuchów mogą mieć do 31 znaków.

<item> Opcja MASQ nazywa się w końcu MASQUERADE i używa innej składni.
REDIRECT zachował nazwę, ale również zmieniono składnię. Sprawdź dokument
NAT-HOWTO by uzyskać więcej informacji jak użyć tych opcji.

<item> Opcja '<tt>-o</tt>' nie jest już używana by kierować pakiety
do urządzenia z przestrzeni użytkownika (sprawdź opcję '<tt>-i</tt>'
powyżej). Wysyła się je tam poprzez skierowanie do celu QUEUE.

<item>Prawdopodobnie cała masa rzeczy o których zapomniałem.
</itemize>

<sect>Porady w projektowaniu filtra pakietów

<p>W dziedzinie bezpieczeństwa komputerowego zwykle za powszechną
mądrość uważa się blokowanie wszystkiego a dopiero potem otwieraniu odpowiednich
portów w miarę jak stają sie potrzebne. Mówi się o tym zwykle
'to co nie jest wyraźnie dozwolone, jest zabronione'. Zalecam to podejście,
jeśli bezpieczeństwo jest twoim największym priorytetem.

<p>Nie uruchamiaj żadnych usług których nie musisz mieć, nawet jeśli
wydaje ci się że zablokowałeś do nich dostęp.

<p>Jeśli budujesz dedykowaną ścianę ogniową, rozpocznij od zera z
blokowaniem wszystkich pakietów, potem dodawaj usługi i reguły które
pozwolą im działać.

<p>Zalecam również bezpieczeństwo 'warstwowe': połącz tcp-wrappers
(dla połączeń do filtra pakietów), proxy (dla połączeń przechodzących
przez filtr pakietów), weryfikację drogi (ang. <em>route verification</em>)
i filtrowanie pakietów. Weryfikacja drogi ma miejsce wtedy, gdy pakiet
dociera z niewłaściwego interfejsu i jest odrzucany: na przykład,
twoja sieć wewnętrzna ma adresy 10.1.1.0/24, a pakiet z takim adresem
dociera do filtra pakietów przez interfejs zewnętrzny - powinien zostać
odrzucony. Może to zostać włączone dla jednego interfejsu (ppp0) tak
jak niżej:

<tscreen><verb>
# echo 1 > /proc/sys/net/ipv4/conf/ppp0/rp_filter
#
</verb></tscreen>

Lub dla wszystkich istniejących i przyszłych interfejsów tak jak
niżej:

<tscreen><verb>
# for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
#     echo 1 > $f
# done
#
</verb></tscreen>

Debian robi to domyślnie jeśli jest to możliwe. Jeśli masz routing
asymetryczny (tzn. spodziewasz się pakietów nadchodzących z dziwnych kierunków),
będziesz prawdopodobnie musiał wyłączyć takie filtrowanie na tych interfejsach.

<p>Logowanie jest użyteczne w trakcie konfigurowania ściany ogniowej,
gdy coś nie działa, ale na działającej ścianie ogniowej zawsze połącz logowanie z
opcją '<tt>limit</tt>', by zapobiec zapełnieniu twoich logów.

<p>Zalecam również śledzenie połączeń dla systemów w których
bezpieczeństwo jest sprawą priorytetową: wprowadza pewne opóźnienia,
ponieważ śledzone są wszystkie połączenia, ale jest to bardzo przydatne w
kontrolowaniu dostępu do twoich sieci. Być może będziesz musiał
załadować moduł '<tt>ip_conntrack.o</tt>' jeśli twój kernel nie
ładuje modułów automatycznie albo jeśli nie jest on już wbudowany w
kernel. Jeśli chcesz śledzić dokładnie skomplikowane protokoły, musisz
załadować odpowiedni moduł wspomagający (np. '<tt>ip_conntrack_ftp.o</tt>').

<tscreen><verb>
# iptables -N no-conns-from-ppp0
# iptables -A no-conns-from-ppp0 -m state --state ESTABLISHED,RELATED -j ACCEPT
# iptables -A no-conns-from-ppp0 -m state --state NEW -i ! ppp0 -j ACCEPT
# iptables -A no-conns-from-ppp0 -i ppp0 -m limit -j LOG --log-prefix "Bad packet from ppp0:"
# iptables -A no-conns-from-ppp0 -i ! ppp0 -m limit -j LOG --log-prefix "Bad packet not from ppp0:"
# iptables -A no-conns-from-ppp0 -j DROP

# iptables -A INPUT -j no-conns-from-ppp0
# iptables -A FORWARD -j no-conns-from-ppp0
</verb></tscreen>

<p>Budowanie dobrej ściany ogniowej jest poza tematem tego HOWTO, ale
moją radą jest 'bądź minimalistą'. Zajrzyj do Security HOWTO po więcej
informacji o testowaniu i sprawdzaniu twojej maszyny.
</p>

</article>

