Wyłączyć IPv6, żeby naprawić wyciek VPN? Lepiej zdecydujcie o polityce
Adres link-local to nie wyciek, a globalna trasa IPv6 też nie. Najpierw wybierzcie między blokowaniem, przenoszeniem i zostawieniem.
Adres z zakresu IPv6 pojawia się na stronie testowej, tunel wyraźnie go nie przenosi, a najpopularniejsza rada w internecie to wyłączenie IPv6 wszędzie. To polecenie rzeczywiście ucisza panel. Usuwa jednak także protokół, od którego może zależeć sieć dostępowa, i zostawia was bez pojęcia, czy adres był prawdziwym wyciekiem, adresem interfejsu link-local, czy resolverem wykonującym swoją pracę. O właściwej kontroli decydują trzy warunki i tylko jeden z nich prowadzi do blokowania.
Ustalcie, co narzędzie faktycznie zmierzyło
Najczęstszym fałszywym alarmem jest adres link-local, który zaczyna się od fe80: i istnieje na każdym interfejsie obsługującym IPv6, niezależnie od tego, czy maszyna dociera do internetu przez IPv6. Pojawia się na listach interfejsów i w niektórych diagnostykach aplikacji i nic nie mówi o ścieżce waszego ruchu.
Drugi fałszywy alarm to unikalny adres lokalny w fc00::/7, czyli zakres prywatny używany wewnątrz sieci. Narzędzie, które wypisuje każdy adres hosta, chętnie wymieni go obok publicznego. Kto czyta szybko, nazywa to wyciekiem, a potem spędza godzinę nad problemem, którego nie ma.
Trzeci wcale nie jest fałszywym alarmem. Globalny adres, który dociera do internetu poza tunelem, to prawdziwy wyciek i warto go zmierzyć, zanim cokolwiek zdecydujecie:
ip -6 addr show scope global
ip -6 route show default
curl -6 -sS --max-time 6 https://ifconfig.co
Jeśli pierwsze polecenie wypisze adres globalny, a trzecie zwróci publiczny adres IPv6, który nie należy do tunelu, macie rzeczywistą ścieżkę poza tunelem. Jeśli pierwsze nie wypisze nic poza wpisami link-local, nigdy nie było wycieku do naprawy.
O kontroli decydują trzy warunki
Decyzja nie brzmi "IPv6 dobry" albo "IPv6 zły". Chodzi o to, w której z trzech sytuacji jesteście, a każda ma inną poprawną odpowiedź i inny koszt, jeśli się pomylcie.
| Situation | Correct control | Cost if you disable IPv6 instead |
|---|---|---|
| Exit has no IPv6, host does | Block IPv6 deliberately in the tunnel policy | Same visible result, no documentation of intent |
| Exit carries IPv6, host leaks | Route IPv6 into the tunnel and verify | You lose IPv6 reachability entirely |
| Access network is IPv6-only | Change nothing; use the tunnel's IPv6 | Machine loses connectivity completely |
Pierwszy wiersz to to, co ludzie zwykle mają na myśli, i jest uzasadniony. Klient, którego wyjście nie obsługuje IPv6, nie powinien po cichu wypuszczać własnego ruchu IPv6 hosta, bo to jest udokumentowany wyciek przy podwójnym stosie. Chodzi o to, by zablokować go jako zadeklarowaną politykę, a nie wyłączyć protokół w jądrze. Widoczny wynik jest identyczny i tylko jeden z nich można później przejrzeć.
Trzeci wiersz to miejsce, w którym ogólna rada staje się aktywnie szkodliwa. Operatorzy komórkowi i niektóre połączenia domowe prowadzą sieci IPv6-only z tłumaczeniem dla celów IPv4. Usuńcie tam IPv6 i usuniecie jedyny transport, jaki sieć oferuje, co daje znacznie gorszą awarię niż ta, którą naprawialiście.
Jeśli wyjście nie ma IPv6, zablokujcie je celowo
Preferujcie mechanizm samego klienta, bo działa dokładnie tak długo, jak tunel jest podniesiony, i wycofuje się, gdy tunel pada. OpenVPN ma na to opcję, a iptables ma równoważną regułę dla innych klientów:
block-ipv6
ip6tables -A OUTPUT -o eth0 -j REJECT --reject-with ipv6-port-unreachable
Dyrektywa należy do profilu; reguła należy do zapory, którą możecie przejrzeć i usunąć. Obie zawodzą zamknięte, czego chcecie, i obie są widoczne w diffie konfiguracji, czego nie można powiedzieć o sysctl jądra zakopanym w skrypcie startowym.
Zapiszcie, dlaczego tam jest. Regułę blokowania bez komentarza usunie następna osoba, której IPv6 potrzebne jest do czegoś innego, i wtedy wyciek po cichu wraca.
Jeśli wyjście przenosi IPv6, skierujcie je i przetestujcie obie rodziny
Przenoszenie IPv6 to lepsza odpowiedź, gdy serwer to obsługuje, i nie jest dużo trudniejsze. Wymóg jest taki, by interfejs tunelu miał adres w tej rodzinie, a jego trasa domyślna wskazywała do tunelu, a nie na zewnątrz interfejsu fizycznego:
ip -6 route get 2606:4700:4700::1111
ip -6 route show default
curl -6 -sS --max-time 6 https://ifconfig.co
curl -4 -sS --max-time 6 https://ifconfig.co
Wyszukanie trasy to decydujący test: jeśli nazywa interfejs tunelu, ruch IPv6 jest przenoszony. Dwa wywołania curl potwierdzają potem, co widzi każda rodzina, a porównanie ich to sposób dowiedzenia, że obie ścieżki wychodzą teraz tym samym wyjściem.
Nie zatrzymujcie się na udanym połączeniu. Połączcie tunel ponownie i sprawdźcie jeszcze raz, bo wypchnięta trasa IPv6 może zginąć przy ponownym ustanowieniu, jeśli serwer wysyła ją tylko w konfiguracji początkowej. Potem sprawdźcie jeden wykluczony cel, bo reguły split-tunnel to miejsce, gdzie obie rodziny najczęściej się różnią.
Jeśli sieć dostępowa jest tylko IPv6, zostawcie ją w spokoju
Niektóre sieci dają tylko IPv6 i oczekują, że urządzenie dotrze do usług IPv4 przez mechanizm tłumaczenia po stronie operatora. Wyłączenie IPv6 na takiej maszynie nie jest poprawą bezpieczeństwa; usuwa jedyną trasę do czegokolwiek. To awaria, którą sami sobie fundujecie dla wyniku testu, którego nikt nie potrzebował.
Objaw tego błędu jest charakterystyczny i nieprzyjemny: tunel wygląda na ustanawiany, rozwiązywanie nazw działa, a nic się nie ładuje. Jeśli to zobaczycie po zmianie IPv6, natychmiast przywróćcie ustawienie i kontynuujcie diagnostykę gdzie indziej.
Cokolwiek wybierzecie, trzymajcie decyzję jawnie w profilu lub zaporze, powiążcie ją z tym, co wyjście naprawdę obsługuje, i zanotujcie zachowanie podwójnego stosu, które opisuje dyskusja o podwójnym stosie w RFC 7359 . Zadeklarowane blokowanie to polityka. Wyłączony protokół to obejście, którego nikt nie może zaudytować, a ze strony testowej wyglądają identycznie.