====== Filtracja pakietów w systemie Linux ====== ===== nefilter, iptables i nftables ===== **[[http://pl.wikipedia.org/wiki/Netfilter|Netfilter]]** to część jądra systemu operacyjnego Linux zbierająca funkcje kontroli ruchu sieciowego. Do konfiguracji mechanizmów kernela składających się na netfilter służą [[https://upload.wikimedia.org/wikipedia/commons/d/dd/Netfilter-components.svg|programy]]: - **''iptables''**, **''ip6tables''**, ''ebtables'', ''arptables'' (starsze) - **''nft''** (nowszy) [[http://netfilter.org/|Netfilter project]] jest zbiorem projektów związanych z frameworkiem do filtrowania pakietów, w tym ''iptables'' i ''nftables''. ==== [ekstra] iptables-…, nft ==== Po stronie jądra istnieją (przynajmniej) dwa mechanizmy do filtrowania pakietów – starszy ''xtables'' i nowszy ([[https://wiki.nftables.org/wiki-nftables/index.php/What_is_nftables%3F#Why_nftables?|i lepszy]]) ''nftables''. "Stare" ''iptables'', często dostępne teraz jako ''iptables-legacy'' umie wykorzystać tylko pierwszy z tych mechanizmów. \\ Do użycia nowego mechanizmu zachowując bez zmiany składni i działania poleceń przygotowano nową implementację komendy ''ipables'', wcześniej dostępną jako ''ipables-nft'', teraz często już jako ''iptables''. \\ Narzędzie ''nft'' konfiguruje nowszy z mechanizmów jądra. Nie zaleca się mieszania konfiguracji programów ''iptables-legacy'', ''ipables-nft'' i ''nft''. ''iptables…'' konfiguruje tylko protokół IPv4, IPv6 jest konfigurowane przez bliźniacze ''ip6tables…''. \\ ''nft'' pozwala na jednoczesną konfigurację obu tych protokołów (tabele ''inet''). Na razie polecenie ''nft'' ma pozostawiającą wiele do życzenia dokumentację, nieprzyjazne komunikaty o błędach składni polecenia i brak wbudowanej w komendę pomocy i brak bądź wysoce niekompletne autouzupełnianie. Z tego powodu na zajęciach jest wciąż pokazywane narzędzie ''iptables''. ==== Hooki, tabele, łańcuchy ==== Podczas przejścia pakietu przez jądro Linuksa wykonywane są w ściśle określonej kolejności [[http://en.wikipedia.org/wiki/Hooking|hooki]] decydujące co zrobić z pakietem. Każdemu hookowi odpowiada jeden **łańcuch** reguł (**chain**). Łańcuch reguły to wiele reguł które przetwarzane są **w kolejności** – jeśli któraś reguła zdecyduje o losie pakietu, późniejsze nie są brane pod uwagę. Łańcuchy są pogrupowane w **tabele** (**table**) pod względem funkcjonalności. \\ W ''iptables'' / ''ip6tables'' dostępne są następujące tabele:
* **filter** – odrzuca niechciane pakiety, * **nat** – zmienia adresy źródłowe lub docelowe pakietu, * mangle – modyfikuje pakiety, * raw – udostępnia pakietów przed ich przetworzeniem przez część kernela (np. conntrack), * security – używana przy zaawansowanych modelach bezpieczeństwa w Linuksie (np. SELinux). Łańcuchy mają nazwy odpowiadające momentowi ich wywołania:
* **PREROUTING** jest wykonywany dla pakietów przychodzących //przed routingiem// (czyli decyzją czy pakiet jest kierowany do tego komputera, czy należy go przesłać dalej lub odrzucić), * **INPUT** jest wykonywany dla pakietów //prz__**y**__chodzących// skierowanych do tego komputera, * **FORWARD** jest wykonywany dla pakietów //prz__**e**__chodzących//, tj. pakietów ze świata, które mają być wysłane dalej, * **OUTPUT** jest wykonywany dla pakietów wyprodukowanych na tym komputerze (//wychodzących//), * **POSTROUTING** jest wykonywany dla pakietów wychodzących po podjęciu decyzji gdzie je wysłać.
Można też tworzyć własne łańcuchy, ale mogą one być uruchomione tylko przez dołączenie ich do już istniejących. Droga pakietu przez mechanizmy filtrujące w systemie Linux podsumowana jest tutaj: **[[https://pl.wikipedia.org/wiki/Plik:Netfilter-packet-flow-pl.svg|[PL]]]** **[[https://commons.wikimedia.org/wiki/File:Netfilter-packet-flow.svg|[EN]]]**. ==== Stanowość i bezstanowość – conntrack ==== Jądro Linuksa jest zaopatrzone w mechanizm śledzenia połączeń (conntrack). Pozwala on dla rozpatrywanego pakietu określić czy wcześniej przez ten komputer był przepuszczony inny pakiet z tego samego połączenia, a nawet czy któryś z wcześniejszych pakietów jest powiązany z rozpatrywanym. \\ Taka wiedza nie tylko ułatwia konfigurację filtracji pakietów, ale też jest konieczna do obsługi niektórych często występujących scenariuszy. ==== [Ekstra] Trwałość reguł (persistance) ==== Iptables nie dostarcza mechanizmu automatycznego zapisywania ustawień – po ponownym uruchomieniu lista reguł jest pusta, a polityki domyślne. Dla odtworzenia reguł przy starcie dystrybucje Linuksa dostarczają odpowiedni skrypt startowy. Zwykle zapisanie reguł odbywa się ręcznie (tj. trzeba wydać odpowiednią komendę). ===== Komendy ===== Komenda ''iptables'' / ''ip6tables'' wszędzie **rozróżnia wielkie i małe litery**, ponadto **kolejność argumentów** decyduje o zrozumieniu polecenia. \\ Składnia ''iptables'' i ''ip6tables'' jest identyczna, w materiałach dla uproszczenia wszędzie użyte są przykłady dla ''iptables'' i IPv4. Wyświetlanie listy reguł:
* ''iptables [-t filter] -L [-n]'' – **wypisanie** (''--list'') **tablicy filtracji** \\ * ''iptables -t -L [-n]'' – wypisanie innych tablic \\ * ''iptables [-t ] --line-numbers -L'' – dodaje **numery reguł** Wzorce poleceń modyfikujących działanie filtracji i dodających reguły filtaracji: * ''iptables [-t filter] -P <łańcuch> '' – zmiana **domyślnego zachowania** (tj. jeśli żadna z reguł nie podejmie decyzji). Zwykle stosowane polityki to ''ACCEPT'' lub ''DROP''. Przykład: \\ ''iptables -P INPUT DROP'' – ignoruje pakiety przychodzące * ''iptables -A <łańcuch> '' – **dodaje** regułę do łańcucha (''--append''), np: \\ ''iptables -A INPUT -s 1.2.3.4 -j ACCEPT'' * ''iptables -I <łańcuch> [pozycja] '' – **wstawia** (''--insert'') regułę **na podane miejsce** do łańcucha (lub na początek jeśli numeru nie podano), np: \\ ''iptables -I INPUT 1 -s 1.2.3.4 -j ACCEPT'' * ''iptables -D <łańcuch> '' – **usuwa** (''--delete'') regułę na podanej pozycji z łańcucha, np: \\ ''iptables -D INPUT 2'' * ''iptables -D <łańcuch> '' – **usuwa** (''--delete'') regułę z łańcucha, np: \\ ''iptables -D INPUT -s 1.2.3.4 -j ACCEPT'' * ''iptables -F [łańcuch]'' – usuwa wszystkie reguły [z łańcucha] (''--flush''); wysoce niebezpieczne Zwykle reguły w ''iptables'' są zakończone akcją:
* **''-j ACCEPT''** – przepuszcza pakiet * **''-j DROP''** – ignoruje (wyrzuca do śmieci) pakiet * **''-j REJECT''** – dodatkowa akcja, symuluje zamknięte gniazdo (wysyła ICMP //destination unreachable//)
Są też dostępne inne akcje, np. ''LOG'', ''MARK'' i ''SET''. Więcej szczegółow w ''man iptables-extensions'' Rdzeń ''iptables'' zawiera niewiele filtrów:
- źródłowy i docelowy adres – ''-s'' i ''-d'', - źródłowy i docelowy interfejs – ''-i'' i ''-o'', - protokół – ''-p''
Filtry można **negować przez użycie '!'** (wykrzyknika) Netfilter jest modularny – większość funkcji mieści się w **rozszerzeniach**, ładowanych przez ''-m '' \\ To pozwala na bardzo szczegółową filtrację. **Komendy ''iptables'' i ''ip6tables'' opisane są w podręczniku systemowym na stronie //iptables// (''[[https://man7.org/linux/man-pages/man8/iptables.8.html|man iptables]]''), a rozszerzenia do tych komend są opisane na stronie //iptables-extensions// (''[[https://man7.org/linux/man-pages/man8/iptables-extensions.8.html|man iptables-extensions]]'').** Przykładowe rozszerzenia:
* ''-m tcp/udp'' jest **automatycznie** ładowany razem z ''-p udp/tcp''; pozwala ustalić m. inn. port źródłowy i docelowy ''--sport / --dport'', * ''-m conntrack'' wybiera stan połączenia ''--ctstate'', m. inn.: ''INVALID,NEW,ESTABLISHED,RELATED'', * ''-m comment'' pozwala na dowolny komentarz ''--comment '', * ''-m limit'' dzięki ''--limit'' ogranicza ilość pakietów na jednostkę czasu, * ''-m hashlimit'' pozwala m. inn. ustawić limit pakietów/czas dla każdego IP z osobna, * ''-m time'' pozwala włączyć regułę o ''--datestart'' i wyłączyć o ''--datestop'', * ''-m u32'' udostępnia ''--u32'' wykonujący dowolny test na danych pakietu, * ''-m connlimit'' używając ''--connlimit-above'' pozwala ograniczyć ilość połączeń z jednego adresu. ''iptables'' ma rozbudowaną pomoc wewnętrzną – po napotkaniu ''--help'' przerwie dodawanie reguły i pokaże listę opcji, np.: \\ ''iptables -I INPUT -p tcp --help'' \\ ''iptables -m hashlimit -m limit -m connlimit --help'' ''iptables-save'' oraz ''iptables-restore'' są używane do zapisu/odczytu tablic do pliku. ==== Filtracja pakietów ==== === Filtracja na wejściu === Najczęściej stosowana do wpuszczania tylko pożądanego ruchu. \\ Typowe podejście to zabronienie wszystkiego, co nie jest wprost dozwolone. Przykładowe polecenia: \\ ''iptables -P INPUT DROP'' – ustawienie domyślnej akcji wybieranej jeśli żadna z reguł nie zadziała \\ ''iptables -A INPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT'' – pozwala na ruch lokalny \\ ''iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT'' – pozwala przychodzić pakietom nawiązanych wcześniej połączeń \\ ''iptables -A INPUT -p tcp --dport 22 -j ACCEPT'' – pozwala na dostęp do ssh === Filtracja pakietów przechodzących === Decyduje jaki ruch może przechodzić przez komputer. Podejście do reguł zależy od zastosowania. Przykładowe polecenia: \\ ''iptables -A FORWARD -m connlimit --connlimit-above 5 -j DROP'' – pozwala na nie więcej niż 5 połączeń przechodzących od każdego nadawcy === Filtracja na wyjściu === Służy do wypuszczania tylko pożądanego ruchu. Typowe podejście to blokowanie niepożądanego ruchu. Przykładowe polecenia: \\ ''iptables -A OUTPUT -p tcp --dport bnetgame -j REJECT'' – odrzuca połączenia na port "Battle.net Chat/Game Protocol" \\ ''iptables -A OUTPUT -p tcp -d %%www.google.pl%% -j DROP; ip6tables -A OUTPUT -p tcp -d %%www.google.pl%% -j DROP'' – blokuje próby połączenia z %%www.google.pl%% (Uwaga: iptables wypyta DNS o adresy IP i doda reguły z adresami IP, nie z nazwą) \\ ''iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT'' – pozwala na używanie http === Liczniki === iptables liczy ilość i rozmiar pakietów które dopasowały się do każdej reguły. Można:
* ''iptables -v [-x] -L'' – wyświetlić listę reguł z uwzględnieniem liczników * ''iptables -Z [co zerować]'' – wyzerować stan liczników – wszystkich lub wybranego łańcucha / reguły **[[sk1:nf_fw|Filtracja pakietów w systemie Linux - ćwiczenia]]** [[iptables-filter-asciinema|Przykładowe komendy iptables ustawiające filtrację i ich działanie]] ==== Manipulowanie pakietami ==== Przykłady na manipulację pakietami: \\ ''iptables -t mangle -A POSTROUTING -o wlan0 -j TTL --ttl-set 1'' \\ ''iptables -t mangle -A PREROUTING -i wlan0 -j TTL --ttl-inc 16'' \\ ''iptables -t mangle -A PREROUTING -i wlan0 -j TEE --gateway 10.0.0.3'' \\ ''iptables -t mangle -A POSTROUTING -p tcp --sport 5222 -j TOS --set-tos Minimize-Delay'' \\ ===== NAT (Network Address Translation) – translacja adresów ===== Ze względu na niewystarczającą ilość adresów IPv4 zwykle komputery w sieciach lokalnych używają adresów //z bloków prywatnych//. Na wiadomość z takiego komputera – wysłaną z adresem źródłowym z bloku adresów prywatnych – odbiorca nie ma szansy odpowiedzieć (bo gdzie miałby?). Routery z publicznym IP powinny automatycznie wycinać takie wiadomości [[https://tools.ietf.org/html/rfc1918|RFC 1918, str. 5]]. Dlatego konieczne jest by na styku adresacji prywatnej i publicznej adresy były tłumaczone, stąd nazwa //NAT// = //Network Address Translation//. Ruch generowany przez komputery z wewnątrz sieci lokalnej musi mieć zmieniony adres źródłowy (source address), stąd nazwa //Source NAT// (//SNAT//). Tradycyjnie adresy źródłowe zmienia się w momencie kiedy pakiet opuszcza system. Jeśli zachodzi konieczność by ruch z sieci publicznej trafiał do komputera wewnątrz sieci lokalnej, trzeba zmienić adres docelowy (destination address), stąd nazwa //Destination NAT// (//DNAT//). Naturalnie urządzenie na styku sieci musi zmienić adres zanim podejmie decyzję o routingu (tj. decyzję gdzie pakiet ma trafić). ++++ Ilustracja do NATów |
{{:sk1:nat.svg|}} SNAT:
- PC1 chce wysłać pytanie DNS pod jakim adresem znajdzie serwer put.poznan.pl - PC1 adresuje wiadomość: * w polu odbiorcy wpisuje 1.1.1.1 (znany adres serwera DNS) * w polu nadawcy wpisuje 192.168.0.2 (swój adres IP) - PC1 wysyła wiadomość przez bramę domyślną - router R1, adres 192.168.0.1 - R1 wybiera trasę dla pakietu (wykonuje routing) i kieruje pakiet w stronę internetu - R1 po wykonaniu trasowania (POSTROUTING) dokonuje **translacji adres źródłowego**: \\ zamienia adres źródłowy z 192.168.0.2 na 93.184.216.34 - R1 wysyła wiadomość w intenet - Serwer DNS (pod adresem 1.1.1.1) dostaje wiadomość adresowaną do niego z adresu 93.184.216.34 i odpowiada na nią adresując ją: * od 1.1.1.1 (od siebie) * do 93.184.216.34 (do adresu, z którego otrzymał pytanie) - R1 otrzymuje wiadomość z adresu 1.1.1.1 kierowaną na adres 93.184.216.34 - Przed wykonaniem trasowania R1 sprawdza, czy pakiet należy do połączenia dla którego już wykonuje translację adresów. W tym przypadku tak – zamienia więc adres //docelowy// z 93.184.216.34 na 192.168.0.2 - R1 wykonuje trasowanie i określa, że pakiet kierowany do 192.168.0.2 ma trafić do PC1 - PC1 otrzymuje odpowiedź z adresem źródłowym 1.1.1.1 i docelowym 192.168.0.2 DNAT:
- PC1 wysyła żądanie nawiązania połączenia TCP na port 443 ze swojego do adresu 150.254.5.114 - R1 wykonuje translację SNAT i wysyła w internet pakiet: * z adresu 93.184.216.34 * do adresu 150.254.5.114 * protokołu TCP, na port docelowy 443 - R2 dostaje wiadomość z 93.184.216.34 na swój adres IP - Przed wykonaniem trasowania (PREROUTING) R2 sprawdza czy dla tego pakietu powinien wykonać trasowanie - R2 znajduje regułę: //pakiety TCP adresowane na port 443 tego komputera mają trafiać do 192.168.0.3//, więc dokonuje **translacji adresu docelowego**: zmienia adres docelowy 150.254.5.114 na 192.168.0.3 - R2 wykonuje trasowanie i określa, że pakiet kierowany do 192.168.0.3 ma trafić do //Serwer WWW// - //Serwer WWW// otrzymuje pakiet: * z adresu 93.184.216.34 * do adresu 192.168.0.3 - //Serwer WWW// generuje w odpowiedzi pakiet i adresuje go: * od 192.168.0.3 (od siebie) * do 93.184.216.34 (do adresu, z którego otrzymał pytanie) - //Serwer WWW// przesyła odpowiedź do bramy domyślnej 192.168.0.1 (R2) - R2 określa, że pakiet kierowany do 93.184.216.34 ma iść do internetu i go tam kieruje - R2 po wykonaniu trasowania sprawdza, czy pakiet należy do połączenia dla którego już wykonuje translację adresów. W tym przypadku tak – zamienia więc adres //źródłowy// z 192.168.0.3 na 150.254.5.114. - R2 wysyła pakiet do internetu - R1 otrzymuje pakiet * z adresu 150.254.5.114 * do adresu 93.184.216.34 - R1 wykonuje translację SNAT, wysyła pakiet do PC1
++++ === iptables i stanowość firewalla === W systemie Linux translacja adresów jest **stanowa**, stąd odpowiedzi zawsze znajdą drogę powrotną. === Translacja źródłowa (Source NAT, SNAT) === Pozwala na dostęp do sieci z adresacją publiczną (np. internet) urządzeniom z sieci z adresacją prywatną. Uproszczony tryb translacji źródłowej – maskarada: \\ ''iptables --table nat --append POSTROUTING --out-interface wlan0 -j MASQUERADE'' \\ Przy użyciu maskarady adres źródłowy jest automatycznie ustawiany na adres interfejsu którym pakiet opuszcza router Klasyczny SNAT wymaga podania adresu (lub adresów) na jakie ma być zmieniane źródło: \\ ''iptables -t nat -A POSTROUTING -j SNAT --to-source 150.254.130.41 [--out-interface wlan0]'' === Translacja docelowa (Destination NAT, DNAT) === Pozwala na dostęp świata do urządzeń znajdujących się w sieci prywatnej, np: \\ ''iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 10.0.0.2'' \\ ''iptables -t nat -A PREROUTING -p tcp ! --dport 22 -j DNAT --to-destination 10.0.0.2'' **[[sk1:nf_nat|NAT w systemie Linux - ćwiczenia]]** ===== [Ekstra] Appendix ===== Dobry artykuł o nftables, z wstępem opisującym historię filtrowania pakietów w Linuksie: [[https://randomseed.pl/pub/nftables-nowy-firewall-linuksa/]] Inne moduły: *'' recent'' pozwala filtrować biorąc pod uwagę wcześniejszą aktywność danego IP/ danej sieci, np: \\ ''iptables -A INPUT -p tcp --dport 139 -m recent --name unwanted --set --seconds 15 -j DROP'' \\ ''iptables -A INPUT -m recent --update --seconds 15 -j DROP'' * ''string'' pozwalający dopasowywać tekst i moduł ''u32'' pozwalający dopasowywać dana na podanej pozycji, np: \\ ''iptables -A FORWARD -p udp --dport domain -m string --algo bm --hex-string '|08|facebook|03|com|00|' -j LOG --log-prefix 'facebook ' '' * ''mac'' pozwala filtrację adresów MAC, np: \\ ''iptables -A input -m mac ! --mac-source 00:12:34:56:78:ab -j DROP'' *''-p icmp'' pozwala na filtrowania icmp, np: \\ ''iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT'' API systemów Windows do tworzenia firewalli: https://msdn.microsoft.com/en-us/library/aa366510%28v=vs.85%29.aspx