Android емулатор и VPN на хоста: моментна снимка на DNS и обяснение на NAT
Гостът стои зад NAT на емулатора и пази списъка с DNS, копиран при зареждането. Вдигнете тунела преди зареждането, после проверете разрешаването отвътре в госта.
Когато емулаторът не може да достигне сървър за сборка, който браузърът на хоста отваря без проблем, полезният въпрос не е дали VPN работи. А кой от два механизъма липсва на госта. Виртуалното устройство изпълнява собствен мрежов стек зад NAT на емулатора и списъкът му с резолвери е копие, направено при зареждането, затова тунел, вдигнат по-късно, променя пътя на хоста, без да променя това, което гостът пита. Разбирането на тези два слоя обяснява почти всеки вариант на този проблем.
Гостът е отделен стек зад фиксиран NAT
Мрежата на QEMU в потребителски режим поставя госта на 10.0.2.15, шлюз на 10.0.2.2 и DNS услуга на 10.0.2.3 до 10.0.2.6. Изходящият трафик на госта не се препраща от ядрото на хоста; той се превежда в сокети от страната на хоста, по един за всяка връзка на госта, и тези сокети излизат от адресното пространство на хоста. Затова връзката на госта наследява решението за маршрутизиране на хоста в момента на създаването и затова гостът няма запис в таблицата за маршрутизиране, който да назовава вашия тунел.
Същият механизъм дава на госта полезен изход. 10.0.2.2 е псевдоним на интерфейса за обратна връзка на хоста, така че услуга, която слуша на 127.0.0.1 на лаптопа, е достъпна от госта на този адрес. Всичко, което клиентът показва само на обратна връзка, е достъпно по този начин и това е основата на прокси схемата, описана по-долу.
Гостът не може да наблюдава мрежата на хоста, сякаш е именно пространство от имена. Няма мост, няма споделена таблица за маршрутизиране и няма наследен резолвер, а само NAT услугата, която приема пакетите му, и снимката, която стартерът е направил при стартирането на виртуалното устройство.
DNS е моментна снимка, а не жив изглед
При стартиране емулаторът чете списъка с резолвери на хоста и дава на госта до четири сървъра, показани на адресите от 10.0.2.3 до 10.0.2.6. Ако тунелът е бил изключен в този момент, снимката съдържа всеки публичен резолвер, който лаптопът е използвал, и гостът продължава да го пита до края на живота си. Публичните имена се разрешават, вътрешните се провалят и всеки симптом сочи към VPN, докато действителната остаряла стойност е списък с резолвери, заснет минути преди тунелът да се вдигне.
Затова поправката чрез подредба не е фолклор. Свържете първо тунела, после рестартирайте емулатора и предпочитайте студено зареждане пред възстановяване на снимка, защото образът за бързо зареждане може да се върне със запазеното по-рано състояние на резолвер и маршрути. Ако трябва да видите какво използва гостът сега, питайте устройството, а не хоста:
adb shell dumpsys connectivity | grep -i -A2 dns
adb shell ping -c 1 build.internal.exampleЕмулаторът приема и изричен резолвер при стартиране, което е полезно, когато знаете точно кой сървър трябва да използва гостът, и опасно, когато този сървър е публичен:
emulator -avd Pixel_API_34 -dns-server 203.0.113.53Публичният резолвер няма копие на вътрешна зона, затова заковаването на един превръща проблем с подредбата в постоянен отказ. Ако профилът налага частен DNS, оставете тунела да го осигури и заредете госта студено, вместо да твърдо задавате адрес.
Маршрутизирането следва хоста към момента на връзката
Тъй като връзките на госта стават сокети на хоста, решението за маршрутизиране се взема при създаването на сокета. Тунел преди заявката означава, че заявката излиза през тунела съгласно маршрутите на профила. Профил с разделен тунел, който носи само избрани префикси, спокойно ще остави частната ви подмрежа отвън, затова достъпността на хоста е хипотеза за госта, а не резултат. Съществуващите връзки на госта запазват пътя, с който са създадени, и затова клиент, който се свързва отново, не винаги поправя заседнало изтегляне в емулатора.
Проверката е на интерфейса на хоста, а не в статистиката на госта:
sudo tcpdump -ni tun0 'host 203.0.113.10'Ако заявката на госта се появи на интерфейса на тунела, маршрутизирането работи и проблемът е над него. Ако се появи на физическия интерфейс, профилът не покрива този префикс и никакво преконфигуриране от страна на госта няма да го промени.
Когато клиентът предлага само прокси на обратна връзка
Някои търговски клиенти изобщо не създават системен тунел. Те отварят HTTP или SOCKS слушател на 127.0.0.1 и очакват приложенията да го използват. Гостът не вижда този сокет директно, но на емулатора може да се нареди да го използва — или чрез разширените контроли (Настройки, после Прокси, ръчен режим, хост 127.0.0.1 и портът, който клиентът отпечатва), или при стартиране:
emulator -avd Pixel_API_34 -http-proxy http://127.0.0.1:8080Копирайте порта от прозореца на клиента; познат наум порт се проваля тихо и изглежда като счупен тунел. Помнете какво покрива това: настройката за HTTP прокси се спазва от приложения, които познават прокси, а суровите сокети я игнорират напълно. Ако натоварването е собствен бинарен файл, който отваря свои връзки, пътят през прокси не е еквивалентен на тунел и сравнението трябва да се направи изрично.
Докажете резултата отвътре в госта
Отделете разрешаването от маршрутизирането с два теста в една сесия. Име, което се проваля, докато числовият адрес отговаря, е проблем със снимката на DNS и поправката е подредба или изричен резолвер. Провалът и на двете сочи към маршрутизиране или политика и следващата проверка е дали приложението работи в работен профил със собствени мрежови ограничения.
Накрая, знайте на кой гост тествате. Много стари образи на емулатора са доставени без поддръжка на tun, нужна на клиент за VPN от страната на госта, затова там никой профил не можеше да работи; настоящите образи я включват. Клиент, който се проваля на настоящ образ, е проблем на клиента или профила и преизграждането на тунела на хоста няма да промени резултата.