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)
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 |
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.
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.
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.
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.
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).
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.
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
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
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
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.
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ę.
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).
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
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.
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.
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
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.
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 -- ?????
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".
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