مسیری که در Android به جدول main اضافه می‌شود در هر فهرستی درست به نظر می‌رسد و با این حال ترافیک را حمل نمی‌کند. دلیل این است که جدول main یکی از چند گزینه است و اول از همه به آن مراجعه نمی‌شود. سرویس شبکه Android قواعد سیاستی می‌سازد که جدول مسیریابی را با اطلاعاتی انتخاب می‌کنند که آدرس مقصد آن را ندارد — uid برنامه، علامتی روی بسته، رابطی که بسته از آن رسیده — و جست‌وجوی مقصد بعد از آن، درون همان جدولی که آن قواعد برگزیده‌اند، انجام می‌شود.

سه تصمیم در ترتیبی ثابت

بسته‌ای که خارج می‌شود سه تصمیم جداگانه می‌گیرد. نخست، یک قاعده سیاست تعیین می‌کند کدام جدول مسیریابی اعمال می‌شود. دوم، یک مسیر درون آن جدول گام بعدی و رابط خروجی را تعیین می‌کند. سوم، قلاب‌های netfilter تعیین می‌کنند که بسته زنده می‌ماند، تغییر می‌کند یا تغییر مسیر می‌یابد.

ترتیب اهمیت دارد چون هر مرحله فقط می‌تواند به پرسش خودش پاسخ دهد. قاعده فایروالی که بسته را می‌پذیرد جدولی انتخاب نمی‌کند، و مسیری که به جدولی اضافه شده که هیچ قاعده‌ای آن را انتخاب نمی‌کند بی‌اثر است. بخش بزرگی از سردرگمی درباره VPNهای Android از این می‌آید که یکی از سه مورد اصلاح می‌شود و تغییری دیده نمی‌شود، چون ایراد در دیگری بوده است.

StageSelectorWhat it cannot decide
Policy ruleuid range, mark, incoming interfaceWhich route exists inside the table
Route lookupDestination prefix, longest matchWhether the packet is allowed out
Netfilter hookChain position, match conditionsWhich table was selected

علامت‌ها یک فیلد بسته‌بندی‌شده‌اند، نه برچسبی که مالک آن باشید

Android چند واقعیت را در همان مقدار علامت بسته‌بندی می‌کند: کدام شبکه انتخاب شده، آیا برنامه‌ای صریحاً شبکه‌ای را برگزیده، آیا سوکت از VPN محافظت شده و بیت‌های مربوط به مجوزها. سرآیند fwmark در AOSP آن چیدمان را برای درخت کنونی تعریف می‌کند و چیدمان یک جزئیات داخلی پلتفرم است که میان نسخه‌ها تغییر می‌کند.

به همین دلیل نوشتن یک مقدار کامل علامت با iptables -j MARK --set-mark در Android خطرناک است. این کار برچسب اضافه نمی‌کند؛ انتخاب شبکه‌ای را که سیستم پیش‌تر انجام داده جایگزین می‌کند. سپس بسته با قواعد دیگری مطابقت می‌یابد، که بسته به بیت‌های بازنویسی‌شده می‌تواند شبیه شروع کار VPN یا شبیه از دست رفتن اتصال یک برنامه بی‌ربط به نظر برسد.

اگر باید به علامت‌ها دست بزنید، نخست مقدار کنونی را بخوانید و از ماسک استفاده کنید تا فقط بیت‌هایی که می‌فهمید تغییر کنند:

ip rule show
ip route show table all | head -40
ip route get 10.20.4.11

علامت اتصال شیئی جدا از علامت بسته است و هیچ‌یک از این دو مسیر نیست. بازگرداندن علامت روی بسته‌های پاسخ گامی جدا از انتخاب جدول در خروج است، و به همین دلیل اصلاح‌های یک‌طرفه اتصالاتی می‌سازند که باز می‌شوند و سپس معلق می‌مانند.

مالک قواعد و جدول‌ها کیست

سرویس شبکه Android، یعنی netd، قواعد و جدول‌های هر شبکه را می‌سازد. AOSP RouteController جایی است که آن قواعد برای VPNها، شبکه‌های فیزیکی و بازه‌های uid گردآوری می‌شوند و چرخه عمرش به رویدادهای شبکه گره خورده است، نه به یک فایل پیکربندی.

دو پیامد دارد. نخست، اولویت‌ها و شماره جدول‌هایی که روی یک گوشی می‌بینید جزئیات داخلی ساخت هستند، نه رابط: شماره‌هایی که در نسخه دیگری از Android دقیقاً یکسان به نظر می‌رسند ممکن است چیزی کاملاً دیگر باشند. دوم، وضعیت هنگام تغییر شبکه‌ها از نو ساخته می‌شود، پس قاعده‌ای که امروز از پوسته root درج شود ممکن است پس از گذار بعدی Wi-Fi از میان رفته باشد.

این ناپدید شدن اغلب به این شکل گزارش می‌شود که سیستم مسیری را نادیده می‌گیرد. آنچه واقعاً رخ داده این است که قاعده‌ای که جدول را انتخاب می‌کرد دیگر وجود ندارد و مسیر درون جدول اکنون از دید بسته دست‌نیافتنی است. وقتی پیکربندی‌ای که کار می‌کرد پس از اتصال دوباره از کار می‌افتد، فهرست قواعد را بررسی کنید، نه فهرست مسیرها.

پرسش‌های ترتیب قلاب‌ها پاسخ جهان‌شمول ندارند

پرسش اینکه آیا iptables پیش از مسیریابی VPN اجرا می‌شود بدون نام بردن مسیر بسته پاسخ‌پذیر نیست. بسته تولیدشده محلی از قلاب output می‌گذرد، جایی که تغییر علامت یک بررسی تغییر مسیر را برمی‌انگیزد — جست‌وجویی دوم، نه ویرایشی پس‌روی جست‌وجوی نخست. بسته رسیده از کارخواه متصل با tethering مسیر prerouting را می‌پیماید و به جای آن ارسال می‌شود، و زنجیره‌هایی که آن را می‌بینند متفاوت‌اند.

پس یک قاعده می‌تواند برای ترافیک یک برنامه مؤثر و برای ترافیک tethering نامرئی باشد، و شمارنده‌ای که صفر می‌ماند به شما می‌گوید بسته کدام مسیر را رفته، نه اینکه قاعده اشتباه است. پیش از تغییر هر شرط تطبیق، با شمارنده‌ها مسیر را مشخص کنید.

این همچنین مرحله‌ای است که خطای مسیریابی سیاستی به‌سختی دیده می‌شود. مسیریابی به جدولی که هست ولی مقصد را ندارد «شبکه دست‌نیافتنی» تولید می‌کند که شبیه افت فایروال است، در حالی که افت فایروال مهلت زمانی تولید می‌کند که شبیه سیاه‌چاله مسیریابی است.

درون سیستم تشخیص دهید، یا رهایش کنید

برای بازبینی مجاز، پیش از دست زدن به هر چیز چهار واقعیت را مشخص کنید: uid و پروفایل برنامه، شبکه‌ای که Android برای آن برگزیده، اینکه آیا VPN اصلاً آن برنامه را شامل می‌شود، و اینکه آیا مشکل برای هر دو خانواده نشانی وجود دارد. استثنای هر برنامه بسیاری از گزارش‌های VPN کار نمی‌کند را بدون هیچ ایراد مسیریابی توضیح می‌دهد.

سپس قواعد، ماسک‌ها و جدول‌هایی را که واقعاً در حال اجرا هستند بخوانید و یک تغییر شبکه را درون پنجره مشاهده نگه دارید. اگر رفتار در طول اتصال دوباره تغییر کند، شما به چرخه عمر مدیریت‌شده نگاه می‌کنید، نه به مسیر گمشده.

برای نیازهای معمولی از کنترل‌های پشتیبانی‌شده استفاده کنید: شمول و استثنای هر برنامه در برنامه VPN، و انتخاب شبکه خود پلتفرم برای هر چیزی که به مسیر مشخصی نیاز دارد. اگر یک یکپارچه‌سازی ممتاز واقعاً باید با ماشین مسیریابی همکاری کند، پیاده‌سازی همان نسخه دقیق Android را که پشتیبانی می‌کنید هدف بگیرید و چرخه عمرش را از طریق مؤلفه‌ای که مالک آن است نگه دارید. پاک کردن زنجیره‌های پلتفرم یا درج قاعده‌ای با اولویت بالا تشخیص را به مدیر شبکه دومی تبدیل می‌کند و گوشی بر همان اساس رفتار خواهد کرد.

مقالات مرتبط