Następna strona Poprzednia strona Spis treści

7. Używanie iptables

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

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

  1. Stworzenie nowego łańcucha (-N).
  2. Skasowanie pustego łańcucha (-X).
  3. Zmiana polityki dla wbudowanego łańcucha (-P).
  4. Wylistowanie reguł w łańcuchu (-L).
  5. Wyczyszczenie łańcucha z reguł (-F).
  6. Wyzerowanie liczników pakietów i bajtów we wszystkich regułach w łańcuchu (-Z).

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

  1. Dodanie nowej reguły do łańcucha (-A).
  2. Wstawienie nowej reguły na pewnej pozycji w łańcuchu (-I).
  3. Zamiana reguły na pewnej pozycji w łańcuchu (-R).
  4. Skasowanie reguły na pewnej pozycji w łańcuchu (-D).
  5. Skasowanie pierwszej reguły pasującej do podanej w łańcuchu (-D).

7.1 Co zobaczysz gdy wystartujesz komputer

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

Zanim nie zostaną wykonane jakieś komendy (zwróć uwagę, że niektóre dystrybucje wykonują już operacje z iptables 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 'forward=0' do modułu iptable_filter.

7.2 Operacje na pojedyńczej regule

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

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 cel, ang. target). 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'.

127.0.0.1 to adres pętli zwrotnej (ang. loopback), 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. echo request) na które wszystkie współpracujące hosty odpowiedzą pakietem ICMP typu 0 - echo. To sprawia, że polecenie to jest wygodne dla testów.

# 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
#

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

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

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.

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:

        # iptables -D INPUT 1
        #

Co spowoduje skasowanie reguły numer 1 w łańcuchu INPUT.

Drugi sposób to dokładne przepisanie poleceń po opcji -A, ale zamiast opcji -A podajemy opcję -D. 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:

        # iptables -D INPUT -s 127.0.0.1 -p icmp -j DROP
        #
Składnia polecenia -D musi dokładnie odpowiadać opcjom które podałeś przy poleceniu -A (lub -I czy -R). Jeśli istnieje wiele identycznych reguł w tym samym łańcuchu, tylko pierwsza pasująca zostania skasowana.

7.3 Specyfikacja filtrowania

Widzieliśmy już jak używać opcji '-p' by wskazać protokół i '-s' 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.

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

Adres IP źródłowy ('-s', '--source' lub '--src') i docelowy ('-d', '--destination' lub '--dst') 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'.

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:

        [ UWAGA: `-s 0/0' jest tu całkowicie zbędne. ]
        # iptables -A INPUT -s 0/0 -j DROP
        #
Ale takich konstrukcji używa się rzadko, ponieważ efekt jest dokładnie taki sam jak w przypadku nie podania opcji '-s' w ogóle.

Inwersja

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

Protokół

Protokół podaje się po parametrze '-p' (lub '--protocol'). 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'.

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

Interfejs

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

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

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

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ę ppp0) i podobnych.

Można również wskazać interfejs kończąc jego nazwę przez '+' 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 '-i ppp+'.

Interfejs może być poprzedzony przez '!' 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. -i ! ppp+.

Fragmenty

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

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).

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.

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, nie będzie 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 '-p TCP --sport www' (podająca port źródłowy 'www') nigdy nie będzie pasowała do fragmentu pakietu (innego niż pierwszy). Nie będzie również pasować reguła odwrotna '-p TCP --sport ! www'.

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

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.

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.

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

# iptables -A OUTPUT -f -d 192.168.1.1 -j DROP
#

Rozszerzenia do iptables: Nowe cele i nowe testy

iptablesrozszerzalne, co oznacza że funkcjonalność zarówno kernela jak i narzędzia iptables może być rozszerzana by dodać nowe opcje.

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.

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

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

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.

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

By uzyskać pomoc do rozszerzenia, użyj opcji ładującej go ('-p', '-j' lub '-m') po której podaj '-h' lub '--help', np.:

# iptables -p tcp --help
#

Rozszerzenia TCP

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

--tcp-flags

Po której następuje opcjonalny znak '!', 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:

# iptables -A INPUT --protocol tcp --tcp-flags ALL SYN,ACK -j DROP

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

--syn

opcjonalnie poprzedzona przez '!', jest skrótem dla '--tcp-flags SYN,RST,ACK SYN'.

--source-port

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

--sport

to synonim '--source-port'.

--destination-port

i

--dport

mają takie same opcje jak powyżej, ale określają port przeznaczenia.

--tcp-option

po którym następuje opcjonalny znak ! 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.

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

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.

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ę.

Rozwiązaniem jest blokowanie tylko pakietów używanych do nawiązania połączenia. Nazywa się je pakietami SYN (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.

Używa się do tego opcji '--syn': 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:

-p TCP -s 192.168.1.1 --syn

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

Rozszerzenia UDP

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

Rozszerzenia ICMP

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

--icmp-type

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

Inne rozszerzenia testowe

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

mac

Moduł ten musi być wskazany przez '-m mac' lub '--match mac'. 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ę:

--mac-source

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

limit

Moduł ten musi być wskazany przez '-m limit' lub '--match limit'. 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:

--limit

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 '/second', '/minute', '/hour' lub '/day', albo ich skrótów (np. '5/second' to to samo co '5/s').

--limit-burst

po którym następuje numer, określający maksymalną serię po której powyższy limit się włącza.

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:

# iptables -A FORWARD -m limit -j LOG

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.

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.

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

Zabezpieczenie przed powodzią pakietów SYN (ang. Syn-flood):

# iptables -A FORWARD -p tcp --syn -m limit --limit 1/s -j ACCEPT

Skaner portół Furtive:

# iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT

Ping of death:

# iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT

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

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

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.



        <--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

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).

owner (ang. właściciel)

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.

--uid-owner userid

Pasuje dla pakietów stworzonych przez proces ze wskazanym efektywnym (numerycznym) identyfikatorem użytkownika.

--gid-owner groupid

Pasuje dla pakietów stworzonych przez proces ze wskazanym efektywnym (numerycznym) identyfikatorem grupy.

--pid-owner processid

Pasuje dla pakietów stworzonych przez proces ze wskazanym efektywnym (numerycznym) identyfikatorem procesu.

--sid-owner sessionid

Pasuje dla pakietów stworzonych przez proces we wskazanej grupie sesji.

unclean (ang. brudny)

Jest to eksperymentalny moduł którego używa się przez podanie '-m unclean' lub '--match unclean'. 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.

Test Stanu

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

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

NEW (NOWY)

Pakiet który tworzy nowe połączenie.

ESTABLISHED (NAWIĄZANY)

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).

RELATED (POWIĄZANY)

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.

INVALID (BŁĘDNY)

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ć.

7.4 Cel

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 celem (ang. target) reguły.

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.

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

Łańcuchy zdefiniowane przez użytkownika

Bardzo potężną własnością którą iptables dziedziczy z ipchains 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 Operacje na całym łańcuchu).

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).

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

         `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    |
        ----------------------------

Rozważmy pakiet TCP nadchodzący z 192.168.1.1 i wysłany do 1.2.3.4. Wchodzi on do łańcucha INPUT i rozpoczyna się sprawdzanie. Reguła 1 (Rule1) nie pasuje, natomiast druga tak. Ponieważ cel zdefiniowany jest jako 'test', następna reguła która jest sprawdzana pochodzi z łańcucha 'test'. 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 'test'. Wracamy do łańcucha INPUT, w którym ostatnio sprawdzaliśmy regułę drugą, teraz więc sprawdzamy trzecią która również nie pasuje.

Zatem droga pakietu wygląda w sposób następujący:

                                v    __________________________
         `INPUT'                |   /    `test'                v
        ------------------------|--/    -----------------------|----
        | Rule1                 | /|    | Rule1                |   |
        |-----------------------|/-|    |----------------------|---|
        | Rule2                 /  |    | Rule2                |   |
        |--------------------------|    -----------------------v----
        | Rule3                 /--+___________________________/
        ------------------------|---
                                v

Ł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).

Rozszerzenia do iptables: Nowe Cele

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

LOG

Moduł ten zapewnia logowanie w kernelu pasujących pakietów. Udostępnia następujące opcje:

--log-level

Po którym następuje nazwa poziomu logowania lub odpowiednik numeryczny. Prawidłowymi nazwami są (wielkość liter nie jest ważna) 'debug', 'info', 'notice', 'warning', 'err', 'crit', 'alert' i 'emerg', którym odpowiadają cyfry od 7 do 0. Sprawdź stronę podręcznika syslog.conf by dowiedzieć się co oznaczają poszczególne poziomy.

--log-prefix

po którym następuje ciąg do 29 znaków, który dodawany jest do logowanej informacji by umożliwić jej jednoznaczną identyfikację.

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

REJECT (ODRZUĆ)

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):

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

Specjalne cele wbudowane

Są dwa wbudowane specjalne cele: RETURN (POWRÓT) i QUEUE (KOLEJKA).

RETURN 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.

QUEUE 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:

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

Poniżej przedstawiono krótki przykład jak użyć iptables z kolejką pakietów do przetwarzania w przestrzeni użytkownika:

# modprobe iptable_filter
# modprobe ip_queue
# iptables -A OUTPUT -p icmp -j QUEUE
W powyższych regułach, pakiety ICMP generowane lokalnie (tak jak na przykład przy użyciu polecenia ping) przekazywane są do modułu ip_queue, który stara się dostarczyć pakiety do aplikacji działającej w przestrzeni użytkownika. Jeśli nie ma takiej aplikacji, pakiety są wyrzucane.

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. redirect.c) z CVS.

Status modułu ip_queue może być sprawdzony przez wywołanie:

/proc/net/ip_queue
Maksymalna długość kolejki (tzn. ilość pakietów dostarczonych do przestrzeni użytkownika bez odpowiedzi) może być kontrolowana przez:
/proc/sys/net/ipv4/ip_queue_maxlen
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.

7.5 Operacje na całym łańcuchu

Bardzo przydatną opcją w iptables 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.

Tworzenie nowego łańcucha

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

# iptables -N test
#

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

Kasowanie łańcucha

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

# iptables -X test
#

Jest jednak parę ograniczeń dotyczących kasowania łańcuchów: muszą być puste (sprawdź sekcję 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.

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

Opróżnianie łańcucha

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

# iptables -F FORWARD
#

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

Listowanie zawartości łańcucha

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

Pozycja 'refcnt' 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ć.

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

Istnieją trzy opcje które mogą towarzyszyć opcji '-L'. Opcja '-n' (numerycznie) jest o tyle przydatna, że zapobiega sprawdzaniu nazw odpowiadającym adresom IP przez iptables, 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.

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

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 '-x' (rozwiń liczby) można uzyskać pełne liczby, bez względu na to jak są duże.

Resetowanie (zerowanie) liczników

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

Rozważ poniższy przykład:

# iptables -L FORWARD
# iptables -Z FORWARD
#

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

Określanie polityki

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 polityka dla łańcucha. Tylko wbudowane łańcuchy (INPUT, OUTPUT i FORWARD) mają przypisaną politykę, ponieważ jeśli pakiet dociera do końca łańcucha zdefiniowanego przez użytkownika, sprawdzanie wraca do poprzedniego łańcucha.

Polityką może być ACCEPT lub DROP, na przykład:

# iptables -P FORWARD DROP
#


Następna strona Poprzednia strona Spis treści