برنامه اندروید نامها را بیرون از VPN حل میکند: فهرست بررسی اتصال
اندروید میتواند در حین فعال بودن VPN نامها را از طریق شبکه پیشفرض حل کند. فرایند را به شبکه VPN متصل کنید و بررسی کنید برنامه در عمل از کدام حلکننده استفاده کرده است.
یک برنامه اندروید نمیتواند نامی داخلی را حل کند، در حالی که مرورگر خود کلاینت VPN به آن میرسد و همان بیلد روی گوشی دیگری کار میکند. متغیر، URL نیست. متغیر این است که فرایند برنامه اجازه دارد از کدام شبکه برای حل استفاده کند، و اندروید تضمین نمیکند که VPN فعال همانی باشد که سوکتهای شما استفاده میکنند. این بررسیها را به ترتیب انجام دهید و وقتی تصویر لحظهای حلکننده با فرض شما نمیخواند متوقف شوید.
گام 1: اثبات کنید برنامه روی کدام شبکه است
نمای خود برنامه را بخوانید، نه نوار وضعیت را. از ConnectivityManager شبکه فعال، LinkProperties آن، فهرست سرورهای DNS و تنظیم DNS خصوصی را بگیرید. اگر فهرست حلکننده VPN را دارد، برنامه مسیری به آن دارد؛ اگر حلکننده Wi-Fi را دارد، تونل شبکه پیشفرض آن فرایند نیست.
یک نماد VPN فقط میگوید تونلی وجود دارد. نمیگوید که فرایند برنامه به آن متصل شده است، و اندروید همیشه حل نام را از شبکهای که فعال به نظر میرسد عبور نمیدهد. برنامههای VPN محلی که به دستگاه دیگری ارسال میکنند، شبکههای Wi-Fi بدون اینترنت و بیلدهای سازندگان میتوانند باعث شوند برنامه از حلکننده پیشفرض بپرسد نه از سرورهای تونل.
گام 2: انتقال VPN را درخواست کنید و فرایند را متصل کنید
وقتی برنامه باید از حلکننده تونل استفاده کند، شبکهای با انتقال VPN درخواست کنید و فرایند را در callback متصل کنید تا کد حدس نزند شبکه چه وقت ظاهر میشود:
val request = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_VPN)
.build()
connectivityManager.requestNetwork(request, object : NetworkCallback() {
override fun onAvailable(network: Network) {
val bound = connectivityManager.bindProcessToNetwork(network)
Log.i(TAG, "bound to VPN network: " + bound)
}
})این فراخوانی شبکه پیشفرض کل فرایند را تغییر میدهد، پس هر سوکتی که بعد از آن ساخته شود از آن استفاده میکند. سوکتهایی که از قبل وجود دارند شبکهای را که در آن ساخته شدهاند نگه میدارند، به همین دلیل یک استخر اتصال که پیش از اتصال باز شده ممکن است از مسیر قدیمی حل کند. مقدار بازگشتی بولی است و نتیجه false یعنی اتصال انجام نشده است؛ پس از تأخیری کوتاه دوباره تلاش کنید و هر دو تلاش را ثبت کنید.
گام 3: اتصال را به آنچه به آن نیاز دارد محدود کنید
اتصال در سطح فرایند خشن است. تلهمتری، بررسیهای بهروزرسانی و SDKهای شخص ثالث هم به تونل میروند و اگر تونل اینترنت نداشته باشد شروع به شکست میکنند. برای یک درخواست، از کارخانه سوکت شبکه استفاده کنید و پیشفرض دستگاه را برای بقیه نگه دارید. آگاهانه یک مدل را انتخاب کنید: اتصال باریک برای هر اتصال، یا اتصال فرایند با جدا کردن صریح وقتی VPN ناپدید میشود.
دو ویژگی حلکننده میتوانند بدون هیچ خطایی اتصال را شکست دهند. DNS خصوصی در حالت سختگیرانه پرسوجوها را به سرور DoT نامدار میفرستد نه به حلکننده شبکه، و برنامهای که کلاینت DNS-over-HTTPS خودش را دارد کاملاً از حلکننده سیستم دور میزند. پیش از نتیجهگیری که اتصال شکست خورده، هر دو را بررسی کنید. پرسوجویی که هرگز به سرور DNS تونل نمیرسد در هیچ لاگی از سمت تونل دیده نمیشود.
گام 4: به محدودیت CONNECTED اعتماد نکنید
پرچم NetworkType.CONNECTED در WorkManager یعنی شبکهای متصل است، و انتقال VPN آن را حتی وقتی پیوند Wi-Fi یا موبایل زیرین از بین رفته برمیآورد. کار اجرا میشود، هر درخواست شکست میخورد و سیاست تلاش دوباره آن را به طوفانی تبدیل میکند که شبیه باگ زمانبندی است. تونل یک شبکه است؛ محدودیت هرگز بررسی اینترنت نبود.
توانمندیای را بررسی کنید که کار واقعاً به آن نیاز دارد، مانند دسترسی اینترنت اعتبارسنجیشده، و سیاست تلاش دوباره محدود با عقبنشینی نگه دارید. اگر کار به نامی داخلی نیاز دارد، آن نام را پیش از انجام کار در شبکه انتخابشده حل کنید و بهجای تکرار درخواستی که نمیتواند موفق شود، سریع با خطای روشن شکست بخورید.
گام 5: شواهد را ثبت کنید و دامنه را دوباره بیازمایید
انواع انتقال شبکه انتخابشده، سرورهای DNS از LinkProperties ، اینکه اتصال true برگرداند و خطای دقیق نخستین درخواست را ثبت کنید. سپس یک نام داخلی و یک نام عمومی را زیر همان اتصال اجرا کنید. این جفت نشان میدهد برنامه از حلکننده تونل استفاده کرده یا بیصدا به پیشفرض دستگاه برگشته است، و این همان تفاوتی است که کاربر تجربه میکند.
این را روی قدیمیترین نسخه اندرویدی که پشتیبانی میکنید و یک نسخه فعلی تکرار کنید. رفتار حلکنندهای که مسیر پیشفرض را درست نشان میدهد دقیقاً همان جایی است که دستگاهها و نسخهها تفاوت دارند، و بیلدی که فقط روی جدیدترین دستگاه آزمون قبول میشود برای دامنهای که ارائه میدهید تأیید نشده است. adb shell dumpsys connectivityراهی سریع برای تأیید این است که دستگاه هنگام بازتولید خطا چه شبکهها و توانمندیهایی را گزارش میکند.