Masz wymaganie, które się nie ugnie: druga strona musi odebrać ten sam pakiet IP 1,500 bajtów, który wysyła nadawca, wraz z nagłówkami. Tunel nie może zapakować tego pakietu razem z własnym ramowaniem w drugi pakiet IP 1,500 bajtów, więc coś w projekcie musi ustąpić. Kolejność poniżej to ta, której używam w oknie zmian: zapisz budżet bajtów, udowodnij, co podkład naprawdę może przenieść, następnie wybierz dokładnie jeden mechanizm przenoszenia i potwierdź pakiet wewnętrzny po drugiej stronie.

Zapisz budżet bajtów, zanim edytujesz profil

Enkapsulacja dodaje bajty na kilku warstwach, a suma jest właściwością twojego profilu, a nie stałą, którą można wyszukać. Rodzina adresów, wybór szyfru, protokół transportowy oraz każda opcja kompresji lub ramowania zmieniają liczbę, dlatego odejmowanie skopiowane z innego wdrożenia jest bezwartościowe jako budżet. Zacznij od wymagania wewnętrznego, dodaj zmierzony narzut na pakiet własnej konfiguracji i zapisz wynikowy rozmiar zewnętrzny w zgłoszeniu zmiany, zanim ktokolwiek edytuje plik.

Dwie liczby decydują o projekcie: największy pakiet zewnętrzny, który ścieżka przenosi bez fragmentacji, oraz dodatkowe bajty potrzebne twojej enkapsulacji. Gdy pierwsza jest mniejsza od drugiej plus 1,500, jedna z nich musi się zmienić. Wybór staje się wtedy wąski, a nie kreatywny, dlatego zapisuję obie liczby przed rozmową o opcjach. Nic na warstwie tunelu nie kompresuje tych bajtów, a żadna pojedyncza liczba całkowita MTU nie usuwa wymagania, które dostałeś.

Sondaż podkład pingami do-not-fragment

Mierz ścieżkę, zamiast ufać MTU interfejsu, bo liczy się najsłabsze ogniwo w ścieżce zewnętrznej. W systemie Linux, -M do ustawia bit do-not-fragment i -s przyjmuje ładunek ICMP, więc ramka 1,500 bajtów odpowiada 1,472 bajtami ładunku po odjęciu 20-bajtowego nagłówka IP i 8-bajtowego nagłówka ICMP. Zwiększaj ładunek, aż sonda zawiedzie, potem przeskocz do rozmiaru jumbo, aby sprawdzić, czy ścieżka w ogóle go przenosi.

ping -M do -s 1472 -c 2 198.51.100.10
ping -M do -s 8972 -c 2 198.51.100.10
tracepath -n 198.51.100.10

Ścieżka, która przechodzi 1,472 i zawodzi na 8,972, nie może przenieść pakietu wewnętrznego 1,500 bajtów wraz z narzutem w jednym pakiecie zewnętrznym. To jest odpowiedź, której potrzebowałeś przed otwarciem konfiguracji VPN. Decyduje też, która z dwóch następnych sekcji dotyczy ciebie, więc trzymaj oba wyniki sondy przy zgłoszeniu. Zgadywanie kosztuje tu okno serwisowe, bo tunel, który zgłasza się jako up, nie mówi nic o największym pakiecie, jaki ścieżka przyjmie.

Podnoś MTU ścieżki tylko tam, gdzie zgadza się każdy hop

Ramki jumbo są właściwością end-to-end, a nie ustawieniem, które włączasz na dwóch punktach końcowych, które akurat kontrolujesz. Każdy przełącznik, router i punkt przekazania u dostawcy na ścieżce zewnętrznej musi zgodzić się na większy rozmiar, a jeden hop 1,500 bajtów po cichu odrzuci pakiet, który właśnie powiększyłeś. Podniesienie tylko lokalnego interfejsu to klasyczna połowiczna zmiana, przez którą tunel wygląda na zepsuty, podczas gdy podkład po cichu gubi.

ip link set dev eth1 mtu 9000
ip link show dev eth1
ping -M do -s 8972 -c 2 198.51.100.10

Zmień interfejs, a potem ponownie zbadaj tę samą ścieżkę, zanim zmienisz cokolwiek innego. Jeśli sonda nadal zawodzi, wycofaj zmianę za pomocą ip link set dev eth1 mtu 1500 i przejdź na fragmentację, zamiast kłócić się z dostawcą o łącze, które nie jest twoje.

Użyj fragmentacji tunelu, gdy podkład nie może urosnąć

Obsługiwany mechanizm fragmentacji poniżej pakietu wewnętrznego pozwala kilku pakietom zewnętrznym przenieść jeden pakiet wewnętrzny, a drugi punkt końcowy tunelu składa je ponownie, zanim przekaże oryginał do stosu. Opcja fragmentacji UDP w Community OpenVPN jest jedną implementacją tego pomysłu i nie jest tym samym co zwykła fragmentacja IP pakietu zewnętrznego. Oba peery muszą działać na wersji obsługującej ten format, a ścieżka danych musi być tą, którą myślisz: klienci OpenVPN 3 i kanały danych przyspieszane w jądrze mają różne limity, więc profil działający na jednym kliencie może zawodzić na innym.

openvpn --config client.ovpn --tun-mtu 1500 --fragment 1400 --verb 4

Zwykła fragmentacja zewnętrzna jest drugą opcją i jest słabsza. Routery IPv6 w ogóle nie fragmentują przekazywanego pakietu, więc zbyt duży pakiet zewnętrzny po prostu ginie, a nadawca dowiaduje się o tym tylko wtedy, gdy odpowiedni komunikat ICMPv6 przetrwa ścieżkę. Fragmenty zachęcają też do filtrowania i wzmacniania strat, dlatego traktuję to jako rozwiązanie awaryjne, a nie plan.

Nośnik zewnętrzny oparty na strumieniu omija kwestię rozmiaru, dzieląc własny strumień bajtów, a odtworzony pakiet wewnętrzny nadal może mieć 1,500 bajtów. To decyzja transportowa z własnym kosztem, w tym ze znanym zachowaniem TCP w TCP, więc podejmij ją świadomie, a nie jako skutek uboczny sporu o MTU.

Potwierdź, że pakiet wewnętrzny dociera niezmieniony

Weryfikacja to nie udany uścisk dłoni. Przechwyć na interfejsie tunelu na obu końcach i porównaj rozmiar oraz zawartość pakietu, który aplikacja faktycznie wysłała, z tym, co odebrała druga strona.

ip link show dev tun0
ping -M do -s 1472 -c 2 10.8.0.1
tcpdump -ni tun0 -c 5 'icmp and greater 1000'

Jeśli przechwycenie pokazuje pełnowymiarowy pakiet wewnętrzny na drugim końcu, wybór przenoszenia działa, a pozostałym zadaniem jest to zapisać. Jeśli nie pokazuje nic, gdy tunel zgłasza się jako up, pakiet zewnętrzny jest gdzieś między punktami końcowymi odrzucany, co odsyła cię do sondy, a nie do ustawień szyfru.

Zapisz w zgłoszeniu zmiany trzy rzeczy, zanim je zamkniesz: zmierzony budżet zewnętrzny, wybrany mechanizm i polecenie, które dowiodło, że pakiet wewnętrzny przetrwał. Następna osoba, która dotknie tego tunelu, będzie potrzebować wszystkich trzech, a żadnego z nich nie da się odtworzyć wyłącznie z pliku konfiguracji.

Powiązane artykuły