Dodajesz regułę dla ruchu VPN w łańcuchu FORWARD, uruchamiasz żądanie z tej samej maszyny Linux, a licznik zostaje na zerze. Reguła prawdopodobnie jest poprawna. Pakiet nigdy nie poszedł tą drogą, bo żądanie powstałe na samej maszynie nie jest przez nią przekazywane dalej. Prześledzenie życia pakietu od gniazda do kabla wyjaśnia, dlaczego tak się dzieje i gdzie reguła powinna właściwie być.

Ustal, gdzie narodził się pakiet

Kolejność hooków Netfiltra rozdziela trzy przypadki, a tylko jeden z nich dotyczy FORWARD:

OriginPathHook that sees it
Local processOUTPUT then POSTROUTINGOUTPUT, POSTROUTING
Addressed to a local servicePREROUTING then INPUTPREROUTING, INPUT
Received for another hostPREROUTING, FORWARD, POSTROUTINGFORWARD

Aplikacja lokalna zaczyna w ścieżce OUTPUT, bo jądro już ustaliło, że pakiet powstaje tutaj i nigdy nie jest kandydatem do przekazania. Utworzenie tunelu nie zmienia tej klasyfikacji; tunel to urządzenie, przez które pakiet może wyjść, a nie etap, który zamienia lokalne wyjście w tranzyt.

Dwa pakiety, jedna historia

Gdy tunel jest podniesiony, wewnętrzny pakiet aplikacji i zaszyfrowany pakiet zewnętrzny to różne obiekty. Wewnętrzny pakiet niesie cel i ładunek wybrane przez aplikację. Zewnętrzny pakiet niesie szyfrogram na adres i port peera, i to właśnie on rzeczywiście przekracza fizyczny interfejs.

Twoja polityka dotyczy jednego z nich, a wybór niewłaściwego to częsty powód, dla którego reguła wydaje się nic nie robić. Reguła pasująca do zewnętrznego adresu peera widzi każdy pakiet tunelu tak samo, cokolwiek robi aplikacja w środku. Reguła pasująca do wewnętrznego celu widzi ruch, na którym ci zależy, i uruchomi się tylko wtedy, gdy ten pakiet dotrze do hooka, na którym zainstalowano regułę.

Przestrzenie nazw przesuwają granicę

Kontener utrudnia to bez zmiany zasady. Żądanie aplikacji jest lokalnym wyjściem wewnątrz przestrzeni nazw sieci kontenera. Host odbiera ten ruch na wirtualnym interfejsie Ethernet i może go przekazać, więc reguła FORWARD na hoście może mieć sens, choć proces, który utworzył żądanie, nigdy nie dotknął łańcucha OUTPUT hosta.

Zanim wybierzesz hook, ustal, gdzie naprawdę żyją zbiór reguł i tunel. Tunel wewnątrz kontenera, tunel na hoście z kontenerem trasowanym przez niego oraz tunel w osobnej przestrzeni nazw to trzy różne topologie z trzema różnymi miejscami reguł. Czytaj reguły w przestrzeni nazw, która posiada urządzenie, a nie tylko w domyślnej.

Zapytaj, czy w ogóle potrzebujesz znacznika

Jeśli celem jest wysłanie jednego prefiksu docelowego przez tunel, trasa dla tego prefiksu może wystarczyć. Najpierw sprawdź efektywne trasy, w tym wszystko, co wypchnął serwer: przekierowana trasa domyślna wysyła przez VPN znacznie więcej ruchu niż wąska polityka, którą miałeś na myśli, i żadna ilość oznaczania nie sprawi, że wynik będzie zgodny z zamiarem.

Klasyfikacja jest potrzebna, gdy decyzja zależy od czegoś, czego trasa nie potrafi wyrazić, na przykład od źródła, użytkownika lub procesu. Dla ruchu odbieranego oznaczanie w PREROUTING działa. Dla ruchu lokalnego oznaczanie musi nastąpić na etapie wyjścia, który po ustawieniu znacznika może wywołać nowe wyszukanie trasy. W nftables to łańcuch typu route na hooku wyjścia; zwykły łańcuch filtra wyjścia ustawi wartość i pozostawi trasę bez zmian.

W iptables odpowiednik żyje w układzie mangle OUTPUT i obowiązuje ten sam wymóg: decyzję o trasowaniu trzeba ponownie rozważyć po powstaniu znacznika. Następnie reguła polityki musi zużyć znacznik i wskazać tabelę zawierającą użyteczną trasę. Ustawienie znacznika conntrack to trzecia, osobna operacja; przechowuje wartość na przepływie i sama nie umieszcza tej wartości na bieżącym pakiecie, aby trasowanie mogło ją odczytać.

Sprawdź wyszukiwanie i licznik razem

nft list ruleset
ip route get 198.51.100.25
ip route get 198.51.100.25 mark 0x1

Adres i znacznik są przykładowe, a oba zapytania o trasę odpowiadają na różne pytania. Drugie pyta, co zrobiłoby jądro, gdyby pakiet niósł ten znacznik; nie pokazuje, że twój zbiór reguł jakiś nadaje. Traktuj je jako test hipotezy, a nie dowód, że polityka działa.

Następnie uruchom nieszkodliwe żądanie i obserwuj dwie rzeczy naraz: licznik na wybranym hooku i wyjście, które pakiet faktycznie przyjął. Jeśli licznik rośnie, a pakiet wychodzi gdzie indziej, znacznik lub tabela są błędne. Jeśli nie rośnie żaden z nich, pakiet w ogóle nie dociera do tego hooka, a następnym pytaniem jest przestrzeń nazw lub ścieżka.

Na koniec ogranicz test do tego, co mechanizm potrafi wyrazić. Jedna trasa dla jednego adresu nie staje się stałą polityką dla usługi, której adresy się zmieniają. Najpierw zdecyduj o zakresie pakietów, potem sprawdź, czy projekt trasowania i oznaczania utrzyma ten zakres po ponownym połączeniu.

Powiązane artykuły