Iptables (Netfilter) - Tutorial

Autor: Daniel Robbins (drobbins@gentoo.org
Wersja polska: 16 września 2001 ver.1.0
        Tom Breza   Tom.B@PCService-NET.co.uk  irc: #debian.pl (siaraX)
        Grzegorz Szurkało  szurek@hoth.amu.edu.pl  irc: #debian.pl (GrZeNiU) 


    Dokument ten opisuje (na przykładach), jak zrobić z Linuxa bardzo funkcjonalny filtr pakietów w oparciu o pakiet iptables (replaces ipchains) i funkcje filtrowania w jądrach z serii 2.4. Napisany został w standardzie ISO-8859-2. Oryginalne pochodzenie tłumaczenia dokumentu: http://hoth.amu.edu.pl/~szurek

Spis treści 

1. O tym tutorialu 
   1.1 O Autorze
   1.2 Od tłumaczy
2. Przygotowania
   2.1 Pobieranie narzędzi
   2.2 Konfiguracja Kernela
3. Firewall - prosty projekt 
4. Firewalle
   4.1 Tradycyjny Firewall
   4.2 Tradycyjny Firewall wózkowy
   4.3 Pełnowartościowy (dynamiczny) Firewall
5. Właściwości Firewalla dynamicznego
   5.1
Śledzenie połączeń (Conntrack)
   5.2 Status pakietu (NEW, ESTABILISHED, RELATED, INVALID)
   5.3 Dodawanie bezpiecznych zasad
6. Prawie perfekcyjny Firewall
    6.1 Prosty skrypt
    6.2 Używanie skryptu
7.Ulepszenia
    7.1
Włączanie/wyłączanie w /proc
       
7.1.1 Explicity - wyłączenie ECN
       
7.1.2 Przekazywanie - forwarding
    7.2 Odrzucanie połączeń
    7.3 Zabezpieczenie przed spoofingiem 
    7.4 Maskarada, NAT i  SNAT
        7.4.1 NAT - zagadnienia
        7.4.2 Tabele
    7.5 Uzupełniony skrypt
    7.6 Przeglądanie zasad
       7.7 HTTP
       7.8 Przykład bezpiecznego HTTP
       7.9 Nasz końcowy skrypt Firewalla
8. Dodatki
       8.1 Logowanie
       8.2
Taktyka sieciowa
       8.3 Jeszcze jedno...
9. Zasoby/Źródła


1.  O tym tutorialu  up

     Czy powinienem przerobić ten tutorial? Ten tutorial pokazuje jak używać netfilter żeby przygotować potężny pełnoprawny Linuxowy firwall. Wszystko co potrzebujesz to komputer z zainstalowanym Linuxem, który obecnie używa jądra 2.4. Laptop, stacje robocza, ruter albo serwer z Linuxem 2.4 będą wystarczające. Powinieneś orientować się w standardowej terminologii sieciowej jak adres IP, źródłowe i docelowe numery portów, TCP, UDP i ICMP, itp. Na koniec tutoriala będziesz rozumiał jak skonstruowany jest pełnoprawny Firewall i będziesz mieć mnóstwo przykładów konfiguracji do użycia w Twoich własnych projektach. 

 O Autorze  up

     Z technicznymi pytaniami dotyczącymi tego tutoriala, skontaktuj się z autorem Danielem Robbinsem (drobbins@gentoo.org) .

Od tłumaczy  up

     Wszędzie, gdzie zostało użyte słowo Firewall, autor (tłumaczenia, i zapewne autor tutoriala) miał na myśli filtr pakietów. Uważamy, iż definicja Firewalla bardziej pasuje do połączeń: filtr pakietów (ipfwadm, ipchains lub iptables - filtrowanie pakietów ze względu na adres i port: źródłowy i docelowy, i ze względu na typ pakietu: UDP, TCP, ICMP) + proxy (np. TIS FWTK lub Socks - badanie poprawności pakietu  na poziomie protokołu, itp.)+ ewentualny NAT (bądź maskarada).
    Uwagi dotyczące błędów gramatycznych, ortograficznych lub merytorycznych są zakazane. Dopuszczamy kontakt na podane wyżej adresy e-mail jedynie w celu ustalenia sposobu i daty przekazania dowolnych ilości piwa dla autorów tłumaczenia, lub w innych sprawach dotyczących piwa. 

2. Przygotowania  up

 W tym tutorialu, będziemy tworzyć pełnowartościowy Linuxowy Firewall. Nasz Firewall będzie uruchamiany na laptopie z zainstalowanym Linuxem, stacji roboczej, serwerze albo ruterze. Naszym głównym celem jest zezwolenie tylko pewnym typom pakietow na przejscie przez nasz Firewall. Żeby zwiększyć bezpieczeństwo, będziemy konfigurować nasz Firewall aby upuścił (DROP), albo odrzucił (REJECT) pakiety którymi nie jesteśmy zainteresowani, jak również ruch, który mógłby być niebezpieczny. 

Pobieranie narzędzi  up

     Zanim zaczniemy projektować nasz Firewall, będziemy musieli zrobić dwie rzeczy. Pierwsza, musimy się upewnić ze komenda "iptables" jest dostępna. Jako root napisz "iptables" i zobacz czy jest. Jeśli nie ma takiej komendy wtedy musimy pobrać pakiet i zainstalować go. Tutaj jest jak tego dokonać http://netfilter.samba.org pobierz jak najnowsza wersje iptables.tar.gz (obecnie jest to iptables-1.1.2.tar.gz ( obecnie jest już 1.2.2)). Następnie zainstaluj przez wydanie poniższych komend (to co zostanie wydrukowane przez system zostało pominięte) * musimy wykonać to jako użytkownik root: 
    # tar -xzvf iptables-1.2.2.tar.gz 
    # cd iptables-1.2.2 
    # make 
    # make install 

 Konfiguracja Kernela  up

    Kiedy już zainstalujesz iptables powinieneś mieć dostępną komendę "iptables", jak również bardzo poręczna stronę podręcznika MAN ("man iptables"). OK, teraz musimy upewnić się ze mamy wszystkie potrzebne funkcje wbudowane w nasz kernel. Ten tutorial przyjmuje ze skompilowałeś własny kernel. Przenieś się do katalogu /usr/src/linux i napisz:
 # make menuconfig ( config lub dla miłośników myszopędnego GUI - xconfig )

    Musimy teraz uaktywnić kilka opcji kernela z sekcji Network options. Upewnij się, że masz uaktywnione przynajmniej te opcje: 
<*> Packet socket 
[*] Network packet filtering (replace ipchains) 
<*> Unix domain sockets
[*] TCP/IP networking
[*] IP: advanced router 
[*] IP: policy routing
[*] IP: use netfilter MARK value as routing key
[*] IP: fast network address translation
[*] IP: use TOS value as routing key 
IP NETFILTER CONFIGURATION ---->
     Uaktywnij KAŻDĄ opcję, dzięki temu będziemy mieli pełną funkcjonalność netfiltra. Pewnie nie użyjemy wszystkich jego możliwości, ale jest dobrym pomysłem żeby je udostępnić, aby później ewentualnie z nimi poeksperymentować.
    Jest jedna opcja w sekcji "Networking options", która NIE POWINNA być uaktywniona: explicit congestion notification. Zostaw tą opcję nie uaktywnioną. 

[ ] IP: TCP Explicit Congestion Notification support 

Jeśli ta opcja jest uaktywniona, twoja maszyna linuxowa nie będzie mogła utrzymać łączności z 8% całego Internetu. Kiedy ECN jest uaktywnione niektóre pakiety, które są wysyłane przez Twoje pudełko z Linuxem będą miały ustawiony bit ECN. Ten bit oszukuje cześć ruterów internetowych, wiec jest bardzo ważne, aby ECN było nie uaktywnione. OK, teraz kernel jest skonfigurowany według naszych potrzeb. Skompiluj go i zainstaluj. Potem przeładuj maszynę. Czas zacząć zabawę z netfiltrem. 

2. Firewall - prosty projekt  up

     Przy budowaniu naszego Firewalla, komenda "iptables" jest naszym przyjacielem. To jest to co będziemy używać do interakcji z zasadami filtrowania w jądrze. Będziemy używać komendy "iptables" aby stworzyć nowe zasady, wylistować istniejące, wyczyścić zasady, oraz ustawić domyślna taktykę postępowania. To znaczy, że aby stworzyć nasz Firewall, będziemy musieli wprowadzić serie komend iptables, i tutaj jest pierwsza, której się przyjrzymy (proszę jej nie pisać!!!!)

    # iptables -P INPUT DROP

 Właśnie patrzysz na prawie "perfekcyjny" Firewall. Jeśli wydasz tą komendę, będziesz niesamowicie dobrze zabezpieczony przeciwko jakiemukolwiek złośliwemu atakowi. Podczas gdy ten Firewall jest niesamowicie bezpieczny, jest również trochę śmieszny. Zanim przejdziemy dalej, spójrzmy co dokładnie robi ta komenda!

     Komenda "iptables -P" jest używana do ustawienia domyślnej taktyki dla zasad łańcuchów filtrowania pakietów. W tym przykładzie "iptables -P" jest użyte do ustawienia domyślnej taktyki dla łańcucha INPUT. Jest to wbudowany łańcuch zasad, który będzie zastosowany dla każdego przychodzącego pakietu. Przez ustawienie domyślnej taktyki na DROP, mówimy kernelowi żeby każdy pakiet, który osiągnie koniec zasad łańcucha INPUT, powinien zostać upuszczony ( to jest odrzucony). A ponieważ nie dodaliśmy żadnych innych zasad do łańcucha INPUT, wszystkie pakiety, które osiągną koniec łańcucha będą odrzucone.

     Jeszcze raz: ta komenda, jako jedyna - jest kompletnie nieużyteczna. Demonstruje jednak dobrą strategie dla projektowania Firewalla. Zaczynamy od odrzucania pakietów w ustawieniu domyślnym, i teraz stopniowo otwieramy nasz Firewall według naszych potrzeb. To nas upewni, że nasz Firewall jest tak bezpieczny, jak to tylko możliwe. 

    W tym przykładzie przyjmujemy, że projektujemy Firewall dla maszyny z dwoma interfejsami sieciowymi eth0 oraz eth1. Interfejs eth0 jest kartą sieciową podłączoną do naszego LAN'u, a interfejs eth1 jest kartą sieciową podłączoną do naszego rutera DSL - nasze podłączenie do Internetu. Dla takiej sytuacji, moglibyśmy ulepszyć nasz "bezlimitowy Firewall" przez dodanie jednej więcej linii:
     iptables -P INPUT DROP 
    iptables -A INPUT -i ! eth1 -j ACCEPT 
To dodatkowa linia "iptables -A" dodaje nową zasadę do końca naszego łańcucha INPUT. Po dodaniu tej zasady, nasz łańcuch INPUT zawiera pojedynczą zasadę i (drop-by-default) odrzuć - jako - domyślną taktykę. Teraz zobaczmy co nasz pół-kompletny Firewall może: kiedy pakiet przyjdzie na jakikolwiek interfejs (lo, eth0, albo eht1) kod netfiltra kieruje go do łańcucha INPUT i sprawdza czy pakiet pasuje do pierwszej zasady. Jeśli pasuje, pakiet jest akceptowany, i żaden kolejny proces nie jest przeprowadzany. Jeśli nie pasuje do łańcucha INPUT, wtedy domyślna taktyka jest wymuszona i pakiet zostaje odrzucony To jest ogólny przegląd. Nasza pierwsza zasada pasowała dokładnie do wszystkich pakietów przychodzących z eth0 i lo, bezzwłocznie pozwalając im na wejście. Jakikolwiek pakiet z eth1 był odrzucony. Jeśli więc uaktywnimy ten Firewall na naszej maszynie, będzie możliwa interakcja z naszym LAN'em, ale będziemy skutecznie odłączeni od Internetu. Spójrzmy na kilka sposobów umożliwienia nadzorowanego ruchu internetowego.

4. Firewalle  up

     Oczywiście, aby nasz Firewall był użyteczny, musimy selektywnie pozwolić niektórym pakietom, aby dotarły do naszej maszyny przez Internet. Są tutaj dwa podejścia do kwestii otwierania naszego Firewalla - pierwsza używa statycznych, druga dynamicznych zasad.

Tradycyjny Firewall  up


    Weźmy jako przykład ściąganą stronę WWW. Jeśli chcemy aby nasza maszyna mogła ściągać strony WWW z Internetu, możemy dodać statyczną zasadę, która zawsze będzie prawdziwa dla każdego pakietu przychodzącego przez protokół http, nie zważając na jego pochodzenie:
     iptables -A INPUT --sport 80 -j ACCEPT 
Od kiedy wszystkie standardowe pakiety HTTP oryginalnie poruszają się przez źródłowy port 80, ta zasada efektywnie pozwala naszej maszynie ściągać strony WWW. Ale to tradycyjne podejście, kiedy jest marginalnie akceptowane, powoduje powstawanie luk w zaporze.

Tradycyjny wózkowy Firewall  up

     Tutaj jest pewien problem: kiedy większość ruchu WWW oryginalnie przychodzi na port 80, niektóre pakiety HTTP tego nie robią. Przykład: widziałeś może taki URL jak ten http://www.foo.com:81 ? Wybierając ten URL, łączymy się na port 81 serwera HTTP, a nie na 80 i dana strona mogła by być nieosiągalna zza naszego Firewalla. Dodawanie wszystkich takich przypadków do naszego Firewalla szybko może obrócić nasz pierwotnie bezpieczny serwer w ser szwajcarski i szybko wypełnić nasz łańcuch INPUT mnóstwem zasad  używanych sporadycznie.
    Główny problem z tą zasadą dotyczy bezpieczeństwa. Oczywiście tylko ruch z 80 portu źródłowego będzie przepuszczany przez Firewall. Ale źródłowy port pakietu nie jest czymś, nad czym mamy jakąkolwiek kontrolę, i może być łatwo zmieniony przez włamywacza. Dla przykładu: jeśli włamywacz wiedział jak nasz Firewall został zaprojektowany, mógł łatwo przejść nasz Firewall przez proste upewnienie się, że wszystkie przychodzące od niego połączenia oryginalnie przychodzą z portu 80 na jedną z jego maszyn. Ponieważ ta statyczna zasada Firewalla jest bardzo łatwa do exploitowania, jest potrzebne bardziej dynamiczne podejście. Szczęśliwie iptables i kernel 2.4 ma wszystko co będzie potrzebne do ustawienia dynamicznego pełnoprawnego Firewalla.

Pełnowartościowy (dynamiczny) Firewall  up

     Zamiast otwierania dziur w naszym Firewallu bazującym na charakterystyce statycznego protokołu, możemy użyć nowej funkcjonalności Linuxa - śledzenia połączeń bazujących na dynamicznym statusie połączenia pakietu. Śledzenie działa przez monitorowanie każdego pakietu z indywidualnych jedno- lub dwukierunkowych komunikacyjnych kanałów albo połączeń. Na przykład, wyobraź sobie, co by się stało, gdybyś użył telnetu albo ssh, aby podłączyć się do zdalnej maszyny. Jeśli byś obserwował swój ruch sieciowy na poziomie pakietów, wszystko, co byś zobaczył to mnóstwo danych przepływających z jednej maszyny do drugiej. Na wyższym poziomie komunikacji ta wymiana pakietów jest dwukierunkowym kanałem pomiędzy Twoją lokalną maszyną i zdalną maszyną, tradycyjnie (staromodnie) Firewall patrzy tylko na indywidualne pakiety i nie rozpoznaje, że są one integralną częścią nawiązanego połączenia.

5. Właściwości Firewalla dynamicznego  up

Śledzenie połączeń (Conntrack)  up

     To jest technologia śledzenia połączeń wchodzących. Linuxowa funkcjonalność śledzenia może "zobaczyć" wyższy poziom połączenia, które nastąpiło. Może rozpoznać twoje połączenie SSH jako logiczną całość. Conntrack (śledzenie) może nawet rozpoznać pakiety UDP i ICMP, które są odpowiedzialne za logiczne "połączenia" nawet jeśli UDP i ICMP połączeniowymi z natury nie są. To jest bardzo pomocne, ponieważ pozwala nam użyć funkcjonalności Conntrack do nadzorowania wymiany pakietów ICMP i UDP. Jeśli już zrebotowales system i używasz nowego netfilter z nowego jądra, możesz przez napisanie: 
    cat /proc/net/ip_conntrack
 zobaczyć listę aktywnych połączeń, które Twoja maszyna obsługuje w danym momencie. Nawet jeśli Firewall nie jest skonfigurowany, Conntrack pracuje w tle, ciągle śledząc połączenia, w które jest zaangażowana Twoja maszyna.

Status pakietu  up

 NOWY (NEW) status połączenia  up

     Conntrack nie tylko rozpoznaje połączenia. Potrafi też klasyfikować każdy pakiet tak, że jest widziany jako jeden z czterech typów połączeń. Pierwszy typ, o którym będziemy mówić nazywany jest NOWY (NEW). Kiedy napiszesz:
     ssh remote.host.com
 inicjacyjny pakiet, albo grupa pakietów, która wychodzi z Twojej maszyny, i które są skierowane docelowo dla remote.host.com, są w stanie NOWY (NEW). Kiedy tylko otrzymasz choćby jeden pakiet w odpowiedzi z (tylko)  remote.host.com, wszystkie następne pakiety, które będą wysłane do remote.host.com jako część tego połączenia, nie będą już traktowane jako NOWE (NEW). Pakiet jest traktowany jako NOWY (NEW), kiedy jest zaangażowany w zestawienie nowego połączenia, i jeśli nie było żadnego ruchu przychodzącego ze zdalnego hosta (oczywiście jako część tego połączenia).

     Opisałem wychodzące NOWE (NEW) pakiety, ale jest również bardzo możliwe (i bardzo popularne), że mamy NOWE (NEW) pakiety przychodzące. Przychodzący NOWY (NEW) pakiet pochodzi głównie ze zdalnej maszyny (ale odkrycie - G.), i bierze udział w inicjalizacji połączenia z Twoją maszyną. Kiedy tylko odpowiesz na choćby jeden NOWY (NEW) przychodzący pakiet, każdy dodatkowy pakiet, który odbierzesz, i który jest związany z tym konkretnym połączeniem nie będzie więcej w stadium NOWY (NEW).

ESTABLISHED (połączony) status połączenia  up

     Kiedy tylko ruch w połączeniu nawiązany zostanie w dwóch kierunkach, dodatkowe pakiety związane z tym połączeniem będą traktowane jako ESTABLISHED (połączone). Ta różnica pomiędzy NEW i ESTABLISHED, jak zobaczymy za chwilę, jest bardzo ważna.

RELATED (powiązany)  up

    Trzeci stan połączenia jest nazwany RELATED (powiązany). Powiązane pakiety nie są tymi, które ustanawiają nowe połączenie, ale służą do obsługi innego obecnie występującego połączenia. Stan powiązany może być użyty do regulowania połączeń, które są częścią multi-połączenia w protokołach takich jak FTP,  albo jako błędne pakiety związane z istniejącymi połączeniami (np. pakiet błędu ICMP związany z obecnie występującymi połączeniami).

Stan INVALID (niepoprawny)  up

     Zdarzają się pakiety niepoprawne. Te pakiety nie mogą być zaklasyfikowane jako jedna z powyższych trzech kategorii. To jest bardzo ważne: jeśli pakiet jest zarejestrowany jako INVALID, nie jest automatycznie odrzucany, jest ciągle aktywny po to, aby wykorzystać poprawną zasadę i dynamicznie ustawić taktykę łańcuchową dzięki czemu mogą być odpowiednio traktowane.

Dodawanie bezpiecznych zasad  up

OK., teraz powinniśmy dobrze rozumieć śledzenie połączenia. Spójrzmy na pojedynczą zasadę, która przemienia nasz mało funkcjonalny Firewall w coś bardziej użytecznego:
     iptables -P INPUT DROP
     iptables -A INPUT -i ! eth1 -j ACCEPT 
     iptables -A INPUT -m --state ESTABLISHED,RELATED -j ACCEPT 

    Jak działa ta zasada? Pojedyncza zasada, kiedy jest włożona do naszego łańcucha INPUT, pozwoli nam utworzyć połączenia ze zdalnymi maszynami. Działa to następująco: powiedzmy, że chcemy się połączyć przez SSH do remote.host.com. Po napisaniu:
    ssh remote.host.com
nasza maszyna wysyła pakiet inicjujący połączenie. Ten konkretny pakiet jest w stanie NEW, i nasz Firewall pozwoli mu wyjść, ponieważ my blokujemy tylko pakiety przychodzące do naszego Firewalla, a nie wychodzące. Kiedy otrzymamy odpowiedź z remote.host.com, ten pakiet jest przepuszczany przez nasz łańcuch INPUT. Jeśli nie pasuje do pierwszej zasady (od kiedy przychodzi na eth1) jest przesuwany do następnej i końcowej zasady. Jeśli przychodzący pakiet pasuje do tej zasady, będzie zaakceptowany. Jeśli nie będzie pasować, przejdzie do końca łańcucha INPUT, a wtedy do pakietu zostanie zastosowana domyślna taktyka (DROP). W takim razie przychodzący pakiet będzie zaakceptowany czy odrzucony ?
    Odpowiedź: zostanie zaakceptowany. Kiedy kernel kontroluje przychodzący pakiet, sprawdza najpierw czy nie jest to część już istniejącego połączenia. Następnie kernel musi zadecydować, czy to jest nowy (NEW), czy połączony (ESTABLISHED) pakiet. Jeśli jest to przychodzący pakiet, sprawdza czy ma jakiś wychodzący ruch, i czy nie wysłaliśmy w związku z nim na zewnątrz naszego pakietu inicjującego (NEW) . Później przychodzący pakiet jest zakatalogowany jako połączony ( ESTABLISHED). Katalogowany jest również każdy następny pakiet, który my otrzymamy, albo który wyślemy, i który jest związany z tym połączeniem.
    Teraz zastanówmy się co się stanie, jeśli ktoś na zdalnej maszynie spróbuje połączyć się za pomocą SSH z naszym serwerem. Inicjacyjny pakiet, który otrzymamy, będzie sklasyfikowany jako nowy (NEW), i nie pokrywa się z zasadą 1, jest wiec przesuwany do zasady 2. Ponieważ ten pakiet nie jest sklasyfikowany jako ESTABLISHED albo RELATED, zostaje przesunięty na koniec łańcucha INPUT i będzie zastosowana domyślna taktyka bezpieczeństwa DROP. Nasz inicjacyjny pakiet SSH przychodzący jest odrzucony bez wysłania  jakichkolwiek informacji do klienta.

6. Prawie perfekcyjny Firewall  up

    Jakiego więc typu mamy Firewall jak na razie? Doskonały dla laptopa lub stacji roboczej - czyli w sytuacjach gdy nie chcesz, aby ktoś z Internetu podłączał się do Twojego PC, i gdy to Ty potrzebujesz połączyć się z globalną siecią. Będziesz mógł używać Netscape, Konquerora, FTP, ping, sprawdzić DNS i wiele innych. Każde połączenie, które zainicjujesz przejdzie z powrotem przez Firewall. Każde nieproszone połączenie, które przyjdzie z Internetu będzie upuszczone, chyba że odnosi się do istniejącego połączenia, lub takiego, które ty zainicjowałeś. Tak długo jak nie potrzebujesz udostępniać żadnych serwisów na zewnątrz ten Firewall będzie niemal perfekcyjny.

 Prosty skrypt Firewalla  up

 To jest prosty skrypt, który może być użyty do utworzenia naszego pierwszego Firewalla: 
#!/bin/bash
# Prosty Firewall dla stacji roboczej albo laptopa, który nie ma uruchomionych żadnych serwisów takich jak web serwer, 
#SMTP serwer, FTP serwer itp. 
    if [ "$1" = "start" ]; then
    echo "Startuję Firewalla..." 
    iptables -P INPUT DROP
    iptables -A INPUT -i ! eth1 -j ACCEPT
    iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT 
    elif [ "$1" = "stop" ]; then 
    echo "Zatrzymanie Firewalla..." 
    iptables -F INPUT iptables -P INPUT ACCEPT 
    fi 

Używanie skryptu  up

Możesz wyłączyć ten skrypt przez napisanie 
    ./firewall stop
 (uprzednio należy nadać atrybut +x plikowi firewall przez wydanie komendy chmod +x firewall) i włączyć go z powrotem przez :
    ./firewall start
Wyłączając Firewall czyścimy nasze zasady łańcucha INPUT przez:
    iptables -F INPUT
 i wtedy wyłączamy domyślna taktykę INPUT z powrotem do ACCEPT (akceptacja) z komendy:
     iptables -P INPUT ACCEPT
Teraz spójrzmy na garść ulepszeń, które zrobiliśmy w naszym Firewallu dla stacji roboczej. Raz wyjaśniłem każde ulepszenie, przedstawię końcową wersje Firewalla dla stacji roboczej. Wtedy zaczniemy tworzyć nasz Firewall dla serwerów. 

7. Ulepszenia.  up

Włączanie/wyłączanie w /proc  up

Explicity - wyłączenie ECN  up

Wcześniej wspomniałem, że ważne jest aby wyłączyć ECN (explicit congestion notification), więc połączenia internetowe będą działać poprawnie. Kiedy ty prawdopodobnie wyłączyłeś ECN w jądrze wedle mojej sugestii, jest możliwe, że w przyszłości zapomnisz tego zrobić, albo przekażesz swój skrypt Firewalla komuś, kto ma włączony ECN. Z tego powodu jest dobrym pomysłem użyć interfejsu /proc aby wyłączyć ECN jak poniżej:
     if [ -e /proc/sys/ipv4/tcp_ecn ]; then
     echo 0 > /proc/sys/net/ipv4/tcp_ecn
     fi

Przekazywanie - forwarding  up

    Jeśli używasz komputer z Linuxem jako ruter, powinieneś udostępnić IP forwarding, które da uprawnienia kernelowi na przeprowadzanie transmisji pomiędzy eth0 i eth1, i z powrotem. W naszym przykładzie, gdzie eth0 jest podłączone do LAN, a eth1 do Internetu, udostępnienie IP_forwardingu jest potrzebnym krokiem do udostępnienia połączeń naszego LANu z Internetem przez Linuxa. Żeby udostępnić IP forwarding użyj tej linii: 
    echo 1 > /proc/sys/net/ipv4/ip_forward

Odrzucanie połączeń  up

    Jak na razie, upuszczaliśmy cały nieproszony ruch przychodzący z Internetu. Jest to efektywny sposób powstrzymania nieproszonego ruchu z sieci. Powoduje to jednak trochę komplikacji. Największym problemem jest to, że nasza maszyna nie odpowiada na standardowy "TCP reset" i "ICMP port-unreachable response", kiedy odpowiedzią generowaną przez normalną maszynę jest  wysłanie z powrotem do inicjatora połączenia informacji o niepowodzeniu podłączenia do nie istniejącego serwisu.
    Zamiast wpuszczać potencjalnych intruzów, wiedzących że mamy Firewall (co to może być dla nich wskazówką, że może mamy uruchomione rożne serwisy, do których nie mogą się podłączyć), było by dobrze, gdybyśmy mogli udawać, że nie mamy uruchomionych żadnych serwisów. Przez dodanie tych dwóch zasad na końcu łańcucha INPUT możemy osiągnąć ten cel: 
    iptables -A INPUT -p tcp -i eth1 -j REJECT --reject-with tcp-reset
    iptables -A INPUT -p udp -i eth1 -j REJECT --reject-with icmp-port-unreachable

Pierwsza zasada zajmuje się poprawnym zamykaniem TCP, podczas gdy druga obsługuje UDP. Z tymi dwiema zasadami intruzowi jest bardzo ciężko wykryć, że mamy Firewall.  W większości przypadków spowoduje to, że intruz zostawi naszą maszynę i poszuka inne - z większą możliwością nadużycia.
     Budowanie naszego Firewalla jako "cichego" (stealthy) eliminuje także opóźnienia związane z połączeniem się z pewnymi serwerami, np. FTP i IRC. To opóźnienie jest powodowane przez czas oczekiwania  (około 15 sec) serwera sprawdzającego identa na Twojej maszynie (połączenie na port 113) i ewentualnie  przekroczenie tego czasu, gdy usługa identd (auth) nie jest uruchomiona, lub gdy jest uruchomiona nieprawidłowo. Teraz nasz Firewall zwróci TCP reset i sprawdzanie identa zakończy się błędem (chyba, że identd działa prawidłowo) natychmiastowo - bez oczekiwania 15 sekund (kiedy ty (nie)cierpliwie czekasz na odpowiedź z serwera) .

Zabezpieczenie przed podszywaniem się (spoofing)  up

     W wielu dystrybucjach, kiedy sieciowe interfejsy są podnoszone, wiele starych zasad ipchains jest również dodawanych do systemu. Te specjalne zasady były dodane przez developerów tworzących dystrybucje, żeby rozwiązać problem podszywania się (gdy źródłowy adres pakietu został podmieniony). Możemy stworzyć podobną tablicę zasad iptables, która również będzie blokować podszyte pakiety. Jest to również łatwiejsza droga. Obecnie kernel ma wbudowaną możliwość upuszczenia podszytych pakietów. Wszystko co potrzebujemy, to uaktywnić to przez interfejs /proc. Tutaj jak to zrobić:

     for x in lo eth0 eth1
     do echo 1 > /proc/sys/net/ipv4/conf/${x}/rp_filter
     done

 Ten skrypt shella, powie kernelowi żeby upuścił każdy podszyty pakiet na interfejsach lo, eth0, eth1. Możesz dodać te linie do twojego skryptu z Firewall, albo dodać je do skryptu, który podnosi lo, eth0, eth1.

Maskarada, NAT i  SNAT  up

 NAT (network address translation) i IP masquarada nie są właściwie bezpośrednio połączone z Firewallem, ale często są używane w połączeniu z nim. Przyjrzymy się dwóm popularnym konfiguracjom NAT/masquarade, które mogą Ci się przydać. Ta pierwsza zasada może zaopiekować się sytuacją, kiedy masz połączenie dial-up z Internetem (ppp0), i która używa dynamicznych IP:
     iptables -t nat -A POSTROUTING -o ppp0 -j MASQUARADE

 Jeśli jesteś w tej sytuacji, będziesz chciał również przekonwertować mój skrypt Firewalla tak, że wszystkie odnośniki do "eth1" (w naszym przypadku ruter DSL) będą zmienione na "ppp0". Dozwolone jest dodanie do zasad Firewalla linii, która odnosi się do "ppp0" nawet kiedy ppp0 jeszcze nie istnieje. Jak tylko się pojawi ppp0, wszystko zacznie działać poprawnie. Upewnij się ze uaktywniłeś IP forwarding.

    Jeśli używasz DSL do połączenia się z Internetem, prawdopodobnie masz jedną z dwóch możliwych konfiguracji. Pierwsza możliwość: twój ruter DSL, albo modem ma własny numer IP i przeprowadza tłumaczenie adresów dla Ciebie. Jeśli jesteś w tej sytuacji, nie potrzebujesz aby Linux przeprowadzał NAT, ponieważ DSL już się tym zajął. Jeśli chcesz mieć więcej kontroli nad funkcjonalnością NAT, możesz spróbować porozmawiać (loool ;] życzę powodzenia ) z twoim ISP (dostawca - oprawca) w sprawie konfiguracji twojego połączenia DSL, tak że DSL-ruter będzie pracował w trybie "bridge mode" (połączenie mostowe). W "bridge mode" twój Firewall stanie się oficjalną częścią sieci twojego ISP. DSL-ruter będzie "przeźroczyście" przekazywał ruch IP w obu kierunkach między twoim ISP i twoim komputerem z Linuxem. Jeśli ktoś spinguje twój IP z Internetu, otrzyma odpowiedź od Twojego komputera z Linuxem, a nie od twojego rutera DSL.

     W tym przypadku będziesz raczej wolał użyć SNAT (source NAT - źródłowy NAT) niż maskarady. To jest linia, jaką powinieneś dodać do Firewalla:
             iptables -t nat -A POSTROUTING -o eth1 -j SNAT --to 1.2.3.4

W tym przykładzie eth1 powinien być zmieniony na interfejs sieciowy bezpośrednio podłączony do rutera DSL, i numer 1.2.3.4 na stały numer IP (IP twojego interfejsu sieciowego). Pamiętaj o udostępnieniu IP forwardingu.

 NAT - zagadnienia  up

     Szczęśliwie dla nas, NAT i maskarada współpracują bardzo dobrze z Firewallem. Kiedy piszesz zasady twojego Firewalla, po prostu zignoruj fakt ze używasz NAT. Twoje zasady powinny zaakceptować, upuścić, albo odrzucić pakiety bazujące na ich "realnym" źródle i adresie docelowym. Źródło filtra Firewalla widzi oryginalny źródłowy adres pakietu i miejsce docelowe. To jest bardzo wygodne dla nas, ponieważ pozwala pracować poprawnie naszemu Firewallowi nawet jak tymczasowo wyłączymy NAT'a albo maskaradę.

Tabele  up

     W powyższym przykładzie NAT/maskarada, dodaliśmy zasady do łańcucha, ale również zrobiliśmy coś innego. Zauważyłeś opcje "-t"? Pozwala ona specyfikować tabele, do której przynależy nasz łańcuch. Kiedy jest pominięta, domyślna tablica dla "filtra". Wiec nasze poprzednie komendy nie związane z NAT modyfikowały łańcuch INPUT, który jest częścią tablicy "filter". Tablica "filter" zawiera wszystkie zasady związane z akceptowaniem albo odrzuceniem pakietu, natomiast tablica "NAT" zawiera zasady związane z tłumaczeniem adresów sieciowych. Tam są również inne wbudowane łańcuchy iptables i są one opisane w MAN iptables, jak również w Rusty's HOWTOs (zobacz źródła na końcu tego tutoriala, aby dobrać się do linków). 

Uzupełniony skrypt  up

     Teraz spójrzmy na kilka możliwych ulepszeń. To jest bardziej elastyczny i bardziej wydajny skrypt:
 firewall włączony/wyłączony :
#!/bin/bash 
# Ulepszony skrypt poręcznego Firewalla dla stacji roboczej, laptopa albo rutera, który nie ma udostępnionych żadnych serwisów jak web serwer, 
#SMTP serwer,  serwer FTP  itp. 
# Zmień tą nazwę na interfejs, który daje Ci połączenie do Internetu "uplink" 
    UPLINK="eth1" 
# Jeśli ta maszyna to jest ruter ( i to powinno przekazywać IP pakiety pomiędzy interfejsami) 
# wtedy chcesz powiedzieć ROUTER="yes"; w innym wypadku powiedz ROUTER="no" 
    ROUTER="yes" 
# zmień linie dla statystycznego interfejsu IP, który łączy Cię z Internetem dla SNAT "dynamic" jeśli masz dynamiczny numer IP. Jeśli nie potrzebujesz żadnego 
# NAT, ustaw NAT do "" żeby go wyłączyć. 
    NAT="1.2.3.4" 
# zmień następna linię dodając wszystkie interfejsy sieciowe, włączając lo 
    INTERFACES="lo eth0 eth1" if [ "$1" = "start" ];
    then echo "Startuje Firewall..." 
    iptables -P INPUT DROP
    iptables -A INPUT -i ! ${UPLINK} -j ACCEPT 
    iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
    iptables -A INPUT -p tcp -i ! ${UPLINK} -j REJECT --reject-with tcp-reset
    iptables -A INPUT -p udp -i ! ${UPLINK} -j REJECT --reject-with icmp-port-unreachable 
#wyłączenie ECN 
    if [ -e /proc/sys/net/ipv4/tcp_ecn ]; then 
    echo 0 > /proc/sys/net/ipv4/tcp_ecn fi 
# wyłączenie spoofowania na wszystkich interfejsach
     for x in ${INTERFACES}
    do echo 1 > /proc/sys/net/ipv4/conf/${x}/rp_filter 
    done
#jeżeli jesteśmy ruterem, włączenie IP forwarding
    if [ "$ROUTER" = "yes" ]; then  
    echo 1 > /proc/sys/net/ipv4/ip_forward
    if [ "$NAT" = "dynamic" ]; then 
#dynamiczne adresy IP, używanie maskarady 
    echo "Udostępnienie maskarady (dynamiczne IP)..." 
    iptables -t nat -A POSTROUTING -o ${UPLINK} -j MASQUERADE 
    elif [ "$NAT" != "" ]; then 
#statyczny IP, używacie NAT 
    echo "Odblokowanie SNAT (statyczny IP)..." 
    iptables -t nat -A POSTROUTING -o ${UPLINK} -j SNAT --to ${UPIP}
    fi
    fi
    elif [ "$1" = "stop" ]; then
    echo "Zatrzymanie Firewall..." 
    iptables -F INPUT 
    iptables -P INPUT ACCEPT 
#wyłączenie NAT'a/maskarady, jeśli jest jakaś 
    iptables -t nat -F POSTROUTING 
    fi

Przeglądanie zasad  up

     Zanim zaczniemy modyfikować nasz Firewall tak, żeby mógł być użyty na serwerze, musze pokazać Ci, jak wylistować obecnie aktywne zasady Twojego Firewalla. Żeby zobaczyć zasady tabel łańcucha INPUT napisz:
     iptables -v -L INPUT 
Opcja -v daje nam verbose output( siaraX: "wielomowny?!", GrZeNiU: "eeetam, raczej gadatliwy:-> ")  
Możemy więc zobaczyć sumę pakietów i bajtów, które przeszły przez każdą definicje zasady. Możemy również spojrzeć na naszą tabelę NAT POSTROUTING przez następującą komendę: 
     iptables -t nat -v -L POSTROUTING Chain POSTROUTING (policy ACCEPT 399 packets, 48418 bytes) pkts bytes target prot opt in out source destintion 2728 170K SNAT all -- any eth1 anywhere anywhere

    Obecnie nasz Firewall nie pozwala internautom, aby połączyli się z jakimś serwisem na naszej maszynie, ponieważ  akceptuje tylko przychodzące pakiety ESTABLISHED oraz RELATED. Skoro upuszcza każdy przychodzący NEW (Nowy) pakiet, każda próba jest od razu odrzucana. Selektywnie zezwalając wybranym klientom łączyć się z naszym Firewallem (lub przez nasz Firewall), możemy udostępniać im potrzebne serwisy i zapewnić sobie maksymalną kontrolę nad ruchem pakietów.

HTTP  up

     Kiedy chcemy zaakceptować jakiekolwiek przychodzące połączenia, prawdopodobnie niektóre będziemy chcieli odrzucić. Rozpoczęcie konfiguracji Firewalla od ustalenia taktyki "REJECT by default" (zabronione jako domyślne) i otwierania tylko tych serwisów, do których byśmy chcieli dopuścić tylko wybranych klientów jest najmądrzejszym i najbezpieczniejszym podejściem. Na przykład, jeśli mamy uruchomiony WEB serwer, pozwolimy przychodzić (NEW) nowym pakietom do naszej maszyny tak długo, jak długo będą łączyć się z portem 80 (HTTP).  Jak raz  pozwolimy nowym (NEW) pakietem wejść, pozwolimy aby połączenie nastąpiło. Teraz, kiedy połączenie nastąpiło, nasza istniejąca zasada pozwalająca przychodzić ESTABLISHED i RELATED "zasysa" kolejne, związane z tym połączeniem pakiety do środka pozwalając połączeniu HTTP kontynuować się bez żadnych problemów.

Przykład bezpiecznego HTTP  up

 Spójrzmy na "serce" naszego Firewalla: nowe zasady dopuszczają przychodzące połączenia HTTP:
     iptables -P INPUT DROP
     iptables -A INPUT -i ! ${UPLINK} -j ACCEPT
     iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# oto nasza nowa zasada:
     iptables -A INPUT -p tcp --dport http -m state --state NEW -j ACCEPT 
     iptables -A INPUT -p tcp -i ${UPLINK} -j REJECT --reject-with tcp-reset
     iptables -A INPUT -p udp -i ${UPLINK} -j REJECT --reject-with icmp-port-unreachable
 Ta nowa zasada pozwala nowym (NEW TCP) pakietom TCP celującym w naszą maszynę na port 80 (http) na przejście przez Firewall. Zauważ miejsce, gdzie została dodana zasada. To jest ważne, że zasada pojawia się przed naszą zasadą REJECT. Iptables używa pierwszej pasującej zasady, i wstawienie jej za REJECT mogło by spowodować, że linia nie odniosła by spodziewanego skutku.

Nasz końcowy skrypt Firewalla  up

 Spójrzmy teraz na nasz końcowy skrypt Firewalla, który może być użyty na laptopie, stacji roboczej, ruterze, albo serwerze (albo kombinacja powyższych):
#!/bin/bash 
# zmień tą nazwę na interfejs, jaki łączy Ciebie z Internetem "uplink" 
    UPLINK="eth1" 
# Jeśli ta maszyna jest ruterem ( i powinna przesyłać pakiety pomiędzy interfejsami ) powinieneś powiedzieć ROUTER="yes" w innym wypadku "no"     
    ROUTER="yes" 
# zmień tą linie na statyczny adres IP z twojego interfejsu; dla statycznego SNAT 
# "dynamic" jeśli masz dynamiczny IP. Albo jeśli nie potrzebujesz NAT zmień na "" żeby wyłączyć NAT'a 
    NAT="1.2.3.4" 
# Zmień następną linię tak, żeby ująć wszystkie interfejsy sieciowe włączając lo 
    INTERFACES="lo eth0 eth1" 
# zmień poniższa linię tak, żeby były wymienione wszystkie numery albo symbole ( z /etc/services) wszystkich serwisów, które chcesz udostępnić 
# dla internautów. Jeśli nie chcesz żadnych serwisów wyłącz je przez "" 
    SERVICES="http ftp smtp ssh rsync" 
    if [ "$1" = "start" ]; then 
    echo "Startowanie Firewall..." 
    iptables -P INPUT DROP
     iptables -A INPUT -i ! ${UPLINK} -j ACCEPT
     iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT 
#dopuszcza internautów do wybranych serwisów
     for x in ${SERVICES}
     do
     iptables -A INPUT -p tcp --dport ${x} -m state --state NEW -j ACCEPT
     done
     iptables -A INPUT -p tcp -i ${UPLINK} -j REJECT --reject-with tcp-reset
     iptables -A INPUT -p udp -i ${UPLINK} -j REJECT --reject-with icmp-port-unreachable 
#wyłączenie ECN
     if [ -e /proc/sys/net/ipv4/tcp_ecn ]; then 
    echo 0 > /proc/sys/net/ipv4/tcp_ecn 
    fi 
#wyłączenie spoofowania na wszystkich interfejsach 
    for x in ${INTERFACES} 
    do 
    echo 1 > /proc/sys/net/ipv4/conf/${x}/rp_filter
    done
     if [ "$ROUTER" = "yes" ]; then
 #jeśli jesteśmy ruterem, włącz IP forwarding 
    echo 1 > /proc/sys/net/ipv4/ip_forward
     if [ "$NAT" = "dynamic" ]; then
 #Dynamiczny IP, użycie maskarady 
    echo "Włączenie maskarady (dynamiczny ip)..." 
    iptables -t nat -A POSTROUTING -o ${UPLINK} -j MASQUERADE 
    elif [ "$NAT" != "" ]; then 
#statyczny IP używa SNAT 
    echo "Włączenie SNAT (statyczny IP)..."
     iptables -t nat -A POSTROUTING -o ${UPLINK} -j SNAT --to ${UPIP}
     fi
     fi 
    elif [ "$1" = "stop" ]; then 
    echo "Zatrzymanie Firewalla..." 
    iptables -F INPUT 
    iptables -P INPUT ACCEPT 
#wyłączenie NAT/maskarady jeśli jest 
    iptables -t nat -F POSTROUTING
    fi 

8. Dodatki  up

 Jest możliwe, aby Firewall był troszeczkę lepszy. Co znaczy "lepszy", zależy od Twoich specyficznych potrzeb i cierpliwości we wdrażaniu i testowaniu zasad. Nasz obecny skrypt mógł odpowiadać Twoim wymaganiom, ale trochę dodatkowych zmian jest wymagane. Ta sekcja jest jak "książka kucharska" z pomysłami, i demonstruje jak ulepszyć Twój obecny skrypt Firewalla.

Logowanie  up

    Jak zarazie, nie przedyskutowaliśmy sposobu logowania czegokolwiek. Jest specjalny cel nazwany LOG, który możesz użyć do tego celu. Jest też specjalna opcja dla LOG: "--log-prefix", która pozwala wyspecyfikować część tekstu, który będzie się pokazywał razem z pakietami zrzuconymi do loga systemowego. Tutaj jest przykład zasady loga:
     iptables -A INPUT -j LOG --log-prefix "bad input:"

Raczej nie chcesz dodać tego jako pierwszej linii twojego łańcucha INPUT, gdyż mógł by spowodować logowanie każdego pakietu, jaki otrzymasz! Zamiast tego umieść tą zasadę poniżej w łańcuchu INPUT, aby logować tylko dziwne pakiety i inne anomalie.
     Ważna informacja na temat celu LOGa: normalnie, kiedy zasada odpowiada, pakiet jest albo akceptowany, odrzucony, albo upuszczony i nie są wykonywane żadne inne zasady. Kiedy zasada LOG'a pasuje, pakiet jest logowany niezależnie, czy jest zaakceptowany, odrzucony czy upuszczony. Pakiet jest przesuwany do następnej zasady, albo domyślna taktyka łańcucha zostaje zastosowana, jeżeli zasada LOG'a jest ostatnią zasadą w łańcuchu. Cel LOG'a może być również skrzyżowany z modułem "limit" (opisanym na stronie podręcznika man iptables), aby zminimalizować duplikaty logowanych zdarzeń. Tutaj jest przykład:     
    iptables -A INPUT -m state --state INVALID -m limit --limit 5/minute -j LOG -- ?????


Taktyka sieciowa  up

    Firewall oferuje mnóstwo możliwości dla tego kto chce ulepszyć taktykę sieciowego bezpieczeństwa dla firmowej albo akademickiej sieci LAN. Możesz kontrolować jakie pakiety Twoja maszyna przekazuje przez dodanie zasady i ustawienie taktyki dla łańcucha FORWARD. Przez dodawanie zasad to łańcucha OUTPUT możesz kontrolować również, co dzieje się z pakietami, które są generowane (tworzone) lokalnie przez użytkownika na maszynie z Linuxem. Iptables ma również niesamowite możliwości filtrowania lokalnie tworzonych pakietów bazując na właścicielu (uid albo gid). Jak chcesz więcej informacji na ten temat szukaj w stronie podręcznika man pod opcją "owner".

Jeszcze jedno...  up

     W naszym przykładowym Firewallu, założyliśmy, że cały ruch w sieci lan jest zaufany/bezpieczny i tylko przychodzący internetowy ruch musi być dokładnie monitorowany. Zależnie od Twojej sieci może to być lub może nie być słuszne. Nie ma oczywiście nic, co może cię powstrzymać (poza szefem ;) ) żebyś skonfigurował Twój Firewall tak aby zabezpieczyć się od przychodzącego ruchu z LAN'u. Potwierdzając inne "angles" z twojej sieci, które chcesz ochronić. Możesz również skonfigurować dwie oddzielne strefy LAN; każda ze swoją własną taktyką bezpieczeństwa. 


 9. Zasoby/Źródła  up


Colophon (cokolwiek to znaczy) Ten tutorial został napisany całkowicie w XML (no teraz to jest w HTML-u - od tłumacza), używając developerWorks Toot-O-Matic tutorial generator. Narzędzie Toot-O-Matic jest krótkim programem w Javie, który używa XSLT stylesheet aby przekonwertować źródło XML w strony HTML albo plik zip, jpg headings grafikę, i pliki PDF. ......