توجيه VPN على Android: قواعد السياسات قبل جدول main
يختار Android جدول توجيه بقواعد uid وعلامات قبل أي بحث عن الوجهة، لذا قد لا يُستشار أصلًا مسار مضاف إلى main.
المسار المضاف إلى جدول main على Android يبدو صحيحًا في كل قائمة ومع ذلك لا يحمل حركة المرور. السبب أن جدول main خيار من بين عدة خيارات، ولا يُستشار أولًا. تبني خدمة الشبكة في Android قواعد سياسات تختار جدول توجيه باستخدام معلومات لا يحتويها عنوان الوجهة — معرّف uid الخاص بالتطبيق، أو علامة على الحزمة، أو الواجهة التي وصلت منها — ثم يحدث البحث عن الوجهة بعد ذلك، داخل الجدول الذي اختارته تلك القواعد.
ثلاثة قرارات بترتيب ثابت
الحزمة الخارجة تتخذ ثلاثة قرارات منفصلة. أولًا، تقرر قاعدة سياسة جدول التوجيه الذي ينطبق. ثانيًا، يقرر مسار داخل ذلك الجدول القفزة التالية والواجهة الصادرة. ثالثًا، تقرر خطافات netfilter ما إذا كانت الحزمة تنجو أو تُعدّل أو تُعاد توجيهها.
الترتيب مهم لأن كل مرحلة لا تستطيع الإجابة إلا عن سؤالها. قاعدة جدار حماية تقبل حزمة لا تختار جدولًا، والمسار المضاف إلى جدول لا تختاره أي قاعدة يبقى معطلًا. قدر كبير من الالتباس حول شبكات VPN على Android يأتي من إصلاح واحد من الثلاثة وملاحظة عدم حدوث تغيير، لأن العطل كان في آخر.
| Stage | Selector | What it cannot decide |
|---|---|---|
| Policy rule | uid range, mark, incoming interface | Which route exists inside the table |
| Route lookup | Destination prefix, longest match | Whether the packet is allowed out |
| Netfilter hook | Chain position, match conditions | Which 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 الدقيق الذي تدعمه وصن دورة حياته عبر المكوّن الذي يملكه. إن تفريغ سلاسل المنصة أو إدخال قاعدة عالية الأولوية يحوّل التشخيص إلى مدير شبكة ثانٍ، وسيتصرف الهاتف وفقًا لذلك.