# Implementacja tunelu ICMP w jądrze Linuksa: enkapsulacja TCP/UDP w żądania echo
Tunel ICMP na poziomie jądra Linuksa pozwala na enkapsulację ruchu TCP/UDP wewnątrz pakietów ICMP typu Echo Request, omijając standardowe filtry sieciowe. Taki podejście jest przydatne do badań stosu sieciowego, testowania przechwytywania pakietów oraz zrozumienia działania Netfilter. W artykule omawiana jest architektura modułu jądra realizującego translację ruchu za pomocą haków NF_INET_POST_ROUTING i NF_INET_LOCAL_IN z wykorzystaniem taskletów do asynchronicznego wysyłania.
Architektura tunelu ICMP w jądrze Linuksa
Moduł składa się z trzech kluczowych komponentów: dwóch haków Netfilter oraz taskleta do wysyłania pakietów. Hak NF_INET_POST_ROUTING przechwytuje wychodzące pakiety TCP/UDP przed ich wysłaniem do sieci, przekształca je w żądania echo ICMP i przekazuje sterowanie do taskleta. Drugi hak — NF_INET_LOCAL_IN — przechwytuje przychodzące pakiety ICMP, wyciąga oryginalny ruch i kieruje go do interfejsu loopback w celu dostarczenia aplikacjom. Tasklet zapewnia opóźnioną wysyłkę pakietów za pomocą dev_queue_xmit, minimalizując blokady w kontekście przerwania.
Rejestracja haków odbywa się z priorytetem NF_IP_PRI_FIRST, aby zagwarantować pierwszą obsługę. Jest to kluczowe, ponieważ ingerencja innych modułów przed naszym może zakłócić integralność enkapsulacji lub dekapsulacji. Do zarządzania pamięcią używana jest struktura sk_buff — podstawowa struktura stosu sieciowego Linuksa, wymagająca ostrożnego rezerwowania nagłówków i poprawnego zwalniania za pomocą kfree_skb w przypadku błędów.
Szczegółowa analiza output_hook i create_packet_output
Funkcja output_hook jest wywoływana dla każdego wychodzącego pakietu. Deleguje tworzenie powłoki ICMP funkcji create_packet_output, która:
- Sprawdza, czy protokół to TCP lub UDP — jeśli nie, zwraca NULL, a pakiet kontynuuje swoją trasę bez zmian.
- Pobiera adres MAC odbiorcy za pomocą
__ipv4_neigh_lookup, co jest niezbędne do utworzenia nagłówka Ethernet. - Liniaryzuje
sk_buffwywołaniemskb_linearize, ponieważ dalsze operacje kopiowania danych wymagają ciągłego bufora. - Określa typ protokołu transportowego (0 dla UDP, 1 dla TCP), długość nagłówka i rozmiar ładunku.
- Alokuje nowy
sk_buffz uwzględnieniem zarezerwowanej przestrzeni na nagłówki (LL_RESERVED_SPACE) oraz danych ogonowych (needed_tailroom). - Krok po kroku tworzy nagłówki: Ethernet, IPv4, ICMP, kopiując nagłówek transportowy i dane do ciała ICMP.
- Oblicza sumy kontrolne dla IP i ICMP za pomocą
ip_fast_csumiip_compute_csum. - Zwraca gotowy pakiet do wysłania.
Kluczowy element — wykorzystanie pola icmp->un.echo.id do przekazywania informacji służbowych o typie oryginalnego protokołu i identyfikatorze strumienia. Dzięki temu strona odbierająca może poprawnie odtworzyć oryginalny pakiet bez dodatkowych metadanych poza strukturą ICMP.
Obsługa przychodzących pakietów i routowanie loopback
Po stronie odbierającej hak input_hook analizuje każdy przychodzący pakiet ICMP. Jeśli pasuje do formatu tunelu (Echo Request z znanym wzorcem w polu ID), moduł:
- Wyciąga nagłówek transportowy i dane z ciała ICMP.
- Tworzy nowy
sk_buff, symulujący przychodzący pakiet TCP/UDP. - Ustawia urządzenie docelowe na interfejs loopback (
dev_set_name(skb, "lo")). - Zmienia adresy MAC na localhost i wywołuje
netif_rx_ni()w celu wstrzyknięcia pakietu do stosu sieciowego.
To zmusza jądro do przetworzenia pakietu tak, jakby przyszedł z zewnątrz, ale przez interfejs lo. Aplikacje otrzymują dane bez zmian, nieświadome enkapsulacji. Ważne, że nie używany jest NF_STOLEN — pakiet nie jest „kradziony", lecz zastępowany, dlatego po udanym wstrzyknięciu zwracany jest NF_ACCEPT.
Krytyczne szczegóły techniczne i ograniczenia
Implementacja napotyka szereg ograniczeń technicznych:
- Fragmentacja: Pakiety ICMP mogą być fragmentowane na trasie, ale obecna implementacja nie obsługuje fragmentów — zakłada MTU wystarczające do pełnej enkapsulacji.
- Bezpieczeństwo: Brak szyfrowania lub uwierzytelniania czyni tunel podatnym na fałszowanie i ataki MITM.
- Wydajność: Każdy pakiet wymaga alokacji nowego
sk_buff, kopiowania danych i obliczania sum kontrolnych — co obciąża CPU. - Tylko IPv4: Moduł nie wspiera IPv6, ponieważ używa
ip_hdri__ipv4_neigh_lookup. - Zależność od MAC: Wymaga wpisu ARP dla docelowego IP, w przeciwnym razie pakiet jest odrzucany.
Pomimo ograniczeń, projekt doskonale nadaje się do celów edukacyjnych: obejmuje pracę z Netfilter, zarządzanie pamięcią jądra, tworzenie nagłówków sieciowych i interakcje między warstwami modelu OSI w czasie rzeczywistym.
Co ważne
- Tunel ICMP enkapsuluje TCP/UDP w żądania Echo, umożliwiając ominięcie niektórych filtrów sieciowych.
- Używane są haki Netfilter z maksymalnym priorytetem do przechwytywania ruchu przed/po routingu.
- Tasklety zapewniają asynchroniczną wysyłkę, nie blokując kontekstu przerwania.
- Po stronie odbierającej pakiety wstrzykiwane są do loopback dla przezroczystego dostarczenia aplikacjom.
- Implementacja jest edukacyjna — nie nadaje się do produkcji z powodu braku zabezpieczeń i obsługi fragmentów.
— Editorial Team
Brak komentarzy.