Trzy przeskoki WireGuard docierają do sieci bez publicznego adresu, a potem środkowa maszyna przestaje odpowiadać na porcie, na którym miała nasłuchiwać. Tunel dalej nadal działa, zdalny host nadal odpowiada, i tylko sam środkowy serwer zamilkł z zewnątrz. Ta kombinacja jest myląca właśnie dlatego, że jest samoistna: środkowy przeskok słucha własnej tablicy routingu, a tablica wysyła jego odpowiedzi w złą stronę.

Łańcuch, który działa, dopóki nie porozmawiasz ze środkowym pudełkiem

Weźmy przykładowy łańcuch: klient A dociera do serwera B przez UDP 500, a B przechodzi dalej do serwera C przez UDP 500. C przyjmuje ruch tylko z adresu swojego jedynego peera, co czyni go liściem i utrzymuje jego zachowanie prostym. B nie jest liściem, i wszystko ciekawe w tej awarii dzieje się właśnie tam.

Ta różnica ma znaczenie, bo role liścia i środka ciągną w przeciwne strony. Liść może wysłać wszystko do jednego tunelu bez konsekwencji, ponieważ nic innego od niego nie zależy. Środkowy przeskok jest jednocześnie punktem końcowym dla klientów i klientem wobec dalszej strony, a te dwa zadania chcą innego routingu.

Dlaczego odpowiedź wychodzi przez tunel

Na B interfejs skierowany do C niesie AllowedIPs = 0.0.0.0/0 wraz z pasującą trasą domyślną. Dlatego każdy pakiet, który B utworzy, trafia do tego tunelu, chyba że coś bardziej konkretnego ma pierwszeństwo.

Pakiet od A adresowany do B przychodzi i jest akceptowany, ponieważ B jest celem, a dostarczenie lokalne następuje pierwsze. Odpowiedź to całkiem nowy, lokalnie utworzony pakiet skierowany na publiczny adres A, i ten cel pasuje do trasy domyślnej do tunelu. C go odbiera, nie posiada tego adresu i odrzuca go.

Objaw czyta się jak problem z zaporą ogniową albo niezgodność kluczy, i żadne z nich nie jest tu prawdą. Przechwycenie na tunelu w stronę C pokazuje, że odpowiedzi idą w złą stronę. To jedno spostrzeżenie oszczędza więcej czasu niż jakakolwiek ilość czytania konfiguracji, więc zapisz je, zanim zaczniesz zmieniać klucze. Kto nie widział przechwycenia, uzna, że sam tunel jest zepsuty.

Wąska naprawa: reguły polityki pasujące do portu źródłowego

Odpowiedzi z gniazda nasłuchującego B wychodzą z portem źródłowym 500. Reguła polityki może to dopasować i skierować te pakiety z powrotem do zwykłej tablicy:

ip rule add sport 500 table main priority 100
ip rule add sport 8080 table main priority 101

Reguły polityki są sprawdzane w kolejności priorytetów, a tablica główna znajduje się na 32766, więc reguła na 100 jest pytana, zanim trasa domyślna tunelu ma coś do powiedzenia. Dodaj jeden wpis na każdy port, który musi pozostać osiągalny z zewnątrz, i nic więcej, aby przekazywany ruch nadal korzystał z tunelu, dla którego został zbudowany.

Znaj granicę tego triku. Selektor sport pasuje do pakietów utworzonych lokalnie, co obejmuje dokładnie przypadek odpowiedzi i celowo nie obejmuje ruchu, który B tylko przekazuje za kogoś innego. Usługa hostowana za B nadal potrzebuje własnej odpowiedzi, a udawanie, że jest inaczej, daje poprawkę, która działa dla pierwszej usługi i zawodzi dla drugiej.

Daj regule właściciela

Reguła wpisana w wierszu poleceń znika przy następnym przebudowaniu interfejsu. W konfiguracji WireGuard umieść ją tam, gdzie interfejs jest tworzony i usuwany:

PostUp = ip rule add sport 500 table main priority 100
PostDown = ip rule del sport 500 table main priority 100

Jeśli interfejsem zarządza NetworkManager, hook dystrybucji lub punkt wejścia kontenera, para należy do tego właściciela, a nie do pliku edytowanego ręcznie. Sprawdź obowiązujące reguły po ponownym połączeniu, nie tylko po pierwszym starcie, bo pierwszy start to przypadek, który zawsze działa.

Porównaj alternatywy uczciwie

Reguła portu źródłowego jest jednym z czterech wyjść i najwęższym z nich. Ma tę zaletę, że w ogóle nie dotyka polityki tunelu, dlatego zwykle przeżywa późniejsze zmiany. Wąskie poprawki również głośno zawodzą, gdy przestają obowiązywać, podczas gdy szeroki wyjątek nadal cicho działa długo po tym, jak powód zniknął. Ta różnica liczy się bardziej niż elegancja, gdy za dwa lata pudełko należy do kogoś innego.

ApproachWhat it costsWhere it breaks
Source-port policy ruleOne rule per exposed portAnything B forwards rather than originates
Destination exception routeA route pinned to specific client addressesClients whose address changes
Stop full-tunnelling on BLoses the catch-all path toward CDesigns that depend on it
Split into two tunnelsMore interfaces and more policyNothing, at the cost of complexity

Sprawdź z obu stron, gdy już wybierzesz. Z A rozpocznij połączenie do portu B i trzymaj je zajęte przez chwilę. Na B każ jądro uzasadnić ścieżkę odpowiedzi czymś w rodzaju ip route get <address-of-A> sport 500, i potwierdź, że wskazuje interfejs WAN, a nie tunel. Następnie sprawdź, że coś za C nadal odpowiada przez łańcuch, co dowodzi, że wyjątek pozostał wąski, a nie zamienił się w obejście. Na koniec zapisz porty w notatkach projektowych, inaczej następny operator odkryje to ponownie w innej usłudze.

Powiązane artykuły