Emulator Androida a VPN na hoście: snapshot DNS i NAT
Gość siedzi za NAT emulatora i trzyma listę DNS skopiowaną przy starcie. Podnieś tunel przed startem, a potem sprawdź rozwiązywanie nazw od wewnątrz gościa.
Gdy emulator nie dociera do serwera kompilacji, który przeglądarka na hoście otwiera bez problemu, użyteczne pytanie nie brzmi, czy VPN działa. Pytanie brzmi, którego z dwóch mechanizmów brakuje gościowi. Urządzenie wirtualne uruchamia własny stos sieciowy za NAT emulatora, a jego lista resolverów jest kopią wykonaną przy starcie, więc tunel, który pojawi się później, zmienia ścieżkę hosta, ale nie zmienia tego, o co pyta gość. Zrozumienie tych dwóch warstw wyjaśnia niemal każdy wariant tego problemu.
Gość to osobny stos za stałym NAT
Sieć QEMU w trybie użytkownika umieszcza gościa pod 10.0.2.15 z bramą pod 10.0.2.2 i usługą DNS pod 10.0.2.3 do 10.0.2.6. Ruch wychodzący gościa nie jest przekazywany przez jądro hosta; jest tłumaczony na gniazda po stronie hosta, po jednym na każde połączenie gościa, i te gniazda wychodzą z przestrzeni adresowej hosta. Dlatego połączenie gościa dziedziczy decyzję routingu hosta w chwili utworzenia, i dlatego gość nie ma w tablicy routingu wpisu, który nazywa twój tunel.
Ten sam mechanizm daje gościowi użyteczne wyjście awaryjne. 10.0.2.2 to alias interfejsu loopback hosta, więc usługa nasłuchująca na 127.0.0.1 na laptopie jest osiągalna z gościa pod tym adresem. Wszystko, co klient udostępnia tylko na loopback, jest w ten sposób osiągalne, i to jest podstawa opisanej niżej konfiguracji proxy.
Gość nie może natomiast obserwować sieci hosta tak, jakby był jej przestrzenią nazw. Nie ma mostka, wspólnej tablicy routingu ani odziedziczonego resolvera; jest tylko usługa NAT, która przyjmuje jego pakiety, i snapshot, który launcher wykonał przy starcie urządzenia wirtualnego.
DNS to snapshot, a nie widok na żywo
Przy starcie emulator czyta listę resolverów hosta i przekazuje gościowi do czterech serwerów, udostępnianych pod adresami 10.0.2.3 do 10.0.2.6. Jeśli tunel był wtedy wyłączony, snapshot zawiera ten publiczny resolver, którego używał laptop, a gość pyta go przez całe życie. Nazwy publiczne się rozwiązują, nazwy wewnętrzne zawodzą, i wszystkie objawy wskazują na VPN, podczas gdy naprawdę nieaktualną wartością jest lista resolverów przechwycona kilka minut przed podniesieniem tunelu.
Poprawka kolejności nie jest więc folklorem. Najpierw połącz tunel, potem uruchom emulator ponownie, i wolij zimny start od przywracania snapshotu, bo obraz quick-boot może wrócić ze stanem resolvera i tras zapisanym wcześniej. Jeśli chcesz zobaczyć, czego gość używa teraz, pytaj urządzenie, a nie hosta:
adb shell dumpsys connectivity | grep -i -A2 dns
adb shell ping -c 1 build.internal.exampleEmulator przyjmuje też jawny resolver przy starcie, co jest przydatne, gdy dokładnie wiesz, którego serwera ma używać gość, i niebezpieczne, gdy ten serwer jest publiczny:
emulator -avd Pixel_API_34 -dns-server 203.0.113.53Publiczny resolver nie ma kopii strefy wewnętrznej, więc przypięcie jednego zamienia problem kolejności w trwałą awarię. Jeśli profil wypycha prywatny DNS, pozwól tunelowi go dostarczyć i uruchom gościa zimno, zamiast wpisywać adres na stałe.
Routing podąża za hostem w chwili połączenia
Ponieważ połączenia gościa stają się gniazdami hosta, decyzja routingu zapada przy tworzeniu gniazda. Tunel podniesiony przed żądaniem oznacza, że żądanie wychodzi przez tunel, zależnie od tras profilu. Profil split-tunnel, który przenosi tylko wybrane prefiksy, chętnie zostawi twoją prywatną podsieć na zewnątrz, więc osiągalność hosta jest hipotezą o gościu, a nie wynikiem. Istniejące połączenia gościa zachowują ścieżkę, z którą powstały, dlatego klient, który łączy się ponownie, nie zawsze naprawia zawieszone pobieranie w emulatorze.
Weryfikacja należy do interfejsu hosta, a nie do statystyk gościa:
sudo tcpdump -ni tun0 'host 203.0.113.10'Jeśli żądanie gościa pojawia się na interfejsie tunelu, routing działa, a problem jest wyżej. Jeśli pojawia się na interfejsie fizycznym, profil nie obejmuje tego prefiksu i żadna rekonfiguracja po stronie gościa tego nie zmieni.
Gdy klient oferuje tylko proxy na loopback
Niektóre komercyjne klienty w ogóle nie tworzą tunelu systemowego. Udostępniają nasłuch HTTP lub SOCKS na 127.0.0.1 i oczekują, że aplikacje go użyją. Gość nie widzi tego gniazda bezpośrednio, ale emulatorowi można kazać go użyć, albo przez rozszerzone kontrolki (Settings, potem Proxy, tryb ręczny, host 127.0.0.1 i port wypisany przez klienta), albo przy starcie:
emulator -avd Pixel_API_34 -http-proxy http://127.0.0.1:8080Skopiuj port z okna klienta; zgadywany port zawodzi po cichu i wygląda jak zepsuty tunel. Pamiętaj, co to obejmuje: ustawienie proxy HTTP jest respektowane przez aplikacje świadome proxy, a surowe gniazda całkowicie je ignorują. Jeśli obciążeniem jest plik binarny native, który otwiera własne połączenia, ścieżka proxy nie jest równoważna tunelowi i porównanie trzeba przeprowadzić jawnie.
Udowodnij wynik od wewnątrz gościa
Oddziel rozwiązywanie nazw od routingu dwoma testami w tej samej sesji. Nazwa, która zawodzi, gdy adres numeryczny odpowiada, to problem snapshotu DNS, a rozwiązaniem jest kolejność lub jawny resolver. Gdy zawodzi jedno i drugie, wskazuje to na routing lub politykę, a następne sprawdzenie dotyczy tego, czy aplikacja działa w profilu roboczym z własnymi ograniczeniami sieci.
Na koniec wiedz, na jakim gościu testujesz. Bardzo stare obrazy emulatora były dostarczane bez obsługi tun, której potrzebuje klient VPN po stronie gościa, więc żaden profil nigdy by tam nie zadziałał; obecne obrazy ją mają. Klient, który zawodzi na obecnym obrazie, to problem klienta lub profilu, a odbudowa tunelu hosta niczego nie zmieni.