Dlaczego prywatne nazwy DNS zawodzą na klientach VPN i gdzie to sprawdzić
Prywatne nazwy rozwiązują się tylko wtedy, gdy klient ufa twojemu resolverowi, sufiks jest ograniczony, a odpowiedź może wrócić przez tunel.
Otwierasz laptop w pokoju hotelowym, uruchamiasz klienta, wpisujesz nazwę wewnętrznego serwera plików i nic nie dostajesz. Tunel zgłasza połączenie, a ping do adresu w tej samej podsieci wciąż odpowiada, więc sam transport jest w porządku. Zawodzi tylko nazwa, a ta luka zawęża problem do dwóch miejsc: którego resolvera klient zapytał i czy otrzymana odpowiedź może wrócić przez tunel. Napraw jedno, a drugie pomiń, a awaria po prostu się przesunie.
Zanim zaczniesz edytować jakikolwiek profil, ustal, co klient robi z nazwą. W Linuksie resolvectl query files.corp.example pokazuje, przez które łącze i który resolver powstała odpowiedź. W Windows Resolve-DnsName files.corp.example pokazuje serwer, który odpowiedział, i adres, który zwrócił.
Przeczytaj odpowiedź, zanim cokolwiek zmienisz
Jeśli nazwa wraca jako NXDOMAIN w kilka milisekund, zapytanie nigdy nie dotarło do twojej strefy i odpowiedział jakiś publiczny lub hotelowy resolver. Jeśli wraca po długiej pauzie, coś po drodze porzuca port UDP 53, a klient w końcu sięgnął po zapasowe wyjście. Jeśli odpowiada poprawnym adresem, ale połączenie nadal się zacina, tłumaczenie jest w porządku, a twój problem leży w routingu albo w samej usłudze.
Ten podział na trzy oszczędza godzinę zgadywania. Mówi też, czy w ogóle ruszać VPN: nazwa, która rozwiązuje się na poprawny prywatny adres, dowiodła już ścieżki resolvera, więc pozostała praca jest na ścieżce danych.
Rozdaj resolver od środka tunelu
Klienci dzielą się na dwie grupy. Jednej serwer może podać resolver podczas zestawiania połączenia; druga trzyma ustawienie w lokalnym pliku, którego żadna brama nie zmieni zdalnie.
OpenVPN należy do pierwszej grupy. Na serwerze push "dhcp-option DNS 10.8.0.53" i push "dhcp-option DOMAIN corp.example" wędrują kanałem sterującym, ale tylko jeśli konfiguracja klienta ma nadal włączone pull. Ręcznie edytowany klient z pull-filter ignore "dhcp-option" nigdy ich nie zobaczy, a ta jedna linia wyjaśnia zaskakująco wiele przypadków typu „serwer to wypycha, ale mój laptop się nie zgadza”.
WireGuard należy do drugiej grupy, bo protokół nie ma żadnego negocjowania opcji. Resolver i domena wyszukiwania trafiają do własnego bloku [Interface] klienta jako DNS = 10.8.0.53, corp.example. wg-quick stosuje to przez resolvconf albo systemd-resolved, a w Windows oficjalny klient instaluje reguły NRPT, które istnieją tylko dopóki tunel jest podniesiony: Get-DnsClientNrptPolicy je wylicza, co czyni z tego szybki sposób sprawdzenia, czy klient kiedykolwiek zastosował twój plik.
IPsec/IKEv2 stoi pośrodku. Wtyczka attr strongSwana może zwrócić serwer DNS wyciągnięty z puli, a klient Windows zwykle to akceptuje, ale profil, który przypina własny serwer nazw, wygrywa z tym, co oferuje brama. Na kliencie Linuksa równoważnym krokiem ręcznym jest resolvectl dns wg0 10.8.0.53, po którym następuje resolvectl domain wg0 '~corp.example'; oba znikają razem z interfejsem, co jest dokładnie tym, czego chcesz przy ustawieniu ograniczonym do tunelu.
Ogranicz sufiks zamiast połykać każde zapytanie
Skierowanie całej listy resolverów klienta na twojego wewnętrznego serwera jest łatwe i zwykle błędne. Wtedy każda publiczna nazwa rozwiązuje się przez wyjście twojego centrum danych, CDN-y zwracają odległe adresy, a jedna awaria resolvera ciągnie za sobą przeglądanie użytkownika.
Wysyłaj do środka tylko prywatny sufiks. W systemd-resolved domena zaczynająca się od ~ służy wyłącznie do routingu, więc ~corp.example oznacza, że zapytania pod tym sufiksem idą do serwerów tego łącza, podczas gdy wszystko inne nadal korzysta z sieci fizycznej. Windows robi to samo za pomocą reguł NRPT ograniczonych do przestrzeni nazw, a macOS za pomocą dodatkowego pliku resolvera w /etc/resolver/.
Nazwy multicast zasługują na własną odpowiedź. Nazwy .local są z założenia link-local (RFC 6762), a interfejs tun typu punkt-punkt nie przenosi tej grupy multicast, więc dodanie publicznego resolvera ich nie opublikuje, a zapytanie do wewnętrznego resolvera unicast zwróci NXDOMAIN. Reflektor taki jak avahi w trybie reflektora potrafi połączyć dwa segmenty, ale to decyzja po stronie serwera, której żaden klient nie może zażądać. Jeśli drukarka albo NAS musi być osiągalny po nazwie, daj mu rekord A w swojej strefie.
Udowodnij, że odpowiedź może wrócić
Poprawna odpowiedź wskazująca nieosiągalny adres wygląda dokładnie jak problem resolvera, dopóki nie sprawdzisz trasy. Zapytaj jądro, dokąd trafiłaby odpowiedź: ip route get 10.20.5.20 nazywa interfejs i, co użyteczniejsze, adres źródłowy, którego by użyło.
Obserwuj sam adres resolvera. Klient z DNS = 10.8.0.53 obok AllowedIPs = 10.20.0.0/16 wysyła swoje zapytania przez fizyczną kartę sieciową, gdzie giną cicho, bo resolver nie leży w żadnym prefiksie, który tunel rezerwuje. Ta niezgodność to najczęstsza jednoprzyczynowa awaria w całym tym obszarze i pozostaje niewidoczna, dopóki nie porównasz ustawienia DNS z dozwolonymi prefiksami linia po linii.
Nakładające się zakresy powodują odwrotną awarię. Odpowiedź jest poprawna, trasa istnieje i wskazuje niewłaściwy host, bo 192.168.0.0/24 w domu jest bardziej szczegółowa niż trasa tunelu do tego samego zakresu. Przenumeruj jedną stronę albo wypchnij węższą trasę, a potem potwierdź zaporę i drogę powrotną hosta usługi; notatki strongSwana o przekazywaniu obejmują stronę sysctl tej drogi.
Certyfikaty to osobna kontrola tożsamości, którą ludzie zrzucają na DNS. Jeśli przeglądarka zgłasza niezgodność nazwy zamiast błędu rozwiązywania, wyszukiwanie już zadziałało i poprawić trzeba SAN w certyfikacie. Testuj HTTPS na nazwę, nigdy na goły adres IP.
Przetestuj ponownie z klienta, nie z bramy
Testuj w aplikacji, na którą skarży się użytkownik, bo wyszukanie z wiersza poleceń nie dowodzi, że przeglądarka idzie tą samą drogą. Bezpieczne DNS Chrome i network.trr.mode w Firefoksie potrafią całkowicie ominąć resolver systemowy, a gdy to robią, prywatna nazwa albo zawodzi, albo wycieka do publicznego resolvera. Porównanie resolvectl query z ręcznie uruchomionym dig @10.8.0.53 files.corp.example powie ci, który z tych dwóch przypadków zaszedł.
Potem rozłącz się i połącz ponownie, zanim uznasz to za naprawione. Ustawienia wprowadzone ręcznie na interfejsie znikają razem z interfejsem, a profil, który wyglądał poprawnie tylko z powodu zapomnianej lokalnej zmiany, zawiedzie przy następnym starcie.
Krótka lista dla następnej maszyny: nazwa rozwiązuje się przez resolver tunelu, sufiks jest ograniczony, a nie globalny, adres resolvera leży w dozwolonych prefiksach, host z odpowiedzi odpowiada na porcie usługi, a certyfikat obejmuje nazwę wpisaną przez użytkownika.