Klient VPN na serwerze LAN: dlaczego odpowiedzi wychodzą złą drogą
Host, który łączy się z VPN, otrzymuje trasę domyślną, więc odpowiedzi do klientów LAN wychodzą przez tunel. Dodaj węższą trasę powrotną i sprawdź ją.
Objawy mają jeden wzorzec: host działa, potem łączy się z VPN jako klient i teraz klienci LAN go osiągają, a jego odpowiedzi znikają. Przechwycenie na hoście pokazuje, że odpowiedzi wychodzą przez urządzenie tunelu zamiast przez interfejs LAN. Nic w tunelu nie jest zepsute, a poprawką jest trasa, nie ponowne połączenie. Wykonaj cztery kontrole poniżej po kolei i zatrzymaj się na pierwszej, która zawiedzie.
Odpowiedź to nowy pakiet, nie zawrócenie
Pomaga porzucić myśl, że odpowiedź wraca tą samą drogą, którą poszło żądanie. Trasowanie jest rozstrzygane dla każdego pakietu i każdego kierunku na hoście wysyłającym. Żądanie, które przyszło z 10.64.0.23 wewnątrz tunelu, nie tworzy drogi powrotnej; gdy host odpowiada, ta odpowiedź jest porównywana z tabelą jako nowy pakiet i wychodzi tą trasą, która wygrywa.
Dlatego klient pełnego tunelu na maszynie, która obsługuje też LAN, daje tak mylącą awarię. Klient instaluje trasę domyślną albo dwie połówkowe trasy domyślne, które wolą niektóre klienty, i odpowiedź do klienta LAN pasuje teraz do tunelu. Trafia do dostawcy, który nie ma powodu jej przekazywać, a klient LAN widzi przekroczenie czasu, choć host działa i odpowiada lokalnie. Przechwycenie to uwidacznia, a tabela tras to wyjaśnia.
Miej w głowie dwie podsieci, czytając resztę. Jedna to pula adresów VPN, z której przychodzą klienci zdalni, w tym przykładzie 10.64.0.0/24. Druga to LAN, który musi dalej działać, 172.16.24.0/24 z routerem pod 172.16.24.1. Błąd polega na tym, że ruch między nimi rozstrzyga trasa domyślna.
Udowodnij to przechwyceniem i zapytaniem
Zanim cokolwiek zmienisz, potwierdź, którego urządzenia użyje odpowiedź. Zapytanie jest szybsze niż przechwycenie i odpowiada dokładnie na to pytanie, na które odpowie jądro przy budowie pakietu.
ip route get 10.64.0.23 from 172.16.24.10
tcpdump -ni any -c 6 icmp
Czytaj odpowiedź w dwóch częściach. Jeśli wskazuje dev tun0, host zamknie odpowiedź w kapsule i przekaże ją dostawcy, a klient LAN nigdy jej nie zobaczy. Jeśli wskazuje dev eth0, ale klient wciąż dostaje przekroczenie czasu, trasa jest już poprawna i pakiet jest później odrzucany, co jest innym problemem z inną poprawką.
Przechwycenie w tym samym kroku rozstrzyga wątpliwość, której ping nie może. Echo odpowiedzi docierające do klienta LAN dowodzi, że jakaś droga działa, a nie która karta ją niosła, więc wykonaj przechwycenie na samym hoście i patrz, skąd wychodzą ramki. Drukarka w tej samej podsieci nadal odpowiada, bo jej trasa bezpośrednia jest bardziej szczegółowa niż trasa domyślna tunelu. Przekierowany port zawodzi dokładnie jak każdy inny strumień, bo interfejs wybiera tabela, a nie połączenie.
Zainstaluj najwęższą trasę, która przewyższa tunel
Decyduje długość prefiksu, nie metryka, więc trasa do puli klientów przez router LAN wygrywa z każdą trasą domyślną, którą zainstaluje klient VPN. Chirurgia metryki nie jest potrzebna, a trasa domyślna może zostać dokładnie tam, gdzie położył ją klient.
ip route replace 10.64.0.0/24 via 172.16.24.1 dev eth0
ip route get 10.64.0.23 from 172.16.24.10
Użyj replace zamiast add, bo klient, który połączy się ponownie, zdążył już zainstalować własny wpis, a drugie add zawodzi błędem o istniejącej trasie, który czyta się jak problem z uprawnieniami. Na hoście Windows odpowiednikiem jest route add 10.64.0.0 mask 255.255.255.0 172.16.24.1 -p, gdzie -p zachowuje wpis między restartami, ponieważ klient może odbudować tabelę, gdy tunel znów się podniesie. Na współczesnym hoście Windows obsługiwanym odpowiednikiem jest New-NetRoute -DestinationPrefix 10.64.0.0/24 -NextHop 172.16.24.1 -InterfaceAlias Ethernet -PolicyStore PersistentStore, a starsze polecenie route pozostaje jako forma zastana.
Jeden szczegół decyduje, czy to jest poprawne, czy tylko wiarygodne: następny skok musi być routerem, który naprawdę posiada drogę powrotną do klientów. Skierowanie trasy na adres, do którego samemu dochodzi się przez tunel, tworzy pętlę, która objawia się jako okresowa utrata, a nie jako czysta awaria. Potwierdź, że następny skok jest w podsieci LAN, zanim zatwierdzisz wiersz.
Zachowaj odpowiedź po ponownym połączeniu
Trasa dodana ręcznie przetrwa w najlepszym razie do następnego połączenia. Jeśli pula klientów jest dynamiczna, przypnij ją w konfiguracji serwera, aby prefiks, który trasowałeś, pozostał prefiksem, który otrzymują klienci; inaczej wpis wskazuje pusty zakres, a objaw wraca tygodnie później bez wyraźnej przyczyny. Zapisanie trasy we własnym skrypcie up klienta to druga pewna opcja, bo działa po tym, jak klient przepisze tabelę.
Zapora stanowa wciąż może pokonać poprawną trasę. Jeśli przechwycenie pokazuje teraz, że odpowiedź wychodzi przez eth0, a klient wciąż dostaje przekroczenie czasu, sprawdź, czy host nie odrzuca pakietu przed wysłaniem. Ścisłe filtrowanie trasy odwrotnej i net.ipv4.conf.all.rp_filter ustawiony na 1 odrzucają pakiety, których źródło nie zostałoby wytraowane z powrotem przez interfejs, którym przyszły, i to jest dokładnie ten asymetryczny przypadek, który właśnie stworzyłeś, a potem naprawiłeś, a stan conntrack opowiada tę samą historię dla przekierowanych portów.
Ostatnia kontrola to ta, którą ludzie pomijają: powtórz zapytanie po tym, jak tunel był wyłączony i znów włączony. Cztery wartości powinny zgadzać się z tym, co zapisałeś: cel, następny skok, urządzenie i wybrane źródło. Jeśli któraś się przesunęła, klient przepisał tabelę, a poprawka należy do jego hooków, a nie do historii powłoki.