Wyobrażasz sobie, że serwer VPN odczytuje adres twojego laptopa z pakietu i zapisuje go w logu. To, co czyta, to to, co ostatni skok NAT umieścił w zewnętrznym nagłówku, a na telefonie używanym jako hotspot jest to często adres współdzielony z setkami innych abonentów. Własny adres twojej maszyny 192.168.x.x nigdy nie przekracza internetu w tym nagłówku, a adres tunelu przydziela serwer dopiero po nawiązaniu połączenia. Kiedy więc log serwera i ip addr na laptopie się nie zgadzają, żaden z nich nie jest błędny; opisują różne warstwy jednej sesji.

Trzy adresy, a w logu tylko jeden

Zamieszanie bierze się ze sprowadzenia trzech adresów do jednego. Każdy ma innego właściciela, żyje w innym nagłówku i dociera do serwera inną drogą.

AddressWho assigns itWhere it sitsVisible to the VPN server
Device address, e.g. 192.168.1.24Your router via DHCPOuter header, before translationNo, rewritten in place
Translated address and portRouter, ISP CGNAT, or bothOuter header, after translationYes, this is the tuple it logs
Tunnel address, e.g. 10.8.0.6The VPN server itselfInner header, after decapsulationYes, but it chose it

Tylko środkowy wiersz jest nieznany w chwili połączenia. Serwer zapisuje go w tabeli partnerów, pliku stanu lub logu przepływów zależnie od demona: WireGuard nazywa go punktem końcowym, plik stanu OpenVPN oznacza go jako Real Address, a strongSwan zgłasza go jako zdalnego hosta IKE_SA. Ta wartość jest odświeżana za każdym razem, gdy przyjdzie pakiet z innego źródła, więc zmienia się bez restartowania czegokolwiek.

Dolny wiersz to to, co ludzie błędnie czytają jako twierdzenie o tożsamości. Oznacza miejsce w konfiguracji serwera, a nie osobę, bo serwer wybrał je z własnej puli. Dwóch użytkowników może dostać ten sam adres tunelu w różne dni, a jeden może mieć dwa z dwóch urządzeń.

Dlaczego zapisana krotka zmienia się, gdy tunel pozostaje aktywny

Tłumaczenie adresów to tabela z licznikiem czasu, a nie trwałe powiązanie. Router domowy trzyma swoje mapowanie UDP jeszcze przez chwilę po ostatnim pakiecie, brama operatora recyklinguje porty według własnego harmonogramu, a telefon, który przechodzi z Wi-Fi na LTE, wraca z zupełnie innym źródłem. Domyślne wartości conntrack w Linuksie są tu przydatnym punktem odniesienia: nf_conntrack_udp_timeout to 30 sekund, a wariant streamingowy 120, więc cichy tunel może stracić mapowanie znacznie wcześniej, niż użytkownik to zauważy.

Tunel przetrwa, bo protokół uwierzytelnia partnera, a nie adres. WireGuard jest bezstanowy po handshake, więc każdy uwierzytelniony pakiet aktualizuje zapisany punkt końcowy, a ponowne powiązanie leczy się przy następnym pakiecie; dlatego istnieje persistent-keepalive = 25, aby utrzymać mapowanie ciepłe podczas bezczynności. --float OpenVPN robi to samo i pozwala uwierzytelnionemu klientowi kontynuować z nowego adresu i portu. W wersjach 2.4 i 2.5, gdzie float jest domyślnie wyłączony, ponowne powiązanie resetuje sesję i klient łączy się ponownie.

IPsec dociera tam z większą liczbą ruchomych części. IKEv2 zauważa tłumaczenie, porównując skróty źródła i celu w ładunkach wykrywania NAT, przechodzi na enkapsulację UDP 4500 i śledzi keepalive do nowej krotki. Gdy keepalive są blokowane, SA pozostaje aktywna tylko na papierze, a ruch w jednym kierunku po cichu się zatrzymuje.

Co serwer może przypisać, a czego nie

Mit, który warto zabić, to przekonanie, że tłumaczenie ukrywa cię przed operatorem. Zmienia etykietę, nie obserwację. Brama za NAT operatora widzi przestrzeń 100.64.0.0/10 albo jeden publiczny adres współdzielony przez wielu abonentów, i nadal może powiązać przepływ z podmiotem certyfikatu, publicznym kluczem WireGuard, przydzielonym adresem tunelu, licznikami bajtów i oknem czasowym. Nic z tego nie potrzebuje twojego adresu LAN.

Granice działają też w drugą stronę. Współdzielony adres w logu wskazuje bramę, a nie gospodarstwo domowe; dwie sesje z tego samego przetłumaczonego adresu na różnych portach to różne urządzenia; ten sam adres w dwa różne dni może oznaczać dwóch niepowiązanych abonentów, jeśli port został poddany recyklingowi. Serwer, który zapisuje tylko klucze partnerów, nie potrafi przypisać ich do klienta bez bazy kont, a serwer, który zapisuje tylko adresy, nie odróżni laptopa od telefonu za tym samym routerem.

Porównaj oba końce zamiast zgadywać

Aby ustalić, co się stało, przechwyć to samo połączenie na obu końcach w tym samym momencie i porównaj krotkę, a nie adres. Na kliencie, przed jakimkolwiek tłumaczeniem:

ss -uapn 'dport = :51820'
ip -4 route get 203.0.113.10
wg show wg0 endpoints

Następnie odczytaj wpis tłumaczenia na routerze lub bramie CGNAT i to, co w końcu dociera do serwera:

conntrack -L -p udp --dport 51820
tcpdump -ni eth0 udp port 51820

Trzy wzorce wyjaśniają większość rozbieżności. Port źródłowy na serwerze różni się od portu lokalnego, a cel się zgadza: zwykłe tłumaczenie portów. Adres źródłowy na serwerze należy do bloku ISP, który nie jest twój: co najmniej jedna dodatkowa warstwa NAT. Pakiety zatrzymują się po okresie bezczynności i wznawiają z nowym portem: mapowanie wygasło, a nie błąd routingu. Jeśli znaczniki czasu dzieli więcej niż sekunda lub dwie, porównujesz dwie różne próby.

Gdzie różnica psuje rzeczy

Awariom wyglądającym na błędy serwera zwykle początek daje właśnie to. Reguła dostępu przypięta do twojego domowego adresu przestaje działać po zmianie dzierżawy ISP. Reguła fail2ban pasująca do przetłumaczonego adresu blokuje wszystkich abonentów za tą bramą naraz. Partner site-to-site ze stałym adresem zdalnym przestaje odnawiać klucze po zmianie łącza mobilnego. Protokół tunelu był w porządku; założenie o zewnętrznej krotce nie.

To samo zamieszanie widać po stronie serwera. Jeśli sama skrzynka VPN stoi za NAT, potrzebujesz przekierowania portu i działającej ścieżki przekazywania; przewodnik strongSwan po przekazywaniu obejmuje ten przypadek dla IPsec. Serwer osiągalny tylko pod prywatnym adresem nigdy nie widzi przetłumaczonej krotki, którą przedstawiają jego klienci, i to jest inny problem niż tłumaczenie klientów.

Przejdź te cztery kontrole po kolei i zatrzymaj się na pierwszej, która zawiedzie:

  • Przechwyć na obu końcach jednocześnie; potwierdź, że port źródłowy, port docelowy i znaczniki czasu się zgadzają.
  • Odczytaj na liście partnerów serwera adres, który obecnie trzyma, a nie ten, którego oczekiwałeś.
  • Sprawdź tabelę conntrack lub NAT pod kątem wpisu i jego pozostałego czasu życia.
  • Potwierdź, że adres interfejsu tunelu na kliencie odpowiada temu przydzielonemu przez serwer, a nie adresowi LAN.

Jeśli oba przechwycenia zgadzają się co do krotki, a tunel nadal zawodzi, tłumaczenie nie jest twoim problemem; przejdź do handshake i do tablicy routingu wewnątrz tunelu.

Powiązane artykuły